The all-mighty org configuration
(require 'my-org )
(require 'my-org-agenda-files )
(add-to-list 'load-path
(ef "submodule/org-fstree"))
(require 'org-fstree)
(use-package org-bullets)
(when (not (eq system-type 'windows-nt))
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
(use-package calfw)
(use-package calfw-ical)
(use-package calfw-gcal)
(use-package calfw-org)
(global-set-key (kbd " C-c A" ) 'cfw:open-org-calendar )
(setq cfw:org-overwrite-default-keybinding t )
sync with google calendar
(defvar url-http-method )
(defvar url-http-data )
(defvar url-http-extra-headers )
(defvar oauth--token-data )
(defvar url-callback-function )
(require 'url-http )
(unless (package-installed-p 'org-caldav )
(use-package oauth2)
(use-package org-caldav))
(setq epa-pinentry-mode 'loopback )
(setq plstore-cache-passphrase-for-symmetric-encryption t )
(save-excursion
(let ((filename (ef " google-calendar-secret.el" )))
(when (file-exists-p filename)
(set-buffer (find-file-noselect filename))
(let ((var (eval (read (buffer-string )))))
(setq org-caldav-oauth2-client-id (car var)
org-caldav-oauth2-client-secret (cadr var)))
(kill-buffer ))))
; ; (setq org-caldav-url 'google
; ; org-caldav-calendar-id "[email protected] "
; ; org-caldav-inbox "~/MEGA/org/agenda/test.org"
; ; org-caldav-files '("~/MEGA/org/agenda/agenda.org")
; ; org-icalendar-include-todo nil
; ; org-icalendar-include-sexps t
; ; org-icalendar-categories '(all-tags category)
; ; org-icalendar-use-deadline '(event-if-todo event-if-not-todo todo-due)
; ; org-icalendar-use-scheduled '(event-if-todo event-if-not-todo todo-start)
; ; org-icalendar-with-timestamps nil
; ; org-caldav-delete-org-entries 'never)
(setq org-caldav-url " https://99.57.234.31/remote.php/dav/calendars/bchu"
org-caldav-calendar-id " orgmode"
org-caldav-inbox " ~/MEGA/org/agenda/test.org"
org-caldav-files '(" ~/MEGA/org/agenda/agenda.org" " ~/MEGA/org/agenda/classes_caldav_workaround.org" ))
(setq org-icalendar-alarm-time 30
org-icalendar-include-todo nil
org-icalendar-include-sexps t
org-icalendar-categories '(all-tags category)
org-icalendar-use-deadline '(event-if-todo event-if-not-todo todo-due)
org-icalendar-use-scheduled '(todo-start event-if-todo)
org-icalendar-with-timestamps nil
org-caldav-delete-org-entries 'never )
(setq org-caldav-skip-conditions '(nottodo (" TODO" " NEXT" ))
org-caldav-exclude-tags '(" ARCHIVE" " _nosync_" ))
(use-package org-re-reveal)
(setq org-re-reveal-root "file:///home/benson/.reveal.js")
(add-to-list 'load-path
(ef "submodule/org-reveal"))
(require 'ox-reveal)
(setq org-reveal-root "file:///home/benson/.reveal.js")
(setq org-structure-template-alist (remove-if (lambda (c) (string= (car c) "n")) org-structure-template-alist))
(use-package org-timeline)
(remove-hook 'org-agenda-finalize-hook 'org-timeline-insert-timeline )
(require 'ob-core )
(require 'ob-clojure )
(require 'ob-plantuml )
(use-package plantuml-mode)
(setq org-babel-clojure-backend 'cider )
(org-babel-do-load-languages
'org-babel-load-languages
'((clojure . t )
(plantuml . t )
(emacs-lisp . t )
(shell . t )
(dot . t )))
(defun my-org-confirm-babel-evaluate (lang body )
(not (member lang '(" plantuml" ))))
(setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate )
(setq org-plantuml-jar-path " /usr/share/java/plantuml/plantuml.jar" )
(use-package helm-org-rifle)
(global-set-key (kbd " C-c o r" ) 'helm-org-rifle )
(setq helm-org-rifle-test-against-path t )
(use-package org-mru-clock)
(defun my/org-clock-move-to-other ()
(interactive )
(forward-char 6 )
(while (condition-case nil
(progn
(previous-line )
(org-clock-convenience-goto-ts)
nil )
(error t ))))
(defun my/org-clock-move-up ()
(interactive )
(org-clock-convenience-timestamp-up)
(my/org-clock-move-to-other)
(org-clock-convenience-timestamp-up))
(use-package org-clock-convenience
:ensure t
:bind (:map org-agenda-mode-map
(" <S-up>" . org-clock-convenience-timestamp-up)
(" <S-down>" . org-clock-convenience-timestamp-down)
(" <S-M-up>" . org-clock-convenience-timestamp-up)
(" <S-M-down>" . org-clock-convenience-timestamp-down)
(" ö" . org-clock-convenience-fill-gap)
(" é" . org-clock-convenience-fill-gap-both)))
(setq org-agenda-clock-consistency-checks
'(:max-duration " 10:00"
:min-duration 0
:max-gap 0
:gap-ok-around (" 4:00" )
; ; :default-face ((:background "DarkRed")
; ; (:foreground "white"))
; ; :overlap-face nil
; ; :gap-face ((:background "DarkRed")
; ; (:foreground "white"))
; ; :no-end-time-face nil
; ; :long-face nil
; ; :short-face nil
))
(org-clock-persistence-insinuate )
(setq org-clock-in-resume t )
(setq org-clock-mode-line-total 'today )
(setq org-clock-persist t )
(org-clock-persistence-insinuate )
(setq org-clock-continuously t )
(use-package org-brain :ensure t
:init
(global-set-key (kbd "M-'") 'org-brain-visualize)
(setq org-brain-path "~/MEGA/org/brain/")
;; For Evil users
(with-eval-after-load 'evil
(evil-set-initial-state 'org-brain-visualize-mode 'emacs))
:config
(setq org-id-track-globally t)
(setq org-id-locations-file (ef ".org-id-locations"))
(push '("b" "Brain" plain (function org-brain-goto-end)
"* %i%?" :empty-lines 1)
org-capture-templates)
(setq org-brain-visualize-default-choices 'all)
(setq org-brain-title-max-length 0)
(define-key org-brain-visualize-mode-map (kbd "^") 'org-brain-visualize-back))
(when (not my-ec/is-wsl)
(setq browse-url-browser-function 'browse-url-firefox ))
(require 'ox-latex )
(require 'ox-beamer )
(use-package org-jira)
(setq jiralib-url " https://wenningbai.atlassian.net/" )
(add-to-list 'load-path (ef " submodule/org-now" ))
(require 'org-now )
(setq org-now-location
nil )
(defun cfw:open-org-calendar-no-projects (&args )
" Open an org schedule calendar in the new buffer."
(interactive )
(save-excursion
(let ((buf (get-buffer " *cfw-calendar*" )))
(if buf
(switch-to-buffer buf)
(let* ((org-agenda-skip-function 'my/agenda-custom-skip )
(source1 (cfw:org-create-source))
(curr-keymap (if cfw:org-overwrite-default-keybinding cfw:org-custom-map cfw:org-schedule-map))
(cp (cfw:create-calendar-component-buffer
:view 'two-weeks
:contents-sources (list source1)
:custom-map curr-keymap
:sorter 'cfw:org-schedule-sorter )))
(switch-to-buffer (cfw:cp-get-buffer cp))
(set (make-variable-buffer-local 'org-agenda-skip-function )
'my/agenda-custom-skip )
(when (not org-todo-keywords-for-agenda)
(message " Warn : open org-agenda buffer first. " )))
))))
(setq org-agenda-tags-todo-honor-ignore-options t)
(defun bh/org-auto-exclude-function (tag)
"Automatic task exclusion in the agenda with / RET"
(when (string= tag "online")
(concat "-" tag)))
(org-defkey org-agenda-mode-map
"A"
'org-agenda)
(setq org-agenda-auto-exclude-function 'bh/org-auto-exclude-function)
(setq org-agenda-skip-deadline-prewarning-if-scheduled 'pre-scheduled)
(setq org-agenda-skip-scheduled-if-deadline-is-shown nil)
(setq org-agenda-log-mode-items '(clock closed))
(defun org-agenda-add-separater-between-project ()
(setq buffer-read-only nil)
(save-excursion
(goto-char (point-min))
(let ((start-pos (point))
(previous t))
(re-search-forward " +agenda: +[^\\. ]" nil t)
(while (re-search-forward " +agenda: +[^\\. ]" nil t)
(beginning-of-line)
(insert "=============================================\n")
(forward-line)))))
;; I don't think this code is necessary
;; (add-to-list 'org-agenda-entry-types :deadlines*)
(setq org-agenda-hide-tags-regexp "NOT_TASKS\\|PROJECT")
(use-package htmlize)
(org-super-agenda-mode)
(setq org-super-agenda-header-separator "")
(defun my/org-checkbox-todo ()
" Switch header TODO state to DONE when all checkboxes are ticked, to TODO otherwise"
(let ((todo-state (org-get-todo-state )) beg end)
(unless (not todo-state)
(save-excursion
(org-back-to-heading t )
(setq beg (point ))
(end-of-line )
(setq end (point ))
(goto-char beg)
(if (re-search-forward " \\ [\\ ([0-9]*%\\ )\\ ]\\ |\\ [\\ ([0-9]*\\ )/\\ ([0-9]*\\ )\\ ]"
end t )
(if (match-end 1 )
(if (equal (match-string 1 ) " 100%" )
(unless (string-equal todo-state " DONE" )
(org-todo 'done ))
(unless (string-equal todo-state " TASK" )
(org-todo 'todo )))
(if (and (> (match-end 2 ) (match-beginning 2 ))
(equal (match-string 2 ) (match-string 3 )))
(unless (string-equal todo-state " DONE" )
(org-todo 'done ))
(unless (string-equal todo-state " TASK" )
(org-todo " TASK" )))))))))
(add-hook 'org-checkbox-statistics-hook 'my/org-checkbox-todo )
(defun make-org-file (filename )
" Make an org buffer in folder for all new incoming org files"
(interactive " MName: " )
(switch-to-buffer (find-file-noselect (concat " ~/MEGA/org/random/" filename " .org" ))))
(defun make-encrypted-org-file (filename )
(interactive " MName: " )
(switch-to-buffer (find-file-noselect (concat " ~/MEGA/org/random/" filename " .gpg" )))
(insert " # -*- mode:org; epa-file-encrypt-to: (\" [email protected] \" ) -*-\n\n " )
(org-mode ))
(defun view-org-files ()
" Convenient way for openning up org folder in dired"
(interactive )
(dired " ~/MEGA/org/" ))
(defun my/org-read-datetree-date (d )
" Parse a time string D and return a date to pass to the datetree functions."
(let ((dtmp (nthcdr 3 (parse-time-string d))))
(list (cadr dtmp) (car dtmp) (caddr dtmp))))
(defun my/org-refile-to-archive-datetree (&optional bfn )
" Refile an entry to a datetree under an archive."
(interactive )
(require 'org-datetree )
(let* ((org-read-date-prefer-future nil )
(bfn (or bfn (find-file-noselect (expand-file-name (my/agenda-file " datetree.org" )))))
(datetree-date (my/org-read-datetree-date (org-read-date t nil ))))
(org-refile nil nil (list nil (buffer-file-name bfn) nil
(with-current-buffer bfn
(save-excursion
(org-datetree-find-date-create datetree-date)
(point ))))))
(setq this-command 'my/org-refile-to-journal ))
(defun my/browse-url-qutebrowser (url &optional new-window )
(interactive )
(start-process (concat " qutebrowser " url)
nil
" qutebrowser"
url))
; ;(setq browse-url-browser-function #'my/browse-url-qutebrowser)
; ;(setq browse-url-browser-function #'browse-url-firefox)
new headline set property
(defun my/org-set-created-property (&rest args )
(when-let (f (buffer-file-name ))
(let ((fname (expand-file-name f)))
(when (remove-if-not (lambda (x ) (string= fname (expand-file-name x))) org-agenda-files)
(let ((ts (format-time-string " [%Y-%m-%d %a %H:%M]" )))
(org-set-property " CREATED" ts))))))
(advice-add #'org-insert-heading
:after
#'my/org-set-created-property )
Code for deleting empty blocks
(defvar my/delete-blocks t )
(defun org-agenda-delete-empty-compact-blocks ()
" Function removes empty compact blocks.
If two lines next to each other have the
org-agenda-structure face, then delete the
previous block."
(unless org-agenda-compact-blocks
(user-error " Compact blocks must be on" ))
(when my/delete-blocks
(setq buffer-read-only nil )
(save-excursion
(goto-char (point-min ))
(let ((start-pos (point ))
(previous nil ))
(while (not (eobp ))
(cond
((let ((face (get-char-property (point ) 'face )))
(or (eq face 'org-agenda-structure )
(eq face 'org-agenda-date-today )))
(if previous
(delete-region start-pos
(point ))
(setq start-pos (point )))
(unless (org-agenda-check-type nil 'agenda )
(setq previous t )))
(t (setq previous nil )))
(forward-line ))))
(setq buffer-read-only t )))
(add-hook 'org-agenda-finalize-hook #'org-agenda-delete-empty-compact-blocks )
Highlight top priority projects
(defvar my/highlight-top-priority t )
(defun org-agenda-highlight-top-priority ()
(when my/highlight-top-priority
(setq buffer-read-only nil )
(save-excursion
(goto-char (point-min ))
(let ((start-pos (point ))
(previous nil ))
(while (re-search-forward " \\ [#A\\ ]" nil t )
(add-face-text-property (point-at-bol ) (point-at-eol ) '(:background " color-19" )))))
(setq buffer-read-only t )))
(add-hook 'org-agenda-finalize-hook #'org-agenda-highlight-top-priority )
(use-package notmuch
:config
(use-package ol-notmuch))
(defun my/org-remove-inherited-tag-strings ()
" Removes inherited tags from the headline-at-point's tag string.
Note this does not change the inherited tags for a headline,
just the tag string."
(interactive )
(org-set-tags (seq-remove (lambda (tag )
(get-text-property 0 'inherited tag))
(org-get-tags ))))
(defun my/org-clean-tags ()
" Visit last refiled headline and remove inherited tags from tag string."
(save-window-excursion
(org-refile-goto-last-stored )
(my/org-remove-inherited-tag-strings)))
(defun my/org-refile-preserve-tags (orig &rest args )
(let ((tags (org-get-tags )))
(apply orig args)))
(add-hook 'org-after-refile-insert-hook 'my/org-clean-tags )
archive sibling remove sub archive sibling
(defun my/is-archive-tree ()
(and (string= " Archive"
(org-get-heading t t t t ))
(member " ARCHIVE" (org-get-tags ))))
(defun my/archive-remove-all-sibling (&rest args )
(save-excursion
(let (points)
(ol/descendants
(when (my/is-archive-tree)
(push (point ) points)))
(mapcar (lambda (p )
(goto-char p)
(my/org-delete-promote))
points))))
(advice-add #'org-archive-to-archive-sibling
:before
#'my/archive-remove-all-sibling )
Learning chinese, setup org-drill
(use-package org-drill)
(defun org-drill-present-one-side-always (session )
(org-drill-with-hidden-comments
(org-drill-with-hidden-cloze-hints
(org-drill-with-hidden-cloze-text
(let ((drill-sections (org-drill-hide-all-subheadings-except nil )))
(when drill-sections
(save-excursion
(goto-char (nth 0 drill-sections))
(org-show-subtree )))
(org-drill--show-latex-fragments)
(ignore-errors
(org-display-inline-images t ))
(org-cycle-hide-drawers 'all )
(prog1 (org-drill-presentation-prompt session)
(org-drill-hide-subheadings-if 'org-drill-entry-p )))))))
(add-to-list 'org-drill-card-type-alist
'(" oneside" org-drill-present-one-side-always nil t ))
; ; (pop org-drill-card-type-alist)
Insert inactive timestamp after last org-datetree–find-create
(defun org-datetree--find-create-add-timestamp (regex-template year &optional month day insert )
(save-excursion
(when day
(let ((lnum (line-number-at-pos )))
(next-line )
(when (= lnum (line-number-at-pos ))
(end-of-line )
(insert " \n " )))
(unless (looking-at-p (rx " [" (repeat 4 digit) " -" (repeat 2 digit) " -"
(repeat 2 digit) " " (repeat 3 alpha) " ]" ))
(insert (format-time-string " [%Y-%m-%d %a]" ))))))
(advice-add #'org-datetree--find-create
:after
#'org-datetree--find-create-add-timestamp )
(defun im-bored ()
(interactive )
(org-ql-search (append org-agenda-files
(list (my/agenda-file " when_im_bored.org" )
(my/agenda-file " eternal.org" )))
'(and (tags-local " bored" ))))
(use-package org-noter
:config
; ; (unless (eq 'hash-table (type-of face-new-frame-defaults))
; ; (require 'face-copier)
; ; (def-face-copier x-show-tip-faces (sym)
; ; nil
; ; tooltip)
; ; (defun dont-copy-faces-for-x-show-tip (orig &rest args)
; ; (override1-face x-show-tip-faces
; ; (apply orig args)))
; ; (advice-add #'x-show-tip
; ; :around
; ; #'dont-copy-faces-for-x-show-tip))
)
(use-exwm
:config
(setq org-noter-always-create-frame nil ))
(defun my/tickle-todo ()
(interactive )
(org-agenda-todo " TICKLER" )
(org-agenda-schedule))
(define-key org-agenda-mode-map (kbd " T" ) #'my/tickle-todo )
(require 'org-wiki)
(setq org-wiki-location-list
'("~/MEGA/org/wiki"))
(setq org-wiki-template
"#+TITLE: %n\n#+DESCRIPTION:\n#+KEYWORDS:\n#+STARTUP: content\n\n\n- Related: \n\n* Backlinks\n#+STARTUP: folded\n\n* %n\n")
(defun org-wiki-insert-backlink (back-from back-to)
(let ((wiki-link (format "[[wiki:%s][%s]]"
back-to back-to))
(file (save-window-excursion (org-wiki--open-page back-from)
(current-buffer))))
(with-current-buffer file
(beginning-of-buffer)
(when (not (save-excursion
(search-forward wiki-link nil t)))
(search-forward "* Backlinks")
(forward-line 2)
(beginning-of-line)
(insert "- " wiki-link "\n")
(save-buffer)))))
(defun my/org-wiki-insert-new ()
(interactive)
(let ((page-name (read-string "Page: ")))
(save-excursion (insert (org-make-link-string (concat "wiki:" page-name)
page-name
)))
(org-wiki-insert-backlink
page-name
(org-wiki--current-page))))
(advice-add #'org-wiki-insert-new
:override
#'my/org-wiki-insert-new)
(defun my/org-wiki-insert-link ()
"Insert a Wiki link at point for a existing page."
(interactive)
(org-wiki--helm-selection
(lambda (page)
(insert (org-wiki--make-link page))
(org-wiki-insert-backlink
page
(org-wiki--current-page)))))
(advice-add #'org-wiki-insert-link
:override
#'my/org-wiki-insert-link)
(require 'org-ql )
; ; (defvar bootstrap-version)
; ; (let ((bootstrap-file
; ; (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
; ; (bootstrap-version 5))
; ; (unless (file-exists-p bootstrap-file)
; ; (with-current-buffer
; ; (url-retrieve-synchronously
; ; "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
; ; 'silent 'inhibit-cookies)
; ; (goto-char (point-max))
; ; (eval-print-last-sexp)))
; ; (load bootstrap-file nil 'nomessage))
; ; (setq straight-vc-git-default-protocol 'ssh)
(define-prefix-command '*org-roam-map* )
(define-key pestctrl-minor-mode-map
(kbd " C-c n" )
'*org-roam-map* )
(use-package org-roam
:after org
:custom
(org-roam-directory (my/org-file " org-roam" ))
(org-roam-use-completion-everywhere t )
:bind (:map *org-roam-map*
(" h" . org-roam-buffer-toggle)
(" f" . my/org-roam-find-file)
(" F" . my/org-roam-find-daily)
(" p" . my/org-roam-find-project)
(" T" . org-roam-dailies-goto-today)
(" t" . org-roam-dailies-capture-today)
(" i" . org-roam-node-insert)
(" w" . org-roam-refile)
(" j" . my/org-roam-logger-capture-current)
:map org-mode-map
(" C-M-i" . completion-at-point))
:init
(setq org-roam-v2-ack t )
:config
(org-roam-setup)
(setq org-roam-dailies-directory " daily/" )
(setq org-roam-dailies-capture-templates
'((" d" " Journal" entry " * %<%H:%M> %?"
:unnarrowed t
:target (file+head+olp " %<%Y-%m-%d>.org"
" #+title: %<%Y-%m-%d>\n #+filetags: %<:%Y:%B:dailies>\n "
(" Journal" )))
; ; ("m" "Most Important Thing" entry "* TODO %? :mit:"
; ; :target (file+head+olp "%<%Y-%m-%d>.org"
; ; "#+title: %<%Y-%m-%d>\n#+filetags: %<:%Y:%B:>\n"
; ; ("Most Important Thing(s)")))
))
(require 'my-org-roam-logger )
(setq org-roam-capture-templates
'((" d" " default" plain " %?" :target
(file+head " %<%Y%m%d%H%M%S>-${slug}.org" " #+title: ${title}\n " )
:unnarrowed t )
(" t" " tech tips" plain " %?" :target
(file+head " %<%Y%m%d%H%M%S>-${slug}.org" " #+title: ${title}\n #+filetags: techtips\n " )
:unnarrowed t )))
(require 'org-roam-util )
(defun my/org-roam-find-file ()
(interactive )
; ; Select a project file to open, creating it if necessary
(org-roam-node-find
nil nil
(lambda (node )
(let ((tags (org-roam-node-tags node)))
(not (member " project" tags))))))
(defun my/org-roam-find-project ()
(interactive )
; ; Select a project file to open, creating it if necessary
(org-roam-node-find
nil nil
(lambda (node )
(let ((tags (org-roam-node-tags node)))
(and (eq (org-roam-node-level node) 0 )
(member " project" tags)
(not (member " done" tags)))))
nil
:templates
'((" p" " project" plain " "
:if-new (file+head " %<%Y%m%d%H%M%S>-${slug}.org" " #+title: ${title}: %^{Description}\n #+category: ${title}\n #+filetags: project" )
:unnarrowed t ))))
(use-package consult-org-roam
:demand t
:commands (my/org-roam-find-daily)
:config
(require 'org-roam-util )
(defun consult-org-roam-file-find (arg )
" Find org-roam node with preview, if ARG open in other window."
(interactive " P" )
(cl-letf (((symbol-function 'org-roam-node-read )
(symbol-function 'consult-org-roam-node-read )))
(let ((other-window (if arg t nil )))
(org-roam-node-find other-window nil #'consult-org-roam--node-file-p ))))
(defun my/org-roam-find-daily ()
(interactive )
(cl-letf (((symbol-function 'org-roam-node-read )
(symbol-function 'consult-org-roam-node-read )))
(org-roam-node-find nil nil
(my/org-roam-filter-by-tag " dailies" )
(lambda (x y )
(string-lessp (org-roam-node-file (cdr y))
(org-roam-node-file (cdr x)))))))))
; ; (require 'org-roam-protocol)
; ; (mapcar
; ; (lambda (face)
; ; (set-face-attribute face nil :inherit 'fixed-pitch))
; ; '(org-block org-block-begin-line org-block-end-line org-code
; ; org-document-info-keyword org-done org-formula org-indent
; ; org-meta-line org-special-keyword org-table org-todo
; ; org-verbatim org-date org-drawer))
Restriction from org-agenda
(define-key org-agenda-mode-map (kbd " N" ) #' (lambda ()
(interactive )
(org-agenda-set-restriction-lock-from-agenda nil )
(org-agenda-redo)))
(define-key org-agenda-mode-map (kbd " U" ) #'org-agenda-remove-restriction-lock )
Org mode magit update commands
(when (executable-find "~/bin/gitwatch")
(defun start-gitwatch ()
(interactive)
(if (and gitwatch-process
(process-live-p gitwatch-process))
(message "gitwatch already exists")
(setq gitwatch-process
(start-process-shell-command "gitwatch"
nil
"~/bin/gitwatch -r origin -b laptop -m 'Gitwatch commit: %d' ~/MEGA/org/agenda"))))
(defun kill-gitwatch ()
(interactive)
(when (and gitwatch-process
(process-live-p gitwatch-process))
(kill-process gitwatch-process)))
(defvar gitwatch-process nil)
(add-to-list 'emacs-startup-hook
#'start-gitwatch))
(defvar magit-sentinel-after-function nil)
(defun magit-sentinel-after (&rest args)
(while
(when-let (fun (pop magit-sentinel-after-function))
(funcall fun)
t)))
(advice-add #'magit-process-sentinel
:after
#'magit-sentinel-after)
(defun org-update-main ()
(interactive)
(let ((default-directory "~/MEGA/org/agenda"))
(kill-gitwatch)
;; Make sure local changes are committed
(when (magit-changed-files "HEAD")
(magit-stage-modified t)
(magit-commit-create `("-m" ,(format "Pre-merge commit: %s" (format-time-string "%D %T")))))
;; Update all submodules
(shell-command "git submodule foreach git pull origin master")
(when (magit-changed-files "HEAD")
(magit-stage-modified t)
(magit-commit-create `("-m" ,(format "Updated submodules: %s" (format-time-string "%D %T")))))
;; Do a fetch
(push #'org-update-initiate-merge magit-sentinel-after-function)
(magit-run-git-async '("fetch" "--all"))))
(defun org-update-initiate-merge ()
;; Check if mobile has updated
(let ((base (vc-git-mergebase "laptop" "origin/mobile"))
(laptop (vc-git--rev-parse "laptop"))
(origin-mobile (vc-git--rev-parse "origin/mobile")))
;; If so, turn off gitwatch and initiate a merge.
(when (and (not (string= base laptop))
(not (string= base origin-mobile)))
(add-hook 'git-commit-post-finish-hook ;;magit-post-commit-hook
#'org-update-post-commit)
(magit-merge-plain "origin/mobile"))))
(defun org-update-post-commit ()
;; After merge, do a push to both laptop and mobile
;; Also restart gitwatch
(call-interactively #'magit-push-current-to-upstream)
(magit-push-current "origin/mobile" nil)
(start-gitwatch)
(remove-hook 'git-commit-post-finish-hook
#'org-update-post-commit))
(magit-run-git-async '("fetch" "--all"))
;; (setq debug-the-process (magit-run-git-async '("fetch" "--all")
;; :sentinel '(lambda (process event) (message "Done"))))
(add-to-list 'load-path (ef " submodule/elgantt" ))
(require 'elgantt )
(use-package org-kanban)
(defun my/org-dblock-write:kanban (params )
" Create the kanban dynamic block.
PARAMS may contain `:mirrored`, `:match`, `:scope`, `:layout`, `:range`, `:depth` and `:compressed`."
(insert
(let*
(
(mirrored (plist-get params :mirrored ))
(compressed (plist-get params :compressed ))
(match (plist-get params :match ))
(range (plist-get params :range ))
(depth (org-kanban--params-depth params))
(layout (org-kanban//params-layout params))
(files (org-kanban//params-files params))
(scope (org-kanban//params-scope params files ))
(todo-keywords (split-string (plist-get params :todo ) " |" ))
(sort-spec-string (plist-get params :sort ))
(sort-spec (org-kanban--prepare-comparator sort-spec-string todo-keywords))
(todo-infos (org-map-entries 'org-kanban//todo-info-extract match scope))
(sorted-todo-infos (if sort-spec (-sort sort-spec todo-infos) todo-infos))
(filtered-todo-infos (-filter (lambda (todo-info )
(org-kanban//range-fun
(org-kanban--todo-info-get-keyword todo-info)
(org-kanban//todo-info-get-keywords todo-info)
(car range)
(cdr range)))
sorted-todo-infos))
(filtered-todo-infos (-filter (lambda (todo-info )
(if (eq scope 'tree )
(let* (
(tree-info (nth 0 todo-infos))
(tree-level (org-kanban--todo-info-get-level tree-info)))
(< (org-kanban--todo-info-get-level todo-info) (+ depth tree-level)))
(<= (org-kanban--todo-info-get-level todo-info) depth))) filtered-todo-infos))
(filtered-todo-infos (-filter (lambda (todo-info ) (nth 4 (org-kanban//todo-info-get-heading todo-info))) filtered-todo-infos))
(row-for (lambda (todo-info ) (org-kanban//row-for todo-info todo-keywords layout)))
(table-title (string-join todo-keywords " |" ))
(filtered (-filter (lambda (todo-info )
(-intersection
(list (org-kanban//heading-get-todo-keyword (org-kanban//todo-info-get-heading todo-info)))
(org-kanban//todo-info-get-keywords todo-info)))
filtered-todo-infos))
(table (if compressed
(org-kanban//compressed-rows (-map row-for filtered))
(let* ((rows (-map row-for filtered)))
(if rows
(--reduce (format " %s \n %s " acc it) rows)
" "
)))))
(format " |%s |\n |--|\n %s " table-title table)))
(org-table-align ))
(advice-add #'org-dblock-write:kanban
:override
#'my/org-dblock-write:kanban )
(quelpa `(org-timeblock :repo " ichernyshovvv/org-timeblock" :fetcher github))
(use-package org-hyperscheduler)
; ; (add-hook 'org-mode-hook (lambda ()
; ; "Beautify Org Checkbox Symbol"
; ; (push '("[ ]" . "☐") prettify-symbols-alist)
; ; (push '("[X]" . "☑" ) prettify-symbols-alist)
; ; (push '("[-]" . "❍" ) prettify-symbols-alist)
; ; (prettify-symbols-mode)))