From af9084e06f7cb38b9fea60a251ce7514ca9f842a Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Sat, 17 Dec 2022 07:58:43 +0200 Subject: [PATCH] ADDED: new command sweeprolog-infer-indent-style * sweeprolog.el (sweeprolog-infer-indent-style): new command. * sweeprolog-tests.el: test it. * README.org ("Indentation"): mention it. --- README.org | 34 +++++++++++++++++++++++++++------- sweeprolog-tests.el | 25 ++++++++++++++++++++++++- sweeprolog.el | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 8 deletions(-) diff --git a/README.org b/README.org index 9e338ca..b6663de 100644 --- a/README.org +++ b/README.org @@ -376,12 +376,33 @@ appropriate indentation to apply based on a set of rules. #+FINDEX: sweeprolog-indent-line The entry point of the indentation engine is the function -=sweeprolog-indent-line= which takes no arguments and indents that line at -point. =sweeprolog-mode= supports the standard Emacs interface for -indentation by arranging for =sweeprolog-indent-line= to be called whenever a -line should be indented, notably after pressing =TAB=. For more a full -description of the available commands and options that pertain to -indentation, see [[info:emacs#Indentation][Indentation in the Emacs manual]]. +=sweeprolog-indent-line= which takes no arguments and indents that line +at point. =sweeprolog-mode= supports the standard Emacs interface for +indentation by arranging for =sweeprolog-indent-line= to be called +whenever a line should be indented, notably after pressing =TAB=. For a +full description of the available commands and options that pertain to +indentation, see [[info:emacs#Indentation][Indentation]] in the Emacs manual. + +#+FINDEX: sweeprolog-infer-indent-style +#+KINDEX: C-c C-I +#+CINDEX: indentation style +#+VINDEX: indent-tabs-mode +#+VINDEX: sweeprolog-indent-offset +The user option ~sweeprolog-indent-offset~ specifies how many columns +lines are indented with. The standard Emacs variable ~indent-tabs-mode~ +determines if indentation can use tabs or only spaces. You may +sometimes want to adjust these options to match the indentation style +used in an existing Prolog codebase, the command +~sweeprolog-infer-indent-style~ can do that for you by analyzing the +contents of the current buffer and updating the buffer-local values of +~sweeprolog-indent-offset~ and ~indent-tabs-mode~ accordingly. Consider +adding ~sweeprolog-infer-indent-style~ to ~sweeprolog-mode-hook~ to have +it set up the indentation style automatically in all ~sweeprolog-mode~ +buffers: + +#+begin_src emacs-lisp + (add-hook 'sweeprolog-mode-hook #'sweeprolog-infer-indent-style) +#+end_src *** Indentation rules :PROPERTIES: @@ -412,7 +433,6 @@ rules: ). #+end_src -#+VINDEX: sweeprolog-indent-offset 4. If the current line is the first non-comment line of a clause body, indent to the starting column of the head term plus the value of the user option =sweeprolog-indent-offset= (by default, four extra diff --git a/sweeprolog-tests.el b/sweeprolog-tests.el index 5ccbb03..c62a031 100644 --- a/sweeprolog-tests.el +++ b/sweeprolog-tests.el @@ -5,6 +5,10 @@ (remove-hook 'flymake-diagnostic-functions #'flymake-proc-legacy-flymake) +(add-hook 'sweeprolog-mode-hook (lambda () + (setq-local indent-tabs-mode nil + inhibit-message t))) + (defconst sweeprolog-tests-greeting "Hello from Elisp from Prolog from Elisp from Prolog from Elisp!") @@ -17,7 +21,7 @@ (cdr sol))) (defun sweeprolog-tests-greet-1 () - (message sweeprolog-tests-greeting)) + sweeprolog-tests-greeting) (ert-deftest elisp->prolog->elisp->prolog->elisp () "Tests calling Elisp from Prolog from Elisp from Prolog from Elisp." @@ -1130,6 +1134,25 @@ test_bindings(Name-Value) --> " )))) +(ert-deftest infer-indent-style () + "Test inferring indentation style from buffer contents." + (with-temp-buffer + (sweeprolog-mode) + (insert " +foo :- + bar.") + (sweeprolog-infer-indent-style) + (should (= sweeprolog-indent-offset 2)) + (should (not indent-tabs-mode))) + (with-temp-buffer + (sweeprolog-mode) + (insert " +foo :- +\tbar.") + (sweeprolog-infer-indent-style) + (should (= sweeprolog-indent-offset tab-width)) + (should indent-tabs-mode))) + (ert-deftest custom-indentation () "Test forcefully setting custom indentation levels." (with-temp-buffer diff --git a/sweeprolog.el b/sweeprolog.el index b50a12b..3bde49f 100644 --- a/sweeprolog.el +++ b/sweeprolog.el @@ -3656,6 +3656,45 @@ valid Prolog atom." ;;;; Indentation +(defun sweeprolog-infer-indent-style () + "Infer indentation style for the current buffer from its contents. + +Examine the indentation of the first clause body starting on a +line of its own and update the buffer-local values of +`sweeprolog-indent-offset' and `indent-tabs-mode' are updated +accordingly." + (interactive "" sweeprolog-mode) + (let ((offset nil) + (usetab nil)) + (sweeprolog-analyze-buffer-with + (lambda (beg _end arg) + (pcase arg + ("body" + (unless offset + (save-excursion + (goto-char beg) + (let ((prefix (buffer-substring (line-beginning-position) + (point)))) + (save-match-data + (cond + ((string-match (rx bos (+ " ") eos) + prefix) + (setq offset (current-column))) + ((string-match (rx bos (+ (or " " "\t")) eos) + prefix) + (setq offset (current-column) + usetab t))))))))))) + (if (not offset) + (message (concat "No indented body term found in" + " current buffer. Keeping current" + " indentation style: offset=%s tabs=%s") + sweeprolog-indent-offset + indent-tabs-mode) + (message "Inferred indentation style: offset=%s tabs=%s" + offset usetab) + (setq-local sweeprolog-indent-offset offset + indent-tabs-mode usetab)))) + (defun sweeprolog-indent-line-after-functor (fbeg _fend) (save-excursion (goto-char fbeg) -- 2.39.2