Персонализирани търсения с използване на времеви клейма в Дневник в организационен режим

Бих искал да създам персонализирано търсене в дневния ред, което ще намира TODO елементи въз основа на записи за време в дневника. По-конкретно, бих искал да намеря елементи, маркирани WAITING въз основа на клеймото за време, което маркира влизането в състояние на изчакване. Тези записи изглеждат така:

:LOGBOOK:
- State "WAITING"     from "TODO"    [2011-11-02 Wed 15:10] \\
  Emailed so-and-so about such-and-such.
:END:

Мога ли да направя това с информацията в бордовия дневник? Използвам версия 7.5, но мога да надстроя, ако е необходимо.

Благодаря!

Редактиране: Един случай на използване може да бъде намирането на WAITING задачи, които са били в състояние на изчакване повече от седмица. (Което обикновено означава, че отново трябва да досаждам на някого.)


person Mike B    schedule 07.11.2011    source източник
comment
Има ли някаква конкретна причина да го искате въз основа на бордовия дневник? Ако елементите в момента ЧАКАТ, трябва да можете просто да направите персонализирано търсене въз основа на това. Подозирам, че нещо може да се адаптира от метода за архивиране тук: doc. norang.ca/org-mode.html#sec-12-2 . Просто коригирайте съвпадащия параметър, за да съответства на състоянието \WAITING\. Въпреки че не съм сигурен как да го сортирам само въз основа на тези времеви клейма, а не на други, които са включени.   -  person Jonathan Leech-Pepin    schedule 08.11.2011
comment
Един случай на употреба е намирането на ЧАКАЩИ елементи, които са влезли в състояние на изчакване преди повече от седмица. Тъй като настройката ми за задачи вече записва времето, когато е влязло в състояние ИЗЧАКВАНЕ в бордовия дневник, това изглеждаше като мястото, от което да започна. Все пак съм отворен за други подходи.   -  person Mike B    schedule 16.11.2011
comment
Дали записът за час в ДНЕВНИКА, който искате да съпоставите, винаги ще бъде най-новият? Трябва или да е най-новият запис в дневника, или да съответства на всички записи в дневника за това заглавие (независимо от актуализациите след това). Подозирам, че искате да съответства само на най-новия запис в ДНЕВНИКА, в противен случай няма да съответства на вашия случай на употреба.   -  person Jonathan Leech-Pepin    schedule 18.11.2011


Отговори (2)


Следното трябва да направи това, от което се нуждаете. Просто ще трябва да коригирате командите за персонализиран дневен ред, за да отговарят на вашия случай на употреба. (При тестването и конфигурирането му използвах моите TODO ключови думи). Възможно е една част от този код да дублира работата на вградена организационна функция, особено след като наподобява подхода/просроченото поведение по график и краен срок, но не можах да видя конкретна функция, която да може да се използва повторно.

Действителната функция за използване в персонализираната команда следва.

(defun zin/since-state (since todo-state &optional done all)
  "List Agenda items that are older than SINCE.

TODO-STATE is a regexp for matching to TODO states.  It is provided to
`zin/find-state' to match inactive timestamps.
SINCE is compared to the result of `zin/org-date-diff'.  If
`zin/org-date-diff' is greater than SINCE, the entry is shown in the
Agenda. 
Optional argument DONE allows for done and not-done headlines to be
evaluated.  If DONE is non-nil, match completed tasks.
Optional argument ALL is passed to `zin/find-state' to specify whether
to search for any possible match of STATE, or only in the most recent
log entry."
  (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))))
    ;; If DONE is non-nil, look for done keywords, if nil look for not-done
    (if (member (org-get-todo-state)
                (if done
                    org-done-keywords
                  org-not-done-keywords))
        (let* ((subtree-end (save-excursion (org-end-of-subtree t)))
               (subtree-valid (save-excursion
                               (forward-line 1)
                               (if (and (< (point) subtree-end)
                                        ;; Find the timestamp to test
                                        (zin/find-state todo-state subtree-end all))
                                   (let ((startpoint (point)))
                                     (forward-word 3)
                                     ;; Convert timestamp into days difference from today
                                     (zin/org-date-diff startpoint (point)))))))
          (if (or (not subtree-valid)
                  (<= subtree-valid since))
              next-headline
            nil))
      (or next-headline (point-max)))))

