org mode 输入时间时,如何同时输入重复间隔 (比如 +1w)repeater interval

同求。以前也问过,没找到答案。

最近加上了 org-display-custom-times 导致手动输入也失效了(不得不 text-mode 改再 org-mode 回去

等 我 找 找 啊

好奇学姐用 org-display-custom-times 魔改了些啥?

也没什么,主要是看上去习惯一些,然后导致没办法手动输入(

'("<%a, %b %d, %Y>" . "<%a, %b %d, %Y at %H:%M>")

Screen Shot 2020-05-23 at 12.27.12 AM

我看了一下 org-time-stamp 的实现,它原本就支持插入 repeater

  (when repeater
	  (backward-char)
	  (insert " " repeater)

但是它有前提条件,我不知道如何操作才能使 ts 为 t。似乎需要把光标置于一个日期的区间,感觉有点复杂(不知有没有理解错,望各位大佬指出):

  (let* ((ts (cond
	      ((org-at-date-range-p t)
	       (match-string (if (< (point) (- (match-beginning 2) 2)) 1 2)))
	      ((org-at-timestamp-p 'lax) (match-string 0))))
          .....
         (repeater (and ts
			(string-match "\\([.+-]+[0-9]+[hdwmy] ?\\)+" ts)
			(match-string 0 ts)))

所以我写了一个 advice 来实现相同的效果:

(define-advice org-time-stamp (:around (fn &rest args) insert-escaped-repeater)
  ;;---------------------------
  ;; C-c . \+1w RET ;; => <2020-05-23 Sat +1w>
  ;; C-c . \-1w RET ;; => <2020-05-23 Sat -1w>
  ;;---------------------------
  (apply fn args)
  (when (string-match "^\\\\\\([\\+\\-].*\\)" org-read-date-final-answer)
    (save-excursion
      (backward-char)
      (insert " "
              (string-trim-right
               (match-string 1 org-read-date-final-answer))))))

只需输入 repeater 的时候前面加一个“转义符”,例如:\+1w

6 个赞

搜遍网络,居然没有人提到过这个间隔输入的方式,难道搜索方式不对?

原来是 金星人 吗?

那我态度得端正一点,一定给你找到啊!

(defun hello ()
  (interactive)
  (let((org-time-stamp-formats
        '("<%Y-%m-%d %a +1w>" . "<%Y-%m-%d %a %H:%M +1w>"))
     )
  (call-interactively 'org-time-stamp)
  ))

这个应该不是你想要的 他不能在C-c dot 中输入

应该看一下 org-read-date 但是人家并没有提供自定义格式的机制

看来这个问题有点难喔

这段我也看到了,就是试了半天,各种姿势都试不出来。

总之先膜了

让ts成为t的条件是

或者在时间区间 或者位于一个时间之后

repeater依赖于ts 也就是说你得先输入 1w 才能得到

对这个问题没有意义

喔 找到了

给 org-read-date-analyze 加advice

动态的改变org-time-stamp-formats

这样就可以只输入 w 就能输出 +1w 了

可以用后缀实现 -1w

这样就可以做到在 read-date的时候显示最终的效果

我不给答案 代码你们来

膜了,不知道乃有没有亲自改变过 org-time-stamp-formats ? 这东西改了以后,会导致 org-mode 不识别时间区域(乃大概不知道吧

那乃看org-at-date-range-p和format有关系吗

我一般是添加 schedule 或者 deadline 有这个需求, 所以看了下这个函数 org--deadline-or-schedule,找到 repeater 那段

(repeater
        (or
         (and
          (org-string-nw-p time)
          (string-match org-repeat-re time)
          (match-string 1 time))
         (and
          (org-string-nw-p old-date)
          (string-match "\\([.+-]+[0-9]+[hdwmy]\\(?:[/ ][-+]?[0-9]+[hdwmy]\\)?\\)" old-date)
          (match-string 1 old-date))))

(xr org-repeat-re) 得到

(seq "<" (= 4 (any "0-9")) "-" (any "0-9") (any "0-9") "-" (any "0-9") (any "0-9") " " (*\? (not (any "
>"))) (group (opt (any "+.")) "+" (one-or-more (any "0-9")) (any "dhmwy") (opt (group "/" (one-or-more (any "0-9")) (any "dhmwy")))))

需要给时间左右两边加上 “<>”,然而试了下还是不行。

接着找到这篇文章 使用elisp创建repeated-schedule-time,发现 (org-schedule 0 "<2020-05-20 +1m>") 这样确实可以,才反应过来有 calendar 那个读时间是通过 org-add-planning-info → org-read-date 这个函数,又进去看了看,貌似没有 repeater 的处理

同问同问!

比如这个时间约定<2019-01-10 星期四 19:00>

我是手动删除了最右边的尖括号“>”, 然后手工输入“ ++1w>”,才能达到我的目的。

另外,如果我不先删除最右边的尖括号“>”,在“<>”内无法直接输入任何内容。

也是希望在C-c dot 那里带入“++1w”。

太棒了,这个define-advice是有用的,不过只能在C-c .操作后直接加入repeater, 不能加时刻然后再加repeater。

改一下匹配条件:

(define-advice org-time-stamp (:around (fn &rest args) insert-escaped-repeater)
  ;;---------------------------
  ;; C-c . \+1w RET ;; => <2020-05-23 Sat +1w>
  ;; C-c . \-1w RET ;; => <2020-05-23 Sat -1w>
  ;;---------------------------
  (apply fn args)
- (when (string-match "^\\\\\\([\\+\\-].*\\)" org-read-date-final-answer)
+ (when (string-match "\\\\\\([\\+\\-].*\\)" org-read-date-final-answer)
    (save-excursion
      (backward-char)
      (insert " "
              (string-trim-right
               (match-string 1 org-read-date-final-answer))))))

输入 +1w \+2w


EDIT:本来这个 advice 就是这么写的,我在盖 #9 楼的时候临时给正则表达式加了个 ^,没想到反而限制了它的用途。

3 个赞