instant.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. package edit
  2. import (
  3. "src.elv.sh/pkg/cli"
  4. "src.elv.sh/pkg/cli/modes"
  5. "src.elv.sh/pkg/cli/tk"
  6. "src.elv.sh/pkg/eval"
  7. "src.elv.sh/pkg/parse"
  8. )
  9. //elvdoc:var -instant:binding
  10. //
  11. // Binding for the instant mode.
  12. //elvdoc:fn -instant:start
  13. //
  14. // Starts the instant mode. In instant mode, any text entered at the command
  15. // line is evaluated immediately, with the output displayed.
  16. //
  17. // **WARNING**: Beware of unintended consequences when using destructive
  18. // commands. For example, if you type `sudo rm -rf /tmp/*` in the instant mode,
  19. // Elvish will attempt to evaluate `sudo rm -rf /` when you typed that far.
  20. func initInstant(ed *Editor, ev *eval.Evaler, nb eval.NsBuilder) {
  21. bindingVar := newBindingVar(emptyBindingsMap)
  22. bindings := newMapBindings(ed, ev, bindingVar)
  23. nb.AddNs("-instant",
  24. eval.BuildNsNamed("edit:-instant").
  25. AddVar("binding", bindingVar).
  26. AddGoFns(map[string]any{
  27. "start": func() { instantStart(ed.app, ev, bindings) },
  28. }))
  29. }
  30. func instantStart(app cli.App, ev *eval.Evaler, bindings tk.Bindings) {
  31. execute := func(code string) ([]string, error) {
  32. outPort, collect, err := eval.StringCapturePort()
  33. if err != nil {
  34. return nil, err
  35. }
  36. err = ev.Eval(
  37. parse.Source{Name: "[instant]", Code: code},
  38. eval.EvalCfg{
  39. Ports: []*eval.Port{nil, outPort},
  40. Interrupt: eval.ListenInterrupts})
  41. return collect(), err
  42. }
  43. w, err := modes.NewInstant(app,
  44. modes.InstantSpec{Bindings: bindings, Execute: execute})
  45. if w != nil {
  46. app.PushAddon(w)
  47. app.Redraw()
  48. }
  49. if err != nil {
  50. app.Notify(modes.ErrorText(err))
  51. }
  52. }