Следната функция намира записи в дневника чрез повторно търсене напред.

(defun zin/find-state (state &optional end all)
  "Used to search through the logbook of subtrees.

Tests to see if the first line of the logbook is a change of todo
status to status STATE
- Status \"STATE\" from ...
The search brings the point to the start of YYYY-MM-DD in inactive timestamps.

Optional argument END defines the point at which to stop searching.
Optional argument ALL when non-nil specifies to look for any occurence
of STATE in the subtree, not just in the most recent entry."
  (let ((drawer (if all "" ":.*:\\W")))
    (re-search-forward (concat drawer ".*State \\\"" state "\\\"\\W+from.*\\[") end t)))

Последната функция определя броя дни разлика между днешния ден и клеймото за време, намерено от горната функция.

(defun zin/org-date-diff (start end &optional compare)
  "Calculate difference between  selected timestamp to current date.

The difference between the dates is calculated in days.
START and END define the region within which the timestamp is found.
Optional argument COMPARE allows for comparison to a specific date rather than to current date."
  (let* ((start-date (if compare compare (calendar-current-date))))
    (- (calendar-absolute-from-gregorian start-date) (org-time-string-to-absolute (buffer-substring-no-properties start end)))
    ))

Две примерни персонализирани команди за дневен ред, използващи горните функции. Първият съвпада с вашия случай на употреба, просто ще трябва да промените "PEND" на "WAITING", за да съответства на правилната ключова дума. Вторият търси ГОТОВИ ключови думи, които са били завършени преди повече от 30 дни (За разлика от търсенето на времеви клейма, които имат месец, съответстващ на този/миналия месец, както е направено в примера, който бях свързал в първия си коментар).

(setq org-agenda-custom-commands
      (quote (("T" "Tasks that have been pending more than 7 days." tags "-REFILE/"
               ((org-agenda-overriding-header "Pending tasks")
                (org-agenda-skip-function '(zin/since-state 7 "PEND"))))
              ("A" "Tasks that were completed more than 30 days ago." tags "-REFILE/"
               ((org-agenda-overriding-header "Archivable tasks")
                (org-agenda-skip-function '(zin/since-state 30 "\\\(DONE\\\|CANC\\\)" t))))
              )))
person Jonathan Leech-Pepin    schedule 18.11.2011
comment
Благодаря! Това изглежда точно това, което ми трябва. Жалко, че някои от вградените не бяха по-полезни, тъй като това изглежда като обичаен случай на употреба. Освен това има допълнителен аргумент „всички“, предаден на zin/find-state. Премахването на това направи кода да функционира правилно. - person Mike B; 07.12.2011
comment
Ами сега, всъщност това е t, което е допълнително в обаждането до zin/find-state от zin/since-state. Предполага се, че по подразбиране е нула и трябва да предаде t от самата команда за дневния ред (ако ALL е t, ще намери всяко събитие, а не само най-новото в дневника, което трябва да генерира фалшиви положителни резултати). Ще поправя стойността в отговора си. - person Jonathan Leech-Pepin; 07.12.2011

В допълнение към отговора на Джонатан Лийч-Пепин, ако искате да разгледате CLOSED: чекмеджето, добавено от (setq org-log-done 'time) конфигурация, можете да подобрите функцията zin/find-state по следния начин:

(defun zin/find-state (state &optional end all)
  (let ((drawer (if all "" ":.*:\\W" "CLOSED:")))
    (or (re-search-forward (concat drawer ".*State \\\"" state "\\\"\\W+from.*\\[") end t)
        (re-search-forward (concat drawer ".*\\[") end t))))

PS: Това е само подобрение на отговора, правилният отговор е отговорът на Джонатан.

person squiter    schedule 30.08.2016