forked from metakirby5/codi.vim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
codi.txt
628 lines (514 loc) · 25.8 KB
/
codi.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
*codi*
.------------.~
| .---. | .---. .----. ---.---~
| / | / \ | \ |~
| ( | ( ) | | |~
| \ | \ / | / |~
| '---' | '---' '----' ---'---~
'------------'~
The interactive scratchpad for hackers.~
Author: Ethan Chan <metakirby5@gmail.com>
License: MIT
Repo: https://github.com/metakirby5/codi.vim
==============================================================================
TABLE OF CONTENTS *codi-contents*
INTRODUCTION...............................................|codi-introduction|
SYNCHRONOUS VS ASYNCHRONOUS.................|codi-introduction-sync-diffs|
WARNINGS......................................|codi-introduction-warnings|
DEPENDENCIES..............................|codi-introduction-dependencies|
GOTCHAS........................................|codi-introduction-gotchas|
USAGE.............................................................|codi-usage|
:Codi {filetype}...................................................|:Codi|
:Codi!............................................................|:Codi!|
:Codi!! {filetype}...............................................|:Codi!!|
:CodiUpdate..................................................|:CodiUpdate|
SHELL WRAPPER.........................................|codi-usage-wrapper|
CONFIGURATION.............................................|codi-configuration|
g:codi#interpreters..................................|g:codi#interpreters|
g:codi#command_prefix..............................|g:codi#command_prefix|
g:codi#aliases............................................|g:codi#aliases|
g:codi#autocmd............................................|g:codi#autocmd|
g:codi#width................................................|g:codi#width|
g:codi#rightsplit......................................|g:codi#rightsplit|
g:codi#rightalign......................................|g:codi#rightalign|
g:codi#autoclose........................................|g:codi#autoclose|
g:codi#raw....................................................|g:codi#raw|
g:codi#sync..................................................|g:codi#sync|
g:codi#use_buffer_dir..............................|g:codi#use_buffer_dir|
g:codi#log....................................................|g:codi#log|
g:codi#virtual_text..................................|g:codi#virtual_text|
g:codi#virtual_text_prefix....................|g:codi#virtual_text_prefix|
CodiVirtualText..........................................|CodiVirtualText|
AUTOCOMMANDS...............................................|codi-autocommands|
CodiEnterPre................................................|CodiEnterPre|
CodiEnterPost..............................................|CodiEnterPost|
CodiUpdatePre..............................................|CodiUpdatePre|
CodiUpdatePost............................................|CodiUpdatePost|
CodiLeavePre................................................|CodiLeavePre|
CodiLeavePost..............................................|CodiLeavePost|
INTERPRETERS...............................................|codi-interpreters|
DEFAULT INTERPRETERS..........................|codi-interpreters-defaults|
OUTPUT SPECIFICATION.......................|codi-interpreters-output-spec|
EXAMPLE INTERPRETER CONFIGURATION..............|codi-interpreters-example|
POSSIBLE ATTRIBUTES.........................|codi-interpreters-attributes|
bin............................................|codi-interpreters-bin|
prompt......................................|codi-interpreters-prompt|
preprocess..............................|codi-interpreters-preprocess|
rephrase..................................|codi-interpreters-rephrase|
quitcmd....................................|codi-interpreters-quitcmd|
==============================================================================
INTRODUCTION *codi-introduction*
Codi is an interactive scratchpad for hackers, with a similar interface to
Numi (https://numi.io). It opens a pane synchronized to your main buffer which
displays the results of evaluating each line as you type (with NeoVim or Vim
with |+job| and |+channel|, asynchronously). It's extensible to nearly any
language that provides a REPL (interactive interpreter)!
If you're using NeoVim, by default it uses virtual text to print the output
from the REPL, similar to other plugins used in other popular editors.
See |g:codi#virtual_text| for more info.
See |codi-interpreters-defaults| for languages with built-in support.
Watch a screencast at https://ptpb.pw/t/~codi!
SYNCHRONOUS VS ASYNCHRONOUS *codi-introduction-sync-diffs*
+---------------+-----------------------------------+-------------+
| Asynchronous? | Default autocommands for updates | Blocking? |
+---------------+-----------------------------------+-------------+
| yes | |TextChanged|, |TextChangedI| | no |
| no | |CursorHold|, |CursorHoldI| | yes |
+---------------+-----------------------------------+-------------+
WARNINGS *codi-introduction-warnings*
Be wary of infinity~
Be EXTREMELY careful with lazily evaluated languages and infinite loops. I
cannot stress this enough: the moment you type an infinite list, your CPU
usage will probably skyrocket. If you are running Codi without asynchronous
support, Vim will also freeze.
For example, as cool as this is, NEVER attempt the below in Codi with Haskell:
>
let fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
f !! 5
<
Even if you only intend to extract the 5th element of f, unless you are clever
about how you write it, the second line will be just "f" at some point. This
leads to evaluating the infinite list, which you might not notice for a few
seconds, but will definitely stress out your computer if you leave it going
for much longer.
Should this happen to you, find and kill the interpreter. Seriously!
Lingering processes~
Codi will occasionally leave interpreters running in the background which need
to be killed. This has only been observed with Haskell (ghci), so if your fans
spin up, you may need to investigate. The reason is unknown, but it happens
infrequently enough that it's not an issue.
Codi has also been observed to leave lingering processes with "csh". If you
use "csh", you may need to add the following line to your .vimrc:
>
let $SHELL='/bin/sh'
<
DEPENDENCIES *codi-introduction-dependencies*
- OS X or Linux (Windows support coming soon!)
https://github.com/metakirby5/codi.vim/issues/14
- Vim 7.4 (with |+job| and |+channel| for asynchronous evaluation) or
NeoVim (still in its infancy - please report bugs!)
- "uname"
- If not using NeoVim, "script" (BSD or Linux, man page should say at least
2013)
Each interpreter also depends on its bin; see |codi-interpreters-bin|. These
are loaded on-demand. For example, if you only want to use the Python Codi
interpreter, you will not need ghci.
See |codi-interpreters-defaults| for default interpreter dependencies.
GOTCHAS *codi-introduction-gotchas*
- Because Codi directly sends keystrokes to the interpreter, it may not work
with some readline configurations. For example, binding <c-j> to
"vi-movement-mode" in ~/.inputrc will not send input as expected, since
<c-j> is '\n'.
==============================================================================
USAGE *codi-usage*
*:Codi*
:Codi {filetype}
Activates Codi for the current buffer, using the interpreter
defined for {filetype}. If {filetype} is not specified, the
buffer's 'filetype' is used instead.
*:Codi!*
:Codi!
Deactivates Codi for the current buffer.
*:Codi!!*
:Codi!! {filetype}
Toggles Codi for the current buffer.
*:CodiUpdate*
:CodiUpdate
Manually triggers a Codi update. Useful in conjunction with the
"None" setting for |g:codi#autocmd|.
SHELL WRAPPER *codi-usage-wrapper*
A nice way to use Codi is through a shell wrapper that you can
stick in your ~/.bashrc:
>
# Codi
# Usage: codi [filetype] [filename]
codi() {
local syntax="${1:-python}"
shift
vim -c \
"let g:startify_disable_at_vimenter = 1 |\
set bt=nofile ls=0 noru nonu nornu |\
hi ColorColumn ctermbg=NONE |\
hi VertSplit ctermbg=NONE |\
hi NonText ctermfg=0 |\
Codi $syntax" "$@"
}
<
==============================================================================
CONFIGURATION *codi-configuration*
*g:codi#interpreters*
g:codi#interpreters
A dictionary of user-defined interpreters.
See |codi-interpreters| for the format specification.
Example configuration for Python:
>
let g:codi#interpreters = {
\ 'python': {
\ 'bin': 'python',
\ 'prompt': '^\(>>>\|\.\.\.\) ',
\ },
\ }
<
Example configuration to change just the Haskell prompt:
>
let g:codi#interpreters = {
\ 'haskell': {
\ 'prompt': '^> ',
\ },
\ }
<
You may also set any of the |per-interpreter| options here. For
example, if you want to left-align all JavaScript Codi instances,
but keep right-align as the default:
>
let g:codi#interpreters = {
\ 'javascript': {
\ 'rightalign': 0,
\ },
\ }
<
Configuration is deeply applied over the default interpreters.
Default value is {}.
*g:codi#command_prefix*
g:codi#command_prefix
A list of commands and parameters prepended to the interpreter.
Defaults to ['env', 'INPUTRC=/dev/null'] to ensure that codi works
independent of the user's inputrc. Can be used as well to change
the priority of Codi's background job by tools such as 'chrt',
'nice' or 'ionice'.
*g:codi#aliases*
g:codi#aliases
A dictionary of user-defined interpreter filetype aliases.
This allows you to use an interpreter for more than one
filetype. For example, you can alias "javascript.jsx" to
"javascript" so the JavaScript interpreter (node) can be used
for the "javascript.jsx" filetype.
>
let g:codi#aliases = {
\ 'javascript.jsx': 'javascript',
\ }
<
Configuration is applied over the default aliases.
Default value is {}.
The below options can also be set on a *per-interpreter* basis via
|g:codi#interpreters|.
*g:codi#autocmd*
g:codi#autocmd
What |autocommand|s trigger updates. Possible values:
|TextChanged|, |CursorHold|, |InsertLeave|, None.
These will also register the insert mode variants.
"None" will make no autocommand trigger updates; use this if you
only want updates to be manually triggered on `:CodiUpdate`.
Default value is 'TextChanged' for async, 'CursorHold' for sync.
*g:codi#width*
g:codi#width
The width of the Codi split, either a |Number| or a |Float|.
When a |Number| is supplied, it will be interpreted as the
absolute width in columns to use.
When a |Float| is supplied, it will be treated as a percentage of
the current buffer width. This setting will then also respect
the |winwidth| builtin which means that each pane will be at
least |winwidth| columns wide.
Default value is 40.
*g:codi#rightsplit*
g:codi#rightsplit
Whether or not to spawn Codi on the right side of the current
buffer. If 0, Codi spawns on the left.
Default value is 1.
*g:codi#rightalign*
g:codi#rightalign
Whether or not to right-align the Codi buffer. If 0, the Codi
buffer is left-aligned.
Default value is 1.
*g:codi#autoclose*
g:codi#autoclose
Whether or not to close Codi when the associated buffer is
closed.
Default value is 1.
*g:codi#raw*
g:codi#raw
Whether or not to display interpreter results without
formatting each expression to align with the line numbers.
Useful if you are debugging a |codi-interpreters-preprocess|.
Default value is 0.
*g:codi#sync*
g:codi#sync
Whether or not force synchronous execution.
No reason to touch this unless you want to compare async to sync.
Default value is 0.
*g:codi#use_buffer_dir*
g:codi#use_buffer_dir
Start the REPL with the working directory of the buffer being
edited instead of Vim's current working directory. This can make
it easier for your code to use paths relative to the script path.
Default value is 1.
*g:codi#log*
g:codi#log
Path to the file where Codi logs information. This can be useful
for debugging (e.g. |codi-interpreters-preprocess|) and when
fixing or submitting issues.
Default value is '', which disbles all logging.
*g:codi#virtual_text*
g:codi#virtual_text
On nvim, instead of printing the REPL output to the Scratch
buffer, it removes that buffer and prints the text next to the
corresponding line.
Default value is 1, if on nvim.
*g:codi#virtual_text_prefix*
g:codi#virtual_text_prefix
Symbol that is prepend to the output text.
Default value is "❯ "
*CodiVirtualText*
CodiVirtualText
Codi uses CodiVirtualText the custom highlight group to syntax
highlight the virtual text output. By default, this is linked to
the Statement group, but you can override like so.
>
highlight CodiVirtualText guifg=cyan
<
==============================================================================
AUTOCOMMANDS *codi-autocommands*
*CodiEnterPre*
CodiEnterPre
Triggered before a Codi pane enters.
*CodiEnterPost*
CodiEnterPost
Triggered after a Codi pane enters.
*CodiUpdatePre*
CodiUpdatePre
Triggered before a Codi pane updates.
*CodiUpdatePost*
CodiUpdatePost
Triggered after a Codi pane updates.
*CodiLeavePre*
CodiLeavePre
Triggered before a Codi pane leaves.
*CodiLeavePost*
CodiLeavePost
Triggered after a Codi pane leaves.
==============================================================================
INTERPRETERS *codi-interpreters*
Codi relies on interpreter configurations to understand how to evaluate your
buffer's contents. A number of default interpreters are bundled in, but you
can easily create your own configurations to add support for more filetypes.
If you add support for a new language, please consider sending in a pull
request at https://github.com/metakirby5/codi.vim/pulls!
DEFAULT INTERPRETERS *codi-interpreters-defaults*
Codi currently has default support for the following filetypes:
clojure~
bin: planck
maintainer: @cirqueit
coffee~
bin: coffee
maintainer: @metakirby5
notes:
- Blank lines show undefined
cpp~
bin: cling
maintainer: @AlesTsurko
elm~
bin: elm
maintainer: @metakirby5
elixir~
bin: iex
maintainer: @megalithic
haskell~
bin: ghci
maintainer: @metakirby5
notes:
- Language pragmas don't work
javascript~
bin: node
maintainer: @metakirby5
notes:
- ignoreUndefined by default
julia~
bin: julia
maintainer: @originalsouth
notes:
- Requires: 'set filetype=julia'
lua~
bin: lua
maintainer: @dbrodie
notes:
- Use a = or return to display val
ocaml~
bin: ocaml
maintainer: @metakirby5
notes:
- Must end every statement with ;;
php~
bin: psysh
maintainer: @AW3i
purescript~
bin: psci
maintainer: @bdellaterra
notes:
- Only works inside a purescript project folder
- End multi-line continuations with :endpaste
python~
bin: python
maintainer: @metakirby5
ruby~
maintainer: @metakirby5
bin: irb
typescript~
maintainer: @topaxi
bin: tsun
notes:
- Requires at least tsun 0.5.0
mathjs~
maintainer: @slavaGanzin
bin: mathjs
notes:
- Evaluation may not work until a newline is entered
Note that Codi is not meant to be a replacement for actually running your
program; it supports nothing more than what the underlying bin supports.
This is why Haskell language pragmas don't work, PureScript only works
inside a project folder, and OCaml statements must end with ;;. Also, in
most whitespace-sensitive languages, an empty line represents the end of a
definition.
OUTPUT SPECIFICATION *codi-interpreters-output-spec*
To ensure evaluated lines align with the corresponding buffer's lines, the
interpreter output (as if you had enabled |g:codi#raw|) must follow this spec:
>
[any number of lines]
[first prompt][any text]
[any number of lines]
[result associated with prompt, no leading whitespace]
[any number of lines with leading whitespace]
[next prompt][any text]
...
<
So, the following would be valid, assuming the prompt regex is "^> ":
>
LANGUAGE INTERPRETER v1.0 | ignored
> 1 + 1 | prompt 1
2 | result for prompt 1
> make_stacktrace() | prompt 2
A BAD ERROR | result for prompt 2
stacktrace line 1 | ignored
stacktrace line 2 | ignored
stacktrace line 3 | ignored
> function_that_prints_and_returns_1() | prompt 3
I printed something! | ignored
1 | result for prompt 3
> and so on... | prompt 4
<
However, be careful of the following cases:
>
> 1 + 1 | prompt 1
2 | IGNORED (leading whitespace)
> return_1() | prompt 2
1 | IGNORED (next line has no leading whitespace)
Returned 1. | result for prompt 2
<
If your interpreter's output does not follow this spec, you MUST implement
|codi-interpreters-preprocess|.
The easiest way to check is to enable |g:codi#raw|.
EXAMPLE INTERPRETER CONFIGURATION *codi-interpreters-example*
A full interpreter configuration for JavaScript can be found below. (Note that
in Vimscript, you still need to add forward slashes for continuing newlines.)
>
'javascript': {
'bin': 'node',
'prompt': '^\(>\|\.\.\.\+\) ',
'preprocess': function('s:pp_js'),
'rephrase': function('s:rp_js'),
}
<
POSSIBLE ATTRIBUTES *codi-interpreters-attributes*
Interpreter configurations have an number of attributes, but only a few of
them are required. However, you may need to use the optional attributes
to get your interpreter to successfully work.
*codi-interpreters-bin*
bin (REQUIRED)
Defines the command to use for the REPL backing the interpreter.
For example, it would be "python" for Python, "node" for
JavaScript, and "irb" for Ruby. Can either be a string or an
array of strings, if the command require arguments. One possible
array, for example, is ["irb", "--prompt", "default"]. Array
arguments will not be automatically quoted.
*codi-interpreters-prompt*
prompt (REQUIRED)
A vim-style regex pattern that exactly matches the prompt of
bin. This will be used to correctly line up the output of bin
with your buffer.
In the JavaScript example, we set prompt to match
">", "...", and any amount of dots greater than that to
accommodate further nesting levels.
*codi-interpreters-preprocess*
preprocess (OPTIONAL)
A function to adjust the output of bin after running the buffer
contents. Useful if control characters need to be filtered out,
or if the output is non-standard in any way. After preprocess,
the output should conform to |codi-interpreters-output-spec|.
That way, output result lines can be successfully lined up with
the corresponding lines.
The function should take a single string argument that is a line
of output, and return a single string that is the adjusted line
of output.
When creating your own preprocess, it is useful to enable
|g:codi#raw| and/or |g:codi#log| to see what the output initially
looks like, and what your preprocess function does to the output.
In the JavaScript example, "node" has a tendency to print out
escape codes with a pattern of <esc> followed by some characters,
so we strip those with the following function:
>
function! s:pp_js(line)
" Strip escape codes
return substitute(a:line, "\<esc>".'\[\d\(\a\|\dm\)', '', 'g')
endfunction
<
Notice that in the example, preprocess is configured as
`function('s:pp_js')`. In case you are unfamiliar with Vimscript,
this is the construct that is normally used to pass functions as
data.
Default value is the identity function.
*codi-interpreters-rephrase*
rephrase (OPTIONAL)
A function to adjust the contents of the current buffer to,
before it is sent to bin. Useful if you need to modify certain
lines to get them to evaluate to your liking.
The function should take a single string argument that is the
contents of the current buffer, and return a single string that
is the adjusted contents to send to bin. Note: unlike preprocess,
which operates per-line, rephrase operates on the entire buffer.
This attribute is actually not recommended, since it is very
difficult to achieve desired goals without unforeseen
side-effects. The PureScript interpreter uses rephrase so
multi-line continuations can be terminated with ":endpaste"
instead of Ctrl-D, which is awkard to type literally.
As another example, if you REALLY want "let var x = 5" to
show "5" instead of "undefined", this is the way to do it.
The configuration process is similar to preprocess, so just look
at |codi-interpreters-preprocess| if you're unsure how to start.
Default value is the identity function.
*codi-interpreters-quitcmd*
quitcmd (OPTIONAL)
A command that can be typed to quit the interpreter. Will be
surrounded by '\n'.
If the interpreter does not support <C-d> to quit, the field is
required; otherwise, it's optional.
A keybind can also be provided as a value for this field.
vim:ft=help:tw=78:sw=13:norl: