-
-
Notifications
You must be signed in to change notification settings - Fork 28
/
aniseed.txt
814 lines (641 loc) · 31.7 KB
/
aniseed.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
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
*aniseed*
___ _ __~
/ | ____ (_)_______ ___ ____/ /~
/ /| | / __ \/ / ___/ _ \/ _ \/ __ /~
/ ___ |/ / / / (__ ) __/ __/ /_/ /~
/_/ |_/_/ /_/_/____/\___/\___/\__,_/~
==============================================================================
CONTENTS *aniseed-contents*
1. Introduction ............................ |aniseed-introduction|
2. Examples .................................... |aniseed-examples|
3. Scripts ...................................... |aniseed-scripts|
4. Commands .................................... |aniseed-commands|
5. Plugins ...................................... |aniseed-plugins|
6. Env .............................................. |aniseed-env|
7. Macros ........................................ |aniseed-macros|
8. Functions .................................. |aniseed-functions|
9. Testing ...................................... |aniseed-testing|
10. Syntax ........................................ |aniseed-syntax|
==============================================================================
INTRODUCTION *aniseed-introduction*
Aniseed bridges the gap between Fennel (a Lisp that compiles to Lua) and
Neovim. Allowing you to easily write plugins (|aniseed-plugins|) or
configuration (|aniseed-env|) in a Clojure-like Lisp with great runtime
performance.
https://fennel-lang.org/
Interactive evaluation as you work is provided by the sister plugin, Conjure.
https://github.com/Olical/conjure
A few scripts are provided to make writing build scripts and Makefiles for
your plugins as simple as possible (|aniseed-scripts|).
You'll also find a set of useful functions (|aniseed-functions|) and macros
(|aniseed-macros|) that Aniseed exposes to you. They're all modeled on
Clojure's API so they should be very familiar if you're already a Clojurian.
Once you're up and running you'll be able write a test suite for your Aniseed
based tools (|aniseed-testing|). Scripts are provided to make it easy to get
them running in CI or your terminal right away.
==============================================================================
EXAMPLES *aniseed-examples*
Aniseed provides module macros that make writing Lua modules as easy as
Clojure namespaces. Here's what a module looks like.
>
(module my-module
{;; Require other modules with aliases.
require {a aniseed.core
nvim aniseed.nvim}
;; Autoload the module when you access a value from it.
;; Just like Vim Script's autoload system!
;; I recommend using this by default and only using require if you run
;; into issues.
autoload {my-big-module foo.bar.my-big-module}
;; Inline modules at compile time.
include {some-dep my-other.dependency}
;; Require macros from nvim/fnl/aniseed/macros/autocmds.fnl
;; and bind to the name `ac`.
import-macros [[ac :aniseed.macros.autocmds]
[my-macros :my-proj.macros]
;; Deprecated in Fennel 0.4.0
;; Require macros from nvim/fnl/my-proj/macros.fnl for compile time
require-macros [my-proj.macros]})
;; Only use def at the top level!
;; It's not designed to be used within functions etc.
(def- some-private-value 2)
(defn- some-private-fn [x]
(* x some-private-value))
(defn a-public-fn [x]
(-> x
(some-private-fn)
(a.inc)))
;; Prevent this value being overwritten on each eval.
(defonce- some-stateful-thing (some-dep.start-server!))
(comment
(a-public-fn 10) ;; => 21
(some-private-fn 10) ;; => 20
(set nvim.g.hello "world!")
*module* ;; => {...} the current Lua module table.
*module-name* ;; => "my-module"
*file* ;; => "relative/path/to/source/file/my-module.fnl"
)
>
Some good examples of what you can do with Aniseed in practice:
* https://github.com/Olical/conjure
* https://github.com/Olical/nvim-local-fennel
* https://github.com/Olical/dotfiles (Neovim configured with Aniseed)
==============================================================================
SCRIPTS *aniseed-scripts*
These helper scripts aim to make plugin development as easy as possible. If
they're not quite to your liking, feel free to copy and modify them in your
own projects.
All of them can be used from `deps/aniseed/scripts/*` once you have Aniseed
installed by `dep.sh`. You should download `dep.sh` into your `scripts`
directory since it's used to fetch Aniseed itself.
`scripts/dep.sh [user] [repo] [revision]`
Clones a GitHub repo into `deps/{name}` if it's not there already. Will update
the repository each time and ensure the right revision is checked out.
When developing a plugin you'll want to manually copy this script into your
own repositories `script` directory and use it to fetch Aniseed.
Usage: `scripts/dep.sh Olical aniseed vX.Y.Z`
`scripts/embed.sh [dep name] [your module prefix]`
Copies a dependency's Lua from deps (result of `dep.sh`) into your own Lua
directory under a prefix directory. Then munges the dependency to replace
all occurrences of the module paths with your unique project specific
prefix.
Usage: `deps/aniseed/scripts/embed.sh aniseed YOUR_PLUGIN_NAME`
`scripts/compile.sh`
Compiles all Fennel code into Lua assuming you have Aniseed cloned into your
`deps` directory via `dep.sh`. Any file path that ends in `macros.fnl` will
be ignored, this allows you to store macro files alongside your source code.
Fennel macro files cannot be directly compiled, they can only be executed at
compile time when referring to them with `import-macros` from a regular
Fennel source file.
Usage: `deps/aniseed/scripts/compile.sh`
`scripts/test.sh`
Executes all of your tests found in `test/fnl` using the Aniseed cloned by
`dep.sh`. Will leave behind files in `test/lua` that you'll want to git
ignore. All test modules must end with `-test` (so the file names need to
end with `-test.fnl`).
Environment:
* `PREFIX` - Inserted before the arguments to Nevoim.
* `SUFFIX` - Inserted after the arguments to Neovim.
Usage: `deps/aniseed/scripts/test.sh`
`scripts/seed.sh`
Sets up a new Aniseed plugin project within the current directory.
Warning: Only run in new empty directories, it will replace your
`.gitignore`, `Makefile` and other such files!
Warning: Requires `make` as part of the workflow.
Warning: Uses the name of your current directory as the name for the plugin.
Make sure it's a valid Fennel symbol! (no spaces etc)
Usage:
`curl -fL https://raw.githubusercontent.com/Olical/aniseed/master/scripts/seed.sh | sh`
==============================================================================
COMMANDS *aniseed-commands*
Aniseed provides a few very simple commands to allow you to quickly evaluate
your Fennel code without having to restart your editor. I highly recommend
that you install Conjure and use that for this purpose instead, but here they
are if you can't or decide you don't want to do that.
*AniseedEval*
Evaluates the provided Fennel code, echoing the resulting value or error.
*AniseedEvalFile*
Reads the Fennel file at the provided path and executes it, displaying
results in the same way to the |AniseedEval| command. If you don't provide
a file name it will default to your current file.
==============================================================================
PLUGINS *aniseed-plugins*
When writing a plugin with Aniseed you'll first need to fetch the `dep.sh`
script and place it in your own `scripts` directory. Then you can clone
the latest Aniseed version into your `deps` directory with.
>
scripts/dep.sh Olical aniseed vX.Y.Z
>
Let's start by adding the following Fennel code to `fnl/my-plugin/init.fnl`.
>
(module my-plugin.init
{autoload {a my-plugin.aniseed.core}})
(a.println "Hello, World!")
>
Now execute `deps/aniseed/scripts/compile.sh` to compile this Fennel into Lua
under the `lua` directory. Now your Fennel has been compiled to Lua but we
need to embed a copy of Aniseed for runtime use by your plugin (the
`my-plugin.aniseed.core` module doesn't exist until we do this!).
>
deps/aniseed/scripts/embed.sh aniseed YOUR_PLUGIN_NAME
Since running `compile.sh` and `embed.sh` every time you make a change is
quite tedious, you should be using Conjure for interactive evaluation as you
work and wrapping up your compile step in your own script or `Makefile`.
>
I'd recommend committing the compiled Lua so that your users can use your
plugin without any sort of compile step.
Your users can require your plugin as a Lua module whenever they want to, or
you can put an initialisation script in `plugin/my-plugin.vim` that does it
for them on startup.
>
lua require("my-plugin.init")
>
Once your plugin is taking shape you'll probably want to have a look at
|aniseed-testing| to provide some automated tests locally or in CI.
==============================================================================
ENV *aniseed-env*
If you want to replace your Neovim configuration in your dotfiles with Fennel
instead of Vim Script or Lua, you can do so with the `aniseed.env` module in
your `init.vim`.
>
let g:aniseed#env = v:true
" Results in this call when Aniseed loads.
" If the option above doesn't work for your use case you can use this legacy
" method as a replacement.
lua require('aniseed.env').init()
>
This will compile all modified Fennel under `~/.config/nvim/fnl` to
`~/.config/nvim/lua` when you open Neovim and then load the `init` module by
default. The module that gets loaded can be configured by passing an `opts`
table like so.
>
let g:aniseed#env = { "module": "foo.my-module" }
" Again, this results in this underlying call, passing the options through.
lua require('aniseed.env').init({ module = 'foo.my-module' })
You can also configure it to load `~/.config/nvim/init.fnl` and base all
requires off of that root directory rather than prefixing everything under the
`fnl` directory by configuring the following:
>
let g:aniseed#env = { "input": "" }
Where the default `input` is `"/fnl"` and `output` is `"/lua"` relative to your
Neovim configuration directory.
If we're using the default options we can add the following code to
`~/.config/nvim/fnl/init.fnl` to produce a "Hello, World!".
>
(module init
{autoload {a aniseed.core}})
(a.println "Hello, World!")
>
Next time you open Neovim you'll see "Hello, World!" in `:messages`! You can
grow your configuration by adding more modules under the `fnl` directory and
requiring them into your initial module.
Be sure to `.gitignore` the `~/.config/nvim/lua` directory if you store your
configuration in git since this will end up being compiled output that's
recompiled whenever you make changes to your Fennel source.
If startup time is extremely valuable to you and you're finding the
compilation on Neovim start to be noticeable you can turn it off by default.
>
let g:aniseed#env = { "compile": v:false }
You can then opt into Fennel compilation by removing the option, setting it to
true or setting the `ANISEED_ENV_COMPILE` environment variable to `true`. This
means you could turn off your `aniseed.env` Fennel compilation for general use
and then turn it back on when working on your configuration or synchronising
your dotfiles.
==============================================================================
MACROS *aniseed-macros*
Fennel and Lua don't have a well defined way of creating modules and exposing
some things while keeping others private. Clojure has a nice way of describing
this in the form of `def` forms and namespaces, we get something similar here.
Aniseed throws out Fennel and Lua's notion of `local`, `fn` and returning a
table from the bottom of your file and replaces them with it's own well
defined module syntax. The result is a normal Lua module, the way you define
it is just very different to what you may have seen before.
Not only does this make it a lot easier to require and export values from your
module, it also allows tools like Conjure to evaluate your code within the
right context.
Bear in mind that these macros are not intended to be called dynamically at
runtime from within functions. You should only refer to them at the very top
level of your module file. They will almost definitely misbehave if you wrap
them in any other forms.
`(module name imports base)`
This form should be the first thing in your file. The name should be exactly
what you'd use to require your module, so `fnl/foo/bar.fnl` would have a
name of `foo.bar` and could be required in Lua with `require("foo.bar")`.
The second argument is an optional table that allows you to require or
include other modules, the key is a function (`require` or `include` for
example) and the value is another table mapping an alias to a module name.
For side effecting functions or macros such as `require-macros` you can pass
a sequential table as opposed to an associative one containing your required
macro module paths. You can also provide sequential sub tables to pass
multiple arguments to the referenced function. So `import-macros [[a :b]]`
would translate to `(import-macros a :b)`, allowing you to import and bind
macros to a symbol.
The final optional argument is a base table you would like Aniseed to merge
your modules properties into, this can be useful for extending an existing
module.
>
(module foo.bar
{autoload {a aniseed.core}
include {baz foo.baz}
import-macros [[fb :foo.bar]]}
{:xyz "this will be the base table that gets exported"})
<
You can access the current module table with `*module*` and the current
module name as a string with `*module-name*`. This can be useful for
introspection or modification of the module table without coupling your code
to the name of the module.
If you need to perform some action relative to your source file, the
relative path to the source is stored in `*file*` at compile time.
`(def name value)`
Define a public value in the current module.
>
(def my-value {:foo :bar})
(a.get my-value :foo) // => "bar"
`(def- name value)`
The same as `def`, but private to your module, only functions and values
within you module can access it.
`(defonce name value)`
Like `def` but will only be defined once. Useful for defining stateful
values that you don't want reset every time you evaluate the file with
Conjure. You can store things like window or process IDs in here.
`(defonce- name value)`
Again, like `defonce` but isn't exposed publicly to everyone using your
module. Only internal values and functions in your module have access.
`(defn name ...)`
Just like Lua's built in `fn` but the result is defined using `def`. So it
takes a name, argument list and optional documentation string.
>
(defn add [a b]
"Adds two numbers together."
(+ a b))
`(defn- name ...)`
The same as `defn` but the function is private and only accessible within
your module.
`(deftest name ...)`
See |aniseed-testing| for more on testing, but this is used to define tests
with `-test` suffixed modules for use with the `test.sh` test runner. It's a
bit like `defn` but you also get access to the `t` assertion table, as
described in the testing section.
`(time ...)`
Time the execution of the code wrapped by this form and print the result in
milliseconds. Great for getting a feel for how long things take while you're
developing your code. Not intended to be used for programmatic measuring of
time, just as a quick and easy to use tool during development.
`(wrap-last-expr last-expr)`
Used by `aniseed.compile` to ensure the current module is returned if
necessary.
`(wrap-module-body ...)`
Used by `aniseed.compile` to wrap the entire body of a file, replacing the
last expression with `wrap-last-expr` which handles the module's return
value.
`(if-let [...] ...)`
`(when-let [...] ...)`
A combination of `if`, `when` and `let` forms. This behaves in the same way
to Clojure's implementation, this means you can only bind ONE value to
branch on. You may use destructuring, if you are using list destructuring
like `[(ok? val) foo]` then the first value will be used for the branch.
==============================================================================
FUNCTIONS *aniseed-functions*
Lua doesn't come along with an extensive standard library like Clojure or
other large languages. You can supplement that by using `dep.sh` and adding
one of the various Lua toolbox libraries that exist out on the internet.
Aniseed provides it's own set of Clojure inspired functions that you may find
extremely useful. It's enough for me to implement Conjure so I hope it'll be
enough for your needs too. If you write a function and you think others would
benefit from it, please do add it to Aniseed and submit a pull request.
The functions below are grouped by module, so you can require `aniseed.core`
under the `a` alias and then access a function with `(a.string? "foo")`, for
example.
------------------------------------------------------------------------------
`aniseed.core`
`(rand n)`
Generate a random float between `0` and `n`, defaults to `1`.
`(string? x)`
Is `x` a string? Returns a boolean.
`(nil? x)`
Is `x` a nil? Returns a boolean.
`(table? x)`
Is `x` a table? Returns a boolean.
`(count xs)`
Return the count of items in `xs`. Always returns a number, it's okay to
give it a `nil`. It will count keys in associative table and items in a
sequential one.
`(empty? xs)`
Is the `count` of `xs` equal to `0`.
`(first xs)`
The first item of the sequential table.
`(second xs)`
The second item of the sequential table.
`(last xs)`
The last item of the sequential table.
`(inc n)`
Add `1` to `n`.
`(dec n)`
Subtract `1` from `n`.
`(even? n)`
True if `n` is even.
`(odd? n)`
True if `n` is odd.
`(keys t)`
A sequential table of the keys from the associative table `t`.
`(vals t)`
A sequential table of the values from the associative table `t`.
`(kv-pairs t)`
A sequential table of `[key value]` tuples from the associative table `t`.
`(run! f xs)`
Execute the function (for side effects) for every `xs`.
`(complement f)`
Takes a fn `f` and returns a fn that takes the same arguments as `f`, has
the same effects, if any, and returns the opposite truth value.
`(filter f xs)`
Filter `xs` down to a new sequential table containing every value that
`(f x)` returned truethy for.
`(remove f xs)`
Opposite of filter, filter `xs` down to a new sequential table containing
every value that `(f x)` returned falsy for.
`(map f xs)`
Map `xs` to a new sequential table by calling `(f x)` on each item.
`(map-indexed f xs)`
Map `xs` to a new sequential table by calling `(f [k v])` on each item.
`(identity x)`
Returns what you pass it.
`(reduce f init xs)`
Reduce `xs` into a result by passing each subsequent value into the
function with the previous value as the first argument, starting with
`init`.
`(some f xs)`
Return the first truthy result from `(f x)` or `nil`.
`(butlast xs)`
Return every value from the sequential table except the last one.
`(rest xs)`
Return every value from the sequential table except the first one.
`(concat ...)`
Concatenates the sequential table arguments together. You can safely mix
`nil` values in with actual tables.
`(mapcat f xs)`
The same as `map` but then `concat` all lists within the result together.
`(pr-str ...)`
Convert the input arguments to a string.
`(str ...)`
Concatenate the values into one string. Converting non-string values into
strings where required.
`(println ...)`
Convert the input arguments to a string (if required) and print them.
`(pr ...)`
Print the arguments as data, strings will remain quoted.
`(slurp path silent?)`
Read the file into a string and return it. Will print a warning if it
fails, use the `silent?` argument to suppress this and just return `nil`.
`(spit path content)`
Write the string into the given path.
`(merge ...)`
Merge the tables together, `nil` will be skipped safely so you can use
`(when ...)` to conditionally include tables. Merges into a fresh table so
no existing tables will be mutated.
`(merge! ...)`
The same as `merge` above but will mutate the first argument, so all
tables are merged into the first one.
`(select-keys t ks)`
Extract the keys listed in `ks` from `t` and return it as a new table.
`(get t k d)`
Get the key `k` from table `t` while safely handling `nil`. If it's not
found it will return the optional default value `d`.
`(get-in t ks d)`
Get the key path `ks` from table `t` while safely handling `nil`. If it's
not found it will return the optional default value `d`.
`(get-in {:foo {:bar 10}} [:foo :bar]) // => 10`
`(assoc t k v ...)`
Set the key `k` in table `t` to the value `v` while safely handling `nil`.
Accepts more `k` and `v` pairs as after the initial pair. This allows you
to assoc multiple values in one call.
Returns the table `t` once it has been mutated.
`(assoc-in t k v)`
Set the key path `ks` in table `t` to the value `v` while safely handling `nil`.
`(assoc-in {:foo {:bar 10}} [:foo :bar] 15) // => {:foo {:bar 15}}`
`(update t k f)`
Replace the key `k` in table `t` by passing the current value through the
function `f`. Returns the table after the key has been mutated.
`(update-in t ks f)`
Same as `update` but replace the key path at `ks` with the result of
passing the current value through the function `f`.
`(constantly v)`
Returns a function that takes any number of arguments and returns `v`.
------------------------------------------------------------------------------
`aniseed.compile`
`(wrap-macros code)`
Surround the given code with a require to the `aniseed.macros` module
among other Aniseed macro tools.
`(str code opts)`
Compile some Fennel code as a string into Lua. Maps to
`fennel.compileString` with some wrapping, returns an `(ok? result)`
tuple. Automatically requires the Aniseed macros.
`(file src dest)`
Compile the source file into the destination file if the source file was
modified more recently. Will create any required ancestor directories for
the destination file to exist.
`(glob src-expr src-dir dest-dir)`
Match all files against the `src-expr` under the `src-dir` then compile
them into the `dest-dir` as Lua.
------------------------------------------------------------------------------
`aniseed.env`
`(init opts)`
Compile and load Fennel stored under your Neovim configuration directory.
See |aniseed-env| for more information. `opts` is an optional table that
can contain the following:
`module` - name of the module to load on init, defaults to `"init"`.
`input` - dir for input, defaults to `"/fnl"` under config.
`output` - dir for compiled output, defaults to `"/lua"` under config.
You should set the `g:aniseed#env` variable to `v:true` or your desired
configuration table rather than calling this directly for optimal
behaviour.
------------------------------------------------------------------------------
`aniseed.eval`
`(str code opts)`
Like `aniseed.compile/str` but uses `fennel.eval`. Returns the result of
evaluating the given Fennel code with the Aniseed macros automatically
required.
------------------------------------------------------------------------------
`aniseed.fennel`
Transparent wrapper around the base `fennel` module. Synchronises the
`fennel.path` with Lua's `package.path` value on require.
https://github.com/bakpakin/Fennel
------------------------------------------------------------------------------
`aniseed.fs`
`(basename path)`
Would return `"foo/bar"` when given `"foo/bar/baz.fnl"`.
`(mkdirp dir)`
Creates the directory and all intermediate directories if required.
------------------------------------------------------------------------------
`aniseed.nvim`
Transparent wrapper around the fantastic `nvim.lua` library. Contains
everything you need to interact with Neovim.
https://github.com/norcalli/nvim.lua
------------------------------------------------------------------------------
`aniseed.nvim.util`
`(normal keys)`
Execute some command as if you were in normal mode silently.
`(fn-bridge viml-name mod lua-name opts)`
Creates a VimL function that calls through to a Lua function in the named
module. Takes an optional opts table, if that contains `:range true` it'll
plumb the range start and end into the function call's first two
arguments. Will return the result from the VimL function by default, this
can be turned off by setting `:return false` in the opts table.
`(with-out-str f)`
Capture all print output from calling the function and return it.
------------------------------------------------------------------------------
`aniseed.string`
`(join [xs] [sep xs])`
Joins all items of a table together with an optional separator. Separator
defaults to an empty string. Values that aren't a string or nil will go
through `aniseed.core/pr-str`.
`(split s pat)`
Split the given string into a sequential table using the pattern.
Modeled on `clojure.string/split`.
`(blank? s)`
Check if the string is `nil`, empty or only whitespace.
`(triml s)`
Removes whitespace from the left side of string.
`(trimr s)`
Removes whitespace from the right side of string.
`(trim s)`
Removes whitespace from both ends of string.
------------------------------------------------------------------------------
`aniseed.test`
You probably want to use the `test.sh` script.
`(ok? results)`
Returns true if all tests passed.
`(display-results results prefix)`
Display the test results with the given prefix.
`(run mod-name)`
Run the tests in the given module name and display their results.
`(run-all)`
Runs all tests in all loaded modules.
`(suite)`
Execute the test suite. Runs all tests, captures all output and exits
Neovim with the relevant exit status.
------------------------------------------------------------------------------
`aniseed.view`
`(serialise ...)`
Simply calls through to Fennel's `fennelview` module.
Turns the input data into a string.
------------------------------------------------------------------------------
`aniseed.macros.autocmds`
`(autocmd event opt)`
Define an auto command.
>
(autocmd
[:BufNewFile :BufRead] {:pattern [:*.txt :*.text] :command "setf text"})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*.txt", "*.text"}, command = "setf text"}
;; )
<
`(autocmds ...)`
Define many auto commands at once.
>
(autocmds
[[:BufNewFile :BufRead] {:pattern [:*.txt :*.text] :command "setf text" }]
[[:BufNewFile :BufRead] {:pattern [:*vifmrc] :command "setf vifm" }]
[[:BufNewFile :BufRead] {:pattern [:*/tmux/conf] :command "setf tmux" }]
[[:BufNewFile :BufRead] {:pattern [:*/git/config] :command "setf gitconfig"}]
[[:BufNewFile :BufRead] {:pattern [:*fetchmail] :command "setf fetchmail"}]
[[:BufNewFile :BufRead] {:pattern [:*procmailrc] :command "setf procmail" }]
[[:BufNewFile :BufRead] {:pattern [:*muttrc] :command "setf muttrc" }])
;; do
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*.txt", "*.text"}, command = "setf text"})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*vifmrc"}, command = "setf vifm"})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*/tmux/conf"}, command = "setf tmux"})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*/git/config"}, command = "setf gitconfig"})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*fetchmail"}, command = "setf fetchmail"})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*procmailrc"}, command = "setf procmail"})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*muttrc"}, command = "setf muttrc"})
;; end
<
`(augroup name ...)`
Defines an auto command group and lets you create autocommands that are a
part of that group.
>
(augroup :my-group
[[:BufNewFile :BufRead] {:pattern [:*vifmrc] :command "setf vifm" }]
[[:BufNewFile :BufRead] {:pattern [:*/tmux/conf] :command "setf tmux" }]
[[:BufNewFile :BufRead] {:pattern [:*muttrc] :command "setf muttrc" }])
;; local group = vim.api.nvim_create_augroup("my-group", {clear = true})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*vifmrc"}, command = "setf vifm", group = group})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*/tmux/conf"}, command = "setf tmux", group = group})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"},
;; {pattern = {"*muttrc"}, command = "setf muttrc", group = group})
==============================================================================
TESTING *aniseed-testing*
Aniseed tests itself with it's own testing tools, so you can see an example
inside this very repository. We start by creating a module within our project
such as `fnl/foo/math.fnl`.
>
(module foo.math)
(defn add [a b]
(+ a b))
>
We can then create our test module in `test/fnl/foo/math-test.fnl`.
>
(module foo.math-test
{autoload {math foo.math}})
;; The `t` assertion table is included automatically via the deftest macro.
(deftest add
(t.= 10 (math.add 6 4) "it adds things together"))
>
All of the tests can then be executed using the helper script which will
startup Neovim, execute the tests, capture the results and finally display
them in stdout. It exits with an appropriate status code for use with CI
systems (you'll need to ensure `nvim` is available inside your CI).
You'll want to git ignore `/test/lua/`. Provide a `SUFFIX` or `PREFIX`
environment var to prepend or append code to the `nvim` command.
>
deps/aniseed/scripts/test.sh
>
The `t` assertion table that's defined for you contains a few assertion
functions.
`(t.= expected result [description])`
Check for an expected result.
`(t.pr= expected result [descrpition])`
The same but both values will be serialised to a string before comparison,
this allows you to compare deeply nested tables.
`(t.ok? result [description])`
Check for some truthy value.
==============================================================================
SYNTAX *aniseed-syntax*
Aniseed ships with embedded Fennel syntax support which is really just a fork
of the official Fennel syntax with modifications and additions.
https://github.com/bakpakin/fennel.vim
This syntax support comes with various settings that allow you to tweak the
behaviour. You can find all of these settings under the `g:fennel_*` prefix,
the best way to find and understand them right now is to look through the
source code. If there's enough interest in configuring the syntax support work
can be done to expand and document each value.
vim:tw=78:sw=2:ts=2:ft=help:norl:et:listchars=