对emacs日记文件中的条目进行排序

时间:2014-02-08 12:50:59

标签: emacs

我使用emacs日记。

当我在日记文件中附加未来计划和每日评论时, 文件中的条目导致不遵循时间顺序。

当我在某些场合查看日记文件时,我希望对这些条目进行排序。 是否有任何命令或lisp可用于修改日记文件,以便条目按时间顺序排序?

2 个答案:

答案 0 :(得分:2)

很久以前,我给自己写了一个排序函数:

(defun diary-sort-diary-keyfun nil
  "Key function to order diary entries.
Entries sort in the groups: (days, anniversaries, cyclics, blocks, dates), with any unrecognised
forms before the groups.
Within each group, entries are in ascending date order.
You can prefix entries with `#' to comment them out without affecting sort order.
Prefixing with `&' also does not affect sort order."
  (let ((number "\\s-+\\([0-9]+\\)")
        (months '("Dec" "Nov" "Oct" "Sep" "Aug" "Jul" "Jun" "May" "Apr" "Mar" "Feb" "Jan"))
        (days '("Saturday" "Friday" "Thursday" "Wednesday" "Tuesday" "Monday" "Sunday")))
    (skip-chars-forward "#&")
    (cond
     ((looking-at (concat "%%(diary-block" number number number number number number ")\\(.*\\)"))
      (format "50%04d%02d%02d%04d%02d%02d%s"
              (string-to-number (match-string 3))
              (string-to-number (match-string 2)) (string-to-number (match-string 1))
              (string-to-number (match-string 6))
              (string-to-number (match-string 5)) (string-to-number (match-string 4))
              (match-string 7)))
     ((looking-at (concat "%%(diary-cyclic" number number number number ")\\(.*\\)"))
      (format "40%04d%02d%02d%05d%s"
              (string-to-number (match-string 4))
              (string-to-number (match-string 3)) (string-to-number (match-string 2))
              (string-to-number (match-string 1))
              (match-string 5)))
     ((looking-at (concat "%%(diary-anniversary" number number number ")\\(.*\\)"))
      (format "30%04d%02d%02d%s"
              (string-to-number (match-string 3))
              (string-to-number (match-string 2)) (string-to-number (match-string 1))
              (match-string 4)))
     ((looking-at "%%(\\(.*\\)")        ; after all othe "%%()" rules
      (format "20(%s" (match-string 1)))
     ((looking-at (concat "\\(" (mapconcat 'identity days "\\|") "\\)"
                          "\\( *[0-2 ][0-9]:[0-9][0-9]\\)?\\(.*\\)"))
      (format "10%d%6s%s"
              (length (member (match-string 1) days))
              (or (match-string 2) "")
              (match-string 3)))
     ((looking-at (concat "\\([0-9]+\\)\\s-+" "\\(" (mapconcat 'identity months "\\|") "\\)"
                          number "\\s-+\\([0-2 ][0-9]:[0-9][0-9]\\)?\\(.*\\)"))
      (format "60%04d%02d%02d%6s%s"
              (string-to-number (match-string 3))
              (length (member (match-string 2) months))
              (string-to-number (match-string 1))
              (or (match-string 4) "")
              (match-string 5)))
     ((looking-at (concat "\\(" (mapconcat 'identity months "\\|") "\\)"
                          number "," number "\\( *[0-2 ][0-9]:[0-9][0-9]\\)?\\(.*\\)"))
      (format "60%04d%02d%02d%6s%s"
              (string-to-number (match-string 3))
              (length (member (match-string 1) months))
              (string-to-number (match-string 2))
              (or (match-string 4) "")
              (match-string 5)))
     ((looking-at "[ \t\r]*$")          ; blank line
      (concat "99" (match-string 0)))
     ((looking-at ".*")                 ; last rule
      (concat "00" (match-string 0))))))

(defun diary-sort-diary-file nil
  "Sort the diary entries.
See `diary-sort-diary-keyfun' for the collation sequence."
  (interactive "*")
  ;; sort-order:
  ;; randoms, days, anniversaries, cyclics, blocks, dates
  (goto-char (point-min))
    (let* ((locals-start (and (re-search-forward "\\(\n.*\\)Local variables:\\(.*\n\\)" nil t)
                              (match-beginning 0)))
           (locals-end (and locals-start
                            (search-forward (concat (match-string 1) "End:" (match-string 2)) nil t)
                            (match-end 0)))
           (locals (and locals-start locals-end 
                        (buffer-substring-no-properties locals-start locals-end))))
      (when locals
        (delete-region locals-start locals-end))
      (and (> (point-max) 1)
           (/= (char-after (1- (point-max))) ?\n)
           (goto-char (point-max))
           (insert ?\n))
      (goto-char (point-min))
      (sort-subr nil 'forward-line 'end-of-line 'diary-sort-diary-keyfun)
      (goto-char (point-max))
      (insert "\n")
      (delete-blank-lines)
      (when locals
        (insert locals))))

我可能已经假定欧洲日期订单,但如果您更喜欢不同的订单,那么应该不难对其进行调整。

它的工作方式是keyfun返回一个字符串,该字符串以条目类型的两位数开头(00表示未知数,10表示星期几条目,最多{{1对于非重复日期),后跟条目的大端表示,如ISO 8601。

交互式函数60然后使用此密钥。它会保存任何diary-sort-diary-file部分,并在文件末尾恢复它(当您从Local variables插入条目时,这很好,因为它们会被追加)。如果您有任何calendar行(对于Ispell),那么您可以使用类似的代码来保持完整,或者您可以调整keyfun以将它们放在最后。

样本结果(有些审查):

  

LocalWords Xxxxxxx
  &Sep 12 Xxxxxxx
  &Monday 21:00 Xxxxxxx
  #&Thursday Xxxxxxx
  %%(diary-float t 0 2) Xxxxxxx
  %%(diary-float t 6 1)
  &%%(diary-phases-of-moon) Xxxxxxx
  &%%(diary-anniversary 26 6 1952) Xxxxxxx
  %%(diary-anniversary 1 6 1972) Xxxxxxx
  &%%(diary-anniversary 15 3 1975) Xxxxxxx
  &%%(diary-anniversary 7 2 1976)国际星球大战日! :-)
  %%(diary-anniversary 4 5 1977) Xxxxxxx
  &%%(diary-anniversary 13 8 1978) Xxxxxxx
  &%%(diary-anniversary 26 8 1980) Xxxxxxx
  &%%(diary-anniversary 16 10 1980) Xxxxxxx
  &%%(diary-anniversary 15 3 2010) Xxxxxxx
  &%%(diary-cyclic 1000 1 6 1972) Xxxxxxx
  &%%(diary-cyclic 1000 13 8 1978) Xxxxxxx
  &%%(diary-cyclic 1000 26 8 1980) Xxxxxxx
  %%(diary-cyclic 1000 9 9 2013) Xxxxxxx
  %%(diary-block 22 3 2013 24 3 2013) Xxxxxxx
  %%(diary-block 6 4 2013 7 4 2013) Xxxxxxx
  &%%(diary-block 20 4 2013 21 4 2013) Xxxxxxx
  %%(diary-block 27 4 2013 28 4 2013) Xxxxxxx
  %%(diary-block 18 5 2013 19 5 2013) Xxxxxxx
  %%(diary-block 1 6 2013 2 6 2013) Xxxxxxx
  %%(diary-block 1 6 2013 2 6 2013) Xxxxxxx
  %%(diary-block 15 6 2013 16 6 2013) Xxxxxxx
  %%(diary-block 22 6 2013 23 6 2013) Xxxxxxx
  %%(diary-block 22 6 2013 30 6 2013) Xxxxxxx
  %%(diary-block 6 7 2013 7 7 2013) Xxxxxxx
  %%(diary-block 20 7 2013 24 7 2013) Xxxxxxx
  %%(diary-block 9 8 2013 11 8 2013) Xxxxxxx
  %%(diary-block 23 4 2016 24 4 2016) Xxxxxxx
  %%(diary-block 13 8 2016 21 8 2016) Xxxxxxx
  %%(diary-block 26 8 2016 28 8 2016) Xxxxxxx
  22 Jun 2009 11:30 Xxxxxxx
  30 Jun 2009 13:00 Xxxxxxx
  &22 Jul 2009 Xxxxxxx
  25 Jul 2009 Xxxxxxx
  &14 Aug 2009 17:30 Xxxxxxx
  &17 Aug 2009 Xxxxxxx
  13 Mar 2010 Xxxxxxx
  23 Mar 2010 10:50 Xxxxxxx
  &17 Jan 2013 14:00 Xxxxxxx
  1 Feb 2013 Xxxxxxx
  &8 Feb 2013 16:00 Xxxxxxx
  12 Feb 2013 18:30 Xxxxxxx
  19 Feb 2013 18:00 Xxxxxxx
  &12 Mar 2013 10:00 Xxxxxxx
  16 Mar 2013 Xxxxxxx
  &19 Mar 2013 13:50 Xxxxxxx
  20 Mar 2016 Xxxxxxx
  2 Apr 2016 Xxxxxxx
  18 Jun 2016 Xxxxxxx
  17 Jul 2016 Xxxxxxx
  12 Nov 2016 Xxxxxxx

如果您希望整理日记文件,您可能也喜欢这些:

28  Mar 2017

答案 1 :(得分:1)

icalendar.el 中,使用 icalendar - datetime-to-iso-date ,更改"%d%s%d的格式%s%d" "%04d%s%02d%s%02d"

将其添加到初始化中:

(setq
  diary-date-forms    diary-iso-date-forms
  calendar-date-style 'iso
  )

日记文件中的旧条目编辑为ISO标准,格式如上,即YYYY / MM / DD。 (ISO标准实际上是YYYY-MM-DD)。

现在进一步将其添加到初始化中:

(defun sort--diary (diary-filename)
  (with-current-buffer
    (set-buffer (find-file-noselect (expand-file-name diary-filename)))
    (goto-char (point-min))
    (while (search-forward "\C-j " nil t)
      (replace-match "^j "))
    (sort-lines nil (point-min) (point-max))
    (goto-char (point-min))
    (while (search-forward "^j" nil t)
      (replace-match "\C-j"))
    (save-buffer)))

(defvar sort--diary-filename (expand-file-name diary-file)
  "History for sort--diary diary-filename")

(defun sort-diary (diary-filename)
  "Sort diary file.  Requires dates to use ISO standard"
  (interactive (list (read-from-minibuffer
                      "diary file name: "
                      (car sort--diary-filename)
                      nil nil 'sort--diary-filename)))
  (sort--diary diary-filename))

现在,您可以通过调用 sort-diary 来对日记进行排序。