Skip to content

Commit 3f33ca3

Browse files
authored
Merge pull request #48 from RomanHargrave/fix-smie-hanging-indent
Fix hanging assignment indentation
2 parents 02bf289 + 73c35c0 commit 3f33ca3

File tree

2 files changed

+75
-26
lines changed

2 files changed

+75
-26
lines changed

raku-indent.el

Lines changed: 69 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,56 +11,99 @@
1111

1212
(defconst raku-smie-grammar
1313
(smie-prec2->grammar
14-
(smie-precs->prec2 '((assoc ";") (assoc ",") (left ":")))))
14+
(smie-precs->prec2
15+
'((assoc ";") (assoc "=") (assoc ",") (left ":")))))
1516

1617
(defcustom raku-indent-offset 4
1718
"Basic size of one indentation step."
1819
:type 'integer
1920
:group 'raku)
2021

2122
(defun raku-smie--not-interpolation-p ()
22-
(save-excursion
23-
(forward-char -1)
24-
(or (zerop (skip-chars-backward "-[:alnum:]"))
25-
(not (looking-back "#{\\$" (- (point) 3))))))
23+
(save-excursion ;; Prepare for excursion
24+
(forward-char -1) ;; Retreat one char
25+
26+
(or
27+
;; Backtrack til we hit something that _isn't_ alnum
28+
;; If we did not backtrack, we're not in interpolation
29+
(zerop (skip-chars-backward "-[:alnum:]"))
30+
31+
;; If we did backtrack, see if #{\$ (EOL) occurs three
32+
;; or more characters prior to point (??????????)
33+
;; if this does NOT match, we are not in an interpolation
34+
(not (looking-back "#{\\$" (- (point) 3))))))
2635

2736
(defun raku-smie--forward-token ()
2837
(cond
29-
((and (eq (char-before) ?\})
30-
(raku-smie--not-interpolation-p)
31-
;; FIXME: If the next char is not whitespace, what should we do?
32-
(or (memq (char-after) '(?\s ?\t ?\n))
33-
(looking-at comment-start-skip)))
34-
(if (memq (char-after) '(?\s ?\t ?\n))
35-
(forward-char 1) (forward-comment 1))
36-
";")
37-
((progn (forward-comment (point-max))
38-
(looking-at "[;,:]"))
39-
(forward-char 1) (match-string 0))
40-
(t (smie-default-forward-token))))
38+
;; Return `;` to fudge end-of-block indentation (I think), as ; is optional after a block
39+
((and (eq (char-before) ?\}) ;; Character immediately prior to point is `}`
40+
(raku-smie--not-interpolation-p) ;; And, not in an interpolation
41+
;; FIXME: If the next char is not whitespace, what should we do?
42+
(or (memq (char-after) '(?\s ?\t ?\n)) ;; And, point is followed by \s, \t, or \n
43+
(looking-at comment-start-skip))) ;; or point is looking-at /#+ */
44+
45+
(if (memq (char-after) '(?\s ?\t ?\n)) ;; If the above is true, and point is followed by /[\s\t\n]/
46+
(forward-char 1) (forward-comment 1)) ;; Then, advance by one character, and one whole comment
47+
";")
48+
49+
((eq (char-after) ?\=) ;; Spit out '=' to kick off proper indentation for hanging assignment
50+
(forward-char 1)
51+
"=")
52+
53+
((progn (forward-comment (point-max)) ;; Read past ALL comments
54+
(looking-at "[;,:]")) ;; Are we looking at ; , or :
55+
56+
(forward-char 1) ;; If so, advance one character
57+
(match-string 0)) ;; And then return whatever looking-at found (?)
58+
59+
(t (smie-default-forward-token)))) ;; If none of the above matched, defer to SMIE default search
4160

4261
(defun raku-smie--backward-token ()
4362
(let ((pos (point)))
44-
(forward-comment (- (point)))
63+
(forward-comment (- (point))) ;; Retreate past ALL comments up to point
4564
(cond
4665
;; FIXME: If the next char is not whitespace, what should we do?
47-
((and (eq (char-before) ?\}) (raku-smie--not-interpolation-p)
48-
(> pos (point))) ";")
49-
((memq (char-before) '(?\; ?\, ?\:))
50-
(forward-char -1) (string (char-after)))
51-
(t (smie-default-backward-token)))))
66+
;; Cond #1 - Same end-of-block hack, I think
67+
((and (eq (char-before) ?\}) ;; Point is preceded immediately by `}`
68+
(raku-smie--not-interpolation-p) ;; And, not in an interpolation
69+
(> pos (point))) ;; And, point has moved backward
70+
71+
";") ;; If so, yield ';'
72+
73+
((eq (char-before) ?\=)
74+
(forward-char -1)
75+
"=")
76+
77+
;; Cond #2 - Get whatever precedes [,:;]
78+
((memq (char-before) '(?\; ?\, ?\:)) ;; Point is preceded immediately by `;`, `,`, or `:`
79+
(forward-char -1) ;; Retreat one char
80+
(string (char-after))) ;; Return char after point (the char we just retreated past)
81+
82+
(t (smie-default-backward-token))))) ;; If none of the above matched, defer to SMIE default search
5283

5384
(defun raku-smie-rules (kind token)
5485
(pcase (cons kind token)
86+
;; Basic indent offset
5587
(`(:elem . basic) raku-indent-offset)
88+
89+
;; Indent offset for function args
5690
(`(:elem . arg) 0)
91+
5792
(`(:list-intro . ,(or `";" `"")) t) ;"" stands for BOB (bug#15467).
93+
94+
;; Make sure that hanging assignment gets indented
95+
(`(:before . "=")
96+
(if (smie-rule-hanging-p)
97+
(smie-rule-parent raku-indent-offset)))
98+
5899
(`(:before . "{")
59-
(when (smie-rule-hanging-p)
60-
(smie-backward-sexp ";")
100+
(when (smie-rule-hanging-p) ; is `{` the last thing on this line?
101+
(smie-backward-sexp ";") ; y tho
61102
(smie-indent-virtual)))
103+
62104
(`(:before . ,(or "{" "("))
63-
(if (smie-rule-hanging-p) (smie-rule-parent 0)))))
105+
(if (smie-rule-hanging-p)
106+
(smie-rule-parent 0)))))
64107

65108
(provide 'raku-indent)
66109

test/test-smie.p6

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ qq:to/HERE/;
55
by emacs. (Except maybe to have left overhanging lines
66
adjusted.)
77
HERE
8+
9+
my %var =
10+
A => 1,
11+
:b<2>,
12+
:3c,
13+
D => 4;

0 commit comments

Comments
 (0)