diff options
author | David Bremner <bremner@debian.org> | 2019-09-07 14:13:47 -0300 |
---|---|---|
committer | David Bremner <bremner@debian.org> | 2019-09-07 14:13:47 -0300 |
commit | 7d4f69c3fc3fcc73e2004107e90ced5e0f0577a0 (patch) | |
tree | d4daefb63f35b940e20c1abe3b780f452565d6f8 | |
parent | cba56f9a4e1147ca042775a8bdd5f26724838014 (diff) | |
parent | 5067e40805c40e83424d206584838ffa8c8117c7 (diff) |
Merge tag 'upstream/3.1.2_pre3+g5067e408'
-rw-r--r-- | .travis.yml | 66 | ||||
-rw-r--r-- | doc/ledger-mode.texi | 89 | ||||
-rw-r--r-- | ledger-commodities.el | 1 | ||||
-rw-r--r-- | ledger-complete.el | 171 | ||||
-rw-r--r-- | ledger-context.el | 2 | ||||
-rw-r--r-- | ledger-exec.el | 29 | ||||
-rw-r--r-- | ledger-flymake.el | 14 | ||||
-rw-r--r-- | ledger-init.el | 7 | ||||
-rw-r--r-- | ledger-mode.el | 20 | ||||
-rw-r--r-- | ledger-navigate.el | 71 | ||||
-rw-r--r-- | ledger-occur.el | 3 | ||||
-rw-r--r-- | ledger-post.el | 22 | ||||
-rw-r--r-- | ledger-reconcile.el | 2 | ||||
-rw-r--r-- | ledger-regex.el | 26 | ||||
-rw-r--r-- | ledger-report.el | 19 | ||||
-rw-r--r-- | ledger-xact.el | 62 | ||||
-rw-r--r-- | test/Makefile | 4 | ||||
-rw-r--r-- | test/complete-test.el | 107 | ||||
-rw-r--r-- | test/mode-test.el | 26 | ||||
-rw-r--r-- | test/navigate-test.el | 28 | ||||
-rw-r--r-- | test/reconcile-test.el | 2 | ||||
-rw-r--r-- | test/test-helper.el | 5 | ||||
-rwxr-xr-x | tools/travis-install-ledger.sh | 48 |
23 files changed, 434 insertions, 390 deletions
diff --git a/.travis.yml b/.travis.yml index edadf85..9209c46 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,64 +1,32 @@ sudo: required - language: generic - -cache: - directories: - - ledger-master - - ledger-next - -os: - - linux - # - osx # Travis is saturated; see https://www.traviscistatus.com/ +dist: xenial env: matrix: - - EMACS_VERSION=emacs24 LEDGER_BRANCH=master - # - EMACS_VERSION=emacs24 LEDGER_BRANCH=apt-get # apt-get's ledger is too old - - EMACS_VERSION=emacs-snapshot LEDGER_BRANCH=next - -matrix: - allow_failures: - - env: EMACS_VERSION=emacs-snapshot LEDGER_BRANCH=next + - EVM_EMACS=emacs-24.3-travis + - EVM_EMACS=emacs-25.1-travis + # EVM doesn't support xenial yet, which we need since it has ledger version 3. + # See https://github.com/rejeep/evm/issues/125 + # - EVM_EMACS=emacs-26.1-travis + # - EVM_EMACS=emacs-26.2-travis + # - EVM_EMACS=emacs-git-snapshot-travis before_install: - - ./tools/travis-install-ledger.sh $LEDGER_BRANCH - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then - export PATH=$TRAVIS_BUILD_DIR/ledger-$LEDGER_BRANCH:$PATH; - fi - -install: - - if [ "$TRAVIS_OS_NAME-$EMACS_VERSION" = "linux-emacs24" ]; then - sudo add-apt-repository -y ppa:cassou/emacs && - sudo apt-get -qq update && - sudo apt-get -qq install emacs24 emacs24-el && - export EMACS=/usr/bin/emacs; - fi - - if [ "$TRAVIS_OS_NAME-$EMACS_VERSION" = "linux-emacs-snapshot" ]; then - sudo add-apt-repository -y ppa:ubuntu-elisp/ppa && - sudo apt-get -qq update && - sudo apt-get -qq install emacs-snapshot && - export EMACS=/usr/bin/emacs-snapshot; - fi - - if [ "$TRAVIS_OS_NAME-$EMACS_VERSION" = "osx-emacs24" ]; then - wget https://emacsformacosx.com/emacs-builds/Emacs-24.4-universal.dmg && - hdiutil attach Emacs-24.4-universal.dmg && - export EMACS=/Volumes/Emacs/Emacs.app/Contents/MacOS/Emacs; - fi - - if [ "$TRAVIS_OS_NAME-$EMACS_VERSION" = "osx-emacs25" ]; then - wget https://emacsformacosx.com/emacs-builds/Emacs-25.1-universal.dmg && - hdiutil attach Emacs-25.1-universal.dmg && - export EMACS=/Volumes/Emacs/Emacs.app/Contents/MacOS/Emacs; - fi + - sudo apt-get install -y ledger + - git clone https://github.com/rejeep/evm.git $HOME/.evm + - export PATH=$HOME/.evm/bin:$PATH + - evm config path /tmp + - evm install $EVM_EMACS --use --skip script: - - $EMACS --version + - emacs --version - ledger --version - - $EMACS --eval "(setq byte-compile-error-on-warn (>= emacs-major-version 25))" -L . --batch -f batch-byte-compile ledger-*.el - - cd test && make test-batch EMACS="$EMACS" + - emacs --eval "(setq byte-compile-error-on-warn (>= emacs-major-version 25))" -L . --batch -f batch-byte-compile *.el + - make -C test test-batch after_script: - - make checkdoc + - make -C test checkdoc notifications: email: false diff --git a/doc/ledger-mode.texi b/doc/ledger-mode.texi index e47bdae..1a5674d 100644 --- a/doc/ledger-mode.texi +++ b/doc/ledger-mode.texi @@ -47,7 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @end copying -@dircategory Major Modes +@dircategory Emacs @direntry * Ledger Mode: (ledger-mode). Command-Line Accounting @end direntry @@ -169,18 +169,13 @@ format. Then type the first few characters of another payee in the search for a Payee that has the same beginning and copy the rest of the transaction to you new entry. -Additionally you can use the ledger @command{xact} command, by either -typing @kbd{C-c C-a} or using @samp{Add Transaction} menu entry. Then -typing a close match to the payee. Ledger-mode will call @command{ledger -xact} with the data you enter and place the transaction in the proper -chronological place in the ledger. - -If you need to add a lot of transactions that are not near your current -date you can set the current year and month so that using @samp{Add -Transaction} will prompt you with a more convenient month and year. To -set the month type @kbd{C-c RET} and enter the month you want. @kbd{C-c -C-y} will prompt you for the year. These settings only effect the -@samp{Add Transaction} command. +Additionally you can use the ledger @command{xact} command, by either typing +@kbd{C-c C-a} or using @samp{Add Transaction} menu entry. Then typing a close +match to the payee. Ledger-mode will call @command{ledger xact} with the data +you enter and place the transaction in the proper chronological place in the +ledger. Subsequent calls to @kbd{C-c C-a} remember the last date so entering +many dates in the past is easy. The date format can be changed by modifying +@option{ledger-default-date-format}. @node Reconciliation, Reports, Quick Add, Quick Demo @subsection Reconciliation @@ -254,6 +249,7 @@ current regex. Cancel the narrowing by typing @kbd{C-c C-f} again. @chapter The Ledger Buffer @menu +* Navigating Transactions:: * Adding Transactions:: * Copying Transactions:: * Editing Amounts:: @@ -264,26 +260,59 @@ current regex. Cancel the narrowing by typing @kbd{C-c C-f} again. * Narrowing Transactions:: @end menu +@node Navigating Transactions, Adding Transactions, The Ledger Buffer, The Ledger Buffer +@section Navigating Transactions +@cindex transaction, navigation + +@findex ledger-navigate-next-xact-or-directive +@findex ledger-navigate-prev-xact-or-directive +@kindex M-p +@kindex M-n + +In addition to the usual Emacs navigation commands, ledger-mode offers several +additional commands to ease navigation. @kbd{M-n} and @kbd{M-p} navigate between +next and previous xacts or directives. -@node Adding Transactions, Copying Transactions, The Ledger Buffer, The Ledger Buffer +@findex ledger-navigate-next-uncleared +@findex ledger-navigate-previous-uncleared + +Additionally, M-x ledger-navigate-previous-uncleared and M-x +ledger-navigate-next-uncleared navigate to the next and precious uncleared +transactions. + + +@node Adding Transactions, Copying Transactions, Navigating Transactions, The Ledger Buffer @section Adding Transactions -@findex ledger-post-auto-adjust-amounts @findex ledger-post-amount-alignment-column @kindex TAB @cindex transaction, adding Beyond the two ways of quickly adding transactions (@pxref{Quick Add}) -Ledger-mode assists you by providing robust @kbd{TAB} completion for -payees and accounts. Ledger-mode will scan the existing buffer for -payees and accounts. Included files are not currently included in the -completion scan. Repeatedly hitting @kbd{TAB} will cycle through the -possible completions. - -Ledger-mode can also help you keep your amounts aligned. Setting -@option{ledger-post-auto-adjust-amounts} to true tells Ledger-mode to -automatically place any amounts such that their last digit is aligned to -the column specified by @option{ledger-post-amount-alignment-column}, -which defaults to @samp{52}. @xref{Ledger Post Customization Group}. +Ledger-mode assists you by providing robust @kbd{TAB} completion for payees and +accounts. Ledger-mode will scan the existing buffer for payees and accounts. +Included files are not currently included in the completion scan. Ledger-mode +respects Emacs's variables that govern @kbd{TAB} completion, see especially +@code{tab-always-indent}. + +To cycle between completions when hitting @kbd{TAB} multiple times, you can +adjust the standard completion configuration like this: + +@lisp +(add-hook 'ledger-mode-hook + (lambda () + (setq-local tab-always-indent 'complete) + (setq-local completion-cycle-threshold t) + (setq-local ledger-complete-in-steps t))) +@end lisp + +Ledger-mode will help you keep your amounts aligned. When indenting or +completing, Ledger-mode will automatically place any amounts such that their +last digit is aligned to the column specified by +@option{ledger-post-amount-alignment-column}, which defaults to +@samp{52}. @xref{Ledger Post Customization Group}. + +To prevent the automatic realignment of amounts, disable +@option{ledger-post-auto-align}. @xref{Ledger Post Customization Group}. @menu * Setting a Transactions Effective Date:: @@ -328,6 +357,10 @@ An easy way to copy a transaction is to type @kbd{C-c C-k} or menu entry copied transaction, and after having confirmed with @kbd{RET}, new transaction will be inserted at @emph{date} position in buffer. +If you prefer to keep blank lines between your transactions, you can +change the default in +@option{ledger-copy-transaction-insert-blank-line-after}. + @node Editing Amounts, Marking Transactions, Copying Transactions, The Ledger Buffer @section Editing Amounts @kindex C-c C-b @@ -1113,10 +1146,6 @@ Ledger Post: @ftable @option -@item ledger-post-auto-adjust-amounts -If non-nil, then automatically align amounts to column specified in -@option{ledger-post-amount-alignment-column}. - @item ledger-post-amount-alignment-column The column Ledger-mode uses to align amounts. diff --git a/ledger-commodities.el b/ledger-commodities.el index 823f045..beb4759 100644 --- a/ledger-commodities.el +++ b/ledger-commodities.el @@ -31,6 +31,7 @@ ;; These keep the byte-compiler from warning about them, but have no other ;; effect: (defvar ledger-environment-alist) +(declare-function ledger-exec-ledger "ledger-exec" (input-buffer &optional output-buffer &rest args)) (defcustom ledger-reconcile-default-commodity "$" "The default commodity for use in target calculations in ledger reconcile." diff --git a/ledger-complete.el b/ledger-complete.el index 48199e7..569031e 100644 --- a/ledger-complete.el +++ b/ledger-complete.el @@ -22,17 +22,7 @@ ;;; Commentary: ;; Functions providing payee and account auto complete. -(require 'pcomplete) (require 'cl-lib) -(unless (fboundp 'pcomplete-uniquify-list) - ;; TODO: Remove after dropping support for Emacs < 27 - (defalias 'pcomplete-uniquify-list 'pcomplete-uniqify-list)) - -;; Emacs 24.3 compatibility -(defun ledger-string-greaterp (string1 string2) - "Return non-nil if STRING1 is greater than STRING2 in lexicographic order. -Case is significant." - (string-lessp string2 string1)) ;; In-place completion support @@ -47,11 +37,19 @@ This file will then be used as a source for account name completions." :type 'file :group 'ledger) +(defcustom ledger-complete-in-steps nil + "When non-nil, `ledger-complete-at-point' completes account names in steps. +If nil, full account names are offered for completion." + :type 'boolean + :group 'ledger + :package-version '(ledger-mode . "2019-05-27")) + (defun ledger-parse-arguments () "Parse whitespace separated arguments in the current region." - ;; this is more complex than it appears to need, so that it can work - ;; with pcomplete. See pcomplete-parse-arguments-function for - ;; details + ;; FIXME: We don't use pcomplete anymore. + ;; This is more complex than it appears + ;; to need, so that it can work with pcomplete. See + ;; pcomplete-parse-arguments-function for details (let* ((begin (save-match-data (if (looking-back (concat "^\\(" ledger-iso-date-regexp "=\\|\\)" ledger-incomplete-date-regexp) nil) @@ -90,16 +88,7 @@ This file will then be used as a source for account name completions." (setq payees-list (cons (match-string-no-properties 3) payees-list))))) ;; add the payee ;; to the list - (pcomplete-uniquify-list (nreverse payees-list)))) - -(defun ledger-accounts-deduplicate-sorted (l) - "Remove duplicates from a sorted list of strings L." - (let ((current l)) - (while (consp current) - (if (string= (car current) (cadr current)) - (setcdr current (cddr current)) - (pop current))) - l)) + (sort (delete-dups payees-list) #'string-lessp))) (defun ledger-accounts-list-in-buffer () "Return a list of all known account names in the current buffer as strings. @@ -108,9 +97,8 @@ Considers both accounts listed in postings and those declared with \"account\" d (goto-char (point-min)) (let (results) (while (re-search-forward ledger-account-name-or-directive-regex nil t) - (setq results (cons (match-string-no-properties 2) results))) - (ledger-accounts-deduplicate-sorted - (sort results #'ledger-string-greaterp))))) + (setq results (cons (match-string-no-properties 1) results))) + (sort (delete-dups results) #'string-lessp)))) (defun ledger-accounts-list () "Return a list of all known account names as strings. @@ -126,12 +114,12 @@ Looks in `ledger-accounts-file' if set, otherwise the current buffer." (interactive) (let ((account-tree (list t)) (account-elements nil) - (prefix (or (car pcomplete-args) ""))) + (prefix "")) (save-excursion (goto-char (point-min)) (dolist (account - (cl-remove-if-not (lambda (c) (string-prefix-p prefix c pcomplete-ignore-case)) + (cl-remove-if-not (lambda (c) (string-prefix-p prefix c)) (ledger-accounts-list))) (let ((root account-tree)) (setq account-elements @@ -223,37 +211,51 @@ Looks in `ledger-accounts-file' if set, otherwise the current buffer." (defun ledger-complete-at-point () "Do appropriate completion for the thing at point." - (interactive) - (while (pcomplete-here - (cond - ((looking-back (concat "^" ledger-incomplete-date-regexp) nil) - (ledger-complete-date (match-string 1) (match-string 2))) - ((looking-back (concat "^" ledger-iso-date-regexp "=" - ledger-incomplete-date-regexp) nil) - (ledger-complete-effective-date - (match-string 2) (match-string 3) (match-string 4) - (match-string 5) (match-string 6))) - ((eq (save-excursion - (ledger-thing-at-point)) 'transaction) - (if (null current-prefix-arg) - (delete - (caar (ledger-parse-arguments)) - (ledger-payees-in-buffer)) ;; this completes against payee names - (progn - (let ((text (buffer-substring-no-properties - (line-beginning-position) - (line-end-position)))) - (delete-region (line-beginning-position) - (line-end-position)) - (condition-case nil - (ledger-add-transaction text t) - (error nil))) - (forward-line) - (goto-char (line-end-position)) - (search-backward ";" (line-beginning-position) t) - (skip-chars-backward " \t0123456789.,") - (throw 'pcompleted t)))) - (t (ledger-accounts-tree)))))) + (let ((end (point)) + start collection + realign-after + delete-suffix) + (cond (;; Date + (looking-back (concat "^" ledger-incomplete-date-regexp) (line-beginning-position)) + (setq collection (ledger-complete-date (match-string 1) (match-string 2)) + start (match-beginning 0) + delete-suffix (save-match-data + (when (looking-at (rx (one-or-more (or digit (any ?/ ?-))))) + (length (match-string 0)))))) + (;; Effective dates + (looking-back (concat "^" ledger-iso-date-regexp "=" ledger-incomplete-date-regexp) + (line-beginning-position)) + (setq start (line-beginning-position)) + (setq collection (ledger-complete-effective-date + (match-string 2) (match-string 3) (match-string 4) + (match-string 5) (match-string 6)))) + (;; Payees + (eq (save-excursion (ledger-thing-at-point)) 'transaction) + (setq start (save-excursion (backward-word) (point))) + (setq collection #'ledger-payees-in-buffer)) + ((looking-back (rx-to-string `(seq bol (one-or-more space) (group (zero-or-more (not space))))) (line-beginning-position)) + (setq start (match-beginning 1) + delete-suffix (save-excursion + (when (search-forward-regexp (rx (or eol (repeat 2 space))) (line-end-position) t) + (- (match-beginning 0) end))) + realign-after t + collection (if ledger-complete-in-steps + #'ledger-accounts-tree + #'ledger-accounts-list)))) + (when collection + (let ((prefix (buffer-substring-no-properties start end))) + (list start end + (if (functionp collection) + (completion-table-dynamic + (lambda (_) + (cl-remove-if (apply-partially 'string= prefix) (funcall collection)))) + collection) + :exit-function (lambda (&rest _) + (when delete-suffix + (delete-char delete-suffix)) + (when (and realign-after ledger-post-auto-align) + (ledger-post-align-postings (line-beginning-position) (line-end-position)))) + 'ignore))))) (defun ledger-trim-trailing-whitespace (str) (replace-regexp-in-string "[ \t]*$" "" str)) @@ -294,57 +296,6 @@ Does not use ledger xact" (if (re-search-backward "\\(\t\\| [ \t]\\)" nil t) (goto-char (match-end 0)))))) - -(defcustom ledger-complete-ignore-case t - "Non-nil means that ledger-complete-at-point will be case-insensitive" - :type 'boolean - :group 'ledger) - -(defun ledger-pcomplete (&optional interactively) - "Complete rip-off of pcomplete from pcomplete.el, only added -ledger-magic-tab in the previous commands list so that -ledger-magic-tab would cycle properly" - (interactive "p") - (let ((pcomplete-ignore-case ledger-complete-ignore-case)) - (if (and interactively - pcomplete-cycle-completions - pcomplete-current-completions - (memq last-command '(ledger-magic-tab - ledger-pcomplete - pcomplete-expand-and-complete - pcomplete-reverse))) - (progn - (delete-char (* -1 pcomplete-last-completion-length)) - (if (eq this-command 'pcomplete-reverse) - (progn - (push (car (last pcomplete-current-completions)) - pcomplete-current-completions) - (setcdr (last pcomplete-current-completions 2) nil)) - (nconc pcomplete-current-completions - (list (car pcomplete-current-completions))) - (setq pcomplete-current-completions - (cdr pcomplete-current-completions))) - (pcomplete-insert-entry pcomplete-last-completion-stub - (car pcomplete-current-completions) - nil pcomplete-last-completion-raw)) - (setq pcomplete-current-completions nil - pcomplete-last-completion-raw nil) - (catch 'pcompleted - (let* (pcomplete-stub - pcomplete-seen pcomplete-norm-func - pcomplete-args pcomplete-last pcomplete-index - pcomplete-autolist - (completions (pcomplete-completions)) - (result (pcomplete-do-complete pcomplete-stub completions)) - (pcomplete-termination-string "")) - (and result - (not (eq (car result) 'listed)) - (cdr result) - (pcomplete-insert-entry pcomplete-stub (cdr result) - (memq (car result) - '(sole shortest)) - pcomplete-last-completion-raw))))))) - (provide 'ledger-complete) ;;; ledger-complete.el ends here diff --git a/ledger-context.el b/ledger-context.el index ac76708..0a225c5 100644 --- a/ledger-context.el +++ b/ledger-context.el @@ -39,7 +39,7 @@ (defconst ledger-balance-assertion-string ledger-balance-assertion-regexp) (defconst ledger-comment-string "[ \t]*;[ \t]*\\(.*?\\)") (defconst ledger-nil-string "\\([ \t]+\\)") -(defconst ledger-date-string "^\\([0-9]\\{4\\}[/-][01]?[0-9][/-][0123]?[0-9]\\)") +(defconst ledger-date-string "^\\([0-9]\\{4\\}[/-][01]?[0-9][/-][0123]?[0-9]\\)\\(?:=[0-9]\\{4\\}[/-][01]?[0-9][/-][0123]?[0-9]\\)?") (defconst ledger-code-string "\\((.*)\\)?") (defconst ledger-payee-string "\\(.*[^[:space:]]\\)") diff --git a/ledger-exec.el b/ledger-exec.el index f83e3cd..84e52b8 100644 --- a/ledger-exec.el +++ b/ledger-exec.el @@ -25,6 +25,8 @@ ;;; Code: +(declare-function ledger-master-file "ledger-report" ()) + (defconst ledger-version-needed "3.0.0" "The version of ledger executable needed for interactive features.") @@ -43,6 +45,7 @@ (defcustom ledger-binary-path "ledger" "Path to the ledger executable." :type 'file + :risky t :group 'ledger-exec) (defun ledger-exec-handle-error (ledger-errfile) @@ -75,18 +78,20 @@ otherwise the error output is displayed and an error is raised." (outbuf (or output-buffer (generate-new-buffer " *ledger-tmp*"))) (errfile (make-temp-file "ledger-errors"))) - (with-current-buffer buf - (let ((exit-code - (let ((coding-system-for-write 'utf-8) - (coding-system-for-read 'utf-8)) - (apply #'call-process-region - (append (list (point-min) (point-max) - ledger-binary-path nil (list outbuf errfile) nil "-f" "-") - args))))) - (if (ledger-exec-success-p exit-code outbuf) - outbuf - (display-buffer (ledger-exec-handle-error errfile)) - (error "Ledger execution failed"))))))) + (unwind-protect + (with-current-buffer buf + (let ((exit-code + (let ((coding-system-for-write 'utf-8) + (coding-system-for-read 'utf-8)) + (apply #'call-process-region + (append (list (point-min) (point-max) + ledger-binary-path nil (list outbuf errfile) nil "-f" "-") + args))))) + (if (ledger-exec-success-p exit-code outbuf) + outbuf + (display-buffer (ledger-exec-handle-error errfile)) + (error "Ledger execution failed")))) + (delete-file errfile))))) (defun ledger-version-greater-p (needed) "Verify the ledger binary is usable for `ledger-mode' (version greater than NEEDED)." diff --git a/ledger-flymake.el b/ledger-flymake.el index b164832..182efd7 100644 --- a/ledger-flymake.el +++ b/ledger-flymake.el @@ -29,6 +29,10 @@ (require 'flymake) (require 'ledger-exec) ; for `ledger-binary-path' +;; To silence byte compiler warnings in Emacs 25 and older: +(declare-function flymake-diag-region "flymake" (buffer line &optional col)) +(declare-function flymake-make-diagnostic "flymake" (buffer beg end type text &optional data overlay-properties)) + (defvar-local ledger--flymake-proc nil) (defcustom ledger-flymake-be-pedantic nil @@ -71,10 +75,12 @@ Flymake calls this with REPORT-FN as needed." (make-process :name "ledger-flymake" :noquery t :connection-type 'pipe :buffer (generate-new-buffer " *ledger-flymake*") - :command `(,ledger-binary-path "-f" ,file - ,(when ledger-flymake-be-pedantic "--pedantic") - ,(when ledger-flymake-be-explicit "--explicit") - "balance") + :command (cl-remove + nil + `(,ledger-binary-path "-f" ,file + ,(when ledger-flymake-be-pedantic "--pedantic") + ,(when ledger-flymake-be-explicit "--explicit") + "balance")) :sentinel (lambda (proc _event) ;; Check that the process has indeed exited, as it might diff --git a/ledger-init.el b/ledger-init.el index a7c412a..f5d4c3f 100644 --- a/ledger-init.el +++ b/ledger-init.el @@ -37,9 +37,12 @@ Adding the dotted pair (\"decimal-comma\" . t) will tell ledger to treat commas as decimal separator.") -(defvar ledger-default-date-format "%Y/%m/%d" +(defcustom ledger-default-date-format "%Y/%m/%d" "The date format that ledger uses throughout. -Set this to `ledger-iso-date-format' if you prefer ISO 8601 dates.") +Set this to the value of `ledger-iso-date-format' if you prefer +ISO 8601 dates." + :type 'string + :group 'ledger) (defconst ledger-iso-date-format "%Y-%m-%d" "The format for ISO 8601 dates.") diff --git a/ledger-mode.el b/ledger-mode.el index dc92f73..bdd1b5e 100644 --- a/ledger-mode.el +++ b/ledger-mode.el @@ -149,17 +149,6 @@ And calculate the target-delta of the account being reconciled." (when balance (message balance)))) -(defun ledger-magic-tab (&optional interactively) - "Decide what to with with <TAB>, INTERACTIVELY. -Can indent, complete or align depending on context." - (interactive "p") - (if (= (point) (line-beginning-position)) - (indent-to ledger-post-account-alignment-column) - (if (and (> (point) 1) - (looking-back "\\([^ \t]\\)" 1)) - (ledger-pcomplete interactively) - (ledger-post-align-postings (line-beginning-position) (line-end-position))))) - (defvar ledger-mode-abbrev-table) (defvar ledger-date-string-today (ledger-format-date)) @@ -264,9 +253,7 @@ With a prefix argument, remove the effective date." (define-key map [(control ?c) (control ?l)] #'ledger-display-ledger-stats) (define-key map [(control ?c) (control ?q)] #'ledger-post-align-xact) - (define-key map [tab] #'ledger-magic-tab) (define-key map [(control tab)] #'ledger-post-align-xact) - (define-key map [(control ?i)] #'ledger-magic-tab) (define-key map [(control ?c) tab] #'ledger-fully-complete-xact) (define-key map [(control ?c) (control ?i)] #'ledger-fully-complete-xact) @@ -330,17 +317,14 @@ With a prefix argument, remove the effective date." (setq font-lock-defaults '(ledger-font-lock-keywords t nil nil nil)) (add-hook 'font-lock-extend-region-functions 'ledger-fontify-extend-region) - - (setq-local pcomplete-parse-arguments-function 'ledger-parse-arguments) - (setq-local pcomplete-command-completion-function 'ledger-complete-at-point) - (add-hook 'completion-at-point-functions 'pcomplete-completions-at-point nil t) + (add-hook 'completion-at-point-functions #'ledger-complete-at-point nil t) (add-hook 'after-save-hook 'ledger-report-redo nil t) (add-hook 'post-command-hook 'ledger-highlight-xact-under-point nil t) (ledger-init-load-init-file) (setq-local comment-start ";") - + (setq-local indent-line-function #'ledger-indent-line) (setq-local indent-region-function 'ledger-post-align-postings)) ;;;###autoload diff --git a/ledger-navigate.el b/ledger-navigate.el index eb5765c..811662c 100644 --- a/ledger-navigate.el +++ b/ledger-navigate.el @@ -97,37 +97,42 @@ Requires empty line separating xacts." (list (ledger-navigate-beginning-of-xact) (ledger-navigate-end-of-xact)))) +(defun ledger-navigate-skip-lines-backwards (re) + "Move backwards if necessary until RE does not match at the beginning of the line." + (beginning-of-line) + (while (and (looking-at-p re) + (zerop (forward-line -1))))) + +(defun ledger-navigate-skip-lines-forwards (re) + "Move forwards if necessary until RE does not match at the beginning of the line." + (beginning-of-line) + (while (and (looking-at-p re) + (zerop (forward-line 1))))) + (defun ledger-navigate-find-directive-extents (pos) "Return the extents of the directive at POS." (goto-char pos) - (let ((begin (progn (beginning-of-line) - (while (looking-at "[ \t]\\|end[[:blank:]]+\\(?:comment\\|test\\)") - (forward-line -1)) + (let ((begin (progn (ledger-navigate-skip-lines-backwards "[ \t]\\|end[[:blank:]]+\\(?:comment\\|test\\)") (point))) (end (progn (forward-line 1) - (while (looking-at "[ \t]") - (forward-line 1)) - (point)))) + (ledger-navigate-skip-lines-forwards "[ \t]") + (point))) + (comment-re " *;")) ;; handle block comments here (goto-char begin) (cond - ((looking-at " *;") + ((looking-at comment-re) (progn - (while (and (looking-at " *;") - (> (point) (point-min))) - (forward-line -1)) + (ledger-navigate-skip-lines-backwards comment-re) ;; We are either at the beginning of the buffer, or we found ;; a line outside the comment, or both. If we are outside ;; the comment then we need to move forward a line. - (unless (looking-at " *;") + (unless (looking-at comment-re) (forward-line 1) (beginning-of-line)) (setq begin (point)) (goto-char pos) - (beginning-of-line) - (while (and (looking-at " *;") - (< (point) (point-max))) - (forward-line 1)) + (ledger-navigate-skip-lines-forwards comment-re) (setq end (point)))) ((looking-at "\\(?:comment\\|test\\)\\>") (setq end (or (save-match-data @@ -142,20 +147,17 @@ Requires empty line separating xacts." (let ((begin (progn (beginning-of-line) (point))) (end (progn (end-of-line) - (point)))) + (point))) + (comment-re " *;")) ;; handle block comments here (beginning-of-line) - (if (looking-at " *;") + (if (looking-at comment-re) (progn - (while (and (looking-at " *;") - (> (point) (point-min))) - (forward-line -1)) + (ledger-navigate-skip-lines-backwards comment-re) (setq begin (point)) (goto-char pos) (beginning-of-line) - (while (and (looking-at " *;") - (< (point) (point-max))) - (forward-line 1)) + (ledger-navigate-skip-lines-forwards comment-re) (setq end (point)))) (list begin end))) @@ -166,12 +168,31 @@ Requires empty line separating xacts." (save-excursion (goto-char pos) (beginning-of-line) - (while (looking-at "[ \t]\\|end[[:blank:]]+\\(?:comment\\|test\\)\\_>") - (forward-line -1)) + (ledger-navigate-skip-lines-backwards "[ \t]\\|end[[:blank:]]+\\(?:comment\\|test\\)\\_>") (if (looking-at "[=~0-9\\[]") (ledger-navigate-find-xact-extents pos) (ledger-navigate-find-directive-extents pos)))) +(defun ledger-navigate-next-uncleared () + "Move point to the next uncleared transaction." + (interactive) + (when (looking-at ledger-payee-uncleared-regex) + (forward-line)) + (if (re-search-forward ledger-payee-uncleared-regex nil t) + (progn (beginning-of-line) + (point)) + (user-error "No next uncleared transactions"))) + +(defun ledger-navigate-previous-uncleared () + "Move point to the previous uncleared transaction." + (interactive) + (when (equal (car (ledger-context-at-point)) 'acct-transaction) + (ledger-navigate-beginning-of-xact)) + (if (re-search-backward ledger-payee-uncleared-regex nil t) + (progn (beginning-of-line) + (point)) + (user-error "No previous uncleared transactions"))) + (provide 'ledger-navigate) diff --git a/ledger-occur.el b/ledger-occur.el index 6741b72..bfd006e 100644 --- a/ledger-occur.el +++ b/ledger-occur.el @@ -106,7 +106,8 @@ currently active." (defun ledger-occur-make-visible-overlay (beg end) (let ((ovl (make-overlay beg end (current-buffer)))) (overlay-put ovl ledger-occur-overlay-property-name t) - (overlay-put ovl 'font-lock-face 'ledger-occur-xact-face))) + (when ledger-occur-use-face-shown + (overlay-put ovl 'font-lock-face 'ledger-occur-xact-face)))) (defun ledger-occur-make-invisible-overlay (beg end) (let ((ovl (make-overlay beg end (current-buffer)))) diff --git a/ledger-post.el b/ledger-post.el index 19b8ae5..982863d 100644 --- a/ledger-post.el +++ b/ledger-post.el @@ -43,7 +43,7 @@ :group 'ledger-post) (defcustom ledger-post-amount-alignment-at :end - "Position at which the amount is ailgned. + "Position at which the amount is aligned. Can be :end to align on the last number of the amount (can be followed by unaligned commodity) or :decimal to align at the @@ -52,6 +52,12 @@ decimal separator." (const :tag "align at the decimal separator" :decimal)) :group 'ledger-post) +(defcustom ledger-post-auto-align t + "When non-nil, realign post amounts when indenting or completing." + :type 'boolean + :group 'ledger-post + :safe 'booleanp) + (defun ledger-next-amount (&optional end) "Move point to the next amount, as long as it is not past END. Return the width of the amount field as an integer and leave @@ -120,6 +126,20 @@ Looks only as far as END, if supplied, otherwise `point-max'." (delete-char amt-adjust))))))) (forward-line 1)))))) +(defun ledger-indent-line () + "Indent the current line." + ;; Ensure indent if the previous line was indented + (let ((indent-level (save-excursion (if (progn (when (zerop (forward-line -1)) + (memq (ledger-thing-at-point) '(transaction posting)))) + ledger-post-account-alignment-column + 0)))) + (unless (= (current-indentation) indent-level) + (back-to-indentation) + (delete-horizontal-space t) + (indent-to indent-level))) + (when ledger-post-auto-align + (ledger-post-align-postings (line-beginning-position) (line-end-position)))) + (defun ledger-post-align-dwim () "Align all the posting of the current xact or the current region. diff --git a/ledger-reconcile.el b/ledger-reconcile.el index fc5779a..4522b21 100644 --- a/ledger-reconcile.el +++ b/ledger-reconcile.el @@ -181,7 +181,7 @@ Possible values are '(date)', '(amount)', '(payee)' or '(0)' for no sorting, i.e ;; split arguments like the shell does, so you need to ;; specify the individual fields in the command line. (ledger-exec-ledger buffer (current-buffer) - "balance" "--limit" "cleared or pending" "--empty" "--collapse" + "balance" "--real" "--limit" "cleared or pending" "--empty" "--collapse" "--format" "%(scrub(display_total))" account) (ledger-split-commodity-string (buffer-substring-no-properties (point-min) (point-max))))) diff --git a/ledger-regex.el b/ledger-regex.el index 9d858c8..8ac3002 100644 --- a/ledger-regex.el +++ b/ledger-regex.el @@ -22,6 +22,8 @@ (require 'rx) (require 'cl-lib) +(defvar ledger-iso-date-regex) + (defconst ledger-amount-regex (concat "\\( \\|\t\\| \t\\)[ \t]*-?" "\\([A-Z$€£₹_(]+ *\\)?" @@ -71,28 +73,28 @@ (defconst ledger-init-string-regex "^--.+?\\($\\|[ ]\\)") +(defconst ledger-account-name-regex + "\\(?1:[^][(); \t\r\n]+\\(?: [^][(); \t\r\n]+\\)*\\)") + (defconst ledger-account-directive-regex - "^account [ \t]*\\(?2:[^;]+?\\)\\(?3:[ \t]*\\)\\(;.*\\)?$") + (concat "^account[ \t]+" ledger-account-name-regex)) -(defconst ledger-account-any-status-no-trailing-spaces-regex - "^[ \t]+\\(?1:[*!]\\s-+\\)?[[(]?\\(?2:[^; ].+?\\)[])]?") +(defconst ledger-account-name-maybe-virtual-regex + (concat "[[(]?" ledger-account-name-regex "[])]?")) (defconst ledger-account-any-status-regex - (format "%s%s" - ledger-account-any-status-no-trailing-spaces-regex - "\\(?3:\t\\| [ \t]\\|$\\)")) + (concat "^[ \t]+\\(?:[!*][ \t]*\\)?" ledger-account-name-maybe-virtual-regex)) +;; This would incorrectly match "account (foo)", but writing the regexp this way +;; allows us to have just one match result (defconst ledger-account-name-or-directive-regex - (format "\\(?:%s\\|%s\\(?3:\t\\| [ \t]\\)\\)" - ledger-account-directive-regex - ledger-account-any-status-no-trailing-spaces-regex)) + (format "\\(?:%s\\|%s\\)" ledger-account-any-status-regex ledger-account-directive-regex)) (defconst ledger-account-pending-regex - "\\(^[ \t]+\\)\\(!\\s-*[^ ].*?\\)\\( \\|\t\\|$\\)") + (concat "\\(^[ \t]+\\)!" ledger-account-name-maybe-virtual-regex)) (defconst ledger-account-cleared-regex - "\\(^[ \t]+\\)\\(*\\s-*[^ ].*?\\)\\( \\|\t\\|$\\)") - + (concat "\\(^[ \t]+\\)*" ledger-account-name-maybe-virtual-regex)) (defmacro ledger-define-regexp (name regex docs &rest args) "Simplify the creation of a Ledger regex and helper functions." diff --git a/ledger-report.el b/ledger-report.el index c0adaba..25f22d9 100644 --- a/ledger-report.el +++ b/ledger-report.el @@ -150,6 +150,9 @@ when running reports?" (defvar ledger-report-is-reversed nil) (defvar ledger-report-cursor-line-number nil) +(defvar-local ledger-master-file nil + "The master file for the current buffer. +See documentation for the function `ledger-master-file'") (defun ledger-report-reverse-report () "Reverse the order of the report." @@ -188,6 +191,7 @@ when running reports?" #'ledger-report-save) (define-key map [(control ?c) (control ?l) (control ?e)] #'ledger-report-edit-report) + (define-key map [(control ?c) (control ?o) (control ?r)] #'ledger-report) (define-key map (kbd "M-p") #'ledger-report-previous-month) (define-key map (kbd "M-n") #'ledger-report-next-month) (define-key map (kbd "$") #'ledger-report-toggle-default-commodity) @@ -265,13 +269,13 @@ used to generate the buffer, navigating the buffer, etc." (let ((rname (ledger-report-read-name)) (edit (not (null current-prefix-arg)))) (list rname edit)))) - (let ((buf (find-file-noselect (ledger-master-file))) - (rbuf (get-buffer ledger-report-buffer-name)) - (wcfg (current-window-configuration))) - (if rbuf - (kill-buffer rbuf)) + (let* ((file (ledger-master-file)) + (buf (find-file-noselect file)) + (wcfg (current-window-configuration))) (with-current-buffer (pop-to-buffer (get-buffer-create ledger-report-buffer-name)) + (let ((inhibit-read-only t)) + (erase-buffer)) (ledger-report-mode) (set (make-local-variable 'ledger-report-saved) nil) (set (make-local-variable 'ledger-buf) buf) @@ -279,6 +283,7 @@ used to generate the buffer, navigating the buffer, etc." (set (make-local-variable 'ledger-original-window-cfg) wcfg) (set (make-local-variable 'ledger-report-is-reversed) nil) (set (make-local-variable 'ledger-report-current-month) nil) + (set 'ledger-master-file file) (ledger-do-report (ledger-report-cmd report-name edit)) (ledger-report-maybe-shrink-window) (set-buffer-modified-p nil) @@ -329,10 +334,6 @@ used to generate the buffer, navigating the buffer, etc." ;; General helper functions -(defvar-local ledger-master-file nil - "The master file for the current buffer. -See documentation for the function `ledger-master-file'") - (defun ledger-master-file () "Return the master file for a ledger file. diff --git a/ledger-xact.el b/ledger-xact.el index 6f61bba..f8fb216 100644 --- a/ledger-xact.el +++ b/ledger-xact.el @@ -30,7 +30,8 @@ (require 'ledger-navigate) (require 'ledger-exec) (require 'ledger-post) -(declare-function ledger-read-date "ledger-mode") +(declare-function ledger-read-date "ledger-mode" (prompt)) +(declare-function ledger-format-date "ledger-init" (&optional date)) ;; TODO: This file depends on code in ledger-mode.el, which depends on this. @@ -62,16 +63,30 @@ (move-overlay ledger-xact-highlight-overlay b (+ 1 e)) (move-overlay ledger-xact-highlight-overlay 1 1)))))) -(defun ledger-xact-payee () - "Return the payee of the transaction containing point or nil." +(defun ledger-xact-context () + "Return the context of the transaction containing point or nil." (let ((i 0)) (while (eq (ledger-context-line-type (ledger-context-other-line i)) 'acct-transaction) (setq i (- i 1))) (let ((context-info (ledger-context-other-line i))) (if (eq (ledger-context-line-type context-info) 'xact) - (ledger-context-field-value context-info 'payee) + context-info nil)))) +(defun ledger-xact-payee () + "Return the payee of the transaction containing point or nil." + (let ((xact-context (ledger-xact-context))) + (if xact-context + (ledger-context-field-value xact-context 'payee) + nil))) + +(defun ledger-xact-date () + "Return the date of the transaction containing point or nil." + (let ((xact-context (ledger-xact-context))) + (if xact-context + (ledger-context-field-value xact-context 'date) + nil))) + (defun ledger-time-less-p (t1 t2) "Say whether time value T1 is less than time value T2." ;; TODO: assert listp, or support when both are strings @@ -120,6 +135,9 @@ MOMENT is an encoded date" mark desc))))) (forward-line)))) +(defvar ledger-copy-transaction-insert-blank-line-after nil + "Non-nil means insert blank line after a transaction inserted with ‘ledger-copy-transaction-at-point’.") + (defun ledger-copy-transaction-at-point (date) "Ask for a new DATE and copy the transaction under point to that date. Leave point on the first amount." (interactive (list @@ -128,7 +146,10 @@ MOMENT is an encoded date" (transaction (buffer-substring-no-properties (car extents) (cadr extents))) (encoded-date (ledger-parse-iso-date date))) (ledger-xact-find-slot encoded-date) - (insert transaction "\n") + (insert transaction + (if ledger-copy-transaction-insert-blank-line-after + "\n\n" + "\n")) (beginning-of-line -1) (ledger-navigate-beginning-of-xact) (re-search-forward ledger-iso-date-regexp) @@ -141,19 +162,23 @@ MOMENT is an encoded date" "Delete the transaction surrounging POS." (interactive "d") (let ((bounds (ledger-navigate-find-xact-extents pos))) - (delete-region (car bounds) (cadr bounds)))) + (delete-region (car bounds) (cadr bounds))) + (delete-blank-lines)) (defvar ledger-add-transaction-last-date nil "Last date entered using `ledger-read-transaction'.") (defun ledger-read-transaction () "Read the text of a transaction, which is at least the current date." - (let ((reference-date (or ledger-add-transaction-last-date (current-time)))) - (read-string - "Transaction: " - ;; Pre-fill year and month, but not day: this assumes DD is the last format arg. - (ledger-format-date reference-date) - 'ledger-minibuffer-history))) + (let* ((reference-date (or ledger-add-transaction-last-date (current-time))) + (full-date-string (ledger-format-date reference-date)) + ;; Pre-fill year and month, but not day: this assumes DD is the last format arg. + (initial-string (replace-regexp-in-string "[0-9]+$" "" full-date-string)) + (entered-string (read-string "Transaction: " + initial-string 'ledger-minibuffer-history))) + (if (string= initial-string entered-string) + full-date-string + entered-string))) (defun ledger-parse-iso-date (date) "Try to parse DATE using `ledger-iso-date-regexp' and return a time value or nil." @@ -172,14 +197,17 @@ correct chronological place in the buffer." (let* ((args (with-temp-buffer (insert transaction-text) (eshell-parse-arguments (point-min) (point-max)))) - (ledger-buf (current-buffer))) + (ledger-buf (current-buffer)) + (separator "\n")) (unless insert-at-point (let* ((date (car args)) (parsed-date (ledger-parse-iso-date date))) (setq ledger-add-transaction-last-date parsed-date) (push-mark) ;; TODO: what about when it can't be parsed? - (ledger-xact-find-slot (or parsed-date date)))) + (ledger-xact-find-slot (or parsed-date date)) + (when (looking-at "\n*\\'") + (setq separator "")))) (if (> (length args) 1) (save-excursion (insert @@ -189,10 +217,10 @@ correct chronological place in the buffer." (goto-char (point-min)) (ledger-post-align-postings (point-min) (point-max)) (buffer-string)) - "\n")) + separator)) (progn - (insert (car args) " \n\n") - (end-of-line -1))))) + (insert (car args) " ") + (save-excursion (insert "\n" separator)))))) (provide 'ledger-xact) diff --git a/test/Makefile b/test/Makefile index 6d15ff0..7d54410 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ EMACS ?= emacs EMACS_FLAGS = --quick --directory . --directory .. -EMACS_BATCH = $(EMACS) --batch $(EMACS_FLAGS) -EMACS_INTERACTIVE = $(EMACS) $(EMACS_FLAGS) +EMACS_BATCH = "$(EMACS)" --batch $(EMACS_FLAGS) +EMACS_INTERACTIVE = "$(EMACS)" $(EMACS_FLAGS) EL := $(wildcard *.el) ELC := $(patsubst %.el,%.elc,$(EL)) diff --git a/test/complete-test.el b/test/complete-test.el index a8028be..d5082ce 100644 --- a/test/complete-test.el +++ b/test/complete-test.el @@ -35,25 +35,26 @@ http://bugs.ledger-cli.org/show_bug.cgi?id=969 http://bugs.ledger-cli.org/show_bug.cgi?id=582" :tags '(complete regress) - (ledger-tests-with-temp-file - "2013/05/19 Retrait + (let ((ledger-complete-in-steps t)) + (ledger-tests-with-temp-file + "2013/05/19 Retrait Dépense:Alimentation:Épicerie 35 € ; Marché Dépense:Alimentation:Épicerie 8,1 € ; Arum café Dépense:Liquide * Passif:Crédit:BanqueAccord -60,00 €" - (forward-line 1) - (move-end-of-line 1) - (newline) - (insert " Dé") - (call-interactively #'ledger-magic-tab) - (should - (equal (buffer-string) - "2013/05/19 Retrait + (forward-line 1) + (move-end-of-line 1) + (newline) + (insert " Dé") + (call-interactively #'completion-at-point) + (should + (equal (buffer-string) + "2013/05/19 Retrait Dépense:Alimentation:Épicerie 35 € ; Marché Dépense: Dépense:Alimentation:Épicerie 8,1 € ; Arum café Dépense:Liquide - * Passif:Crédit:BanqueAccord -60,00 €")))) + * Passif:Crédit:BanqueAccord -60,00 €"))))) (ert-deftest ledger-complete/test-002 () @@ -62,17 +63,17 @@ http://bugs.ledger-cli.org/show_bug.cgi?id=252" :tags '(complete regress) (ledger-tests-with-temp-file - "2010/04/08 payee + "2010/04/08 payee account1 1 € account2 " - (goto-char (point-max)) - (newline) - (insert "2016/09/01 payee") - (ledger-fully-complete-xact) - (should - (equal (buffer-string) - "2010/04/08 payee + (goto-char (point-max)) + (newline) + (insert "2016/09/01 payee") + (ledger-fully-complete-xact) + (should + (equal (buffer-string) + "2010/04/08 payee account1 1 € account2 @@ -81,14 +82,54 @@ http://bugs.ledger-cli.org/show_bug.cgi?id=252" account2 ")))) +(ert-deftest ledger-complete/test-complete-account-without-amount () + "https://github.com/ledger/ledger-mode/issues/141" + :tags '(complete regress) + (ledger-tests-with-temp-file + "2010/04/08 payee + blah 1 € + bloop + +2010/04/09 payee + blo" + (goto-char (point-max)) + (call-interactively 'completion-at-point) + (should + (equal (buffer-string) + "2010/04/08 payee + blah 1 € + bloop + +2010/04/09 payee + bloop")))) + +(ert-deftest ledger-complete/test-complete-single-payee () + "https://github.com/ledger/ledger-mode/issues/181" + :tags '(complete regress) + (ledger-tests-with-temp-file + "2019/06/28 Foobar + Expenses:Baz 11.99 CAD + Assets:Cash + +2019/06/20 Foo" + (goto-char (point-max)) + (call-interactively 'completion-at-point) + (should + (equal (buffer-string) + "2019/06/28 Foobar + Expenses:Baz 11.99 CAD + Assets:Cash + +2019/06/20 Foobar")))) + (ert-deftest ledger-complete/test-find-accounts-in-buffer () (let ((ledger "*** Expenses account Expenses:Accomodation account Assets:Cash ; some comment account Assets:Current - alias 1187465S022 +; alias 1187465S022 -- Ideally this line could be uncommented commodity EUR - format 1,000.00 EUR +; format 1,000.00 EUR -- Ideally this line could be uncommented tag ofxid 2018/05/07 * Company Assets:Current -38.33 EUR @@ -103,15 +144,25 @@ tag ofxid (insert ledger) (should (equal (ledger-accounts-list-in-buffer) - (list ; I don't know why accounts are sorted in reverse order - "Something" - "Expenses:Utilities:Insurance" - "Expenses:Accomodation" - "Dimensions:Foo" - "Dimensions:Equity" + (list + "Assets:Cash" "Assets:Current" - "Assets:Cash")))))) + "Dimensions:Equity" + "Dimensions:Foo" + "Expenses:Accomodation" + "Expenses:Utilities:Insurance" + "Something")))))) +(ert-deftest ledger-complete/test-find-accounts-with-spaces-in-buffer () + (let ((ledger "*** Expenses +account Expenses:The Bakery +")) + (with-temp-buffer + (insert ledger) + (should (equal + (ledger-accounts-list-in-buffer) + (list + "Expenses:The Bakery")))))) (provide 'complete-test) diff --git a/test/mode-test.el b/test/mode-test.el index 1bfefdd..0135243 100644 --- a/test/mode-test.el +++ b/test/mode-test.el @@ -61,27 +61,19 @@ "Regress test for Bug 256 http://bugs.ledger-cli.org/show_bug.cgi?id=256" :tags '(mode regress) - - (ledger-tests-with-temp-file - "" - - (comment-dwim nil) - (should (equal (buffer-string) "; ")) ; Expected: no space before ';' - )) - + (ledger-tests-with-temp-file "" + (comment-dwim nil) + (should (string-match (rx buffer-start ";" (0+ whitespace)) + ;; Expected: no space before ';' + (buffer-string))))) (ert-deftest ledger-mode/test-003 () "Baseline test for comment-start" :tags '(mode baseline) - - (ledger-tests-with-temp-file - "" - - (setq comment-start "#") - (comment-dwim nil) - (should (equal (buffer-string) "# ")) - )) - + (ledger-tests-with-temp-file "" + (setq comment-start "#") + (comment-dwim nil) + (should (string-match (rx buffer-start "#" (0+ whitespace)) (buffer-string))))) (provide 'mode-test) diff --git a/test/navigate-test.el b/test/navigate-test.el index 84656b1..503dbc8 100644 --- a/test/navigate-test.el +++ b/test/navigate-test.el @@ -43,6 +43,34 @@ http://bugs.ledger-cli.org/show_bug.cgi?id=441" (ledger-navigate-prev-xact-or-directive) (should (eq 104 (point))))) +(ert-deftest ledger-navigate-uncleared () + :tags '(navigate) + (with-temp-buffer + (insert + "2011/01/27 Book Store + Expenses:Books $20.00 + Liabilities:MasterCard + +2011/04/25 * Tom's Used Cars + Expenses:Auto $ 5,500.00 + Assets:Checking + +2011/04/27 Bookstore + Expenses:Books $20.00 + Assets:Checking + +2011/12/01 * Sale + Assets:Checking $ 30.00 + Income:Sales") + (ledger-mode) + (goto-char (point-min)) + (ledger-navigate-next-uncleared) + (should (looking-at-p (regexp-quote "2011/04/27 Bookstore"))) + (should-error (ledger-navigate-next-uncleared)) + (ledger-navigate-previous-uncleared) + (should (bobp)) + )) + (provide 'navigate-test) diff --git a/test/reconcile-test.el b/test/reconcile-test.el index 4c7c481..289ca16 100644 --- a/test/reconcile-test.el +++ b/test/reconcile-test.el @@ -716,7 +716,7 @@ http://bugs.ledger-cli.org/show_bug.cgi?id=262" (should ;; Expected: this must be ledger buffer (equal (buffer-name) ; current buffer name (buffer-name ledger-buffer))) - (should (= 1323 (point)))))) ; expected on "Book Store" xact + (should (= 1321 (point)))))) ; expected on "Book Store" xact (ert-deftest ledger-reconcile/test-028 () diff --git a/test/test-helper.el b/test/test-helper.el index f26b4e2..66fb09e 100644 --- a/test/test-helper.el +++ b/test/test-helper.el @@ -126,7 +126,8 @@ always located at the beginning of buffer." (goto-char (point-min)) ,@body) (and ledger-buffer (kill-buffer ledger-buffer)) - (ledger-tests-reset-custom-values 'ledger)))) + (ledger-tests-reset-custom-values 'ledger) + (delete-file temp-file)))) (defun ledger-test-visible-buffer-string () @@ -166,7 +167,7 @@ The two arguments START and END are character positions." (defun ledger-test-face-groups (fontified) - "Group a fontified string by face. + "Group a FONTIFIED string by face. Return a list of substrings each followed by its face." (cl-loop for start = 0 then end while start diff --git a/tools/travis-install-ledger.sh b/tools/travis-install-ledger.sh deleted file mode 100755 index e30ba3b..0000000 --- a/tools/travis-install-ledger.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -set -eu -o pipefail -set -o xtrace - -BRANCH=$1 -LAST_BUILD_FILE=travis-last-build - -if [ "${TRAVIS_OS_NAME}" = "linux" ]; then - if [ "${BRANCH}" = "apt-get" ]; then - sudo apt-get update -qq - sudo apt-get install -qq ledger - else - sudo apt-get install -qq git - sudo apt-get install -qq libboost-all-dev # ledger needs Boost's runtime libraries - sudo apt-get install -qq libgmp-dev libmpfr-dev libedit-dev - - if [ ! -d "ledger-$BRANCH/.git" ]; then - git clone --depth 1 -b "$BRANCH" "https://github.com/ledger/ledger/" "ledger-$BRANCH" - fi - - cd "ledger-$BRANCH" - - git fetch origin - git reset --hard "origin/$BRANCH" - - REV="$(git rev-parse "$BRANCH")" - - if [ "$(cat "$LAST_BUILD_FILE" 2> /dev/null)" = "$REV" ]; then - echo "Build is up to date" - else - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - sudo apt-get update -qq - sudo apt-get install -qq gcc-4.8 g++-4.8 - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 90 - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 90 - - cmake . - make -j2 - echo "$REV" > "$LAST_BUILD_FILE" - fi - fi -fi - -if [ "${TRAVIS_OS_NAME}" = "osx" ]; then - brew update - brew install ledger -fi |