-
Notifications
You must be signed in to change notification settings - Fork 8
/
hotpot.fnl
107 lines (98 loc) · 4.37 KB
/
hotpot.fnl
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
;; Preflight checks
(assert (= 1 (vim.fn.has "nvim-0.6")) "Hotpot requires neovim 0.6+")
(local uv vim.loop)
;; duplicated out of hotpot.fs because we can't require anything yet
(local path-separator (string.match package.config "(.-)\n"))
(lambda join-path [head ...]
(accumulate [t head _ part (ipairs [...])]
(.. t path-separator part)))
(fn new-canary [hotpot-dir]
;; represents both ends of the "canary", which lets hotpot know when it has
;; to rebuild. repo-canary is the repo "true" canary, build-canary is made
;; after compiliation and symlinks to the repo canary that was present at
;; that time.
(let [repo-canary (let [canary-folder (join-path hotpot-dir :canary)
handle (uv.fs_opendir canary-folder nil 1)
files (uv.fs_readdir handle)
_ (uv.fs_closedir handle)
[{: name}] files]
(join-path canary-folder name))
build-canary (join-path hotpot-dir :lua :canary)]
{: repo-canary
: build-canary}))
(fn canary-valid? [{: build-canary}]
;; resolve link to real file, if that fails, the link is stale
;; and we need to rebuild.
(match (uv.fs_realpath build-canary)
(nil err) false
path true))
(fn create-canary-link [{: build-canary : repo-canary}]
;; create the canary link
(uv.fs_unlink build-canary)
(uv.fs_symlink repo-canary build-canary))
(fn load-hotpot []
(let [hotpot (require :hotpot.runtime)]
(hotpot.install)
;; user should never have to run install
(tset hotpot :install nil)
(values hotpot)))
(fn compile-hotpot [hotpot-dir]
(fn compile-file [fnl-src lua-dest]
;; compile fnl src to lua dest, can raise.
(let [{: compile-string} (require :hotpot.fennel)]
(with-open [fnl-file (io.open fnl-src)
lua-file (io.open lua-dest :w)]
(let [fnl-code (fnl-file:read :*a)
lua-code (compile-string fnl-code {:filename fnl-src
:correlate true})]
(lua-file:write lua-code)))))
(fn compile-dir [in-dir out-dir]
;; recursively scan in-dir, compile fnl files to out-dir,
;; except for some special files.
(let [scanner (uv.fs_scandir in-dir)]
(each [name kind #(uv.fs_scandir_next scanner)]
(match kind
"directory"
(let [in-down (join-path in-dir name)
out-down (join-path out-dir name)]
(vim.fn.mkdir out-down :p)
(compile-dir in-down out-down))
"file"
(let [in-file (join-path in-dir name)
out-name (string.gsub name ".fnl$" ".lua")
out-file (join-path out-dir out-name)]
(when (not (or (= name :macros.fnl)
(= name :hotpot.fnl)))
(compile-file in-file out-file)))))))
(let [fennel (require :hotpot.fennel)
saved {:macro-path fennel.macro-path}
fnl-dir (join-path hotpot-dir :fnl)
lua-dir (join-path hotpot-dir :lua)
fnl-dir-search-path (join-path fnl-dir "?.fnl")]
;; let fennel find hotpot macros while compiling, then restore old path
(set fennel.macro-path (.. fnl-dir-search-path ";" fennel.macro-path))
(compile-dir fnl-dir lua-dir)
(set fennel.macro-path saved.macro-path))
;; make sure the cache dir exists
(let [cache-dir (join-path (vim.fn.stdpath :cache) :hotpot)]
(vim.fn.mkdir cache-dir :p))
(values true))
;; nb: on windows debug.getinfo.source comes back with *mixed* separators,
;; something like @c:\\abc\\hotpot.nvim/lua/hotpot.lua, this may be a windows,
;; lua or nvim thing.
;;
;; benchmarking between string.match and string.sub is pretty tiny
;; (~0.0005ms???) but match will be more resilient to upstream changes.
;;
;; finding the source via debug is ~0.002ms while "safely" searching the rtp is
;; ~0.02ms but could be much longer with large runtimepaths.
(let [hotpot-dir (-> (debug.getinfo 1 :S)
(. :source)
;; we cant be certain what folder hotpot was installed to
;; so instead match on <sep><maybe-sep?>lua<...>hotpot.lua
(string.match "@(.+)..?lua..?hotpot%.lua$"))
canary (new-canary hotpot-dir)]
(when (not (canary-valid? canary))
(compile-hotpot hotpot-dir)
(create-canary-link canary))
(load-hotpot))