emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/beancount 35ef808e1c 026/103: beancount.el: Implement inde


From: ELPA Syncer
Subject: [nongnu] elpa/beancount 35ef808e1c 026/103: beancount.el: Implement indentation support
Date: Mon, 29 Apr 2024 15:59:43 -0400 (EDT)

branch: elpa/beancount
commit 35ef808e1c533314a90532376e70798b0e209e72
Author: Daniele Nicolodi <daniele@grinta.net>
Commit: Daniele Nicolodi <daniele@grinta.net>

    beancount.el: Implement indentation support
---
 beancount.el | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 104 insertions(+), 5 deletions(-)

diff --git a/beancount.el b/beancount.el
index 9a9f19e44a..47fb8ce9a2 100644
--- a/beancount.el
+++ b/beancount.el
@@ -37,6 +37,19 @@
   "Editing mode for Beancount files."
   :group 'beancount)
 
+(defcustom beancount-transaction-indent 2
+  "Transaction indent."
+  :type 'integer
+  :group 'beancount)
+
+(defcustom beancount-number-alignment-column 52
+  "Column to which align numbers in postinng definitions. Set to
+0 to automatically determine the minimum column that will allow
+to align all amounts."
+  :type 'integer
+  :group 'beancount)
+
+
 (defgroup beancount-faces nil "Beancount mode highlighting" :group 'beancount)
 
 (defface beancount-directive
@@ -222,8 +235,7 @@
     (,(concat "\\#[" beancount-tag-chars "]*") . 'beancount-tag)
     (,(concat "\\^[" beancount-tag-chars "]*") . 'beancount-link)
     ;; Number followed by currency not covered by previous rules.
-    (,(concat beancount-number-regexp
-             "\\s-+" beancount-currency-regexp) . 'beancount-amount)
+    (,(concat beancount-number-regexp "\\s-+" beancount-currency-regexp) . 
'beancount-amount)
     ;; Accounts not covered by previous rules.
     (,beancount-account-regexp . 'beancount-account) ))
 
@@ -260,18 +272,19 @@
   :syntax-table beancount-mode-syntax-table
 
   (setq-local paragraph-ignore-fill-prefix t)
-  (setq-local fill-paragraph-function #'lisp-fill-paragraph)
+  (setq-local fill-paragraph-function #'beancount-indent-transaction)
 
   (setq-local comment-start ";")
   (setq-local comment-start-skip ";+\\s-*")
   (setq-local comment-add 1)
 
+  (setq-local indent-line-function #'beancount-indent-line-function)
+  (setq-local indent-region-function #'beancount-indent-region)
   (setq-local indent-tabs-mode nil)
 
-  (add-hook 'completion-at-point-functions #'beancount-completion-at-point nil 
t)
-
   (setq-local tab-always-indent 'complete)
   (setq-local completion-ignore-case t)
+  (add-hook 'completion-at-point-functions #'beancount-completion-at-point nil 
t)
 
   (setq-local font-lock-defaults '(beancount-font-lock-keywords))
   (setq-local font-lock-syntax-table t))
@@ -439,6 +452,92 @@ With an argument move to the next non cleared transaction."
   '(beancount-account (styles basic partial-completion substring)))
 (add-to-list 'completion-category-defaults beancount--completion-overrides)
 
+(defun beancount-number-alignment-column ()
+  "Return the column to which postings amounts should be aligned to.
+Returns `beancount-number-alignment-column' unless it is 0. In
+that case, scan the buffer to determine the minimum column that
+will allow to align all numbers."
+  (if (> beancount-number-alignment-column 0)
+      beancount-number-alignment-column
+    (save-excursion
+      (save-match-data
+        (let ((account-width 0)
+              (number-width 0))
+          (goto-char (point-min))
+          (while (re-search-forward beancount-posting-regexp nil t)
+            (if (match-string 2)
+                (let ((accw (- (match-end 1) (line-beginning-position)))
+                      (numw (- (match-end 3) (match-beginning 3))))
+                  (setq account-width (max account-width accw)
+                        number-width (max number-width numw)))))
+          (+ account-width 2 number-width))))))
+
+(defun beancount-compute-indentation ()
+  "Return the column to which the current line should be indented."
+  (save-excursion
+    (beginning-of-line)
+    (cond
+     ;; Only timestamped directives start with a digit.
+     ((looking-at-p "[0-9]") 0)
+     ;; Otherwise look at the previous line.
+     ((and (= (forward-line -1) 0)
+           (or (looking-at-p "[ \t].+")
+               (looking-at-p beancount-timestamped-directive-regexp)
+               (looking-at-p beancount-transaction-regexp)))
+      beancount-transaction-indent)
+     ;; Default.
+     (t 0))))
+
+(defun beancount-align-number (target-column)
+  (save-excursion
+    (beginning-of-line)
+    ;; Check if the current line is a posting with a number to align.
+    (when (and (looking-at beancount-posting-regexp)
+               (match-string 2))
+      (let* ((account-end-column (- (match-end 1) (line-beginning-position)))
+             (number-width (- (match-end 3) (match-beginning 3)))
+             (account-end (match-end 1))
+             (number-beginning (match-beginning 3))
+             (spaces (max 2 (- target-column account-end-column 
number-width))))
+        (goto-char account-end)
+        (delete-region account-end number-beginning)
+        (insert (make-string spaces ? ))))))
+
+(defun beancount-indent-line ()
+  (let ((indent (beancount-compute-indentation))
+        (savep (> (current-column) (current-indentation))))
+    (if (eq last-command 'beancount-indent-line)
+        (setq indent 0))
+    (unless (eq indent (current-indentation))
+      (if savep (save-excursion (indent-line-to indent))
+        (indent-line-to indent))))
+  (beancount-align-number (beancount-number-alignment-column)))
+
+(defun beancount-indent-line-function ()
+  (beancount-indent-line)
+  (setq this-command 'beancount-indent-line))
+
+(defun beancount-indent-region (start end)
+  "Indent a region automagically. START and END specify the region to indent."
+  (let ((deactivate-mark nil)
+        (beancount-number-alignment-column 
(beancount-number-alignment-column)))
+    (save-excursion
+      (setq end (copy-marker end))
+      (goto-char start)
+      (or (bolp) (forward-line 1))
+      (while (< (point) end)
+        (unless (looking-at-p "\\s-*$")
+          (beancount-indent-line))
+        (forward-line 1))
+      (move-marker end nil))))
+
+(defun beancount-indent-transaction (&optional justify region)
+  "Indent Beancount transaction at point."
+  (interactive)
+  (save-excursion
+    (let ((bounds (beancount-find-transaction-extents (point))))
+      (beancount-indent-region (car bounds) (cadr bounds)))))
+
 (defcustom beancount-use-ido t
   "If non-nil, use ido-style completion rather than the standard completion."
   :type 'boolean)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]