From 385b1cad1be244b3b7b5e8cfa85b0f36bc367d9b Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 09:18:39 -0700 Subject: [PATCH 01/11] Whitespace cleanup Clean up tabs, indentation. --- fsharp-mode-indent-smie.el | 56 +++++++++++++++++++------------------- inf-fsharp-mode.el | 20 +++++++------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/fsharp-mode-indent-smie.el b/fsharp-mode-indent-smie.el index 29ef13d..460d234 100644 --- a/fsharp-mode-indent-smie.el +++ b/fsharp-mode-indent-smie.el @@ -30,42 +30,42 @@ :type 'integer) (defconst fsharp-smie-grammar - ;; SMIE grammar follow the refernce of SML-mode. + ;; SMIE grammar follow the refernce of SML-mode. (smie-prec2->grammar (smie-merge-prec2s (smie-bnf->prec2 '((id) (expr ("while" expr "do" expr) - ("if" expr "then" expr "else" expr) - ("for" expr "in" expr "do" expr) - ("for" expr "to" expr "do" expr) - ("try" expr "with" branches) - ("try" expr "finally" expr) - ("match" expr "with" branches) - ("type" expr "=" branches) - ("begin" exprs "end") - ("[" exprs "]") - ("[|" exprs "|]") - ("{" exprs "}") - ("<@" exprs "@>") - ("<@@" exprs "@@>") - ("let" sexp "=" expr) - ("fun" expr "->" expr)) + ("if" expr "then" expr "else" expr) + ("for" expr "in" expr "do" expr) + ("for" expr "to" expr "do" expr) + ("try" expr "with" branches) + ("try" expr "finally" expr) + ("match" expr "with" branches) + ("type" expr "=" branches) + ("begin" exprs "end") + ("[" exprs "]") + ("[|" exprs "|]") + ("{" exprs "}") + ("<@" exprs "@>") + ("<@@" exprs "@@>") + ("let" sexp "=" expr) + ("fun" expr "->" expr)) (sexp ("rec") - (sexp ":" type) - (sexp "||" sexp) - (sexp "&&" sexp) - ("(" exprs ")")) + (sexp ":" type) + (sexp "||" sexp) + (sexp "&&" sexp) + ("(" exprs ")")) (exprs (exprs ";" exprs) - (exprs "," exprs) - (expr)) + (exprs "," exprs) + (expr)) (type (type "->" type) - (type "*" type)) + (type "*" type)) (branches (branches "|" branches)) (decls (sexp "=" expr)) (toplevel (decls) - (expr) - (toplevel ";;" toplevel))) + (expr) + (toplevel ";;" toplevel))) '((assoc "|")) '((assoc "->") (assoc "*")) '((assoc "let" "fun" "type" "open" "->")) @@ -95,12 +95,12 @@ (`(:after . "in") 0) (`(:after . ,(or `"[" `"]" `"[|" `"|]")) fsharp-indent-level) (`(,_ . ,(or `";" `",")) (if (smie-rule-parent-p "begin") - 0 - (smie-rule-separator kind))) + 0 + (smie-rule-separator kind))) (`(:after . "=") fsharp-indent-level) (`(:after . ";;") (smie-rule-separator kind)) (`(:before . ";;") (if (smie-rule-bolp) - 0)) + 0)) )) diff --git a/inf-fsharp-mode.el b/inf-fsharp-mode.el index 13210d8..cbde6a0 100644 --- a/inf-fsharp-mode.el +++ b/inf-fsharp-mode.el @@ -87,17 +87,17 @@ be sent from another buffer in fsharp mode. "Launch fsi if needed, using CMD if supplied." (unless (comint-check-proc inferior-fsharp-buffer-name) (setq inferior-fsharp-program - (or cmd (read-from-minibuffer "fsharp toplevel to run: " - inferior-fsharp-program))) + (or cmd (read-from-minibuffer "fsharp toplevel to run: " + inferior-fsharp-program))) (let ((cmdlist (inferior-fsharp-args-to-list inferior-fsharp-program)) (process-connection-type nil)) (with-current-buffer (apply (function make-comint) inferior-fsharp-buffer-subname (car cmdlist) nil - (cdr cmdlist)) - (when (eq system-type 'windows-nt) - (set-process-coding-system (get-buffer-process (current-buffer)) - 'utf-8 'utf-8)) + (cdr cmdlist)) + (when (eq system-type 'windows-nt) + (set-process-coding-system (get-buffer-process (current-buffer)) + 'utf-8 'utf-8)) (inferior-fsharp-mode)) (display-buffer inferior-fsharp-buffer-name)))) @@ -139,13 +139,13 @@ Input and output via buffer `*inferior-fsharp*'." (previous-multiframe-window) (setq count (- count 1))) ) -) + ) (defun inferior-fsharp-eval-region (start end) "Send the current region to the inferior fsharp process." (interactive "r") (fsharp-run-process-if-needed) - ;; send location to fsi + ;; send location to fsi (let* ((name (file-truename (buffer-file-name (current-buffer)))) (dir (fsharp-ac--localname (file-name-directory name))) (line (number-to-string (line-number-at-pos start))) @@ -174,8 +174,8 @@ output can be retreived later, asynchronously.") "Insert the result of the evaluation of previous phrase" (interactive) (let ((pos (process-mark (get-buffer-process inferior-fsharp-buffer-name)))) - (insert-buffer-substring inferior-fsharp-buffer-name - fsharp-previous-output (- pos 2)))) + (insert-buffer-substring inferior-fsharp-buffer-name + fsharp-previous-output (- pos 2)))) (defun fsharp-simple-send (proc string) From 1074a3ddb5e94ce90e9f2debf186e49b27bd8438 Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 12:33:06 -0700 Subject: [PATCH 02/11] Merge `indent-smie` and `indent` These are two modules that do tightly related things. In two separate files, they can't cleanly share variables (`indent-smie` re-defined an indent offset var also defined in `indent`). This commit merges them together and re-names the variable used for offset by the `smie` configs, but does nothing else. --- fsharp-mode-indent-smie.el | 111 ------------------------------------- fsharp-mode-indent.el | 110 ++++++++++++++++++++++++++++++------ 2 files changed, 94 insertions(+), 127 deletions(-) delete mode 100644 fsharp-mode-indent-smie.el diff --git a/fsharp-mode-indent-smie.el b/fsharp-mode-indent-smie.el deleted file mode 100644 index 460d234..0000000 --- a/fsharp-mode-indent-smie.el +++ /dev/null @@ -1,111 +0,0 @@ -;;; fsharp-mode-indent-smie.el --- SMIE indentation for F# -*- lexical-binding: t; coding: utf-8 -*- - -;; Copyright (C) 2015 m00nlight Wang - -;; Author: 2015 m00nlight Wang - -;; This file is not part of GNU Emacs. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. - -;; This file is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to -;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. - -(require 'smie) - - -(defcustom fsharp-indent-level 4 - "Basic indentation step for fsharp mode" - :group 'fsharp - :type 'integer) - -(defconst fsharp-smie-grammar - ;; SMIE grammar follow the refernce of SML-mode. - (smie-prec2->grammar - (smie-merge-prec2s - (smie-bnf->prec2 - '((id) - (expr ("while" expr "do" expr) - ("if" expr "then" expr "else" expr) - ("for" expr "in" expr "do" expr) - ("for" expr "to" expr "do" expr) - ("try" expr "with" branches) - ("try" expr "finally" expr) - ("match" expr "with" branches) - ("type" expr "=" branches) - ("begin" exprs "end") - ("[" exprs "]") - ("[|" exprs "|]") - ("{" exprs "}") - ("<@" exprs "@>") - ("<@@" exprs "@@>") - ("let" sexp "=" expr) - ("fun" expr "->" expr)) - (sexp ("rec") - (sexp ":" type) - (sexp "||" sexp) - (sexp "&&" sexp) - ("(" exprs ")")) - (exprs (exprs ";" exprs) - (exprs "," exprs) - (expr)) - (type (type "->" type) - (type "*" type)) - (branches (branches "|" branches)) - (decls (sexp "=" expr)) - (toplevel (decls) - (expr) - (toplevel ";;" toplevel))) - '((assoc "|")) - '((assoc "->") (assoc "*")) - '((assoc "let" "fun" "type" "open" "->")) - '((assoc "let") (assoc "=")) - '((assoc "[" "]" "[|" "|]" "{" "}")) - '((assoc "<@" "@>")) - '((assoc "<@@" "@@>")) - '((assoc "&&") (assoc "||") (noassoc ":")) - '((assoc ";") (assoc ",")) - '((assoc ";;"))) - (smie-precs->prec2 - '((nonassoc (">" ">=" "<>" "<" "<=" "=")) - (assoc "::") - (assoc "+" "-" "^") - (assoc "/" "*" "%"))))) - ) - -(defun fsharp-smie-rules (kind token) - (pcase (cons kind token) - (`(:elem . basic) fsharp-indent-level) - (`(:after . "do") fsharp-indent-level) - (`(:after . "then") fsharp-indent-level) - (`(:after . "else") fsharp-indent-level) - (`(:after . "try") fsharp-indent-level) - (`(:after . "with") fsharp-indent-level) - (`(:after . "finally") fsharp-indent-level) - (`(:after . "in") 0) - (`(:after . ,(or `"[" `"]" `"[|" `"|]")) fsharp-indent-level) - (`(,_ . ,(or `";" `",")) (if (smie-rule-parent-p "begin") - 0 - (smie-rule-separator kind))) - (`(:after . "=") fsharp-indent-level) - (`(:after . ";;") (smie-rule-separator kind)) - (`(:before . ";;") (if (smie-rule-bolp) - 0)) - )) - - -(defun fsharp-mode-indent-smie-setup () - (smie-setup fsharp-smie-grammar #'fsharp-smie-rules)) - - -(provide 'fsharp-mode-indent-smie) diff --git a/fsharp-mode-indent.el b/fsharp-mode-indent.el index 67c7672..216ff5e 100644 --- a/fsharp-mode-indent.el +++ b/fsharp-mode-indent.el @@ -26,9 +26,9 @@ (require 'comint) (require 'custom) (require 'compile) -(require 'fsharp-mode) +(require 'smie) + - ;; user definable variables ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv @@ -448,11 +448,11 @@ This function is normally bound to `indent-line-function' so move-to-indentation-p) (progn (if (/= ci need) (save-excursion - (beginning-of-line) - (delete-horizontal-space) - (indent-to need))) + (beginning-of-line) + (delete-horizontal-space) + (indent-to need))) (if move-to-indentation-p (back-to-indentation))) - (insert-tab)))))) + (insert-tab)))))) (defun fsharp-newline-and-indent () "Strives to act like the Emacs `newline-and-indent'. @@ -925,7 +925,7 @@ NOMARK is not nil." (fsharp-goto-initial-line) ;; if on and (mutually recursive bindings), blank or non-indenting comment line, use the preceding stmt (when (or (looking-at "[ \t]*\\($\\|//[^ \t\n]\\)") - (looking-at-p "[ \t]*and[ \t]+")) + (looking-at-p "[ \t]*and[ \t]+")) (fsharp-goto-statement-at-or-above) (setq found (fsharp-statement-opens-block-p))) ;; search back for colon line indented less @@ -1573,8 +1573,7 @@ This tells add-log.el how to find the current function/method/variable." nil scopes)))) - -;;; fsharp-mode.el ends here + (defun fsharp-eval-phrase () "Send current phrase to the interactive mode" (interactive) @@ -1607,11 +1606,11 @@ This tells add-log.el how to find the current function/method/variable." (interactive) (let ((prev (point))) (condition-case nil - (while (progn (fsharp-goto-block-up 'no-mark) - (< (point) prev)) - (setq prev (point))) + (while (progn (fsharp-goto-block-up 'no-mark) + (< (point) prev)) + (setq prev (point))) (error (while (continuation-p) - (forward-line -1))))) + (forward-line -1))))) (beginning-of-line)) (defun fsharp-end-of-block () @@ -1629,11 +1628,90 @@ This tells add-log.el how to find the current function/method/variable." (error (progn (goto-char (point-max))))) (end-of-line) - (when (looking-at-p "\n[ \t]*and[ \t]+") - (forward-line 1) - (fsharp-end-of-block))) + (when (looking-at-p "\n[ \t]*and[ \t]+") + (forward-line 1) + (fsharp-end-of-block))) (goto-char (point-max)))) +(defconst fsharp-smie-grammar + ;; SMIE grammar follow the refernce of SML-mode. + (smie-prec2->grammar + (smie-merge-prec2s + (smie-bnf->prec2 + '((id) + (expr ("while" expr "do" expr) + ("if" expr "then" expr "else" expr) + ("for" expr "in" expr "do" expr) + ("for" expr "to" expr "do" expr) + ("try" expr "with" branches) + ("try" expr "finally" expr) + ("match" expr "with" branches) + ("type" expr "=" branches) + ("begin" exprs "end") + ("[" exprs "]") + ("[|" exprs "|]") + ("{" exprs "}") + ("<@" exprs "@>") + ("<@@" exprs "@@>") + ("let" sexp "=" expr) + ("fun" expr "->" expr)) + (sexp ("rec") + (sexp ":" type) + (sexp "||" sexp) + (sexp "&&" sexp) + ("(" exprs ")")) + (exprs (exprs ";" exprs) + (exprs "," exprs) + (expr)) + (type (type "->" type) + (type "*" type)) + (branches (branches "|" branches)) + (decls (sexp "=" expr)) + (toplevel (decls) + (expr) + (toplevel ";;" toplevel))) + '((assoc "|")) + '((assoc "->") (assoc "*")) + '((assoc "let" "fun" "type" "open" "->")) + '((assoc "let") (assoc "=")) + '((assoc "[" "]" "[|" "|]" "{" "}")) + '((assoc "<@" "@>")) + '((assoc "<@@" "@@>")) + '((assoc "&&") (assoc "||") (noassoc ":")) + '((assoc ";") (assoc ",")) + '((assoc ";;"))) + (smie-precs->prec2 + '((nonassoc (">" ">=" "<>" "<" "<=" "=")) + (assoc "::") + (assoc "+" "-" "^") + (assoc "/" "*" "%"))))) + ) + +(defun fsharp-smie-rules (kind token) + (pcase (cons kind token) + (`(:elem . basic) fsharp-indent-offset) + (`(:after . "do") fsharp-indent-offset) + (`(:after . "then") fsharp-indent-offset) + (`(:after . "else") fsharp-indent-offset) + (`(:after . "try") fsharp-indent-offset) + (`(:after . "with") fsharp-indent-offset) + (`(:after . "finally") fsharp-indent-offset) + (`(:after . "in") 0) + (`(:after . ,(or `"[" `"]" `"[|" `"|]")) fsharp-indent-offset) + (`(,_ . ,(or `";" `",")) (if (smie-rule-parent-p "begin") + 0 + (smie-rule-separator kind))) + (`(:after . "=") fsharp-indent-offset) + (`(:after . ";;") (smie-rule-separator kind)) + (`(:before . ";;") (if (smie-rule-bolp) + 0)) + )) + + +(defun fsharp-mode-indent-smie-setup () + (smie-setup fsharp-smie-grammar #'fsharp-smie-rules)) + + (provide 'fsharp-mode-indent) ;;; fsharp-mode-indent.el ends here From e5f8dd70f9ae8fdf1df763170bda69b6206d1996 Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 12:37:32 -0700 Subject: [PATCH 03/11] Alias now-removed fsharp-indent-level --- fsharp-mode-indent.el | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fsharp-mode-indent.el b/fsharp-mode-indent.el index 216ff5e..d495c43 100644 --- a/fsharp-mode-indent.el +++ b/fsharp-mode-indent.el @@ -45,6 +45,12 @@ you're editing someone else's Fsharp code." :type 'integer :group 'fsharp) +(defalias 'fsharp-indent-level 'fsharp-indent-offset + "Backwards-compatibility alias. `fsharp-indent-level' was + configuring the same thing as `fsharp-indent-offset', but less + clearly and in a different file, and free from update by + functions like offset-guessing.") + (defcustom fsharp-continuation-offset 4 "*Additional amount of offset to give for some continuation lines. Continuation lines are those that immediately follow a backslash From eee6bdfb6b98c90ec805979a75708e00c659e1ed Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 12:43:41 -0700 Subject: [PATCH 04/11] Rename `fsharp-mode-indent` to `fsharp-mode-structure` and clean up This commit renames `fsharp-mode-indent` and cleans up references to it. It also scoots `fsharp-eval-phrase` next to `fsharp-eval-region` in `fsharp-mode`, where it makes a bit more sense. Tests are all currently passing. --- ...mode-indent.el => fsharp-mode-structure.el | 19 +++---------------- fsharp-mode.el | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 18 deletions(-) rename fsharp-mode-indent.el => fsharp-mode-structure.el (99%) diff --git a/fsharp-mode-indent.el b/fsharp-mode-structure.el similarity index 99% rename from fsharp-mode-indent.el rename to fsharp-mode-structure.el index d495c43..bfb0c62 100644 --- a/fsharp-mode-indent.el +++ b/fsharp-mode-structure.el @@ -1,4 +1,4 @@ -;;; fsharp-mode-indent.el --- Indentation for F# +;;; fsharp-mode-indent.el --- Stucture Definition, Mark, and Motion for F# ;; Copyright (C) 2010 Laurent Le Brun @@ -1579,18 +1579,6 @@ This tells add-log.el how to find the current function/method/variable." nil scopes)))) - -(defun fsharp-eval-phrase () - "Send current phrase to the interactive mode" - (interactive) - (save-excursion - (let ((p1) (p2)) - (fsharp-beginning-of-block) - (setq p1 (point)) - (fsharp-end-of-block) - (setq p2 (point)) - (fsharp-eval-region p1 p2)))) - (defun fsharp-mark-phrase () "Mark current phrase" (interactive) @@ -1718,6 +1706,5 @@ This tells add-log.el how to find the current function/method/variable." (smie-setup fsharp-smie-grammar #'fsharp-smie-rules)) -(provide 'fsharp-mode-indent) - -;;; fsharp-mode-indent.el ends here +(provide 'fsharp-mode-structure) +;;; fsharp-mode-structure.el ends here diff --git a/fsharp-mode.el b/fsharp-mode.el index aa2e62f..ade23e0 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -29,13 +29,13 @@ ;;; Code: (require 'fsharp-mode-completion) +(require 'fsharp-mode-structure) (require 'flycheck-fsharp) (require 'fsharp-doc) (require 'inf-fsharp-mode) (require 'fsharp-mode-util) (require 'compile) (require 'dash) -(require 'fsharp-mode-indent-smie) (defgroup fsharp nil "Support for the Fsharp programming language, " @@ -194,7 +194,6 @@ \\{fsharp-mode-map}" - (require 'fsharp-mode-indent) (require 'fsharp-mode-font) (require 'fsharp-doc) (require 'fsharp-mode-completion) @@ -322,6 +321,17 @@ Otherwise, treat as a stand-alone file." (require 'inf-fsharp-mode) (inferior-fsharp-eval-region start end)) +(defun fsharp-eval-phrase () + "Send current phrase to the interactive mode" + (interactive) + (save-excursion + (let ((p1) (p2)) + (fsharp-beginning-of-block) + (setq p1 (point)) + (fsharp-end-of-block) + (setq p2 (point)) + (fsharp-eval-region p1 p2)))) + (defun fsharp-load-buffer-file () "Load the filename corresponding to the present buffer in F# with #load" (interactive) From 91c0ace33c72eabad1502836976aa97c58626235 Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 12:50:35 -0700 Subject: [PATCH 05/11] So Much Whitespace Cleanup --- flycheck-fsharp.el | 34 +++---- fsharp-mode-completion.el | 206 +++++++++++++++++++------------------- fsharp-mode-util.el | 10 +- 3 files changed, 125 insertions(+), 125 deletions(-) diff --git a/flycheck-fsharp.el b/flycheck-fsharp.el index 3e111f6..10f4240 100644 --- a/flycheck-fsharp.el +++ b/flycheck-fsharp.el @@ -40,30 +40,30 @@ (defun flycheck-verify-fsautocomlete (_checker) "Verify the F# syntax checker." (let* ((host (fsharp-ac--hostname (buffer-file-name))) - (process (fsharp-ac-completion-process host)) - (status (when process (process-status process))) - (project-file (when (eq status 'run) (fsharp-ac--in-project-p (buffer-file-name)))) - (projects (when (eq status 'run) (hash-table-keys fsharp-ac--project-data))) - (command (when process (combine-and-quote-strings (process-command process))))) + (process (fsharp-ac-completion-process host)) + (status (when process (process-status process))) + (project-file (when (eq status 'run) (fsharp-ac--in-project-p (buffer-file-name)))) + (projects (when (eq status 'run) (hash-table-keys fsharp-ac--project-data))) + (command (when process (combine-and-quote-strings (process-command process))))) (cons (flycheck-verification-result-new :label "FSharp.AutoComplete process" :message (cond - ((eq status 'run) command) - (status (format "Invalid process status: %s (%s)" command status)) - ("not running")) + ((eq status 'run) command) + (status (format "Invalid process status: %s (%s)" command status)) + ("not running")) :face (if (eq status 'run) 'success '(bold error))) (when (eq status 'run) (list (flycheck-verification-result-new - :label "F# Project" - :message (or project-file "None") - :face (if project-file 'success '(bold warning))) - (flycheck-verification-result-new - :label "Loaded Projects" - :message (if projects - (mapconcat #'identity projects ", ") - "No projects loaded") - :face (if projects 'success '(bold warning)))))))) + :label "F# Project" + :message (or project-file "None") + :face (if project-file 'success '(bold warning))) + (flycheck-verification-result-new + :label "Loaded Projects" + :message (if projects + (mapconcat #'identity projects ", ") + "No projects loaded") + :face (if projects 'success '(bold warning)))))))) (defun flycheck-fsharp-fsautocomplete-lint-start (checker callback) "Start a F# syntax check with CHECKER. diff --git a/fsharp-mode-completion.el b/fsharp-mode-completion.el index e8c24b2..5547497 100644 --- a/fsharp-mode-completion.el +++ b/fsharp-mode-completion.el @@ -85,7 +85,7 @@ If set to nil, display in a help buffer instead.") (defun fsharp-ac-completion-process-del (host) (setq fsharp-ac-completion-process-alist - (delq (assoc host fsharp-ac-completion-process-alist) fsharp-ac-completion-process-alist))) + (delq (assoc host fsharp-ac-completion-process-alist) fsharp-ac-completion-process-alist))) (defvar fsharp-ac--project-data (make-hash-table :test 'equal) "Data returned by fsautocomplete for loaded projects.") @@ -199,7 +199,7 @@ If FILENAME is not a Tramp filename return nil" If FILENAME is not a Tramp filename return FILENAME" (if (tramp-tramp-file-p file) (with-parsed-tramp-file-name file nil - localname) + localname) file)) (defun fsharp-ac--tramp-file (file) @@ -209,7 +209,7 @@ When completion process is not started on a remote location return FILE. This function should always be evaluated in the process-buffer!" (if (tramp-tramp-file-p default-directory) (concat (file-remote-p default-directory) file) - file)) + file)) ;;; ---------------------------------------------------------------------------- ;;; File Parsing and loading @@ -218,12 +218,12 @@ This function should always be evaluated in the process-buffer!" "Get the truename of BUF, or the current buffer by default. For indirect buffers return the truename of the base buffer." (-some-> (buffer-file-name (or (buffer-base-buffer buf) buf)) - (file-truename))) + (file-truename))) (defun fsharp-ac/load-project (file) "Load the specified fsproj FILE as a project." (interactive - ;; Prompt user for an fsproj, searching for a default. + ;; Prompt user for an fsproj, searching for a default. (let* ((proj (fsharp-mode/find-fsproj buffer-file-name)) (relproj (when proj (file-relative-name proj (file-name-directory buffer-file-name)))) (prompt (if relproj (format "Path to project (default %s): " relproj) @@ -237,12 +237,12 @@ For indirect buffers return the truename of the base buffer." ;; Load given project. (when (fsharp-ac--process-live-p (fsharp-ac--hostname file)) (log-psendstr (fsharp-ac-completion-process (fsharp-ac--hostname file)) - (format "project \"%s\"%s\n" - (fsharp-ac--localname (file-truename file)) - (if (and (numberp fsharp-ac-debug) - (>= fsharp-ac-debug 2)) - " verbose" - "")))) + (format "project \"%s\"%s\n" + (fsharp-ac--localname (file-truename file)) + (if (and (numberp fsharp-ac-debug) + (>= fsharp-ac-debug 2)) + " verbose" + "")))) file)) (defun fsharp-ac/load-file (file) @@ -282,9 +282,9 @@ Return nil if FILE is not part of a F# project." (clrhash fsharp-ac-current-helptext) (let (files projects) (maphash (lambda (file project) (when (equal (fsharp-ac--hostname file) (fsharp-ac--hostname default-directory)) - (push file files) - (push project projects))) - fsharp-ac--project-files) + (push file files) + (push project projects))) + fsharp-ac--project-files) (--each projects (remhash it fsharp-ac--project-files)) (--each files (remhash it fsharp-ac--project-files)))) @@ -332,43 +332,43 @@ If HOST is nil, check process on local system." "Default sentinel used by `fsharp-ac--configure-proc`." (when (memq (process-status process) '(exit signal)) (--each (buffer-list) (with-current-buffer it - (when (eq major-mode 'fsharp-mode) - (setq fsharp-ac-last-parsed-ticks 0) - (fsharp-ac--clear-symbol-uses)))) + (when (eq major-mode 'fsharp-mode) + (setq fsharp-ac-last-parsed-ticks 0) + (fsharp-ac--clear-symbol-uses)))) (fsharp-ac--reset))) (defun fsharp-ac--configure-proc () (let* ((fsac (if (tramp-tramp-file-p default-directory) - (concat (file-remote-p default-directory) (car (last fsharp-ac-complete-command))) - (car (last fsharp-ac-complete-command)))) - (process-environment - (if (null fsharp-ac-using-mono) - process-environment - ;; workaround for Mono = 4.2.1 thread pool bug - ;; https://bugzilla.xamarin.com/show_bug.cgi?id=37288 - (let ((x (getenv "MONO_THREADS_PER_CPU"))) - (if (or (null x) - (< (string-to-number x) 8)) - (cons "MONO_THREADS_PER_CPU=8" process-environment) - process-environment)))) - process-connection-type) + (concat (file-remote-p default-directory) (car (last fsharp-ac-complete-command))) + (car (last fsharp-ac-complete-command)))) + (process-environment + (if (null fsharp-ac-using-mono) + process-environment + ;; workaround for Mono = 4.2.1 thread pool bug + ;; https://bugzilla.xamarin.com/show_bug.cgi?id=37288 + (let ((x (getenv "MONO_THREADS_PER_CPU"))) + (if (or (null x) + (< (string-to-number x) 8)) + (cons "MONO_THREADS_PER_CPU=8" process-environment) + process-environment)))) + process-connection-type) (if (file-exists-p fsac) - (let ((proc (apply 'start-file-process - fsharp-ac--completion-procname - (get-buffer-create (generate-new-buffer-name " *fsharp-complete*")) - fsharp-ac-complete-command))) - (sleep-for 0.1) - (if (process-live-p proc) - (progn - (set-process-sentinel proc #'fsharp-ac--process-sentinel) - (set-process-coding-system proc 'utf-8-auto) - (set-process-filter proc 'fsharp-ac-filter-output) - (set-process-query-on-exit-flag proc nil) - (with-current-buffer (process-buffer proc) - (delete-region (point-min) (point-max))) - proc) - (error "Failed to launch: '%s'" (s-join " " fsharp-ac-complete-command)) - nil)) + (let ((proc (apply 'start-file-process + fsharp-ac--completion-procname + (get-buffer-create (generate-new-buffer-name " *fsharp-complete*")) + fsharp-ac-complete-command))) + (sleep-for 0.1) + (if (process-live-p proc) + (progn + (set-process-sentinel proc #'fsharp-ac--process-sentinel) + (set-process-coding-system proc 'utf-8-auto) + (set-process-filter proc 'fsharp-ac-filter-output) + (set-process-query-on-exit-flag proc nil) + (with-current-buffer (process-buffer proc) + (delete-region (point-min) (point-max))) + proc) + (error "Failed to launch: '%s'" (s-join " " fsharp-ac-complete-command)) + nil)) (error "%s not found" fsac)))) (defun fsharp-ac-document (item) @@ -383,7 +383,7 @@ If HOST is nil, check process on local system." (accept-process-output (fsharp-ac-completion-process (fsharp-ac--hostname default-directory)) 0 100)) (gethash key fsharp-ac-current-helptext "Loading documentation...")))) - help))) + help))) (defun fsharp-ac-make-completion-request () (interactive) @@ -395,10 +395,10 @@ If HOST is nil, check process on local system." (setq fsharp-ac-last-parsed-line line) (fsharp-ac-parse-current-buffer)) (fsharp-ac-send-pos-request - "completion" - (fsharp-ac--buffer-truename) - (line-number-at-pos) - (+ 1 (current-column))))) + "completion" + (fsharp-ac--buffer-truename) + (line-number-at-pos) + (+ 1 (current-column))))) (require 'cl-lib) @@ -409,7 +409,7 @@ If HOST is nil, check process on local system." (setq fsharp-ac-status 'idle)) (if (and (fsharp-ac-can-make-request t) - (eq fsharp-ac-status 'idle)) + (eq fsharp-ac-status 'idle)) (progn (setq fsharp-company-callback callback) (fsharp-ac-make-completion-request)) @@ -421,7 +421,7 @@ If HOST is nil, check process on local system." (defun fsharp-ac-completion-done () (->> (--map (let ((s (gethash "Name" it))) (if (fsharp-ac--isNormalId s) (fsharp-ac-add-annotation-prop s it) - (s-append "``" (s-prepend "``" (fsharp-ac-add-annotation-prop s it))))) + (s-append "``" (s-prepend "``" (fsharp-ac-add-annotation-prop s it))))) fsharp-ac-current-candidate) (funcall fsharp-company-callback))) @@ -436,28 +436,28 @@ If HOST is nil, check process on local system." (buffer-substring-no-properties (fsharp-ac--residue) (point)))) (defun fsharp-ac/company-backend (command &optional arg &rest ignored) - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'fsharp-ac/company-backend)) - (prefix (when (not (company-in-string-or-comment)) - ;; Don't pass to next backend if we are not inside a string or comment - (-if-let (prefix (fsharp-ac-get-prefix)) - (cons prefix t) - 'stop))) - (ignore-case t) - (sorted t) - (candidates (cons :async 'fsharp-company-candidates)) - (annotation (get-text-property 0 'annotation arg)) - (doc-buffer (company-doc-buffer (fsharp-ac-document arg))))) + (interactive (list 'interactive)) + (cl-case command + (interactive (company-begin-backend 'fsharp-ac/company-backend)) + (prefix (when (not (company-in-string-or-comment)) + ;; Don't pass to next backend if we are not inside a string or comment + (-if-let (prefix (fsharp-ac-get-prefix)) + (cons prefix t) + 'stop))) + (ignore-case t) + (sorted t) + (candidates (cons :async 'fsharp-company-candidates)) + (annotation (get-text-property 0 'annotation arg)) + (doc-buffer (company-doc-buffer (fsharp-ac-document arg))))) (defconst fsharp-ac--ident (rx (one-or-more (not (any ".` ,(\t\r\n")))) "Regexp for normal identifiers.") -; Note that this regexp is not 100% correct. -; Allowable characters are defined using unicode -; character classes, so this will match some very -; unusual strings composed of rare unicode chars. + ; Note that this regexp is not 100% correct. + ; Allowable characters are defined using unicode + ; character classes, so this will match some very + ; unusual strings composed of rare unicode chars. (defconst fsharp-ac--rawIdent (rx (seq "``" @@ -500,12 +500,12 @@ If HOST is nil, check process on local system." (defun fsharp-ac--residue () (let ((line (buffer-substring-no-properties (line-beginning-position) (point)))) - (- (point) - (cadr - (-min-by 'car-less-than-car - (--map (or (-map 'length (s-match it line)) '(0 0)) - (list fsharp-ac--dottedIdentRawResidue - fsharp-ac--dottedIdentNormalResidue))))))) + (- (point) + (cadr + (-min-by 'car-less-than-car + (--map (or (-map 'length (s-match it line)) '(0 0)) + (list fsharp-ac--dottedIdentRawResidue + fsharp-ac--dottedIdentNormalResidue))))))) (defun fsharp-ac-can-make-request (&optional quiet) "Test whether it is possible to make a request with the compiler binding. @@ -607,15 +607,15 @@ prevent usage errors being displayed by FSHARP-DOC-MODE." (save-match-data (--map (let ((beg (fsharp-ac-line-column-to-pos (gethash "StartLine" it) - (gethash "StartColumn" it))) - (end (fsharp-ac-line-column-to-pos (gethash "EndLine" it) - (gethash "EndColumn" it))) - (face 'fsharp-usage-face) - (file (fsharp-ac--tramp-file (gethash "FileName" it)))) + (gethash "StartColumn" it))) + (end (fsharp-ac-line-column-to-pos (gethash "EndLine" it) + (gethash "EndColumn" it))) + (face 'fsharp-usage-face) + (file (fsharp-ac--tramp-file (gethash "FileName" it)))) (make-fsharp-symbol-use :start beg - :end end - :face face - :file file)) + :end end + :face face + :file file)) data))) (defun fsharp-ac/show-symbol-use-overlay (use) @@ -650,7 +650,7 @@ prevent usage errors being displayed by FSHARP-DOC-MODE." (defun fsharp-ac/usage-overlay-at (pos) (--first (fsharp-ac--has-faces-p it 'fsharp-usage-face) - (overlays-at pos))) + (overlays-at pos))) ;;; ---------------------------------------------------------------------------- ;;; Process handling @@ -679,8 +679,8 @@ prevent usage errors being displayed by FSHARP-DOC-MODE." (delete-region (point-min) (1+ (point)))) (error (fsharp-ac--log "Malformed JSON: %s" (buffer-substring-no-properties (point-min) (point-max))) - (delete-region (point-min) eofloc) - (fsharp-ac--get-msg proc))))))) + (delete-region (point-min) eofloc) + (fsharp-ac--get-msg proc))))))) (defun fsharp-ac-filter-output (proc str) "Filter STR from the completion process PROC and handle appropriately." @@ -689,8 +689,8 @@ prevent usage errors being displayed by FSHARP-DOC-MODE." (goto-char (process-mark proc)) ;; Remove BOM, if present (insert-before-markers (if (string-prefix-p "\ufeff" str) - (substring str 1) - str)))) + (substring str 1) + str)))) (let (msg) (while (and (setq msg (fsharp-ac--get-msg proc)) (/= (hash-table-count msg) 0)) @@ -700,18 +700,18 @@ prevent usage errors being displayed by FSHARP-DOC-MODE." kind (hash-table-count msg)) (pcase kind - ("error" (fsharp-ac-handle-process-error data)) - ("info" (when fsharp-ac-verbose (fsharp-ac-message-safely data))) - ("completion" (fsharp-ac-handle-completion data)) - ("helptext" (fsharp-ac-handle-doctext data)) - ("lint" (funcall fsharp-ac-handle-lint-function data)) - ("errors" (funcall fsharp-ac-handle-errors-function data)) - ("project" (fsharp-ac-handle-project data)) - ("tooltip" (fsharp-ac-handle-tooltip data)) - ("typesig" (fsharp-ac--handle-typesig data)) - ("finddecl" (fsharp-ac-visit-definition data)) - ("symboluse" (fsharp-ac--handle-symboluse data)) - (_ (fsharp-ac-message-safely "Error: unrecognised message kind: '%s'" kind))))))) + ("error" (fsharp-ac-handle-process-error data)) + ("info" (when fsharp-ac-verbose (fsharp-ac-message-safely data))) + ("completion" (fsharp-ac-handle-completion data)) + ("helptext" (fsharp-ac-handle-doctext data)) + ("lint" (funcall fsharp-ac-handle-lint-function data)) + ("errors" (funcall fsharp-ac-handle-errors-function data)) + ("project" (fsharp-ac-handle-project data)) + ("tooltip" (fsharp-ac-handle-tooltip data)) + ("typesig" (fsharp-ac--handle-typesig data)) + ("finddecl" (fsharp-ac-visit-definition data)) + ("symboluse" (fsharp-ac--handle-symboluse data)) + (_ (fsharp-ac-message-safely "Error: unrecognised message kind: '%s'" kind))))))) (defun fsharp-ac-handle-completion (data) (setq fsharp-ac-current-candidate data @@ -747,8 +747,8 @@ prevent usage errors being displayed by FSHARP-DOC-MODE." (defun fsharp-ac--format-tooltip (items) "Format a list of items as a tooltip" (let ((result (s-join "\n--------------------\n" - (--map (fsharp-ac--format-tooltip-overloads (< (length items) 2) it) items)))) - (s-chomp result))) + (--map (fsharp-ac--format-tooltip-overloads (< (length items) 2) it) items)))) + (s-chomp result))) (defun fsharp-ac--handle-symboluse (data) (when (eq major-mode 'fsharp-mode) diff --git a/fsharp-mode-util.el b/fsharp-mode-util.el index d484eee..416ddd3 100644 --- a/fsharp-mode-util.el +++ b/fsharp-mode-util.el @@ -44,11 +44,11 @@ for all *nix.") (defun fsharp-mode--vs2017-msbuild-find (exe) "Return EXE absolute path for Visual Studio 2017, if existent, else nil." (->> (--map (concat (fsharp-mode--program-files-x86) - "Microsoft Visual Studio/2017/" - it - "msbuild/15.0/bin/" - exe) - '("Enterprise/" "Professional/" "Community/" "BuildTools/")) + "Microsoft Visual Studio/2017/" + it + "msbuild/15.0/bin/" + exe) + '("Enterprise/" "Professional/" "Community/" "BuildTools/")) (--first (file-executable-p it)))) (defun fsharp-mode--msbuild-find (exe) From 151579312a9a252562e4d338fcd9c0cdf06df61e Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 13:07:09 -0700 Subject: [PATCH 06/11] A little extra commentary, attributions --- fsharp-mode-structure.el | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el index bfb0c62..47a36a2 100644 --- a/fsharp-mode-structure.el +++ b/fsharp-mode-structure.el @@ -23,14 +23,23 @@ ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. +;;; Commentary: +;; This module defines variables and functions related to the structure of F# +;; code, and motion around and through that code. SMIE is used to set certain +;; default configurations. +;; +;; SMIE configs by m00nlight Wang , 2015 +;; Last major update by Ross Donaldson <@gastove>, 2019 + +;;; Code: + (require 'comint) (require 'custom) (require 'compile) (require 'smie) +;;-------------------------- Customization Variables --------------------------;; -;; user definable variables -;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv (defcustom fsharp-tab-always-indent t "*Non-nil means TAB in Fsharp mode should always reindent the current line, From 56e5a4bf4f86c58a4ee5080be00e11adced57912 Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 13:11:59 -0700 Subject: [PATCH 07/11] Move var, remove old stuff This commit removes some old "major mode boilerplate" from `fsharp-mode-structure`: - The abbrev table is moved in to `fsharp-mode`, where it belongs. - `fsharp-safe` is _only_ used to wrap calls to `search-backwards`; the only value it provides is to swallow errors and instead return `nil`. However: this can now be much more idiomatically achieved by passing `t` as the `NOERROR` argument to `search-backward`. - XEmacs hasn't had a release in ten years. The extra region setting calls of `fsharp-keep-region-active` aren't needed -- it's just extra noise. --- fsharp-mode-structure.el | 46 +++++++++------------------------------- fsharp-mode.el | 5 +++++ 2 files changed, 15 insertions(+), 36 deletions(-) diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el index 47a36a2..7db8f33 100644 --- a/fsharp-mode-structure.el +++ b/fsharp-mode-structure.el @@ -223,31 +223,6 @@ as indentation hints, unless the comment character is in column zero." "\\)") "Regular expression matching expressions which begin a block") - -;; Major mode boilerplate - -;; define a mode-specific abbrev table for those who use such things -(defvar fsharp-mode-abbrev-table nil - "Abbrev table in use in `fsharp-mode' buffers.") -(define-abbrev-table 'fsharp-mode-abbrev-table nil) - - - -;; Utilities -(defmacro fsharp-safe (&rest body) - "Safely execute BODY, return nil if an error occurred." - `(condition-case nil - (progn ,@ body) - (error nil))) - - -(defsubst fsharp-keep-region-active () - "Keep the region active in XEmacs." - ;; Ignore byte-compiler warnings you might see. Also note that - ;; FSF's Emacs 19 does it differently; its policy doesn't require us - ;; to take explicit action. - (and (boundp 'zmacs-region-stays) - (setq zmacs-region-stays t))) (defsubst fsharp-point (position) "Returns the value of point at certain commonly referenced POSITIONs. @@ -784,8 +759,8 @@ You cannot dedent the region if any line is already at column zero." (error "Region is at left edge")) (forward-line 1))) (fsharp-shift-region start end (- (prefix-numeric-value - (or count fsharp-indent-offset)))) - (fsharp-keep-region-active)) + (or count fsharp-indent-offset))))) + (defun fsharp-shift-region-right (start end &optional count) "Shift region of Fsharp code to the right. @@ -803,8 +778,8 @@ many columns. With no active region, indent only the current line." (list (min p m) (max p m) arg) (list p (save-excursion (forward-line 1) (point)) arg)))) (fsharp-shift-region start end (prefix-numeric-value - (or count fsharp-indent-offset))) - (fsharp-keep-region-active)) + (or count fsharp-indent-offset)))) + (defun fsharp-indent-region (start end &optional indent-offset) "Reindent a region of Fsharp code. @@ -1261,10 +1236,8 @@ pleasant." (forward-line 1)) ;; no comment, so go back (goto-char start))))))) - (exchange-point-and-mark) - (fsharp-keep-region-active)) + (exchange-point-and-mark)) - (require 'info-look) ;; The info-look package does not always provide this function (it @@ -1356,14 +1329,14 @@ for." (when skip (save-excursion (while continue - (fsharp-safe (search-backward skip)) + (search-backward skip nil t) (setq continue (and (not (bobp)) (= (char-before) ?\\)))) (if (and (= (char-before) delim) (= (char-before (1- (point))) delim)) (setq skip (make-string 3 delim)))) ;; we're looking at a triple-quoted string - (fsharp-safe (search-backward skip))))) + (search-backward skip nil t)))) (defun fsharp-goto-initial-line () "Go to the initial line of the current statement. @@ -1588,14 +1561,15 @@ This tells add-log.el how to find the current function/method/variable." nil scopes)))) + (defun fsharp-mark-phrase () "Mark current phrase" (interactive) (fsharp-beginning-of-block) (push-mark (point)) (fsharp-end-of-block) - (exchange-point-and-mark) - (fsharp-keep-region-active)) + (exchange-point-and-mark)) + (defun continuation-p () "Return t iff preceding line is not a finished expression (ends with an operator)" diff --git a/fsharp-mode.el b/fsharp-mode.el index ade23e0..9c64598 100644 --- a/fsharp-mode.el +++ b/fsharp-mode.el @@ -66,6 +66,11 @@ (defvar fsharp-run-executable-file-history nil "History of executable commands run.") +;; define a mode-specific abbrev table for those who use such things +(defvar fsharp-mode-abbrev-table nil + "Abbrev table in use in `fsharp-mode' buffers.") +(define-abbrev-table 'fsharp-mode-abbrev-table nil) + (unless fsharp-mode-map (setq fsharp-mode-map (make-sparse-keymap)) (if running-xemacs From 00785f0f9f70710ad6459219091bdc81ef46bbe1 Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 13:24:53 -0700 Subject: [PATCH 08/11] Clear out commented-out code, ^Ls --- fsharp-mode-structure.el | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el index 7db8f33..8504a4b 100644 --- a/fsharp-mode-structure.el +++ b/fsharp-mode-structure.el @@ -131,8 +131,8 @@ as indentation hints, unless the comment character is in column zero." :type 'function :group 'fsharp) - -;; Constants + +;;--------------------------------- Constants ---------------------------------;; (defconst fsharp-stringlit-re (concat @@ -157,10 +157,6 @@ as indentation hints, unless the comment character is in column zero." (defconst fsharp-continued-re ;; This is tricky because a trailing backslash does not mean ;; continuation if it's in a comment - ;; (concat - ;; "\\(" "[^#'\"\n\\]" "\\|" fsharp-stringlit-re "\\)*" - ;; "\\\\$") - ;; "Regular expression matching Fsharp backslash continuation lines.") (concat ".*\\(" (mapconcat 'identity '("+" "-" "*" "/") "\\|") @@ -168,7 +164,6 @@ as indentation hints, unless the comment character is in column zero." "Regular expression matching unterminated expressions.") - ;(defconst fsharp-blank-or-comment-re "[ \t]*\\($\\|#\\)" (defconst fsharp-blank-or-comment-re "[ \t]*\\(//.*\\)?" "Regular expression matching a blank or comment line.") @@ -270,7 +265,7 @@ i.e. the limit on how far back to scan." ((nth 4 state) 'comment) (t nil)))) -;; electric characters + (defun fsharp-outdent-p () "Returns non-nil if the current line should dedent one level." (save-excursion @@ -278,6 +273,9 @@ i.e. the limit on how far back to scan." (looking-at fsharp-outdent-re)) )) + +;;---------------------------- Electric Keystrokes ----------------------------;; + (defun fsharp-electric-colon (arg) "Insert a colon. In certain cases the line is dedented appropriately. If a numeric @@ -317,7 +315,6 @@ comment." (indent-to (- indent outdent)) ))))) - ;; Electric deletion (defun fsharp-electric-backspace (arg) @@ -347,10 +344,8 @@ above." (interactive "*p") (if (or (/= (current-indentation) (current-column)) (bolp) - (fsharp-continuation-line-p) - ; (not fsharp-honor-comment-indentation) - ; (looking-at "#[^ \t\n]") ; non-indenting # - ) + (fsharp-continuation-line-p)) + (funcall fsharp-backspace-function arg) ;; else indent the same as the colon line that opened the block ;; force non-blank so fsharp-goto-block-up doesn't ignore it @@ -392,12 +387,7 @@ function in `fsharp-delete-function'. number of characters to delete (default is 1)." (interactive "*p") (funcall fsharp-delete-function arg)) -;; (if (or (and (fboundp 'delete-forward-p) ;XEmacs 21 -;; (delete-forward-p)) -;; (and (boundp 'delete-key-deletes-forward) ;XEmacs 20 -;; delete-key-deletes-forward)) -;; (funcall fsharp-delete-function arg) -;; (fsharp-electric-backspace arg))) + ;; required for pending-del and delsel modes (put 'fsharp-electric-colon 'delete-selection t) ;delsel @@ -408,7 +398,6 @@ number of characters to delete (default is 1)." (put 'fsharp-electric-delete 'pending-delete 'supersede) ;pending-del - (defun fsharp-indent-line (&optional arg) "Fix the indentation of the current line according to Fsharp rules. With \\[universal-argument] (programmatically, the optional argument @@ -857,7 +846,7 @@ initial line; and comment lines beginning in column 1 are ignored." (forward-line 1)))) (set-marker end nil)) - + ;; Functions for moving point (defun fsharp-previous-statement (count) "Go to the start of the COUNTth preceding Fsharp statement. @@ -937,6 +926,9 @@ NOMARK is not nil." (goto-char start) (error "Enclosing block not found")))) +;; The FIXME comment here is antique, and unexplained. My suspicion is that this +;; function was lifted from a Python mode (F# doesn't have the `def' keyword). +;; -- RMD 2019-10-20 ;;FIXME (defun fsharp-beginning-of-def-or-class (&optional class count) "Move point to start of `def' or `class'. From 6d1ade87ac53a3efdbd41cff397de91533e53afe Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 16:20:53 -0700 Subject: [PATCH 09/11] Whitespace and comment cleanup --- fsharp-mode-structure.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el index 8504a4b..bbc2c81 100644 --- a/fsharp-mode-structure.el +++ b/fsharp-mode-structure.el @@ -26,7 +26,9 @@ ;;; Commentary: ;; This module defines variables and functions related to the structure of F# ;; code, and motion around and through that code. SMIE is used to set certain -;; default configurations. +;; default configurations. In particular, `smie' expects to set +;; `forward-sexp-function' and `indent-line-function', the latter of which we +;; currently override. ;; ;; SMIE configs by m00nlight Wang , 2015 ;; Last major update by Ross Donaldson <@gastove>, 2019 @@ -40,7 +42,6 @@ ;;-------------------------- Customization Variables --------------------------;; - (defcustom fsharp-tab-always-indent t "*Non-nil means TAB in Fsharp mode should always reindent the current line, regardless of where in the line point is when the TAB command is used." @@ -180,8 +181,8 @@ as indentation hints, unless the comment character is in column zero." "\\)") "Regular expression matching statements to be dedented one level.") + (defconst fsharp-block-closing-keywords-re - ; "\\(return\\|raise\\|break\\|continue\\|pass\\)" "\\(end\\|done\\|raise\\|failwith\\|failwithf\\|rethrow\\|exit\\)" "Regular expression matching keywords which typically close a block.") From 05b4bba06422213ac3b725ed03b886656b66c204 Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 16:21:10 -0700 Subject: [PATCH 10/11] Update `fsharp-point` to use `save-mark-and-excursion` This allows it to do precisely the same thing, while making very sure to fulfill the guarantee of not changing whatever point and mark the user set. --- fsharp-mode-structure.el | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el index bbc2c81..bbd79c4 100644 --- a/fsharp-mode-structure.el +++ b/fsharp-mode-structure.el @@ -233,23 +233,21 @@ POSITION can be one of the following symbols: boi -- back to indentation bos -- beginning of statement -This function does not modify point or mark." - (let ((here (point))) +This function preserves point and mark." + (save-mark-and-excursion (cond ((eq position 'bol) (beginning-of-line)) ((eq position 'eol) (end-of-line)) ((eq position 'bod) (fsharp-beginning-of-def-or-class 'either)) ((eq position 'eod) (fsharp-end-of-def-or-class 'either)) - ;; Kind of funny, I know, but useful for fsharp-up-exception. ((eq position 'bob) (point-min)) ((eq position 'eob) (point-max)) ((eq position 'boi) (back-to-indentation)) ((eq position 'bos) (fsharp-goto-initial-line)) - (t (error "Unknown buffer position requested: %s" position)) - ) - (prog1 - (point) - (goto-char here)))) + (t (error "Unknown buffer position requested: %s" position))) + + (point))) + (defun fsharp-in-literal-p (&optional lim) "Return non-nil if point is in a Fsharp literal (a comment or string). From 82e61d62131e433a6441672e9e019af528a8e226 Mon Sep 17 00:00:00 2001 From: Ross Donaldson Date: Sun, 20 Oct 2019 16:24:01 -0700 Subject: [PATCH 11/11] More comments and whitespace --- fsharp-mode-structure.el | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el index bbd79c4..497cbe4 100644 --- a/fsharp-mode-structure.el +++ b/fsharp-mode-structure.el @@ -388,7 +388,7 @@ number of characters to delete (default is 1)." (funcall fsharp-delete-function arg)) -;; required for pending-del and delsel modes +;; required for pending-del/delsel/delete-selection minor modes (put 'fsharp-electric-colon 'delete-selection t) ;delsel (put 'fsharp-electric-colon 'pending-delete t) ;pending-del (put 'fsharp-electric-backspace 'delete-selection 'supersede) ;delsel @@ -418,10 +418,12 @@ This function is normally bound to `indent-line-function' so (beginning-of-line) (delete-horizontal-space) (indent-to (* (/ (- cc 1) fsharp-indent-offset) fsharp-indent-offset))) + (progn ;; see if we need to dedent (if (fsharp-outdent-p) (setq need (- need fsharp-indent-offset))) + (if (or fsharp-tab-always-indent move-to-indentation-p) (progn (if (/= ci need) @@ -430,7 +432,9 @@ This function is normally bound to `indent-line-function' so (delete-horizontal-space) (indent-to need))) (if move-to-indentation-p (back-to-indentation))) - (insert-tab)))))) + (insert-tab))) + ))) + (defun fsharp-newline-and-indent () "Strives to act like the Emacs `newline-and-indent'. @@ -447,6 +451,7 @@ the new line indented." (insert-char ?\n 1) (move-to-column ci)))) + (defun fsharp-compute-indentation (honor-block-close-p) "Compute Fsharp indentation. When HONOR-BLOCK-CLOSE-P is non-nil, statements such as `return',