branch: elpa/csv2ledger commit 4bd99b140aea5ecb2cbc36826f15039f47afd3c1 Author: Joost Kremers <joostkrem...@fastmail.com> Commit: Joost Kremers <joostkrem...@fastmail.com>
Make sure all relevant variables become buffer-local when needed. Specifically, c2l-transaction-modifier, c2l-matcher-regexps and c2l–accounts need to be buffer-local. Of these, c2l-matcher-regexps must also be able to have a default value. --- csv2ledger.el | 92 +++++++++++++++++++++++++---------------------------------- 1 file changed, 39 insertions(+), 53 deletions(-) diff --git a/csv2ledger.el b/csv2ledger.el index 24236c9c98..22caca04da 100644 --- a/csv2ledger.el +++ b/csv2ledger.el @@ -150,38 +150,32 @@ for the field in question." :type '(repeat (cons (symbol :tag "Field") function)) :group 'csv2ledger) -(defvar c2l-transaction-modifier nil +(defcustom c2l-transaction-modify-functions '(c2l-create-title c2l-create-amount c2l-create-account) + "List of functions applied to the transaction before creating an entry. +The functions are applied in the order in which they appear in +the list. Each function should take an alist representing a +transaction as argument and should return the modified +transaction." + :type '(repeat function) + :safe (lambda (v) + (seq-every-p #'symbolp v)) + :group 'csv2ledger) + +(defvar-local c2l-transaction-modifier nil "The function that modifies a CSV transaction before creating a ledger entry. This is the composite function created with the functions in `c2l-transaction-modify-functions'.") -(defun c2l-compose-transaction-modifier (fns) +(defun c2l-compose-transaction-modifier () "Function to set the variable `c2l-transaction-modifier'. FNS is a list of functions, which is reversed and then composed into a single function taking a transaction alist as argument and returning a modified transaction alist." ;; Note: We need to reverse FNS, because `-compose' composes them from right ;; to left (i.e., the last function in FNS is applied first). - (setq c2l-transaction-modifier (apply #'-compose (reverse fns)))) - -(defcustom c2l-transaction-modify-functions '(c2l-create-title c2l-create-amount c2l-create-account) - "List of functions applied to the transaction before creating an entry. -The functions are applied in the order in which they appear in -the list. Each function should take an alist representing a -transaction as argument and should return the modified -transaction. + (or c2l-transaction-modifier + (setq c2l-transaction-modifier (apply #'-compose (reverse c2l-transaction-modify-functions))))) -These functions are composed into a single function which is then -stored in the variable `c2l-transaction-modifier'. If you set -this option outside of Customize, make sure to call the function -`c2l-compose-transaction-modifier' as well." - :type '(repeat function) - :set (lambda (var val) - (c2l-compose-transaction-modifier val) - (set-default var val)) - :safe (lambda (v) - (seq-every-p #'symbolp v)) - :group 'csv2ledger) (defcustom c2l-entry-function #'c2l-compose-entry "Function to create a ledger entry. @@ -220,26 +214,6 @@ See the documentation for the variable accounts)) (user-error "[Csv2Ledger] Account matcher file `%s' not found" file)))) -(defun c2l--compile-matcher-regexps (accounts) - "Create efficient regular expressions for the matchers in ACCOUNTS. -ACCOUNTS is a list of (<matcher> . <account>) conses, where -<matcher> should be unique but <account> may occur multiple -times. Return value is an alist in which each account in -ACCOUNTS is mapped to a regular expression matching all matchers -for that account." - (mapcar (lambda (e) - (cons (regexp-opt (mapcar #'car (cdr e))) - (car e))) - (seq-group-by #'cdr accounts))) - -(defun c2l-set-matcher-regexps (val) - "Set `c2l-matcher-regexps' based on VAL, unless it already has a value." - (unless c2l-matcher-regexps - (setq c2l-matcher-regexps - (-> val - (c2l--read-account-matchers) - (c2l--compile-matcher-regexps))))) - (defcustom c2l-account-matchers-file nil "File containing matcher strings mapped to accounts. This should be a TSV (tab-separated values) file containing one @@ -254,19 +228,31 @@ where the two columns are separated by a TAB. The matcher is a string (not a regular expression). If a matcher is found in any of the fields listed in the option `c2l-target-match-fields', the corresponding account is used to -book the transaction. - -Note that the variable `c2l-matcher-regexps' is set based on the -value of this option. Therefore, if you set this option outside -of Customize, make sure to also call the function -`c2l-set-matcher-regexps'." +book the transaction." :type 'file - :set (lambda (sym val) - (set sym val) - (c2l-set-matcher-regexps val)) :safe #'stringp :group 'csv2ledger) +(defun c2l--compile-matcher-regexps (accounts) + "Create efficient regular expressions for the matchers in ACCOUNTS. +ACCOUNTS is a list of (<matcher> . <account>) conses, where +<matcher> should be unique but <account> may occur multiple +times. Return value is an alist in which each account in +ACCOUNTS is mapped to a regular expression matching all matchers +for that account." + (mapcar (lambda (e) + (cons (regexp-opt (mapcar #'car (cdr e))) + (car e))) + (seq-group-by #'cdr accounts))) + +(defun c2l-set-matcher-regexps () + "Set `c2l-matcher-regexps' based on VAL, unless it already has a value." + (unless c2l-matcher-regexps + (setq-local c2l-matcher-regexps + (-> c2l-account-matchers-file + (c2l--read-account-matchers) + (c2l--compile-matcher-regexps))))) + ;;;###autoload (put 'c2l-target-match-fields 'safe-local-variable '(lambda (v) (seq-every-p #'stringp v))) (defcustom c2l-target-match-fields '(payee description) "List of fields used for determining the target account. @@ -292,7 +278,7 @@ This should most likely be set to the same value as :safe #'integerp :group 'csv2ledger) -(defvar c2l--accounts nil "List of ledger accounts, mainly used for completion.") +(defvar-local c2l--accounts nil "List of ledger accounts, mainly used for completion.") (defvar c2l--results-buffer nil "Buffer for conversion results.") ;;; Functions for use as values of customisation options. @@ -400,7 +386,7 @@ cleared, even if there is no value for `posted' in TRANSACTION." "Try to match STR to an account." (--some (if (string-match-p (car it) str) (cdr it)) - c2l-matcher-regexps)) + (c2l-set-matcher-regexps))) (defun c2l--csv-line-to-ledger (transaction) "Convert TRANSACTION to a ledger entry. @@ -422,7 +408,7 @@ TRANSACTION and then passes the transaction through (cons field (funcall (alist-get field c2l-field-modify-functions #'identity) value)))) transaction)) - (modified-transaction (funcall c2l-transaction-modifier modified-fields))) + (modified-transaction (funcall (c2l-compose-transaction-modifier) modified-fields))) (funcall c2l-entry-function modified-transaction))) (defun c2l--get-current-row ()