ADD test for past meetings

This commit is contained in:
Nathan Dwarshuis 2021-09-24 20:21:06 -04:00
parent 36715faf6d
commit e70488515b
2 changed files with 136 additions and 33 deletions

View File

@ -100,6 +100,9 @@ The danger with only having emacs on my daily driver is that I could silently in
* library * library
This is code that is used generally throughout the emacs config This is code that is used generally throughout the emacs config
** system dependencies ** system dependencies
:PROPERTIES:
:ID: 2dc12a82-cb0c-40f1-ab5a-46d2800e9e53
:END:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(defvar nd/required-exes '() (defvar nd/required-exes '()
"Running list of executables required to run various configuations. "Running list of executables required to run various configuations.
@ -862,6 +865,9 @@ Elisp can use vanilla company with no plugins
:straight t) :straight t)
#+END_SRC #+END_SRC
*** Clojure *** Clojure
:PROPERTIES:
:ID: f1638eae-295f-4040-9d87-1e5d2457356a
:END:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(nd/require-bin "lein" :pacman "leiningen") (nd/require-bin "lein" :pacman "leiningen")
@ -1067,6 +1073,9 @@ Note this also requires all external packages to be installed in each environeme
(advice-add #'pyenv-mode-full-path :filter-return #'file-truename)) (advice-add #'pyenv-mode-full-path :filter-return #'file-truename))
#+END_SRC #+END_SRC
**** conda **** conda
:PROPERTIES:
:ID: 0294d429-2bfa-4e38-aed0-55942b87d7cc
:END:
Conda is a package manager and virtual environment manager. It handles much more than just python-related things, a fact I will conveniently ignore because I don't know where I would put this otherwise. Conda is a package manager and virtual environment manager. It handles much more than just python-related things, a fact I will conveniently ignore because I don't know where I would put this otherwise.
Also, this seems to have no relation to the =anaconda.el= package installed above. Also, this seems to have no relation to the =anaconda.el= package installed above.
@ -1082,6 +1091,9 @@ Also, this seems to have no relation to the =anaconda.el= package installed abov
conda-env-home-directory (expand-file-name "~/.local/share/conda/"))) conda-env-home-directory (expand-file-name "~/.local/share/conda/")))
#+end_src #+end_src
*** Snakemake *** Snakemake
:PROPERTIES:
:ID: 0d8c4a61-5657-4972-89ce-cabb336b1319
:END:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(use-package snakemake-mode (use-package snakemake-mode
:straight t) :straight t)
@ -1524,6 +1536,9 @@ No custom code here, but flycheck needs =shellcheck= (a Haskell program).
;;(require 'essh) ;;(require 'essh)
#+END_SRC #+END_SRC
*** SQL *** SQL
:PROPERTIES:
:ID: 0c0e08e4-6b18-410c-adf3-51a086abfa96
:END:
No custom code here, but flycheck needs =sqlint= (a ruby gem). No custom code here, but flycheck needs =sqlint= (a ruby gem).
#+begin_src emacs-lisp #+begin_src emacs-lisp
(nd/require-bin "sqlint" :gem) (nd/require-bin "sqlint" :gem)
@ -1538,6 +1553,9 @@ No custom code here, but flycheck needs =sqlint= (a ruby gem).
:straight t)) :straight t))
#+END_SRC #+END_SRC
*** AMPL *** AMPL
:PROPERTIES:
:ID: 014fef8e-b65e-47dc-874a-d4acb1683d5b
:END:
Code shamelessly ripped off from [[https://github.com/dpo/ampl-mode/blob/master/emacs/ampl-mode.el][here]]. It is not in MELPA and is short enough for me to just put in a block in my config. Code shamelessly ripped off from [[https://github.com/dpo/ampl-mode/blob/master/emacs/ampl-mode.el][here]]. It is not in MELPA and is short enough for me to just put in a block in my config.
#+begin_src emacs-lisp #+begin_src emacs-lisp
(defvar ampl-mode-hook nil (defvar ampl-mode-hook nil
@ -1782,6 +1800,9 @@ Save all org buffers 1 minute before the hour.
#+END_SRC #+END_SRC
*** personal library *** personal library
:PROPERTIES:
:ID: 85234c55-a34d-43c3-93bc-e9499c368bb4
:END:
My org config became so huge that I decided to move it all to a separate library. Anything starting with =org-x-= is from this library. My org config became so huge that I decided to move it all to a separate library. Anything starting with =org-x-= is from this library.
The advantage of doing it this way is that I can byte-compile and test independent of the other messy things in the main config. Furthermore, I can use it as a testing ground for new packages if I deem some functionality useful enough for more than just me. The advantage of doing it this way is that I can byte-compile and test independent of the other messy things in the main config. Furthermore, I can use it as a testing ground for new packages if I deem some functionality useful enough for more than just me.
@ -1794,6 +1815,9 @@ The advantage of doing it this way is that I can byte-compile and test independe
#+end_src #+end_src
** buffer interface ** buffer interface
*** startup folding *** startup folding
:PROPERTIES:
:ID: 14eda4c9-8b4d-4c9e-99a6-6515897f3f3b
:END:
Org 9.4 by default makes files open with the outline totally unfolded. I don't like this; it makes it seem like my laptop is screaming at me whenever I view an org file. Org 9.4 by default makes files open with the outline totally unfolded. I don't like this; it makes it seem like my laptop is screaming at me whenever I view an org file.
#+begin_src emacs-lisp #+begin_src emacs-lisp
(setq org-startup-folded t) (setq org-startup-folded t)
@ -1884,6 +1908,7 @@ Make todo insertion respect contents
*** flights *** flights
:PROPERTIES: :PROPERTIES:
:CREATED: [2021-08-24 Tue 11:56] :CREATED: [2021-08-24 Tue 11:56]
:ID: 85e4dd36-0192-4ee3-b51e-95d101ef4fed
:END: :END:
To remind myself to check into flights and stuff To remind myself to check into flights and stuff
#+begin_src emacs-lisp #+begin_src emacs-lisp
@ -1981,6 +2006,7 @@ Set org columns view to be more informative with clocksums and effort.
*** navigation *** navigation
:PROPERTIES: :PROPERTIES:
:CREATED: [2021-08-26 Thu 11:21] :CREATED: [2021-08-26 Thu 11:21]
:ID: 2c8e9989-3b21-45a1-962e-00557b258862
:END: :END:
Some common functions that I use often that don't seem to exist Some common functions that I use often that don't seem to exist
#+begin_src emacs-lisp #+begin_src emacs-lisp
@ -2536,6 +2562,9 @@ In some capture templates I want to automatically store a link to the entry so I
(call-interactively #'org-store-link))))) (call-interactively #'org-store-link)))))
#+END_SRC #+END_SRC
**** creation time **** creation time
:PROPERTIES:
:ID: 9b40efc1-c47b-417c-ba7c-332972fb0541
:END:
Add the creation time upon completing a capture. Add the creation time upon completing a capture.
#+begin_src emacs-lisp #+begin_src emacs-lisp
(add-hook 'org-capture-before-finalize-hook (add-hook 'org-capture-before-finalize-hook
@ -2610,6 +2639,9 @@ Solution: flashy colors.
(setq spaceline-highlight-face-func 'nd/spaceline-highlight-face-clocked) (setq spaceline-highlight-face-func 'nd/spaceline-highlight-face-clocked)
#+END_SRC #+END_SRC
*** aggregation *** aggregation
:PROPERTIES:
:ID: c0ed520b-2da8-48c3-bef5-116372fab7b3
:END:
Org mode has no way of detecting if conflicts exist. It also has no way of alerting someone if they have overbooked their schedule. Org mode has no way of detecting if conflicts exist. It also has no way of alerting someone if they have overbooked their schedule.
The main code is defined in =org-x= so the following is only to set some domain-specific options. The main code is defined in =org-x= so the following is only to set some domain-specific options.
@ -2646,6 +2678,9 @@ In these cases, it is nice to know what happened during each cycle, so force not
(setq org-log-repeat 'note) (setq org-log-repeat 'note)
#+END_SRC #+END_SRC
**** created time **** created time
:PROPERTIES:
:ID: 85335398-df60-4b4a-8903-7c6caff1d42e
:END:
Override the standard headline insertion function to add a timestamp for the time at which it was created. Override the standard headline insertion function to add a timestamp for the time at which it was created.
#+begin_src emacs-lisp #+begin_src emacs-lisp
(advice-add 'org-insert-heading :after (advice-add 'org-insert-heading :after
@ -3076,16 +3111,12 @@ original function being advised and ARGS are the arguments."
(org-x-headline-is-iterator-without-archive-target-p)) (org-x-headline-is-iterator-without-archive-target-p))
,(nd/org-def-super-agenda-pred "Future Creation Timestamp" ,(nd/org-def-super-agenda-pred "Future Creation Timestamp"
(org-x-headline-is-task-with-future-creation-timestamp-p)) (org-x-headline-is-task-with-future-creation-timestamp-p))
,(nd/org-def-super-agenda-pred "Unscheduled Meetings"
(org-x-headline-is-unscheduled-meeting-p))
,(nd/org-def-super-agenda-pred "Meeting without Effort" ,(nd/org-def-super-agenda-pred "Meeting without Effort"
(org-x-headline-is-meeting-without-effort-p)) (org-x-headline-is-meeting-without-effort-p))
,(nd/org-def-super-agenda-pred "Meeting without Agenda"
(org-x-headline-is-meeting-without-agenda-p))
(:discard (:anything t)))))))) (:discard (:anything t))))))))
("m" ("m"
"Past Meetings" "Meetings"
((tags-todo ((tags-todo
,(nd/org-mk-match-string ,(nd/org-mk-match-string
- org-x-tag-refile - org-x-tag-refile
@ -3093,13 +3124,26 @@ original function being advised and ARGS are the arguments."
((org-agenda-overriding-header "Meetings") ((org-agenda-overriding-header "Meetings")
(org-agenda-sorting-strategy '(time-up scheduled-down)) (org-agenda-sorting-strategy '(time-up scheduled-down))
(org-super-agenda-groups (org-super-agenda-groups
',(nd/org-def-super-agenda-automap `((:discard
(-when-let (ts (org-x--headline-get-property-epoch-time "SCHEDULED")) (:pred (lambda (_)
(cond (-if-let (ts (org-x--headline-get-property-epoch-time "SCHEDULED"))
((< (float-time) ts) (< ts (- (float-time) 10368000))
"1. Future Meetings") nil))))
((< (- (float-time) 10368000) ts) ,(nd/org-def-super-agenda-pred "Error: Unscheduled Meetings"
"2. Past Meetings (120 days)"))))))))) (org-x-headline-is-unscheduled-meeting-p))
,(nd/org-def-super-agenda-pred "Error: Invalid States"
(org-x-headline-is-meeting-with-invalid-keyword-p))
,(nd/org-def-super-agenda-pred "Open: Needs Agenda Items"
(org-x-headline-is-open-meeting-without-agenda-p))
,(nd/org-def-super-agenda-pred "Open: Scheduled"
(org-x-headline-is-open-meeting-p))
,(nd/org-def-super-agenda-pred "Closed: Unresolved Agenda"
(org-x-headline-is-closed-meeting-with-unresolved-agenda-p))
,(nd/org-def-super-agenda-pred "Closed: Needs Action Items"
(org-x-headline-is-closed-meeting-without-action-items-p))
,(nd/org-def-super-agenda-pred "Closed: Resolved"
(org-x-headline-is-closed-meeting-p))
(:discard (:anything t))))))))
("A" ("A"
"Archivable Tasks and Projects" "Archivable Tasks and Projects"
@ -3120,6 +3164,7 @@ original function being advised and ARGS are the arguments."
** tracking and analytics ** tracking and analytics
:PROPERTIES: :PROPERTIES:
:CREATED: [2021-04-25 Sun 12:46] :CREATED: [2021-04-25 Sun 12:46]
:ID: 0b13360d-58ee-45f3-a03f-ca05d2ddd5a1
:END: :END:
Because =org-mode= has rich metadata (clocking, logbook, tags, etc) and a robust long-term storage mechanism (archive which can be git-backed), it is a powerful lens with which to study one's own behavior. Because =org-mode= has rich metadata (clocking, logbook, tags, etc) and a robust long-term storage mechanism (archive which can be git-backed), it is a powerful lens with which to study one's own behavior.
@ -3630,6 +3675,9 @@ Hydra allows commands to be arranged on a set of keybindings like a tree.
:straight t) :straight t)
#+end_src #+end_src
*** common interfaces *** common interfaces
:PROPERTIES:
:ID: f5a7c5a3-b96e-46e0-9895-eb58a6f39b94
:END:
Many programming modes have a common set of commands (compiling, sending to repl, looking up function doc, etc). Rather than memorize a bunch of esoteric keybindings from each individual mode, define a common interface here and map those functions to a common set of keys. Many programming modes have a common set of commands (compiling, sending to repl, looking up function doc, etc). Rather than memorize a bunch of esoteric keybindings from each individual mode, define a common interface here and map those functions to a common set of keys.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(defvar nd/hydra-standard-interactive-map (defvar nd/hydra-standard-interactive-map
@ -4131,6 +4179,9 @@ Since I use vi mode in my terminal emulator, need to preserve the escape key's r
"G" #'ivy-end-of-buffer) "G" #'ivy-end-of-buffer)
#+end_src #+end_src
**** cider **** cider
:PROPERTIES:
:ID: 6b77d3df-f7ae-4ec8-8f13-4d2b43ce11fb
:END:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(nd/when-bin "lein" (nd/when-bin "lein"
(evil-define-key '(normal insert) cider-repl-mode-map (evil-define-key '(normal insert) cider-repl-mode-map
@ -4150,6 +4201,9 @@ Since I use vi mode in my terminal emulator, need to preserve the escape key's r
"gk" #'lispy-up)) "gk" #'lispy-up))
#+end_src #+end_src
**** mu4e **** mu4e
:PROPERTIES:
:ID: 7aa97eb9-84a5-4efb-86dc-249e1b5914ce
:END:
#+begin_src emacs-lisp #+begin_src emacs-lisp
;; the old open attachment function broke in mu 1.6, fix it here ;; the old open attachment function broke in mu 1.6, fix it here
(nd/when-bin "mu" (nd/when-bin "mu"
@ -4288,6 +4342,9 @@ They removed the underscore-inserts-arrow feature. Bring it back.
(define-key emacs-lisp-mode-map (kbd "M-RET") #'emr-show-refactor-menu) (define-key emacs-lisp-mode-map (kbd "M-RET") #'emr-show-refactor-menu)
#+END_SRC #+END_SRC
*** clojure *** clojure
:PROPERTIES:
:ID: eb624852-2e59-455d-bfa6-c2f1cc79859e
:END:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(nd/when-bin "lein" (nd/when-bin "lein"
(require 'cider-connection) (require 'cider-connection)
@ -4344,6 +4401,9 @@ The only thing I like about elpy is the interactive shell
(:doc-at . anaconda-mode-show-doc)) (:doc-at . anaconda-mode-show-doc))
#+END_SRC #+END_SRC
*** javascript *** javascript
:PROPERTIES:
:ID: f6131de8-4068-413b-90e6-c8796abd6b88
:END:
#+begin_src emacs-lisp #+begin_src emacs-lisp
(nd/hydra-standard-int js-mode-map (nd/hydra-standard-int js-mode-map
(:send-line . js-comint-send-last-sexp) (:send-line . js-comint-send-last-sexp)

View File

@ -674,17 +674,31 @@ property."
(org-x-headline-is-created-in-future) (org-x-headline-is-created-in-future)
t))) t)))
(defun org-x-headline-is-meeting-p () (defun org-x-headline-is-open-meeting-p ()
"Return t if current headline is a meeting." "Return t if current headline is a meeting."
(-when-let (keyword (org-x-headline-is-task-p)) (-when-let (keyword (org-x-headline-is-task-p))
(and (not (member keyword org-x-done-keywords)) (and (equal keyword org-x-kw-todo)
(org-x-headline-has-tag-p org-x-tag-meeting)
t)))
(defun org-x-headline-is-meeting-with-invalid-keyword-p ()
"Return t if current headline is a meeting."
(-when-let (keyword (org-x-headline-is-task-p))
(and (not (member keyword (cons org-x-kw-todo org-x-done-keywords)))
(org-x-headline-has-tag-p org-x-tag-meeting)
t)))
(defun org-x-headline-is-closed-meeting-p ()
"Return t if current headline is a meeting."
(-when-let (keyword (org-x-headline-is-task-p))
(and (member keyword org-x-done-keywords)
(org-x-headline-has-tag-p org-x-tag-meeting) (org-x-headline-has-tag-p org-x-tag-meeting)
t))) t)))
(defun org-x-headline-is-unscheduled-meeting-p () (defun org-x-headline-is-unscheduled-meeting-p ()
"Return t if current headline is an unscheduled meeting." "Return t if current headline is an unscheduled meeting."
(-when-let (keyword (org-x-headline-is-task-p)) (-when-let (keyword (org-x-headline-is-task-p))
(and (not (member keyword org-x-done-keywords)) (and (equal keyword org-x-kw-todo)
(org-x-headline-has-tag-p org-x-tag-meeting) (org-x-headline-has-tag-p org-x-tag-meeting)
(not (org-x-headline-is-scheduled-p)) (not (org-x-headline-is-scheduled-p))
t))) t)))
@ -697,27 +711,40 @@ property."
(not (org-entry-get nil "Effort" nil)) (not (org-entry-get nil "Effort" nil))
t))) t)))
(defun org-x-headline-get-meeting-drawer (drawer-name)
"Return DRAWER-NAME under current headline.
If drawer is present but has no children, return 'none'. If
drawer is present and has a plain-list, return its items as a
list of nodes. If none of these conditions are true, return nil."
(-when-let (d (->> (org-ml-parse-this-headline)
(org-ml-headline-get-section)
(--find (and (org-ml-is-type 'drawer it)
(equal (org-ml-get-property :drawer-name it)
drawer-name)))))
(-if-let (n (car (org-ml-get-children d)))
(when (org-ml-is-type 'plain-list n)
(org-ml-get-children n))
'none)))
(defun org-x-headline-get-meeting-agenda-items () (defun org-x-headline-get-meeting-agenda-items ()
"Return the agenda items for the current headline. "Return the agenda items for the current headline.
If none are present, return nil. If \"NA\" is present, return See `org-x-headline-get-meeting-drawer' for rules on what is
'none'. Agenda items are in the 'AGENDA_ITEMS' drawer and should returned."
actually be items (that is part of a plain-list node)" (org-x-headline-get-meeting-drawer "AGENDA_ITEMS"))
(-when-let (n (-some->> (org-ml-parse-this-headline)
(org-ml-headline-get-section)
(--find (and (org-ml-is-type 'drawer it)
(equal (org-ml-get-property :drawer-name it)
"AGENDA_ITEMS")))
(org-ml-get-children)
(car)))
(let ((y (org-ml-get-type n)))
(cond
((eq y 'plain-list)
(org-ml-get-children n))
((and (eq y 'paragraph)
(equal "NA" (s-trim (car (org-ml-get-children n)))))
'none)))))
(defun org-x-headline-is-meeting-without-agenda-p () (defun org-x-headline-get-meeting-action-items ()
"Return the action items for the current headline.
See `org-x-headline-get-meeting-drawer' for rules on what is
returned."
(org-x-headline-get-meeting-drawer "ACTION_ITEMS"))
(defun org-x-headline-get-meeting-unresolved-agenda-items ()
"Return unresolved agenda items for current headline."
(let ((items (org-x-headline-get-meeting-agenda-items)))
(when (and items (not (eq 'none items)))
(--remove (eq 'on (org-ml-get-property :checkbox it)) items))))
(defun org-x-headline-is-open-meeting-without-agenda-p ()
"Return t if current headline is a meeting with no agenda." "Return t if current headline is a meeting with no agenda."
(-when-let (keyword (org-x-headline-is-task-p)) (-when-let (keyword (org-x-headline-is-task-p))
(and (not (member keyword org-x-done-keywords)) (and (not (member keyword org-x-done-keywords))
@ -725,6 +752,22 @@ actually be items (that is part of a plain-list node)"
(not (org-x-headline-get-meeting-agenda-items)) (not (org-x-headline-get-meeting-agenda-items))
t))) t)))
(defun org-x-headline-is-closed-meeting-without-action-items-p ()
"Return t if current headline is a meeting with no action items."
(-when-let (keyword (org-x-headline-is-task-p))
(and (member keyword org-x-done-keywords)
(org-x-headline-has-tag-p org-x-tag-meeting)
(not (org-x-headline-get-meeting-action-items))
t)))
(defun org-x-headline-is-closed-meeting-with-unresolved-agenda-p ()
"Return t if current headline is a meeting with unresolved agenda items."
(-when-let (keyword (org-x-headline-is-task-p))
(and (member keyword org-x-done-keywords)
(org-x-headline-has-tag-p org-x-tag-meeting)
(org-x-headline-get-meeting-unresolved-agenda-items)
t)))
;; (defun org-x-is-todo-child (keyword) ;; (defun org-x-is-todo-child (keyword)
;; "Return t if current headline has a parent (at any level) with todo KEYWORD." ;; "Return t if current headline has a parent (at any level) with todo KEYWORD."
;; (let ((has-keyword-parent)) ;; (let ((has-keyword-parent))