diff --git a/emacs/flan-fln-mode.el b/emacs/flan-fln-mode.el index 9c69e88c..e34cf308 100644 --- a/emacs/flan-fln-mode.el +++ b/emacs/flan-fln-mode.el @@ -680,6 +680,10 @@ a `(' -- a pattern's constructor, which binds nothing." (let (names) (while (re-search-forward "\\(?:\\sw\\|\\s_\\)+" nil t) (let ((n (match-string-no-properties 0))) + ;; A `-' glued to a letter, `$', `_' or `*' is negation, not part + ;; of the name (`is_neg_char' in lib/indent_reader.ml): `-n' is n. + (when (string-match "\\`-[a-zA-Z$_*]" n) + (setq n (substring n 1))) (unless (and skip-heads (eq (char-after) ?\()) (push n names) (dolist (part (split-string n "\\." t)) @@ -1563,14 +1567,25 @@ that says so and otherwise is its own." (and (flan-fln--blank-p pos) (not (flan-fln--empty-line-p pos)))) (defun flan-fln--with-comments (b) - "Whole lines B, and the comment lines directly above them: a comment block -with no blank line under it belongs to what it sits on." + "Whole lines B, and the comments that belong to them. +Above: a comment block at B's own column with no blank line under it. +Below: comment lines deeper than B's column straight after it, which close +its block. A comment at another column belongs to the block it lines up +with." (and b (save-excursion - (goto-char (car b)) - (while (and (zerop (forward-line -1)) - (flan-fln--comment-line-p (point))) - (setq b (cons (point) (cdr b)))) - b))) + (let ((col (flan-fln--indent-at (car b)))) + (goto-char (car b)) + (while (and (zerop (forward-line -1)) + (flan-fln--comment-line-p (point)) + (= (current-indentation) col)) + (setq b (cons (point) (cdr b)))) + (goto-char (cdr b)) + (while (and (not (eobp)) + (flan-fln--comment-line-p (point)) + (> (current-indentation) col)) + (forward-line 1) + (setq b (cons (car b) (point)))) + b)))) (defun flan-fln--commented-toplevel (pos) "The top-level form at POS, whole lines with its comment block. @@ -1579,6 +1594,7 @@ On a comment block that sits directly on a form, that form." (goto-char pos) (beginning-of-line) (while (and (flan-fln--comment-line-p (point)) + (zerop (current-indentation)) (zerop (forward-line 1)))) (if (flan-fln--toplevel-start-p (point)) (point) pos)))) (flan-fln--with-comments diff --git a/emacs/test-flan-fln.el b/emacs/test-flan-fln.el index eb1c7b51..0dbb9014 100644 --- a/emacs/test-flan-fln.el +++ b/emacs/test-flan-fln.el @@ -533,7 +533,9 @@ comment: (dolist (c '(("Some(_v) -> _v + 1" "a name starting with _") ("Some(éé) -> éé" "a name that is not ASCII") ("Some(N) -> N" "a capitalised name") - ("Some(p) -> p.x" "a name used as a field's base"))) + ("Some(p) -> p.x" "a name used as a field's base") + ("Some(n) -> -n" "a name its value negates") + ("Some(p) -> -p.x" "a name whose field its value negates"))) (test-flan-fln--in (concat "fn f(o: Option(i64)) -> i64\n match o\n " (car c) "\n") (goto-char (point-max)) (skip-chars-backward "\n") @@ -888,7 +890,31 @@ comment: "; loose\n\n; on f\nfn f() -> ()\n a()\n; after f\n\n; on g\nfn g() -> ()\n"))) (test-flan-fln--is (format "under Evil, %s on %s keeps comments with their forms" (car c) (nth 1 c)) - (funcall deleted (car c) (nth 1 c)) (nth 2 c)))) + (funcall deleted (car c) (nth 1 c)) (nth 2 c))) + ;; A comment deeper than a form, at the end of its block, is + ;; that block's, not the next form's. + (dolist (c '(("dad" "fn a" "fn a() -> i64\n 1\n ; end of a\nfn b() -> i64\n 2\n" + "fn b() -> i64\n 2\n") + ("dad" "fn b" "fn a() -> i64\n 1\n ; end of a\nfn b() -> i64\n 2\n" + "fn a() -> i64\n 1\n ; end of a\n") + ("das" "let y" + "fn a(x: i64) -> i64\n if x > 0\n 1\n ; end of the if\n let y = 2\n y\n" + "fn a(x: i64) -> i64\n if x > 0\n 1\n ; end of the if\n y\n"))) + (let ((b (generate-new-buffer "owned.fln"))) + (switch-to-buffer b) + (insert (nth 2 c)) + (flan-fln-mode) + (evil-initialize-state) + (evil-normal-state) + (goto-char (point-min)) + (search-forward (nth 1 c)) + (goto-char (match-beginning 0)) + (execute-kbd-macro (car c)) + (test-flan-fln--is (format "under Evil, %s on %s: a deeper comment stays with the block above" + (car c) (nth 1 c)) + (buffer-string) (nth 3 c)) + (set-buffer-modified-p nil) + (kill-buffer b)))) (let ((b (generate-new-buffer "keys.fln"))) (switch-to-buffer b) (insert "fn f() -> i32 = 1\n")