forked from bakpakin/Fennel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
old_launcher.lua
executable file
·237 lines (214 loc) · 8.42 KB
/
old_launcher.lua
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
#!/usr/bin/env lua
-- This is the old version of the launcher wrapper script; we keep it around
-- for bootstraping purposes to avoid chicken/egg problems using launcher.fnl
-- to compile Fennel itself. In general there is no need to keep this file in
-- sync with launcher.fnl; changes for new features should just go there.
local fennel_dir = arg[0]:match("(.-)[^\\/]+$")
package.path = fennel_dir .. "?.lua;" .. package.path
local fennel = require('fennel')
local unpack = unpack or table.unpack
local help = [[
Usage: fennel [FLAG] [FILE]
Run fennel, a lisp programming language for the Lua runtime.
--repl : Command to launch an interactive repl session
--compile FILES : Command to compile files and write Lua to stdout
--eval SOURCE (-e) : Command to evaluate source code and print the result
--no-searcher : Skip installing package.searchers entry
--indent VAL : Indent compiler output with VAL
--add-package-path PATH : Add PATH to package.path for finding Lua modules
--add-fennel-path PATH : Add PATH to fennel.path for finding Fennel modules
--globals G1[,G2...] : Allow these globals in addition to standard ones
--globals-only G1[,G2] : Same as above, but exclude standard ones
--check-unused-locals : Raise error when compiling code with unused locals
--require-as-include : Inline required modules in the output
--metadata : Enable function metadata, even in compiled output
--no-metadata : Disable function metadata, even in REPL
--correlate : Make Lua output line numbers match Fennel input
--load FILE (-l) : Load the specified FILE before executing the command
--no-fennelrc : Skip loading ~/.fennelrc when launching repl
--help (-h) : Display this text
--version (-v) : Show version
Metadata is typically considered a development feature and is not recommended
for production. It is used for docstrings and enabled by default in the REPL.
When not given a command, runs the file given as the first argument.
When given neither command nor file, launches a repl.
If ~/.fennelrc exists, loads it before launching a repl.]]
local options = {}
local function dosafe(filename, opts, args)
local ok, val = xpcall(function()
return fennel.dofile(filename, opts, unpack(args))
end, fennel.traceback)
if not ok then
io.stderr:write(val .. "\n")
os.exit(1)
end
return val
end
local function allowGlobals(globalNames)
options.allowedGlobals = {}
for g in globalNames:gmatch("([^,]+),?") do
table.insert(options.allowedGlobals, g)
end
end
for i=#arg, 1, -1 do
if arg[i] == "--no-searcher" then
options.no_searcher = true
table.remove(arg, i)
elseif arg[i] == "--indent" then
options.indent = table.remove(arg, i+1)
if options.indent == "false" then options.indent = false end
table.remove(arg, i)
elseif arg[i] == "--add-package-path" then
local entry = table.remove(arg, i+1)
package.path = entry .. ";" .. package.path
table.remove(arg, i)
elseif arg[i] == "--add-fennel-path" then
local entry = table.remove(arg, i+1)
fennel.path = entry .. ";" .. fennel.path
table.remove(arg, i)
elseif arg[i] == "--load" or arg[i] == "-l" then
local file = table.remove(arg, i+1)
dosafe(file, options, {})
table.remove(arg, i)
elseif arg[i] == "--no-fennelrc" then
options.fennelrc = false
table.remove(arg, i)
elseif arg[i] == "--correlate" then
options.correlate = true
table.remove(arg, i)
elseif arg[i] == "--check-unused-locals" then
options.checkUnusedLocals = true
table.remove(arg, i)
elseif arg[i] == "--globals" then
allowGlobals(table.remove(arg, i+1))
for globalName in pairs(_G) do
table.insert(options.allowedGlobals, globalName)
end
table.remove(arg, i)
elseif arg[i] == "--globals-only" then
allowGlobals(table.remove(arg, i+1))
table.remove(arg, i)
elseif arg[i] == "--require-as-include" then
options.requireAsInclude = true
table.remove(arg, i)
elseif arg[i] == "--metadata" then
options.useMetadata = true
table.remove(arg, i)
elseif arg[i] == "--no-metadata" then
options.useMetadata = false
table.remove(arg, i)
end
end
if not options.no_searcher then
local opts = {}
for k,v in pairs(options) do opts[k] = v end
table.insert((package.loaders or package.searchers), fennel.make_searcher(opts))
end
-- Try to load readline library
local function tryReadline(opts)
local readline_ok, readline = pcall(require, "readline")
if readline_ok then
if readline.set_readline_name then -- added as of readline.lua 2.6-0
readline.set_readline_name('fennel')
end
readline.set_options({
keeplines = 1000, histfile = '', })
function opts.readChunk(parserState)
local prompt = parserState.stackSize > 0 and '.. ' or '>> '
local str = readline.readline(prompt)
if str then
return str .. "\n"
end
end
-- completer is registered by the repl, until then returns empty list
local completer
function opts.registerCompleter(replCompleter)
completer = replCompleter
end
local function replCompleter(text, from, to)
if completer then
-- stop completed syms from adding extra space on match
readline.set_completion_append_character('')
return completer(text:sub(from, to))
else
return {}
end
end
readline.set_complete_function(replCompleter)
return readline
end
end
-- TODO: generalize this instead of hardcoding it
local fok, friendly = pcall(fennel.dofile, fennel_dir .. "fennelfriend.fnl", options)
if fok then
options["assert-compile"] = friendly["assert-compile"]
options["parse-error"] = friendly["parse-error"]
end
if arg[1] == "--repl" or #arg == 0 then
local ppok, pp = pcall(fennel.dofile, fennel_dir .. "fennelview.fnl", options)
if ppok then
options.pp = pp
else
ppok, pp = pcall(require, "fennelview")
if ppok then
options.pp = pp
end
end
local readline = tryReadline(options)
if options.fennelrc ~= false then
local home = os.getenv("HOME")
local xdg_config_home = os.getenv("XDG_CONFIG_HOME") or home .. "/.config"
local xdg_initfile = xdg_config_home .. "/fennel/fennelrc"
local home_initfile = home .. "/.fennelrc"
local init, initFilename = io.open(xdg_initfile, "rb"), xdg_initfile
if not init then
init, initFilename = io.open(home_initfile, "rb"), home_initfile
end
if init then
init:close()
-- pass in options so fennerlrc can make changes to it
dosafe(initFilename, options, {options})
end
end
print("Welcome to Fennel " .. fennel.version .. "!")
if options.useMetadata ~= false then
print("Use (doc something) to view documentation.")
end
fennel.repl(options)
-- if readline loaded, persist history (noop if histfile == '')
if readline then readline.save_history() end
elseif arg[1] == "--compile" then
for i = 2, #arg do
local f = arg[i] == "-" and io.stdin or assert(io.open(arg[i], "rb"))
options.filename=arg[i]
local ok, val = xpcall(function()
return fennel.compileString(f:read("*all"), options)
end, fennel.traceback)
if ok then
print(val)
else
io.stderr:write(val .. "\n")
os.exit(1)
end
f:close()
end
elseif arg[1] == "--eval" or arg[1] == "-e" then
if arg[2] and arg[2] ~= "-" then
print(fennel.eval(arg[2], options))
else
local source = io.stdin:read("*a")
print(fennel.eval(source, options))
end
elseif arg[1] == "--version" or arg[1] == "-v" then
print("Fennel " .. fennel.version)
elseif #arg >= 1 and arg[1] ~= "--help" and arg[1] ~= "-h" then
local filename = table.remove(arg, 1) -- let the script have remaining args
if filename == "-" then
local source = io.stdin:read("*a")
fennel.eval(source, options)
else
dosafe(filename, options, arg)
end
else
print(help)
end