]> git.eshelyaron.com Git - sweep.git/commitdiff
ADDED: new user option for choosing indentation increments v0.3.1
authorEshel Yaron <me@eshelyaron.com>
Fri, 23 Sep 2022 09:43:52 +0000 (12:43 +0300)
committerEshel Yaron <me@eshelyaron.com>
Fri, 23 Sep 2022 09:43:52 +0000 (12:43 +0300)
* sweep.el:
** sweep-indent-offset: new user option
** (sweep-indent-line): use it

* README.org: document new indentation engine

NEWS.org
README.org
sweep-tests.el
sweep.el

index 9ce726fe15d22443a866e8dd818ecf2c10a90722..cfc5222bc471fd79d3d9632a91674953227291b5 100644 (file)
--- a/NEWS.org
+++ b/NEWS.org
@@ -30,6 +30,11 @@ Follows file specifications in =sweep-mode= buffers.
 
 * New user options available in =sweep= {{{version({{{input-file}}})}}}
 
+** New user option =sweep-indent-offset=
+
+This option, set by default to 4, is an integer denoting the number of
+columns used as the indent increment in =sweep-mode= buffers.
+
 ** New user option =sweep-colourise-buffer-on-idle=
 
 This option is a boolean flag that determines whether to enable
index 9336dcb62359241edc0001a18bbee3487ea92af3..2657d9c939e1c887693843a324b1363d4dcd3cc9 100644 (file)
@@ -278,6 +278,111 @@ sweep-mode=.  To instruct Emacs to always open Prolog files in
   (add-to-list 'auto-mode-alist '("\\.plt\\'"  . sweep-mode))
 #+end_src
 
