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  }