X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=emacs_el%2Fconfiguration%2Forg-mode-configuration.el;h=b5d94a2c58481752e13ba5d41050945bf7b64324;hb=93da262266c8eaa12aee290d1d9111cf1bb6e3dd;hp=4ac6cf77ebbbe663ad04439cb7e89ecc98fe7a67;hpb=dcdee75b622e5c4760b657e6db400195000d2d45;p=lib.git diff --git a/emacs_el/configuration/org-mode-configuration.el b/emacs_el/configuration/org-mode-configuration.el index 4ac6cf7..b5d94a2 100644 --- a/emacs_el/configuration/org-mode-configuration.el +++ b/emacs_el/configuration/org-mode-configuration.el @@ -1,6 +1,14 @@ +(require 'org-id) +(require 'reftex) +(require 'gnus) + +(require 'org) +(require 'org-agenda) +(require 'org-habit) ;; The following lines are always needed. Choose your own keys. -(add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode)) -(add-hook 'org-mode-hook 'turn-on-font-lock) ; not needed when global-font-lock-mode is on +(add-to-list 'auto-mode-alist '("\\.\\(org\\|org_archive\\|txt\\)$" . org-mode)) +(eval-when-compile + (require 'cl)) (global-set-key "\C-cl" 'org-store-link) (global-set-key "\C-ca" 'org-agenda) (global-set-key "\C-cb" 'org-iswitchb) @@ -87,40 +95,69 @@ ; org mode agenda files (setq org-agenda-files - (quote ("~/projects/debbugs/debbugs.org" - "~/projects/notes/notes.org" - "~/projects/origins_of_life/ool.org" - "~/projects/sysadmin/sndservers/sndservers.org" - "~/projects/chaim/chaim.org" - "~/projects/chaim/papers/gwas_paper_2012/gwas_paper.org" - "~/projects/reviews/reviews.org" - "~/projects/fh/fh.org"))) + (quote ("~/projects/org-notes/debbugs.org" + "~/projects/org-notes/notes.org" + "~/projects/org-notes/refile.org" + "~/projects/org-notes/diary.org" + "~/projects/org-notes/ool.org" + "~/projects/org-notes/sndservers.org" + "~/projects/org-notes/chaim.org" + "~/projects/org-notes/wildman.org" + "~/projects/org-notes/uddin.org" + "~/projects/org-notes/reviews.org" + "~/projects/org-notes/hpcbio.org" + "~/org-mode/from-mobile.org" + "~/projects/org-notes/fh.org"))) + +(set-register ?n (cons 'file "~/projects/org-notes/notes.org")) +(set-register ?r (cons 'file "~/projects/org-notes/refile.org")) +(set-register ?o (cons 'file "~/projects/org-notes/ool.org")) +(set-register ?s (cons 'file "~/projects/org-notes/sndservers.org")) +(set-register ?c (cons 'file "~/projects/org-notes/chaim.org")) +(set-register ?w (cons 'file "~/projects/org-notes/wildman.org")) +(set-register ?u (cons 'file "~/projects/org-notes/uddin.org")) +(set-register ?R (cons 'file "~/projects/reviews/reviews.org")) +(set-register ?d (cons 'file "~/projects/org-notes/diary.org")) (setq org-global-properties '(("Effort_ALL 0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00"))) -(setq org-columns-default-format "%40ITEM(Task) %TAGS %PRIORITY %TODO %13SCHEDULED %13DEADLINE %6Effort{:} %CLOCKSUM") +(setq org-columns-default-format "%40ITEM(Task) %6Effort{:} %CLOCKSUM %PRIORITY %TODO %13SCHEDULED %13DEADLINE %TAGS") + +;; add automatic reminders for appointments +(defadvice org-agenda-redo (after org-agenda-redo-add-appts) + "Pressing `r' on the agenda will also add appointments." + (progn + (setq appt-time-msg-list nil) + (org-agenda-to-appt))) -(setq org-default-notes-file "~/projects/notes/notes.org") +(setq org-default-notes-file "~/projects/org-notes/notes.org") +(setq org-id-link-to-org-use-id t) (setq org-capture-templates ;; mail-specific note template, identified by "m" - '(("m" "Mail" entry (file+headline "~/projects/notes/refile.org" "Mail") + '(("m" "Mail" entry (file+headline "~/projects/org-notes/refile.org" "Mail") "* %?\n\n Source: %u, %c\n %i") - ("t" "todo" entry (file "~/projects/notes/refile.org") - "* TODO %?\n%U\n%a\n" :clock-in t :clock-resume t) - ("r" "respond" entry (file "~/projects/notes/refile.org") + ("t" "todo" entry (file "~/projects/org-notes/refile.org") + "* TODO %?\n :PROPERTIES:\n :END:\n :LOGBOOK:\n :END:\n%U\n%a\n" :clock-in t :clock-resume t) + ("r" "respond" entry (file "~/projects/org-notes/refile.org") "* NEXT Respond to %:from on %:subject\nSCHEDULED: %t\n%U\n%a\n" :clock-in t :clock-resume t :immediate-finish t) - ("n" "note" entry (file "~/projects/notes/refile.org") + ("n" "note" entry (file "~/projects/org-notes/refile.org") "* %? :NOTE:\n%U\n%a\n" :clock-in t :clock-resume t) - ("s" "schedule" entry (file "~/projects/notes/refile.org") - "* %? \n%^{scheduled:}t\n%U\n%a\n" :clock-in t :clock-resume t) - ("j" "Journal" entry (file+datetree "~/projects/notes/diary.org") + ("s" "schedule" entry (file "~/projects/org-notes/refile.org") + "* %? :cal:\n%^{scheduled:}t\n%U\n%a\n" :clock-in t :clock-resume t) + ("j" "Journal" entry (file+datetree "~/projects/org-notes/diary.org") "* %?\n%U\n" :clock-in t :clock-resume t) - ("w" "org-protocol" entry (file "~/projects/notes/refile.org") + ("w" "org-protocol" entry (file "~/projects/org-notes/refile.org") "* TODO Review %c\n%U\n" :immediate-finish t) - ("m" "Meeting" entry (file "~/projects/notes/refile.org") + ("M" "Meeting" entry (file "~/projects/org-notes/refile.org") "* MEETING with %? :MEETING:\n%U" :clock-in t :clock-resume t) - ("p" "Phone call" entry (file "~/projects/notes/refile.org") + ("S" "Seminar" entry (file "~/projects/org-notes/refile.org") + "* SEMINAR notes %? :SEMINAR:\n%U" :clock-in t :clock-resume t) + ("P" "Paper to read" entry (file+headline "~/projects/research/papers_to_read.org" "Refile") + "* TODO Get/Read %? \n%U" :clock-in t :clock-resume t) + ("p" "Phone call" entry (file "~/projects/org-notes/refile.org") "* PHONE %? :PHONE:\n%U" :clock-in t :clock-resume t) - ("h" "Habit" entry (file "~/projects/notes/refile.org") - "* NEXT %?\n%U\n%a\nSCHEDULED: %(format-time-string \"<%Y-%m-%d %a .+1d/3d>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n") + ("J" "job" entry (file "~/projects/org-notes/refile.org") + "* TODO Apply for %a%? :job:\nSCHEDULED: %(format-time-string \"<%Y-%m-%d 17:00-17:30>\")\n%U\n%a\n" :clock-in t :clock-resume t) + ("h" "Habit" entry (file "~/projects/org-notes/refile.org") + "* NEXT %?\n%U\n%a\nSCHEDULED: %(format-time-string \"<%Y-%m-%d .+1d/3d>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n%a\n") ) ) @@ -129,7 +166,7 @@ (interactive) (save-excursion (beginning-of-line 0) - (org-remove-empty-drawer-at "LOGBOOK" (point)))) + (org-remove-empty-drawer-at (point)))) (defun my/org-add-id () (interactive) @@ -157,6 +194,12 @@ (global-set-key (kbd " n") 'bh/toggle-next-task-display) (global-set-key (kbd " w") 'widen) +; change the outline mode prefix from C-c @ to C-c C-2 +(setq outline-minor-mode-prefix "C-c C-2") +;(add-hook 'outline-minor-mode-hook +; (lambda () (local-set-key (kbd "C-c C-2") +; outline-mode-prefix-map))) + (global-set-key (kbd " I") 'bh/punch-in) (global-set-key (kbd " O") 'bh/punch-out) @@ -235,7 +278,7 @@ -(add-hook 'org-clock-out-hook 'bh/remove-empty-drawer-on-clock-out 'append) +; (add-hook 'org-clock-out-hook 'bh/remove-empty-drawer-on-clock-out 'append) ; add ids on creation of nodes (add-hook 'org-capture-prepare-finalize-hook 'my/org-add-id) ; create function to create headlines in file. This comes from @@ -252,8 +295,8 @@ do not already have one." ; resolve clocks after 10 minutes of idle; use xprintidle -(setq org-clock-idle-time 10) -(setq org-clock-x11idle-program-name "xprintidle") +; (setq org-clock-idle-time 10) +; (setq org-clock-x11idle-program-name "xprintidle") ; this is from http://doc.norang.ca/org-mode.html#Capture ; use C-M-r for org mode capture @@ -272,16 +315,16 @@ do not already have one." ; Allow refile to create parent tasks with confirmation (setq org-refile-allow-creating-parent-nodes (quote confirm)) -; Use IDO for both buffer and file completion and ido-everywhere to t -(setq org-completion-use-ido t) -(setq ido-everywhere t) -(setq ido-max-directory-size 100000) -(ido-mode (quote both)) -; Use the current window when visiting files and buffers with ido -(setq ido-default-file-method 'selected-window) -(setq ido-default-buffer-method 'selected-window) -; Use the current window for indirect buffer display -(setq org-indirect-buffer-display 'current-window) +; ; Use IDO for both buffer and file completion and ido-everywhere to t +; (setq org-completion-use-ido t) +; (setq ido-everywhere t) +; (setq ido-max-directory-size 100000) +; (ido-mode (quote both)) +; ; Use the current window when visiting files and buffers with ido +; (setq ido-default-file-method 'selected-window) +; (setq ido-default-buffer-method 'selected-window) +; ; Use the current window for indirect buffer display +; (setq org-indirect-buffer-display 'current-window) ;;;; Refile settings @@ -296,7 +339,7 @@ do not already have one." ;; from Mutt, and that it will shut down emacsclient once finished; ;; fallback to legacy behavior when not invoked via org-protocol. (require 'org-protocol) -(add-hook 'org-capture-mode-hook 'delete-other-windows) +; (add-hook 'org-capture-mode-hook 'delete-other-windows) (setq my-org-protocol-flag nil) (defadvice org-capture-finalize (after delete-frame-at-end activate) "Delete frame at remember finalization" @@ -318,6 +361,9 @@ do not already have one." (defadvice org-protocol-capture (before set-org-protocol-flag activate) (setq my-org-protocol-flag t)) +(defadvice org-insert-todo-heading (after dla/create-id activate) + (org-id-get-create) + ) ;; org modules (add-to-list 'org-modules 'org-habit) @@ -343,10 +389,10 @@ Maildir, or by Message-ID." (progn (reftex-parse-all) (reftex-set-cite-format - '((?b . "[[bib::%l][%l-bib]]") - (?n . "[[note::%l][%l-notes]]") + '((?b . "[[bib:%l][%l-bib]]") + (?n . "[[notes:%l][%l-notes]]") (?c . "\\cite{%l}") - (?h . "*** %t\n:PROPERTIES:\n:Custom_ID: %l\n:END:\n[[papers:%l][%l paper]]"))) + (?h . "*** %t\n:PROPERTIES:\n:Custom_ID: %l\n:END:\n[[papers:%l][%l xoj]] [[papers-pdf:%l][pdf]]"))) )) (define-key org-mode-map (kbd "C-c )") 'reftex-citation) (define-key org-mode-map (kbd "C-c [") 'reftex-citation) @@ -357,7 +403,7 @@ Maildir, or by Message-ID." (defun org-mode-reftex-search () (interactive) - (org-open-link-from-string (format "[[notes:%s]]" (reftex-citation t)))) + (org-open-link-from-string (format "[[notes:%s]]" (first (reftex-citation t))))) (defun open-research-paper (bibtexkey) "Open a paper by bibtex key" @@ -366,11 +412,26 @@ Maildir, or by Message-ID." (format "%s %s" (substitute-in-file-name "$HOME/bin/bibtex_to_paper") bibtexkey))) (org-add-link-type "papers" 'open-research-paper) +(defun open-research-paper-pdf (bibtexkey) + "Open a paper pdf by bibtex key" + (interactive "bibtex key: ") + (shell-command + (format "%s -p evince_annot %s" + (substitute-in-file-name "$HOME/bin/bibtex_to_paper") bibtexkey))) +(org-add-link-type "papers-pdf" 'open-research-paper-pdf) + +(add-to-list 'org-link-abbrev-alist + '("notes" . + "~/projects/research/paper_notes.org::#%s")) ; I pretty much always want hiearchical checkboxes (setq org-hierachical-checkbox-statistics nil) - -;; stolen from + +;; Add \begin{equation}\end{equation} templates to the org mode easy templates +(add-to-list 'org-structure-template-alist + '("E" "\\begin{equation}\n?\n\\end{equation}")) + + ;; stolen from ;; http://www-public.it-sudparis.eu/~berger_o/weblog/2012/03/23/how-to-manage-and-export-bibliographic-notesrefs-in-org-mode/ (defun my-rtcite-export-handler (path desc format) (message "my-rtcite-export-handler is called : path = %s, desc = %s, format = %s" path desc format) @@ -388,51 +449,64 @@ Maildir, or by Message-ID." 'my-rtcite-export-handler) -(setq-default org-mobile-directory "/rzlab.ucr.edu:/sites/dav.donarmstrong.com/root/org/") +(setq-default org-mobile-directory "/linnode.donarmstrong.com:/sites/dav.donarmstrong.com/root/org/") +(when (string= system-name "linnode.donarmstrong.com") + (setq-default org-mobile-directory "/sites/dav.donarmstrong.com/root/org/")) (setq-default org-directory "/home/don/org-mode/") (setq-default org-mobile-inbox-for-pull "/home/don/org-mode/from-mobile.org") ;; org mode ical export (setq org-icalendar-timezone "America/Los_Angeles") (setq org-icalendar-use-scheduled '(todo-start event-if-todo)) -(setq org-icalendar-store-UID t) +;; we already add the id manually +;; (setq org-icalendar-store-UID t) ;; org babel support (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t ) (R . t) - (latex . t))) + (latex . t) + (ditaa . t) + (dot . t) + )) +;; use graphviz-dot for dot things +(add-to-list 'org-src-lang-modes '("dot" . graphviz-dot)) ;; org-babel-by-backend (defmacro org-babel-by-backend (&rest body) `(case (if (boundp 'backend) (org-export-backend-name backend) nil) ,@body)) +(defun my/fix-inline-images () + (when org-inline-image-overlays + (org-redisplay-inline-images))) +(add-hook 'org-babel-after-execute-hook + 'my/fix-inline-images) -;; org latex -;; stolen from http://kieranhealy.org/esk/kjhealy.html -(require 'org-latex) -;; Choose either listings or minted for exporting source code blocks. -;; Using minted (as here) requires pygments be installed. To use the -;; default listings package instead, use -;; (setq org-latex-listings t) -;; and change references to "minted" below to "listings" -; (setq org-latex-listings 'minted) - -;; default settings for minted code blocks -(setq org-latex-minted-options - '(;("frame" "single") - ("bgcolor" "bg") ; bg will need to be defined in the preamble of your document. It's defined in org-preamble-pdflatex.sty and org-preamble-xelatex.sty below. - ("fontsize" "\\small") - )) -;; turn off the default toc behavior; deal with it properly in headers to files. -(defun org-latex-no-toc (depth) - (when depth - (format "%% Org-mode is exporting headings to %s levels.\n" - depth))) -(setq org-latex-format-toc-function 'org-latex-no-toc) +;; ;; org latex +;; ;; stolen from http://kieranhealy.org/esk/kjhealy.html +;; (require 'org-latex) +;; ;; Choose either listings or minted for exporting source code blocks. +;; ;; Using minted (as here) requires pygments be installed. To use the +;; ;; default listings package instead, use +;; ;; (setq org-latex-listings t) +;; ;; and change references to "minted" below to "listings" +;; ; (setq org-latex-listings 'minted) +;; +;; ;; default settings for minted code blocks +;; (setq org-latex-minted-options +;; '(;("frame" "single") +;; ("bgcolor" "bg") ; bg will need to be defined in the preamble of your document. It's defined in org-preamble-pdflatex.sty and org-preamble-xelatex.sty below. +;; ("fontsize" "\\small") +;; )) +;; ;; turn off the default toc behavior; deal with it properly in headers to files. +;; (defun org-latex-no-toc (depth) +;; (when depth +;; (format "%% Org-mode is exporting headings to %s levels.\n" +;; depth))) +;; (setq org-latex-format-toc-function 'org-latex-no-toc) (require 'ox-latex) (add-to-list 'org-latex-classes @@ -444,6 +518,20 @@ Maildir, or by Message-ID." ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) +(setq org-beamer-outline-frame-options "") +(require 'ox-beamer) +(add-to-list 'org-latex-classes + '("beamer" + "\\documentclass[ignorenonframetext]{beamer} +[NO-DEFAULT-PACKAGES] +[PACKAGES] +[EXTRA]" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) + (add-to-list 'org-latex-classes '("membook" "\\documentclass[11pt,oneside]{memoir}\n" @@ -464,13 +552,41 @@ Maildir, or by Message-ID." ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) +(add-to-list 'org-latex-classes + '("dlacv" + "\\documentclass{dlacv} +[NO-DEFAULT-PACKAGES] +[NO-PACKAGES] +[NO-EXTRA]" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) + + +(add-to-list 'org-latex-classes + '("dlaresume" + "\\documentclass{dlaresume} +[NO-DEFAULT-PACKAGES] +[NO-PACKAGES] +[NO-EXTRA]" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) + + ;; Originally taken from Bruno Tavernier: http://thread.gmane.org/gmane.emacs.orgmode/31150/focus=31432 ;; but adapted to use latexmk 4.22 or higher. (setq org-latex-pdf-process '("latexmk -pdflatex=xelatex -bibtex -use-make -pdf %f")) ;; Default packages included in /every/ tex file, latex, pdflatex or xelatex (setq org-latex-default-packages-alist - '()) + '(("" "amsmath" t) + ("" "unicode-math" t) + )) (setq org-latex-packages-alist '(("" "graphicx" t) ("" "fontspec" t) @@ -481,6 +597,9 @@ Maildir, or by Message-ID." ("" "longtable" nil) ("" "float" ))) +;; make equations larger +(setq org-format-latex-options (plist-put org-format-latex-options :scale 2.0)) + (defun org-create-formula--latex-header () "Return LaTeX header appropriate for previewing a LaTeX snippet." (let ((info (org-combine-plists (org-export--get-global-options @@ -504,3 +623,483 @@ Maildir, or by Message-ID." (if (member "ignoreheading" (org-element-property :tags headline)) (setq ad-return-value contents) ad-do-it)) + +;; keep latex logfiles + +(setq org-latex-remove-logfiles nil) + +;; helper functions +(defun bh/is-project-p () + "Any task with a todo keyword subtask" + (save-restriction + (widen) + (let ((has-subtask) + (subtree-end (save-excursion (org-end-of-subtree t))) + (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) + (save-excursion + (forward-line 1) + (while (and (not has-subtask) + (< (point) subtree-end) + (re-search-forward "^\*+ " subtree-end t)) + (when (member (org-get-todo-state) org-todo-keywords-1) + (setq has-subtask t)))) + (and is-a-task has-subtask)))) + +(defun bh/is-project-subtree-p () + "Any task with a todo keyword that is in a project subtree. +Callers of this function already widen the buffer view." + (let ((task (save-excursion (org-back-to-heading 'invisible-ok) + (point)))) + (save-excursion + (bh/find-project-task) + (if (equal (point) task) + nil + t)))) + +(defun bh/is-task-p () + "Any task with a todo keyword and no subtask" + (save-restriction + (widen) + (let ((has-subtask) + (subtree-end (save-excursion (org-end-of-subtree t))) + (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) + (save-excursion + (forward-line 1) + (while (and (not has-subtask) + (< (point) subtree-end) + (re-search-forward "^\*+ " subtree-end t)) + (when (member (org-get-todo-state) org-todo-keywords-1) + (setq has-subtask t)))) + (and is-a-task (not has-subtask))))) + +(defun bh/is-subproject-p () + "Any task which is a subtask of another project" + (let ((is-subproject) + (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) + (save-excursion + (while (and (not is-subproject) (org-up-heading-safe)) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq is-subproject t)))) + (and is-a-task is-subproject))) + +(defun bh/list-sublevels-for-projects-indented () + "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. + This is normally used by skipping functions where this variable is already local to the agenda." + (if (marker-buffer org-agenda-restrict-begin) + (setq org-tags-match-list-sublevels 'indented) + (setq org-tags-match-list-sublevels nil)) + nil) + +(defun bh/list-sublevels-for-projects () + "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. + This is normally used by skipping functions where this variable is already local to the agenda." + (if (marker-buffer org-agenda-restrict-begin) + (setq org-tags-match-list-sublevels t) + (setq org-tags-match-list-sublevels nil)) + nil) + +(defvar bh/hide-scheduled-and-waiting-next-tasks t) + +(defun bh/toggle-next-task-display () + (interactive) + (setq bh/hide-scheduled-and-waiting-next-tasks (not bh/hide-scheduled-and-waiting-next-tasks)) + (when (equal major-mode 'org-agenda-mode) + (org-agenda-redo)) + (message "%s WAITING and SCHEDULED NEXT Tasks" (if bh/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) + +(defun bh/skip-stuck-projects () + "Skip trees that are not stuck projects" + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (if (bh/is-project-p) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (has-next )) + (save-excursion + (forward-line 1) + (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) + (unless (member "WAITING" (org-get-tags-at)) + (setq has-next t)))) + (if has-next + nil + next-headline)) ; a stuck project, has subtasks but no next task + nil)))) + +(defun bh/skip-non-stuck-projects () + "Skip trees that are not stuck projects" + ;; (bh/list-sublevels-for-projects-indented) + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (if (bh/is-project-p) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (has-next )) + (save-excursion + (forward-line 1) + (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) + (unless (member "WAITING" (org-get-tags-at)) + (setq has-next t)))) + (if has-next + next-headline + nil)) ; a stuck project, has subtasks but no next task + next-headline)))) + +(defun bh/skip-non-projects () + "Skip trees that are not projects" + ;; (bh/list-sublevels-for-projects-indented) + (if (save-excursion (bh/skip-non-stuck-projects)) + (save-restriction + (widen) + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((bh/is-project-p) + nil) + ((and (bh/is-project-subtree-p) (not (bh/is-task-p))) + nil) + (t + subtree-end)))) + (save-excursion (org-end-of-subtree t)))) + +(defun bh/skip-project-trees-and-habits () + "Skip trees that are projects" + (save-restriction + (widen) + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((bh/is-project-p) + subtree-end) + ((org-is-habit-p) + subtree-end) + (t + nil))))) + +(defun bh/skip-projects-and-habits-and-single-tasks () + "Skip trees that are projects, tasks that are habits, single non-project tasks" + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (cond + ((org-is-habit-p) + next-headline) + ((and bh/hide-scheduled-and-waiting-next-tasks + (member "WAITING" (org-get-tags-at))) + next-headline) + ((bh/is-project-p) + next-headline) + ((and (bh/is-task-p) (not (bh/is-project-subtree-p))) + next-headline) + (t + nil))))) + +(defun bh/skip-project-tasks-maybe () + "Show tasks related to the current restriction. +When restricted to a project, skip project and sub project tasks, habits, NEXT tasks, and loose tasks. +When not restricted, skip project and sub-project tasks, habits, and project related tasks." + (save-restriction + (widen) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (next-headline (save-excursion (or (outline-next-heading) (point-max)))) + (limit-to-project (marker-buffer org-agenda-restrict-begin))) + (cond + ((bh/is-project-p) + next-headline) + ((org-is-habit-p) + subtree-end) + ((and (not limit-to-project) + (bh/is-project-subtree-p)) + subtree-end) + ((and limit-to-project + (bh/is-project-subtree-p) + (member (org-get-todo-state) (list "NEXT"))) + subtree-end) + (t + nil))))) + +(defun bh/skip-project-tasks () + "Show non-project tasks. +Skip project and sub-project tasks, habits, and project related tasks." + (save-restriction + (widen) + (let* ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((bh/is-project-p) + subtree-end) + ((org-is-habit-p) + subtree-end) + ((bh/is-project-subtree-p) + subtree-end) + (t + nil))))) + +(defun bh/skip-non-project-tasks () + "Show project tasks. +Skip project and sub-project tasks, habits, and loose non-project tasks." + (save-restriction + (widen) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (cond + ((bh/is-project-p) + next-headline) + ((org-is-habit-p) + subtree-end) + ((and (bh/is-project-subtree-p) + (member (org-get-todo-state) (list "NEXT"))) + subtree-end) + ((not (bh/is-project-subtree-p)) + subtree-end) + (t + nil))))) + +(defun bh/skip-projects-and-habits () + "Skip trees that are projects and tasks that are habits" + (save-restriction + (widen) + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((bh/is-project-p) + subtree-end) + ((org-is-habit-p) + subtree-end) + (t + nil))))) + +(defun bh/skip-non-subprojects () + "Skip trees that are not projects" + (let ((next-headline (save-excursion (outline-next-heading)))) + (if (bh/is-subproject-p) + nil + next-headline))) +; +;; Resume clocking task when emacs is restarted +(org-clock-persistence-insinuate) +;; +;; Show lot of clocking history so it's easy to pick items off the C-F11 list +(setq org-clock-history-length 23) +;; Resume clocking task on clock-in if the clock is open +(setq org-clock-in-resume t) +;; Change tasks to NEXT when clocking in +(setq org-clock-in-switch-to-state 'bh/clock-in-to-next) +;; (setq org-clock-in-switch-to-state "NEXT") +;; Separate drawers for clocking and logs +(setq org-drawers (quote ("PROPERTIES" "LOGBOOK"))) +;; Save clock data and state changes and notes in the LOGBOOK drawer +(setq org-clock-into-drawer t) +(setq org-log-into-drawer t) +;; Sometimes I change tasks I'm clocking quickly - this removes clocked tasks with 0:00 duration +(setq org-clock-out-remove-zero-time-clocks t) +;; Clock out when moving task to a done state +(setq org-clock-out-when-done t) +;; Save the running clock and all clock history when exiting Emacs, load it on startup +(setq org-clock-persist t) +;; Do not prompt to resume an active clock +(setq org-clock-persist-query-resume nil) +;; Enable auto clock resolution for finding open clocks +(setq org-clock-auto-clock-resolution (quote when-no-clock-is-running)) +;; Include current clocking task in clock reports +(setq org-clock-report-include-clocking-task t) + +;; the cache seems to be broken +(setq org-element-use-cache nil) + +(defvar bh/keep-clock-running nil) + +(defun bh/clock-in-to-next (kw) + "Switch a task from TODO to NEXT when clocking in. +Skips capture tasks, projects, and subprojects. +Switch projects and subprojects from NEXT back to TODO" + (when (not (and (boundp 'org-capture-mode) org-capture-mode)) + (cond + ((and (member (org-get-todo-state) (list "TODO")) + (bh/is-task-p)) + "NEXT") + ((and (member (org-get-todo-state) (list "NEXT")) + (bh/is-project-p)) + "TODO")))) + +(defun bh/find-project-task () + "Move point to the parent (project) task if any" + (save-restriction + (widen) + (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) + (while (org-up-heading-safe) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq parent-task (point)))) + (goto-char parent-task) + parent-task))) + +(defun bh/punch-in (arg) + "Start continuous clocking and set the default task to the +selected task. If no task is selected set the Organization task +as the default task." + (interactive "p") + (setq bh/keep-clock-running t) + (if (equal major-mode 'org-agenda-mode) + ;; + ;; We're in the agenda + ;; + (let* ((marker (org-get-at-bol 'org-hd-marker)) + (tags (org-with-point-at marker (org-get-tags-at)))) + (if (and (eq arg 4) tags) + (org-agenda-clock-in '(16)) + (bh/clock-in-organization-task-as-default))) + ;; + ;; We are not in the agenda + ;; + (save-restriction + (widen) + ; Find the tags on the current task + (if (and (equal major-mode 'org-mode) (not (org-before-first-heading-p)) (eq arg 4)) + (org-clock-in '(16)) + (bh/clock-in-organization-task-as-default))))) + +(defun bh/punch-out () + (interactive) + (setq bh/keep-clock-running nil) + (when (org-clock-is-active) + (org-clock-out)) + (org-agenda-remove-restriction-lock)) + +(defun bh/clock-in-default-task () + (save-excursion + (org-with-point-at org-clock-default-task + (org-clock-in)))) + +(defun bh/clock-in-parent-task () + "Move point to the parent (project) task if any and clock in" + (let ((parent-task)) + (save-excursion + (save-restriction + (widen) + (while (and (not parent-task) (org-up-heading-safe)) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq parent-task (point)))) + (if parent-task + (org-with-point-at parent-task + (org-clock-in)) + (when bh/keep-clock-running + (bh/clock-in-default-task))))))) + +(defvar bh/organization-task-id "e22cb8bf-07c7-408b-8f60-ff3aadac95e4") + +(defun bh/clock-in-organization-task-as-default () + (interactive) + (org-with-point-at (org-id-find bh/organization-task-id 'marker) + (org-clock-in '(16)))) + +(defun bh/clock-out-maybe () + (when (and bh/keep-clock-running + (not org-clock-clocking-in) + (marker-buffer org-clock-default-task) + (not org-clock-resolving-clocks-due-to-idleness)) + (bh/clock-in-parent-task))) + +; (add-hook 'org-clock-out-hook 'bh/clock-out-maybe 'append) + +(require 'org-id) +(defun bh/clock-in-task-by-id (id) + "Clock in a task by id" + (org-with-point-at (org-id-find id 'marker) + (org-clock-in nil))) + +(defun bh/clock-in-last-task (arg) + "Clock in the interrupted task if there is one +Skip the default task and get the next one. +A prefix arg forces clock in of the default task." + (interactive "p") + (let ((clock-in-to-task + (cond + ((eq arg 4) org-clock-default-task) + ((and (org-clock-is-active) + (equal org-clock-default-task (cadr org-clock-history))) + (caddr org-clock-history)) + ((org-clock-is-active) (cadr org-clock-history)) + ((equal org-clock-default-task (car org-clock-history)) (cadr org-clock-history)) + (t (car org-clock-history))))) + (widen) + (org-with-point-at clock-in-to-task + (org-clock-in nil)))) + + +(defun org-export-to-ods () + (interactive) + (let ((csv-file "data.csv")) + (org-table-export csv-file "orgtbl-to-csv") + (org-odt-convert csv-file "ods" 'open))) + +; allow for zero-width-space to be a break in regexp too +; (setcar org-emphasis-regexp-components "​ [:space:] \t('\"{") +; (setcar (nthcdr 1 org-emphasis-regexp-components) "​ [:space:]- \t.,:!?;'\")}\\") +; (org-set-emph-re 'org-emphasis-regexp-components org-emphasis-regexp-components) + +;; support inserting screen shots +(defun my/org-insert-screenshot () + "Take a screenshot into a time stamped unique-named file in the +same directory as the org-buffer and insert a link to this file." + (interactive) + (defvar my/org-insert-screenshot/filename) + (setq my/org-insert-screenshot/filename + (read-file-name + "Screenshot to insert: " + nil + (concat (buffer-file-name) "_" (format-time-string "%Y%m%d_%H%M%S") ".png") + ) + ) + (call-process "import" nil nil nil my/org-insert-screenshot/filename) + (insert (concat "[[" my/org-insert-screenshot/filename "]]")) + (org-display-inline-images)) + +(defun my/fix-inline-images () + (when org-inline-image-overlays + (org-redisplay-inline-images))) + +(add-hook 'org-babel-after-execute-hook 'my/fix-inline-images) + +;; use xelatex to preview with imagemagick +(add-to-list 'org-preview-latex-process-alist + '(xelateximagemagick + :programs ("xelatex" "convert") + :description "pdf > png" + :message "you need to install xelatex and imagemagick" + :use-xcolor t + :image-input-type "pdf" + :image-output-type "png" + :image-size-adjust (1.0 . 1.0) + :latex-compiler ("xelatex -interaction nonstopmode -output-directory %o %f") + :image-converter ("convert -density %D -trim -antialias %f -quality 100 %O")) + ) +;; use xelatex by default +(setq org-preview-latex-default-process 'xelateximagemagick) + +; from http://orgmode.org/Changes.html +(defun my/org-repair-property-drawers () + "Fix properties drawers in current buffer. + Ignore non Org buffers." + (interactive) + (when (eq major-mode 'org-mode) + (org-with-wide-buffer + (goto-char (point-min)) + (let ((case-fold-search t) + (inline-re (and (featurep 'org-inlinetask) + (concat (org-inlinetask-outline-regexp) + "END[ \t]*$")))) + (org-map-entries + (lambda () + (unless (and inline-re (org-looking-at-p inline-re)) + (save-excursion + (let ((end (save-excursion (outline-next-heading) (point)))) + (forward-line) + (when (org-looking-at-p org-planning-line-re) (forward-line)) + (when (and (< (point) end) + (not (org-looking-at-p org-property-drawer-re)) + (save-excursion + (and (re-search-forward org-property-drawer-re end t) + (eq (org-element-type + (save-match-data (org-element-at-point))) + 'drawer)))) + (insert (delete-and-extract-region + (match-beginning 0) + (min (1+ (match-end 0)) end))) + (unless (bolp) (insert "\n")))))))))))) + +(provide 'org-mode-configuration)