fix barfing
[lisp-parkour.git] / fmt / common.lua
blob7d463d7a4c455c9b1538ea46d73c9033ae49ca99
1 local M = {}
3 local function get_special(words, list)
4 local head = list[1] and list[1].text
5 return head and (words[head] or words[0] and words[0]:match(head))
6 end
8 function M.adjust_bracket_p(self, indices, nodes, range)
9 local parent = nodes[#nodes - 1]
10 if not parent then return true end
11 local nth = indices[#indices]
12 if not nth then
13 local _, nxt = parent.find_after(range, function() return true end)
14 nth = nxt or #parent + 1
15 end
16 local sexp = parent[nth] or parent[#parent]
17 local distance = nth - (sexp and range.start == sexp.finish + 1 and 0 or 1)
18 local rule = get_special(self.squarewords, parent)
19 if type(rule) == "number" then
20 if rule < 0 then
21 return -rule > distance
22 elseif rule > 0 then
23 -- XXX: the "[" check is because in Fennel fn has optional name
24 return rule < distance or sexp.d == "["
25 end
26 elseif not rule then
27 local grandparent, pnth = nodes[#nodes - 2], indices[#indices - 1]
28 if not grandparent then return true end
29 rule = get_special(self.squarewords, grandparent)
30 if not rule or type(rule) ~= "table" then return true end
31 local _, first_list_arg = grandparent.find_after(grandparent[1], function(t) return t.is_list end)
32 local first_nonlist_uncle = first_list_arg - 1
33 -- TODO: handle negative rule[1] and rule[2] (just for consistency with the scalar rules)
34 -- first_nonlist_uncle is checked so we can handle both let and named let:
35 if (not rule[1] or first_nonlist_uncle + rule[1] >= pnth) then
36 if (not rule[2] or rule[2] >= distance + 1) then
37 if parent[distance] then
38 -- allows mixing [clauses] with #:when conditions in Racket for loops:
39 if parent[distance].is_list then
40 return false
41 end
42 else
43 return false
44 end
45 end
46 end
47 end
48 return true
49 end
51 function M.last_distinguished(self, list)
52 return get_special(self.lispwords, list)
53 end
55 return M