shrub/pkg/arvo/sur/sole.hoon
Philip Monk 76b917f426
dojo: add tab completion
This is initial support for type-aware tab completion.  When you hit tab, it tries to complete the word you're in the middle of using a face or arm in the subject at that point in the code.  It also shows all possible matches and their associated types.  It's nearly instantaneous.  Notes:

- It advances to the longest common prefix, so if you hit tab on `ab` and the only possible results are `abcde` and `abcdz`, then it'll write `abcd` and print both out (with their types).

- If there are fewer than ten matches, it prints the type along with the face.  Printing types is too slow to use all the time, but with 10 it's essentially instantaneous.

- The match closest in the subject to you (i.e. smallest axis number) is displayed lowest (closest to your focus).

Examples below, where `<TAB>` represents me hitting tab while my cursor is at that position (the line with the `<TAB>` is not preserved in the actual output).

```
~zod:dojo> eth<TAB>
-----
ethereum        #t/<11.qcl {<3.ltb 27.ipf 7.ecf 36.uek 92.bjk 247.ows 51.mvt 126.xjf 41.mac 1.ane $141> <21.yeb 27.ipf 7.ecf 36.uek 92.bjk 247.ows 51.mvt 126.xjf 41.mac 1.ane $141>}>
ethereum-types  #t/<3.ltb 27.ipf 7.ecf 36.uek 92.bjk 247.ows 51.mvt 126.xjf 41.mac 1.ane $141>
~zod:dojo> ethereum
~zod:dojo> |=  zong=@ud  z<TAB>
-----
zing  #t/<1.dqs {* <126.xjf 41.mac 1.ane $141>}>
zap   #t/<1.iot {tub/{p/{p/@ud q/@ud} q/""} <1.rff {daf/@t <247.ows 51.mvt 126.xjf 41.mac 1.ane $141>}>}>
zuse  #t/$309
zong  #t/@ud
~zod:dojo> |=  zong=@ud  zo<TAB>
-----
zong  #t/@ud
~zod:dojo> |=  zong=@ud  zong
~zod:dojo> <TAB>
hoon-version
trel
quip
pole
unit
qual
lone
... about 600 more lines ...
unity
html
zuse
eny
now
our
~zod:dojo>
```

Functionally, this is in a state where I'd be comfortable shipping it.  It doesn't interfere with anything if you don't press tab, and it's perfectly OTA-able.  I do think its output is a little verbose, but that can be tuned over time as people try it and determine what feels good in practice.

Additional notes:

- There are plenty of similar systems for other languages, but my most direct inspiration is Idris's editor tools.  This is implemented for the dojo, but I actually want it in my editor, which is why the meat is all defind in a library.  I've only tested on dojo one-liners, so I don't know the performance on large blocks of code.

- The default type printer isn't great for this use case.  In particular,
	- Cores should not print anything about their context
  - The `#t/` should go away
  - If it looks like a gate, we should print its return value
  - Maybe special handling for molds, but if the above is done, then for example `bone` is  `* -> @ud`.

- The worst part about our wing ordering is that it really screws up tab completion.  You want to do `point.owner-address` instead of `owner-address.point` because that lets you type `point.ow<TAB>`.  I weakly prefer reading it how we do it now, but it's really not great.  You could do an (dojo-specific?) alternate syntax of `point;owner-address`; this is a simple transformation.

- Regardless of the above, this should handle the case where we're in the middle of defining a wing; it doesn't right now.

- When a variable is shadowed, we show both of them.  We should probably show the shadowed one with a `^`.

- We probably shouldn't print out hundreds of results.  Maybe just the closest 50 with ellipses.

- This gets you any face in your subject, regardless of whether its type is reasonable.  We could limit that some by copying the `gol` logic in mint, so that if the pseudo-backward-inference engine happens to know what type it should be, you can filter the tab results according to if they nest in that type.  This would be "strongly type-aware".
2019-10-30 23:19:25 -07:00

85 lines
5.4 KiB
Plaintext

::
:::: /hoon/sole/sur
::
^?
|%
++ sole-action :: sole to app
$% :: {$abo ~} :: reset interaction
{$det sole-change} :: command line edit
{$ret ~} :: submit and clear
{$clr ~} :: exit context
{$tab pos=@ud} :: tab complete
== ::
++ sole-buffer (list @c) :: command state
++ sole-change :: network change
$: ler/sole-clock :: destination clock
haw/@uvH :: source hash
ted/sole-edit :: state change
== ::
++ sole-clock {own/@ud his/@ud} :: vector clock
++ sole-edit :: shared state change
$% {$del p/@ud} :: delete one at
{$ins p/@ud q/@c} :: insert at
{$mor p/(list sole-edit)} :: combination
{$nop ~} :: no-op
{$set p/sole-buffer} :: discontinuity
== ::
++ sole-effect :: app to sole
$% {$bel ~} :: beep
{$blk p/@ud q/@c} :: blink+match char at
{$clr ~} :: clear screen
{$det sole-change} :: edit command
{$err p/@ud} :: error point
{$klr p/styx} :: styled text line
{$mor p/(list sole-effect)} :: multiple effects
{$nex ~} :: save clear command
{$pro sole-prompt} :: set prompt
{$sag p/path q/*} :: save to jamfile
{$sav p/path q/@} :: save to file
{$tan p/(list tank)} :: classic tank
:: {$taq p/tanq} :: modern tank
{$txt p/tape} :: text line
{$url p/@t} :: activate url
== ::
++ sole-command :: command state
$: pos/@ud :: cursor position
say/sole-share :: cursor
== ::
++ sole-prompt :: prompt definition
$: vis/? :: command visible
tag/term :: history mode
cad/styx :: caption
== ::
++ sole-share :: symmetric state
$: ven/sole-clock :: our vector clock
leg/(list sole-edit) :: unmerged edits
buf/sole-buffer :: sole state
== ::
:: ::
:: ::
++ sole-dialog :: standard dialog
|* out/$-(* *) :: output structure
$-(sole-input (sole-result out)) :: output function
:: ::
++ sole-input tape :: prompt input
++ sole-result :: conditional result
|* out/$-(* *) :: output structure
$@(@ud (sole-product out)) :: error position
:: ::
++ sole-product :: success result
|* out/$-(* *) ::
%+ pair (list tank) ::
%+ each (unit out) :: ~ is abort
(pair sole-prompt (sole-dialog out)) :: ask and continue
:: ::
++ sole-gen :: XX virtual type
$% {$say $-((sole-args) (cask))} :: direct noun
{$ask $-((sole-args) (sole-product (cask)))} :: dialog
== ::
++ sole-args :: generator arguments
|* _[* *] ::
{{now/@da eny/@uvJ bek/beak} {,+<- ,+<+}} ::
:: ::
:: ::
--