In a .fln buffer ik takes the value on a one-line else or elif line, a wrapped fn header's return type is coloured, and C-u C-c C-c on a let the let above merges in stops at its value
This commit is contained in:
parent
02fcb1725e
commit
ba3ad6b1bc
@ -285,6 +285,23 @@ depth, outside strings and comments, or nil."
|
||||
(flan-fln--joined-end l))))
|
||||
(and m (car m))))
|
||||
|
||||
(defun flan-fln--clause-value (l)
|
||||
"Bounds of the value on the clause line L itself: `x' of `else x' or of
|
||||
`elif c then x'; nil when the clause's value is its block."
|
||||
(let ((end (flan-fln--joined-end l))
|
||||
(then (flan-fln--then l)))
|
||||
(save-excursion
|
||||
(goto-char (flan-fln--first-char l))
|
||||
(cond
|
||||
((and (looking-at "elif[ \t]") then)
|
||||
(goto-char then)
|
||||
(skip-chars-forward " \t")
|
||||
(forward-char 4)
|
||||
(skip-chars-forward " \t")
|
||||
(and (< (point) end) (cons (point) end)))
|
||||
((and (looking-at "else[ \t]+") (< (match-end 0) end))
|
||||
(cons (match-end 0) end))))))
|
||||
|
||||
(defun flan-fln--value-start (l)
|
||||
"Where the value of the joined line L starts, after its first `=' or
|
||||
`+=' at the line's own depth, or nil when it binds or assigns nothing."
|
||||
@ -675,7 +692,21 @@ forms, where the clause line itself is not."
|
||||
(arm (plist-get arm :value))
|
||||
((and l (flan-fln--clause-line-p l)) (flan-fln--clause-target l))
|
||||
(t (let ((s (flan-fln--statement-start-at pos)))
|
||||
(and s (flan-fln--statement-bounds s)))))))
|
||||
(and s (or (flan-fln--merged-let-value s)
|
||||
(flan-fln--statement-bounds s))))))))
|
||||
|
||||
(defun flan-fln--merged-let-value (s)
|
||||
"Bounds of the value of the `let' at S when the let before it takes it in.
|
||||
The reader merges consecutive lets into one binding vector, so a second
|
||||
`let b = 2' starts no form of its own; its value, or its value's block, is
|
||||
the form that runs where the line stands."
|
||||
(let ((p (and (flan-fln--let-p s) (flan-fln--sibling s -1))))
|
||||
(when (and p (flan-fln--let-p p))
|
||||
(let ((v (flan-fln--value-start s))
|
||||
(end (flan-fln--joined-end s)))
|
||||
(if (and v (< v end))
|
||||
(cons v (cdr (flan-fln--statement-bounds s)))
|
||||
(flan-fln--body-bounds s))))))
|
||||
|
||||
(defun flan-fln--clause-target (l)
|
||||
"What a clause line L stops at: an elif's condition, else its block.
|
||||
@ -686,8 +717,7 @@ A one-line `else x' stops at x."
|
||||
(cond
|
||||
((looking-at "elif[ \t]+")
|
||||
(cons (match-end 0) (or (flan-fln--then l) end)))
|
||||
((and (looking-at "else[ \t]+") (< (match-end 0) end))
|
||||
(cons (match-end 0) end))
|
||||
((flan-fln--clause-value l))
|
||||
(t (flan-fln--body-bounds l))))))
|
||||
|
||||
(defun flan-fln--condition (l)
|
||||
@ -1505,8 +1535,20 @@ lambda or a `Fn(...)' type, and not after a match arm's."
|
||||
(setq found (save-excursion
|
||||
(save-match-data
|
||||
(goto-char (line-beginning-position))
|
||||
(re-search-forward "\\(?:^[ \t]*fn-?[ \t]\\|\\_<C?[fF]n(\\)"
|
||||
arrow t))))))
|
||||
(or (re-search-forward "\\(?:^[ \t]*fn-?[ \t]\\|\\_<C?[fF]n(\\)"
|
||||
arrow t)
|
||||
;; A header wrapped inside its parentheses: the
|
||||
;; `)' before the arrow closes a `fn f(' above.
|
||||
(progn
|
||||
(goto-char arrow)
|
||||
(skip-chars-backward " \t")
|
||||
(and (eq (char-before) ?\))
|
||||
(let ((open (ignore-errors (scan-lists (point) -1 0))))
|
||||
(and open
|
||||
(progn
|
||||
(goto-char open)
|
||||
(looking-back "\\(?:^[ \t]*fn-?[ \t]+[^][ \t\n(){},;\":]+\\|\\_<C?[fF]n\\)"
|
||||
(line-beginning-position)))))))))))))
|
||||
found))
|
||||
|
||||
(defvar flan-fln-font-lock-keywords
|
||||
@ -1777,10 +1819,12 @@ below a form is not taken: it belongs to what follows."
|
||||
(bounds-of-thing-at-point 'flan-fln-statement))
|
||||
'line))
|
||||
(evil-define-text-object flan-fln-inner-clause (count &optional _beg _end _type)
|
||||
"A clause's block, its lines; a match arm's value when it is on the line."
|
||||
"A clause's block, its lines; the value on the line of a match arm, a
|
||||
one-line else or an elif's `then'."
|
||||
(let* ((c (flan-fln--clause-at (point)))
|
||||
(arm (and c (flan-fln--arm c)))
|
||||
(v (and arm (plist-get arm :value))))
|
||||
(v (if arm (plist-get arm :value)
|
||||
(and c (flan-fln--clause-value c)))))
|
||||
(if (and v (= (flan-fln--bol (car v)) c))
|
||||
(flan-fln--evil v 'exclusive)
|
||||
(flan-fln--evil (flan-fln--whole-lines (and c (flan-fln--body-bounds c)))
|
||||
|
||||
@ -74,6 +74,12 @@ fn rs() -> i64
|
||||
restart retry() \"Try again\"
|
||||
4
|
||||
|
||||
fn t2(k: i64) -> i64
|
||||
let a = 1
|
||||
let b = 2
|
||||
let c: i64 = 3
|
||||
a + b + c + k
|
||||
|
||||
fn dir(d: Dir) -> i64
|
||||
match d
|
||||
Dir.north -> 7
|
||||
@ -276,7 +282,9 @@ comment():
|
||||
("a: i64, b" "a typed lambda, from its fn")
|
||||
("a * 2" "a typed lambda's block")
|
||||
("restart retry" "a restart with a report, at its block")
|
||||
("Dir.north" "an enum member's arm, at its value")))
|
||||
("Dir.north" "an enum member's arm, at its value")
|
||||
("let b = 2" "a let the let above takes in, at its value")
|
||||
("let c: i64" "a typed one, at its value")))
|
||||
(funcall goto (car c))
|
||||
(let ((reply (flan-fln-eval-defun '(4))))
|
||||
(test-flan--check (funcall name (format "C-u C-c C-c marks %s where the reader starts it"
|
||||
|
||||
@ -639,6 +639,18 @@ of its line with AT-END."
|
||||
(test-flan-fln--is "an else x after a block if too"
|
||||
(cadr (test-flan-fln--oneline-at "else 2" (lambda () (flan-fln-eval-defun '(4)))))
|
||||
'(9 8))
|
||||
(test-flan-fln--is "C-u C-c C-c on a let the let above takes in stops at its value"
|
||||
(test-flan-fln--in "fn t2(n: i64) -> i64\n let a = 1\n |let b = 2\n a + b + n\n"
|
||||
(plist-get (test-flan-fln--sending (flan-fln-eval-defun '(4))) :pause))
|
||||
'(3 11))
|
||||
(test-flan-fln--is "and at its block when the value is one"
|
||||
(test-flan-fln--in "fn t2(n: i64) -> i64\n let a = 1\n |let b =\n n + 1\n a + b\n"
|
||||
(plist-get (test-flan-fln--sending (flan-fln-eval-defun '(4))) :pause))
|
||||
'(4 5))
|
||||
(test-flan-fln--is "the first let of a run stops at the let"
|
||||
(test-flan-fln--in "fn t2(n: i64) -> i64\n n + 1\n |let a = 1\n a\n"
|
||||
(plist-get (test-flan-fln--sending (flan-fln-eval-defun '(4))) :pause))
|
||||
'(3 3))
|
||||
(test-flan-fln--is "C-c C-e on a let whose value is a block sends its scope with it"
|
||||
(car (test-flan-fln--oneline-at "let r" #'flan-fln-eval-statement))
|
||||
"let r = match n\n 0 -> 1\n _ -> 2\n add(r, 1)")
|
||||
@ -699,6 +711,13 @@ of its line with AT-END."
|
||||
(test-flan-fln--is "an enum member as a constant" (funcall face "Dir.north") 'font-lock-constant-face)
|
||||
(test-flan-fln--is "an arm's value is not a type" (funcall face "twice(1)") nil)
|
||||
(test-flan-fln--is "nor after a pattern with parentheses" (funcall face "r\n") nil)))
|
||||
(test-flan-fln--in "fn far(a: i64,\n b: i64) -> Point\n match a\n Some(x) -> Other\n"
|
||||
(font-lock-ensure)
|
||||
(let ((face (lambda (needle)
|
||||
(save-excursion (goto-char (point-min)) (search-forward needle)
|
||||
(get-text-property (match-beginning 0) 'face)))))
|
||||
(test-flan-fln--is "a wrapped fn header's return type is a type" (funcall face "Point") 'font-lock-type-face)
|
||||
(test-flan-fln--is "an arm's value after a call pattern is not" (funcall face "Other") nil)))
|
||||
|
||||
;;; Indentation
|
||||
|
||||
@ -954,6 +973,12 @@ of its line with AT-END."
|
||||
"5")
|
||||
("yak" ,(test-flan-fln--at test-flan-fln--wrapped "Some(_)")
|
||||
" Some(_) -> 5\n")
|
||||
("yik" ,(test-flan-fln--at test-flan-fln--oneline "else 1")
|
||||
"1")
|
||||
("yik" ,(test-flan-fln--at test-flan-fln--oneline "elif n")
|
||||
"0")
|
||||
("yik" ,(test-flan-fln--at test-flan-fln--oneline "else 2")
|
||||
"2")
|
||||
("yid" ,(test-flan-fln--at test-flan-fln--settle "paint-at")
|
||||
,(substring test-flan-fln--settle
|
||||
(string-search "fn step" test-flan-fln--settle)))))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user