From 0c480bb3570bf68f9a845c45f184da738d432c3f Mon Sep 17 00:00:00 2001 From: Roman Hargrave Date: Sat, 20 Feb 2021 17:44:11 -0600 Subject: [PATCH 1/4] Hanging assignment support --- raku-indent.el | 118 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 85 insertions(+), 33 deletions(-) diff --git a/raku-indent.el b/raku-indent.el index 517fcea..fa600f7 100644 --- a/raku-indent.el +++ b/raku-indent.el @@ -11,7 +11,8 @@ (defconst raku-smie-grammar (smie-prec2->grammar - (smie-precs->prec2 '((assoc ";") (assoc ",") (left ":"))))) + (smie-precs->prec2 + '((assoc ";") (assoc "=") (assoc ",") (left ":"))))) (defcustom raku-indent-offset 4 "Basic size of one indentation step." @@ -19,48 +20,99 @@ :group 'raku) (defun raku-smie--not-interpolation-p () - (save-excursion - (forward-char -1) - (or (zerop (skip-chars-backward "-[:alnum:]")) - (not (looking-back "#{\\$" (- (point) 3)))))) + (save-excursion ;; Prepare for excursion + (forward-char -1) ;; Retreat one char + + (or + ;; Backtrack til we hit something that _isn't_ alnum + ;; If we did not backtrack, we're not in interpolation + (zerop (skip-chars-backward "-[:alnum:]")) + + ;; If we did backtrack, see if #{\$ (EOL) occurs three + ;; or more characters prior to point (??????????) + ;; if this does NOT match, we are not in an interpolation + (not (looking-back "#{\\$" (- (point) 3)))))) (defun raku-smie--forward-token () (cond - ((and (eq (char-before) ?\}) - (raku-smie--not-interpolation-p) - ;; FIXME: If the next char is not whitespace, what should we do? - (or (memq (char-after) '(?\s ?\t ?\n)) - (looking-at comment-start-skip))) - (if (memq (char-after) '(?\s ?\t ?\n)) - (forward-char 1) (forward-comment 1)) - ";") - ((progn (forward-comment (point-max)) - (looking-at "[;,:]")) - (forward-char 1) (match-string 0)) - (t (smie-default-forward-token)))) + ((progn + ;; (message "frwd char-before=`%c` char-after=`%c` point=%s" (char-before) (char-after) (point)) + nil) nil) + + ;; Return `;` to fudge end-of-block indentation (I think), as ; is optional after a block + ((and (eq (char-before) ?\}) ;; Character immediately prior to point is `}` + (raku-smie--not-interpolation-p) ;; And, not in an interpolation + ;; FIXME: If the next char is not whitespace, what should we do? + (or (memq (char-after) '(?\s ?\t ?\n)) ;; And, point is followed by \s, \t, or \n + (looking-at comment-start-skip))) ;; or point is looking-at /#+ */ + + (if (memq (char-after) '(?\s ?\t ?\n)) ;; If the above is true, and point is followed by /[\s\t\n]/ + (forward-char 1) (forward-comment 1)) ;; Then, advance by one character, and one whole comment + + (message "forward cond#1") + ";") + + ((eq (char-after) ?\=) ;; Spit out '=' to kick off proper indentation for hanging assignment + (forward-char 1) + "=") + + ((progn (forward-comment (point-max)) ;; Read past ALL comments + (looking-at "[;,:]")) ;; Are we looking at ; , or : + + (forward-char 1) ;; If so, advance one character + (match-string 0)) ;; And then return whatever looking-at found (?) + + (t (smie-default-forward-token)))) ;; If none of the above matched, defer to SMIE default search (defun raku-smie--backward-token () (let ((pos (point))) - (forward-comment (- (point))) + (forward-comment (- (point))) ;; Retreate past ALL comments up to point + ;; (message "back char-before=`%c` char-after=`%c` point=%s" (char-before) (char-after) (point)) (cond ;; FIXME: If the next char is not whitespace, what should we do? - ((and (eq (char-before) ?\}) (raku-smie--not-interpolation-p) - (> pos (point))) ";") - ((memq (char-before) '(?\; ?\, ?\:)) - (forward-char -1) (string (char-after))) - (t (smie-default-backward-token))))) + ;; Cond #1 - Same end-of-block hack, I think + ((and (eq (char-before) ?\}) ;; Point is preceded immediately by `}` + (raku-smie--not-interpolation-p) ;; And, not in an interpolation + (> pos (point))) ;; And, point has moved backward + + ";") ;; If so, yield ';' + + ((eq (char-before) ?\=) + (forward-char -1) + "=") + + ;; Cond #2 - Get whatever precedes [,:;] + ((memq (char-before) '(?\; ?\, ?\:)) ;; Point is preceded immediately by `;`, `,`, or `:` + (forward-char -1) ;; Retreat one char + (string (char-after))) ;; Return char after point (the char we just retreated past) + + (t (smie-default-backward-token))))) ;; If none of the above matched, defer to SMIE default search (defun raku-smie-rules (kind token) - (pcase (cons kind token) - (`(:elem . basic) raku-indent-offset) - (`(:elem . arg) 0) - (`(:list-intro . ,(or `";" `"")) t) ;"" stands for BOB (bug#15467). - (`(:before . "{") - (when (smie-rule-hanging-p) - (smie-backward-sexp ";") - (smie-indent-virtual))) - (`(:before . ,(or "{" "(")) - (if (smie-rule-hanging-p) (smie-rule-parent 0))))) + (progn + ;; (message "%S (point: %s)" (cons kind token) (point)) + (pcase (cons kind token) + ;; Basic indent offset + (`(:elem . basic) raku-indent-offset) + + ;; Indent offset for function args + (`(:elem . arg) 0) + + (`(:list-intro . ,(or `";" `"")) t) ;"" stands for BOB (bug#15467). + + ;; Make sure that hanging assignment gets indented + (`(:before . "=") + (if (smie-rule-hanging-p) + (smie-rule-parent raku-indent-offset))) + + (`(:before . "{") + (when (smie-rule-hanging-p) ; is `{` the last thing on this line? + (smie-backward-sexp ";") ; y tho + (smie-indent-virtual))) + + (`(:before . ,(or "{" "(")) + (if (smie-rule-hanging-p) + (smie-rule-parent 0)))))) (provide 'raku-indent) From f0b6adcb74849518e3a8471445c5e47ad4214776 Mon Sep 17 00:00:00 2001 From: Roman Hargrave Date: Tue, 23 Mar 2021 11:45:47 -0500 Subject: [PATCH 2/4] Add hanging hash assignment to smie test file --- test/test-smie.p6 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/test-smie.p6 b/test/test-smie.p6 index f035ebe..5fea4b7 100644 --- a/test/test-smie.p6 +++ b/test/test-smie.p6 @@ -5,3 +5,9 @@ qq:to/HERE/; by emacs. (Except maybe to have left overhanging lines adjusted.) HERE + +my %var = + A => 1, + :b<2>, + :3c, + D => 4; From a316c3f19509bebd58655052db6225f702204f06 Mon Sep 17 00:00:00 2001 From: Roman Hargrave Date: Wed, 7 Apr 2021 15:51:56 -0500 Subject: [PATCH 3/4] Remove leftover debugging garbage --- raku-indent.el | 8 -------- 1 file changed, 8 deletions(-) diff --git a/raku-indent.el b/raku-indent.el index fa600f7..9b78aff 100644 --- a/raku-indent.el +++ b/raku-indent.el @@ -35,10 +35,6 @@ (defun raku-smie--forward-token () (cond - ((progn - ;; (message "frwd char-before=`%c` char-after=`%c` point=%s" (char-before) (char-after) (point)) - nil) nil) - ;; Return `;` to fudge end-of-block indentation (I think), as ; is optional after a block ((and (eq (char-before) ?\}) ;; Character immediately prior to point is `}` (raku-smie--not-interpolation-p) ;; And, not in an interpolation @@ -48,8 +44,6 @@ (if (memq (char-after) '(?\s ?\t ?\n)) ;; If the above is true, and point is followed by /[\s\t\n]/ (forward-char 1) (forward-comment 1)) ;; Then, advance by one character, and one whole comment - - (message "forward cond#1") ";") ((eq (char-after) ?\=) ;; Spit out '=' to kick off proper indentation for hanging assignment @@ -67,7 +61,6 @@ (defun raku-smie--backward-token () (let ((pos (point))) (forward-comment (- (point))) ;; Retreate past ALL comments up to point - ;; (message "back char-before=`%c` char-after=`%c` point=%s" (char-before) (char-after) (point)) (cond ;; FIXME: If the next char is not whitespace, what should we do? ;; Cond #1 - Same end-of-block hack, I think @@ -90,7 +83,6 @@ (defun raku-smie-rules (kind token) (progn - ;; (message "%S (point: %s)" (cons kind token) (point)) (pcase (cons kind token) ;; Basic indent offset (`(:elem . basic) raku-indent-offset) From 73c35c089b8da4d6bdeaa337264310d96f93c387 Mon Sep 17 00:00:00 2001 From: Roman Hargrave Date: Wed, 7 Apr 2021 20:14:28 -0500 Subject: [PATCH 4/4] Remove an unnecessary (progn) that I missed. --- raku-indent.el | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/raku-indent.el b/raku-indent.el index 9b78aff..6c1aa73 100644 --- a/raku-indent.el +++ b/raku-indent.el @@ -82,29 +82,28 @@ (t (smie-default-backward-token))))) ;; If none of the above matched, defer to SMIE default search (defun raku-smie-rules (kind token) - (progn - (pcase (cons kind token) - ;; Basic indent offset - (`(:elem . basic) raku-indent-offset) + (pcase (cons kind token) + ;; Basic indent offset + (`(:elem . basic) raku-indent-offset) - ;; Indent offset for function args - (`(:elem . arg) 0) + ;; Indent offset for function args + (`(:elem . arg) 0) - (`(:list-intro . ,(or `";" `"")) t) ;"" stands for BOB (bug#15467). + (`(:list-intro . ,(or `";" `"")) t) ;"" stands for BOB (bug#15467). - ;; Make sure that hanging assignment gets indented - (`(:before . "=") - (if (smie-rule-hanging-p) - (smie-rule-parent raku-indent-offset))) + ;; Make sure that hanging assignment gets indented + (`(:before . "=") + (if (smie-rule-hanging-p) + (smie-rule-parent raku-indent-offset))) - (`(:before . "{") - (when (smie-rule-hanging-p) ; is `{` the last thing on this line? - (smie-backward-sexp ";") ; y tho - (smie-indent-virtual))) + (`(:before . "{") + (when (smie-rule-hanging-p) ; is `{` the last thing on this line? + (smie-backward-sexp ";") ; y tho + (smie-indent-virtual))) - (`(:before . ,(or "{" "(")) - (if (smie-rule-hanging-p) - (smie-rule-parent 0)))))) + (`(:before . ,(or "{" "(")) + (if (smie-rule-hanging-p) + (smie-rule-parent 0))))) (provide 'raku-indent)