+** Indentation
+:PROPERTIES:
+:CUSTOM_ID: indentation
+:END:
+
+#+CINDEX: indentation
+
+In =sweep-mode= buffers, the appropriate indentation for each line is
+determined by a bespoke /indentation engine/.  The indentation engine
+analyses the syntactic context of a given line and determines the
+appropriate indentation to apply based on a set of rules.
+
+#+FINDEX: sweep-indent-line
+The entry point of the indentation engine is the function
+=sweep-indent-line= which takes no arguments and indents that line at
+point.  =sweep-mode= supports the standard Emacs interface for
+indentation by arranging for =sweep-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]].
+
+*** Indentation rules
+:PROPERTIES:
+:CUSTOM_ID: indentation-rules
+:END:
+
+Lines in =sweep-mode= buffers are indented according to the following
+rules:
+
+1. If the current line starts inside a string or a multi-line comment,
+   do not indent.
+2. If the current line starts with a top term, do not indent.
+3. If the current line starts with a closing parenthesis and the
+   matching opening parenthesis is part of a functor, indent to the
+   column of the opening parenthesis if any arguments appear on the
+   same line as the functor, otherwise indent to the start of the
+   functor.
+
+   This rule yields the following layouts:
+
+   #+begin_src prolog
+     some_functor(
+         some_arg
+     ).
+
+     some_functor( some_arg
+                 ).
+   #+end_src
+
+#+VINDEX: sweep-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 =sweep-indent-offset= (by default, four extra
+   columns).
+
+   As an example, this rule yields the following layouts when
+   =sweep-indent-offset= is set to the default value of four columns:
+
+   #+begin_src prolog
+     some_functor(arg1, arg2) :-
+         body_term.
+
+     asserta( some_functor(arg1, arg2) :-
+                  body_term
+            ).
+   #+end_src
+
+5. If the current line starts with the right hand side operand of an
+   infix operator, indent to the starting column of the first operand
+   in the chain of infix operators of the same precedence.
+
+   This rule yields the following layouts:
+
+   #+begin_src prolog
+     head :- body1, body2, body3,
+             body4, body5.
+
+     A is 1 * 2 ^ 3 * 4 *
+          5.
+
+     A is 1 * 2 + 3 * 4 *
+                  5.
+   #+end_src
+
+6. If the last non-comment line ends with a functor and its opening
+   parenthesis, indent to the starting column of the functor plus
+   =sweep-indent-offset=.
+
+   This rule yields the following layout:
+
+   #+begin_src prolog
+     some_functor(
+         arg1, ...
+   #+end_src
+
+7. If the last non-comment line ends with a prefix operator, indent to
+   starting column of the operator plus =sweep-indent-offset=.
+
+   This rule yields the following layout:
+
+   #+begin_src prolog
+     :- multifile
+            predicate/3.
+   #+end_src
+
 ** Semantic highlighting
 :PROPERTIES:
 :CUSTOM_ID: semantic-highlighting
index 347f485278cf99587afb9ba3bbde3e740ce9dfe5..6733838780d119f99a950edc7f1ffb35974c363c 100644 (file)
   "Tests indentation rules."
   (sweep-test-indentation
    "
+some_functor(
+arg1,
+arg2,
+)."
+   "
+some_functor(
+    arg1,
+    arg2,
+)."
+   )
+  (sweep-test-indentation
+   "
+asserta( some_functor(arg1, arg2) :-
+body_term
+).
+"
+   "
+asserta( some_functor(arg1, arg2) :-
+             body_term
+       ).
+"
+   )
+  (sweep-test-indentation
+   "
+:- module(spam, [ foo,
+bar,
+baz
+]
+).
+"
+   "
+:- module(spam, [ foo,
+                  bar,
+                  baz
+                ]
+         ).
+"
+   )
+  (sweep-test-indentation
+   "
+:- module(spam, [
+foo,
+bar,
+baz
+]
+).
+"
+   "
+:- module(spam, [
+                    foo,
+                    bar,
+                    baz
+                ]
+         ).
+"
+   )
+  (sweep-test-indentation
+   "
+[
+    ].
+"
+   "
+[
+].
+"
+   )
+  (sweep-test-indentation
+   "
+:-
+use_module(foo),
+use_module(bar).
+"
+   "
+:-
+    use_module(foo),
+    use_module(bar).
+"
+   )
+  (sweep-test-indentation
+   "
 colourise_declaration(Module:PI, _, TB,
                       term_position(_,_,QF,QT,[PM,PG])) :-
     atom(Module), nonvar(PI), PI = Name/Arity,
index 60f825c3e850b33cd8da670b3b0c66c67b3aa082..a9c9c311b08c557f96cc511c8a5a8d72a257057b 100644 (file)
--- a/sweep.el
+++ b/sweep.el
@@ -6,7 +6,7 @@
 ;; Maintainer: Eshel Yaron <me(at)eshelyaron(dot)com>
 ;; Keywords: prolog languages extensions
 ;; URL: https://git.sr.ht/~eshel/sweep
-;; Package-Version: 0.3.0
+;; Package-Version: 0.3.1
 ;; Package-Requires: ((emacs "28"))
 
 ;; This file is NOT part of GNU Emacs.
   "SWI-Prolog Embedded in Emacs."
   :group 'prolog)
 
+(defcustom sweep-indent-offset 4
+  "Number of columns to indent lines with in `sweep-mode' buffers."
+  :package-version '((sweep . "0.3.1"))
+  :type 'integer
+  :group 'sweep)
+
 (defcustom sweep-colourise-buffer-on-idle t
   "If non-nil, update highlighting of `sweep-mode' buffers on idle."
   :package-version '((sweep . "0.2.0"))
@@ -1299,12 +1305,12 @@ Interactively, a prefix arg means to prompt for BUFFER."
 (defun sweep-indent-line-after-functor (fbeg _fend)
   (save-excursion
     (goto-char fbeg)
-    (+ (current-column) 4)))
+    (+ (current-column) sweep-indent-offset)))
 
 (defun sweep-indent-line-after-open (fbeg _fend)
   (save-excursion
     (goto-char fbeg)
-    (+ (current-column) 4)))
+    (+ (current-column) sweep-indent-offset)))
 
 (defun sweep-indent-line-after-prefix (fbeg _fend _pre)
   (save-excursion
@@ -1322,7 +1328,7 @@ Interactively, a prefix arg means to prompt for BUFFER."
   (save-excursion
     (goto-char fbeg)
     (sweep-backward-term 1200)
-    (+ (current-column) 4)))
+    (+ (current-column) sweep-indent-offset)))
 
 (defun sweep-indent-line-after-infix (fbeg _fend pre)
   (save-excursion
@@ -1340,36 +1346,49 @@ Interactively, a prefix arg means to prompt for BUFFER."
     (current-column)))
 
 (defun sweep-indent-line ()
+  "Indent the current line in a `sweep-mode' buffer."
   (interactive)
   (let ((pos (- (point-max) (point))))
     (back-to-indentation)
     (let ((indent (if (nth 8 (syntax-ppss))
                       'noindent
-                    (pcase (sweep-last-token-boundaries)
-                      ('nil 'noindent)
-                      (`(functor ,lbeg ,lend)
-                       (sweep-indent-line-after-functor lbeg lend))
-                      (`(open ,lbeg ,lend)
-                       (sweep-indent-line-after-open lbeg lend))
-                      (`(symbol ,lbeg ,lend)
-                       (let ((sym (buffer-substring-no-properties lbeg lend)))
-                         (cond
-                          ((pcase (sweep-op-prefix-precedence sym)
-                             ('nil (sweep-indent-line-after-term))
-                             (pre  (sweep-indent-line-after-prefix lbeg lend pre)))))))
-                      (`(operator ,lbeg ,lend)
-                       (let ((op (buffer-substring-no-properties lbeg lend)))
-                         (cond
-                          ((string= op ".") 'noindent)
-                          ((pcase (sweep-op-infix-precedence op)
-                             ('nil nil)
-                             (1200 (sweep-indent-line-after-neck lbeg lend))
-                             (pre  (sweep-indent-line-after-infix lbeg lend pre))))
-                          ((pcase (sweep-op-prefix-precedence op)
-                             ('nil nil)
-                             (pre  (sweep-indent-line-after-prefix lbeg lend pre)))))))
-                      (`(,_ltyp ,_lbeg ,_lend)
-                       (sweep-indent-line-after-term))))))
+                    (if-let ((open (and (= (char-syntax (char-after)) ?\))
+                                        (nth 1 (syntax-ppss)))))
+                        (save-excursion
+                          (goto-char open)
+                          (when (or (= (char-syntax (char-before)) ?w)
+                                    (= (char-syntax (char-before)) ?_))
+                            (when (save-excursion
+                                    (forward-char)
+                                    (skip-syntax-forward " " (line-end-position))
+                                    (eolp))
+                              (skip-syntax-backward "w_")))
+                          (current-column))
+                      (pcase (sweep-last-token-boundaries)
+                        ('nil 'noindent)
+                        (`(functor ,lbeg ,lend)
+                         (sweep-indent-line-after-functor lbeg lend))
+                        (`(open ,lbeg ,lend)
+                         (sweep-indent-line-after-open lbeg lend))
+                        (`(symbol ,lbeg ,lend)
+                         (let ((sym (buffer-substring-no-properties lbeg lend)))
+                           (cond
+                            ((pcase (sweep-op-prefix-precedence sym)
+                               ('nil (sweep-indent-line-after-term))
+                               (pre  (sweep-indent-line-after-prefix lbeg lend pre)))))))
+                        (`(operator ,lbeg ,lend)
+                         (let ((op (buffer-substring-no-properties lbeg lend)))
+                           (cond
+                            ((string= op ".") 'noindent)
+                            ((pcase (sweep-op-infix-precedence op)
+                               ('nil nil)
+                               (1200 (sweep-indent-line-after-neck lbeg lend))
+                               (pre  (sweep-indent-line-after-infix lbeg lend pre))))
+                            ((pcase (sweep-op-prefix-precedence op)
+                               ('nil nil)
+                               (pre  (sweep-indent-line-after-prefix lbeg lend pre)))))))
+                        (`(,_ltyp ,_lbeg ,_lend)
+                         (sweep-indent-line-after-term)))))))
       (when (numberp indent)
         (unless (= indent (current-column))
           (combine-after-change-calls