请问beancount如何补全多个账户文件?

求教各位大佬,我有多个bean文件,但是beancount无法正确识别。 在论坛我找到了这个帖子「提问」 怎么补全没打开的文件?,但是解决办法的GitHub仓库已经太久没有更新。 我现在使用的是Emacs Beancount :记账时从其他的账户文件补全账户

(defvar beancount-account-files nil
  "List of account files")

(defun w/beancount--collect-accounts-from-files (oldfun regex n)
  (let ((keys (funcall oldfun regex n))
        (hash (make-hash-table :test 'equal)))
    (dolist (key keys)
      (puthash key nil hash))
    ;; collect accounts from files
    (save-excursion
      (dolist (f beancount-account-files)
        (with-current-buffer (find-file-noselect f)
          (goto-char (point-min))
          (while (re-search-forward beancount-account-regexp nil t)
            (puthash (match-string-no-properties n) nil hash)))))
    (hash-table-keys hash)))

(advice-add #'beancount-collect
            :around #'w/beancount--collect-accounts-from-files
            '((name . "collect accounts from files as well")))

把上面代码 copy 到你的配置中,然后通过 (setq beancount-account-files '("/path/to/accounts.bean")) 来把你的账户文件配置进来。现在你就可以通过 M-x beancount-insert-account 愉快地从自定义的账户文件中补全了。(如果你在记账的时候进行以上配置,你可能需要 revert the current beancount buffer 来让配置生效)。

但是好像还是不起作用,使用 beancount-account-regexp输出是

“\ ( ?: Assets \ /E\( ?: quity\/xpenses\)\/Income\/Liabilities\)\( ?:: [[:upper: ][ :digit: ]] [ [ :alnum: ] -_ ]*\ )+”

使用beancount-insert-account 也识别不到账户

试试我的配置,目前用着没啥问题。

指定 beancount 文件的目录,然后用一个函数遍历,好像和你是同一个人的链接= =

1 个赞
beancount\accounts
beancount\accounts\liabilities.bean
beancount\accounts\income.bean
beancount\accounts\expenses.bean
beancount\accounts\equity.bean
beancount\accounts\assets.bean
beancount\2025
beancount\2025\2025_income.bean
beancount\2025\2025_circle.bean
beancount\2025\2025_06_expense.bean
beancount\2025\2025.bean
beancount\main.bean

目录就是按年份分的,一个accounts目录多文件保存了账户。

折腾了一下,终于可以了,感谢。 看来这个报错是LSP的问题,账户已经能识别到了

1 个赞

你可以提供一份你的 beancount 文件结构吗,可以把一些隐私信息屏蔽,提供一个最小可测试的数据集。

另外,错误信息也可以尝试问问 LLM,把你的文件目录结构,配置,报错发给它试试看。

Emacs 里可以试试 aider,aideramcs,gptel 之类的工具问,或者再网页问问。

1 个赞
(defvar beancount-account-files nil
  "List of account files")

(defun adv/beancount-collect-pos-alist (regexp n)
  "Return a list of conses mapping matches of REGEXP group N in the
  current buffer to a position of the match beginning."
  (let ((result))
    ;; collect accounts from files
    (save-excursion
      (dolist (f beancount-account-files)
        (with-current-buffer (find-file-noselect f)
          (goto-char (point-min))
          (while (re-search-forward regexp nil t)
            (push (cons (match-string-no-properties n) (match-beginning 0))
                  result))))
      (nreverse result))))

(advice-add #'beancount-collect-pos-alist :override #'adv/beancount-collect-pos-alist)

;; 指定账户补全文件路径
(setq beancount-account-files '("~/.emacs.d/org/bill/accounts.bean"))

另外还可以通过以下代码添加中文子账户支持

;;为账户名匹配添加中文支持
(setq beancount-account-chars "[:alnum:]-_\\cC:")
;; 同上
(setq beancount-account-regexp
      (concat (regexp-opt beancount-account-categories)
              "\\(?::[[:alnum:]-_\\cC]+\\)+"))
;; 现在可以匹配加减乘和括号,但是不支持千分位逗号
(setq beancount-number-regexp "[-]?(?\\(?:[-+*]?[0-9]+\\.?[0-9]*\\)+)?")
;; 以下是在'beancoun.el'中一次性定义好的变量,需要重新载入
(setq beancount-posting-regexp
      (concat "^\\s-+"
              "\\(" beancount-account-regexp "\\)"
              "\\(?:\\s-+\\(\\(" beancount-number-regexp "\\)"
              "\\s-+\\(" beancount-currency-regexp "\\)\\)\\)?"))
(setq beancount-balance-regexp
      (concat "^" beancount-date-regexp "\\s-+balance\\s-+"
              "\\(" beancount-account-regexp "\\)\\s-+"
              "\\(\\(" beancount-number-regexp "\\)\\s-+\\(" beancount-currency-regexp "\\)\\)"))
(setq beancount-font-lock-keywords
      `((,beancount-transaction-regexp (1 'beancount-date)
                                       (2 (beancount-face-by-state (match-string 2)) t)
                                       (3 (beancount-face-by-state (match-string 2)) t))
        (,beancount-posting-regexp (1 'beancount-account)
                                   (2 'beancount-amount nil :lax))
        (,beancount-metadata-regexp (1 'beancount-metadata)
                                    (2 'beancount-metadata t))
        (,beancount-directive-regexp (1 'beancount-directive))
        (,beancount-timestamped-directive-regexp (1 'beancount-date)
                                                 (2 'beancount-directive))
        ;; Fontify section headers when composed with outline-minor-mode.
        (,(concat "^\\(" beancount-outline-regexp "\\).*") (0 (beancount-outline-face)))
        ;; Tags and links.
        (,(concat "\\#[" beancount-tag-chars "]*") . 'beancount-tag)
        (,(concat "\\^[" beancount-tag-chars "]*") . 'beancount-link)
        ;; Accounts not covered by previous rules.
        (,beancount-account-regexp . 'beancount-account)
        ;; Number followed by currency not covered by previous rules.
        (,(concat beancount-number-regexp "\\s-+" beancount-currency-regexp) . 'beancount-amount)
        ))
1 个赞

大佬,我还想问一下:

就很奇怪,不知道是lsp和beancount-mode哪个有问题。关掉lsp也会报错。

难道必须每个bean文件都要include对应的account文件吗?

光看信息也不太清楚为啥,从截图上看,有的行被红色波浪线和感叹号标记了,看起来很像是 flymake 之类的检查器的标记。

minibuffer 里的如果是报错信息,你可以执行一下 toogle-debug-on-error 看看错误的调用栈是什么,是什么引起的。

也可以尝试 emacs -Q -l beancount.el 只加载 beancount 相关配置,排除看看是不是 beancount 配置的问题,如果不是,可以继续用排除法,把一些怀疑有影响的包暂时停用看看,定位到出问题的包。

1 个赞