github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/shell/prompt.go (about) 1 package shell 2 3 import ( 4 "fmt" 5 6 "github.com/lmorg/murex/app" 7 "github.com/lmorg/murex/lang" 8 "github.com/lmorg/murex/lang/types" 9 "github.com/lmorg/murex/utils" 10 "github.com/lmorg/murex/utils/ansititle" 11 ) 12 13 func getPrompt() []byte { 14 var ( 15 err, err2 error 16 exitNum int 17 b []byte 18 ) 19 20 prompt, fileRef, err := lang.ShellProcess.Config.GetFileRef("shell", "prompt", types.CodeBlock) 21 if err == nil { 22 fork := lang.ShellProcess.Fork(lang.F_FUNCTION | lang.F_BACKGROUND | lang.F_NO_STDIN | lang.F_CREATE_STDOUT | lang.F_NO_STDERR) 23 fork.Variables.Set(fork.Process, "linenum", 1, types.Integer) 24 fork.Name.Set("(prompt)") 25 fork.FileRef = fileRef 26 fork.Execute([]rune(prompt.(string))) 27 28 b, err2 = fork.Stdout.ReadAll() 29 b = utils.CrLfTrim(b) 30 } 31 32 if exitNum != 0 || err != nil || len(b) == 0 || err2 != nil { 33 lang.ShellProcess.Stderr.Writeln([]byte("Invalid prompt. Block returned false.")) 34 b = []byte("murex » ") 35 } 36 37 return b 38 } 39 40 func getMultilinePrompt(nLines int) []byte { 41 var ( 42 err, err2 error 43 exitNum int 44 b []byte 45 ) 46 47 prompt, fileRef, err := lang.ShellProcess.Config.GetFileRef("shell", "prompt-multiline", types.CodeBlock) 48 if err == nil { 49 fork := lang.ShellProcess.Fork(lang.F_FUNCTION | lang.F_BACKGROUND | lang.F_NO_STDIN | lang.F_CREATE_STDOUT | lang.F_NO_STDERR) 50 fork.Variables.Set(fork.Process, "linenum", nLines, types.Integer) 51 fork.Name.Set("(prompt-multiline)") 52 fork.FileRef = fileRef 53 fork.Execute([]rune(prompt.(string))) 54 55 b, err2 = fork.Stdout.ReadAll() 56 b = utils.CrLfTrim(b) 57 } 58 59 if exitNum != 0 || err != nil || len(b) == 0 || err2 != nil { 60 lang.ShellProcess.Stderr.Writeln([]byte("Invalid prompt. Block returned false.")) 61 b = []byte(fmt.Sprintf("%5d » ", nLines)) 62 } 63 64 return b 65 } 66 67 func writeTitlebar() { 68 v, fileRef, err := lang.ShellProcess.Config.GetFileRef("shell", "titlebar-func", types.CodeBlock) 69 title, ok := v.(string) 70 if !ok || err != nil || title == `out: ''` { 71 return 72 } 73 74 fork := lang.ShellProcess.Fork(lang.F_FUNCTION | lang.F_BACKGROUND | lang.F_NO_STDIN | lang.F_CREATE_STDOUT | lang.F_NO_STDERR) 75 fork.Name.Set("(titlebar-func)") 76 fork.FileRef = fileRef 77 exitNum, err := fork.Execute([]rune(title)) 78 79 var b []byte 80 if err == nil { 81 b, err = fork.Stdout.ReadAll() 82 b = utils.CrLfTrim(b) 83 } 84 85 if exitNum != 0 || err != nil { 86 lang.ShellProcess.Stderr.Writeln([]byte(fmt.Sprintf("Invalid titlebar-func: %V", err))) 87 ansititle.Write([]byte(app.Name)) 88 } 89 90 ansititle.Write(b) 91 } 92 93 // ConfigReadGetCursorPos is a dynamic config wrapper function for Prompt.EnableGetCursorPos 94 func ConfigReadGetCursorPos() (interface{}, error) { 95 return Prompt.EnableGetCursorPos, nil 96 } 97 98 // ConfigWriteGetCursorPos is a dynamic config wrapper function for Prompt.EnableGetCursorPos 99 func ConfigWriteGetCursorPos(v interface{}) error { 100 switch v := v.(type) { 101 case bool: 102 Prompt.EnableGetCursorPos = v 103 104 case string: 105 switch v { 106 case types.TrueString: 107 Prompt.EnableGetCursorPos = true 108 109 case types.FalseString: 110 Prompt.EnableGetCursorPos = false 111 112 default: 113 return fmt.Errorf("expecting 'true' or 'false'. Instead received '%s'", v) 114 } 115 116 default: 117 return fmt.Errorf("expecting boolean value. Instead received %T", v) 118 } 119 120 return nil 121 }