size: 2 KiB

1local djot = require("djot")
2
3local help = [[
4djot [opts] [file*]
5
6Options:
7--matches -m Show matches.
8--ast -a Show AST.
9--json -j Use JSON for -m or -a.
10--sourcepos -p Include source positions in AST.
11--filter FILE -f FILE Filter AST using filter in FILE.
12--verbose -v Verbose (show warnings).
13--version Show version information.
14--help -h Help.
15]]
16
17local function err(msg, code)
18 io.stderr:write(msg .. "\n")
19 os.exit(code)
20end
21
22local opts = {}
23local files = {}
24
25local shortcuts =
26 { m = "--matches",
27 a = "--ast",
28 j = "--json",
29 p = "--sourcepos",
30 v = "--verbose",
31 f = "--filter",
32 h = "--help" }
33
34local argi = 1
35while arg[argi] do
36 local thisarg = arg[argi]
37 local longopts = {}
38 if string.find(thisarg, "^%-%-%a") then
39 longopts[#longopts + 1] = thisarg
40 elseif string.find(thisarg, "^%-%a") then
41 string.gsub(thisarg, "(%a)",
42 function(x)
43 longopts[#longopts + 1] = shortcuts[x] or ("-"..x)
44 end)
45 else
46 files[#files + 1] = thisarg
47 end
48 for _,x in ipairs(longopts) do
49 if x == "--matches" then
50 opts.matches = true
51 elseif x == "--ast" then
52 opts.ast = true
53 elseif x == "--json" then
54 opts.json = true
55 elseif x == "--sourcepos" then
56 opts.sourcepos = true
57 elseif x == "--verbose" then
58 opts.verbose = true
59 elseif x == "--filter" then
60 if arg[argi + 1] then
61 opts.filters = opts.filters or {}
62 table.insert(opts.filters, arg[argi + 1])
63 argi = argi + 1
64 end
65 elseif x == "--version" then
66 io.stdout:write("djot " .. djot.version .. "\n")
67 os.exit(0)
68 elseif x == "--help" then
69 io.stdout:write(help)
70 os.exit(0)
71 else
72 err("Unknown option " .. x, 1)
73 end
74 end
75 argi = argi + 1
76end
77
78local inp
79if #files == 0 then
80 inp = io.read("*all")
81else
82 local buff = {}
83 for _,f in ipairs(files) do
84 local ok, msg = pcall(function() io.input(f) end)
85 if ok then
86 table.insert(buff, io.read("*all"))
87 else
88 err(msg, 7)
89 end
90 end
91 inp = table.concat(buff, "\n")
92end
93
94local warn = function(warning)
95 if opts.verbose then
96 io.stderr:write(string.format("%s at byte position %d\n",
97 warning.message, warning.pos))
98 end
99end
100
101if opts.matches then
102
103 io.stdout:write(djot.parse_and_render_events(inp, warn))
104
105else
106
107 local ast = djot.parse(inp, opts.sourcepos, warn)
108
109 if opts.filters then
110 for _,fp in ipairs(opts.filters) do
111 local filt, err = djot.filter.require_filter(fp)
112 if filt then
113 djot.filter.apply_filter(ast, filt)
114 else
115 io.stderr:write("Error loading filter " .. fp .. ":\n" .. err .. "\n")
116 end
117 end
118 end
119
120 if opts.ast then
121 if opts.json then
122 io.stdout:write(djot.render_ast_json(ast))
123 else
124 io.stdout:write(djot.render_ast_pretty(ast))
125 end
126 else
127 io.stdout:write(djot.render_html(ast))
128 end
129
130end
131
132os.exit(0)