src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/edit/highlight_test.go (about) 1 package edit 2 3 import ( 4 "os" 5 "path/filepath" 6 "runtime" 7 "testing" 8 9 "src.elv.sh/pkg/cli/term" 10 "src.elv.sh/pkg/env" 11 "src.elv.sh/pkg/eval" 12 "src.elv.sh/pkg/testutil" 13 "src.elv.sh/pkg/tt" 14 "src.elv.sh/pkg/ui" 15 ) 16 17 // High-level sanity test. 18 19 func TestHighlighter(t *testing.T) { 20 f := setup(t) 21 22 // Highlighting 23 feedInput(f.TTYCtrl, "put $true") 24 f.TestTTY(t, 25 "~> put $true", Styles, 26 " vvv $$$$$", term.DotHere, 27 ) 28 29 // Check errors 30 feedInput(f.TTYCtrl, "x") 31 f.TestTTY(t, 32 "~> put $truex", Styles, 33 " vvv ??????", term.DotHere, "\n", 34 "compilation error: [interactive]:1:5-10: variable $truex not found", 35 ) 36 } 37 38 func TestHighlighter_Autofix(t *testing.T) { 39 f := setup(t) 40 f.Evaler.AddModule("mod1", &eval.Ns{}) 41 42 feedInput(f.TTYCtrl, "put $mod1:") 43 f.TestTTY(t, 44 "~> put $mod1:", Styles, 45 " vvv ??????", term.DotHere, "\n", 46 "compilation error: [interactive]:1:5-10: variable $mod1: not found\n", 47 "Ctrl-A autofix: use mod1 Tab Enter autofix first", Styles, 48 "++++++ +++ +++++", 49 ) 50 51 f.TTYCtrl.Inject(term.K('A', ui.Ctrl)) 52 f.TestTTY(t, 53 "~> put $mod1:", Styles, 54 " vvv $$$$$$", term.DotHere, 55 ) 56 } 57 58 // Fine-grained tests against the highlighter. 59 60 const colonInFilenameOk = runtime.GOOS != "windows" 61 62 func TestMakeHasCommand(t *testing.T) { 63 ev := eval.NewEvaler() 64 65 // Set up global functions and modules in the evaler. 66 goodFn := eval.NewGoFn("good", func() {}) 67 ev.ExtendGlobal(eval.BuildNs(). 68 AddFn("good", goodFn). 69 AddNs("a", 70 eval.BuildNs(). 71 AddFn("good", goodFn). 72 AddNs("b", eval.BuildNs().AddFn("good", goodFn)))) 73 74 // Set up environment. 75 testDir := testutil.InTempDir(t) 76 testutil.Setenv(t, env.PATH, filepath.Join(testDir, "bin")) 77 if runtime.GOOS == "windows" { 78 testutil.Unsetenv(t, env.PATHEXT) // force default value 79 } 80 81 // Set up a directory in PATH. 82 mustMkdirAll("bin") 83 mustMkExecutable("bin/external") 84 mustMkExecutable("bin/@external") 85 if colonInFilenameOk { 86 mustMkExecutable("bin/ex:tern:al") 87 } 88 89 // Set up a directory not in PATH. 90 mustMkdirAll("a/b/c") 91 mustMkExecutable("a/b/c/executable") 92 93 tt.Test(t, hasCommand, 94 // Builtin special form 95 Args(ev, "if").Rets(true), 96 97 // Builtin function 98 Args(ev, "put").Rets(true), 99 100 // User-defined function 101 Args(ev, "good").Rets(true), 102 103 // Function in modules 104 Args(ev, "a:good").Rets(true), 105 Args(ev, "a:b:good").Rets(true), 106 Args(ev, "a:bad").Rets(false), 107 Args(ev, "a:b:bad").Rets(false), 108 109 // Non-searching directory and external 110 Args(ev, "./a").Rets(true), 111 Args(ev, "a/b").Rets(true), 112 Args(ev, "a/b/c/executable").Rets(true), 113 Args(ev, "./bad").Rets(false), 114 Args(ev, "a/bad").Rets(false), 115 116 // External in PATH 117 Args(ev, "external").Rets(true), 118 Args(ev, "@external").Rets(true), 119 Args(ev, "ex:tern:al").Rets(colonInFilenameOk), 120 // With explicit e: 121 Args(ev, "e:external").Rets(true), 122 Args(ev, "e:bad-external").Rets(false), 123 124 // Non-existent 125 Args(ev, "bad").Rets(false), 126 Args(ev, "a:").Rets(false), 127 ) 128 } 129 130 func mustMkdirAll(path string) { 131 err := os.MkdirAll(path, 0700) 132 if err != nil { 133 panic(err) 134 } 135 } 136 137 func mustMkExecutable(path string) { 138 if runtime.GOOS == "windows" { 139 path += ".exe" 140 } 141 err := os.WriteFile(path, nil, 0700) 142 if err != nil { 143 panic(err) 144 } 145 }