Org-mode config is back baby! With a vengeance!

This commit is contained in:
Henrik Lissner 2016-03-01 01:59:36 -05:00
parent 6851951aaf
commit 477ef168d4
19 changed files with 1227 additions and 309 deletions

15
Cask
View file

@ -209,6 +209,21 @@
(depends-on "jaded-mode" :git "https://github.com/hlissner/jaded-mode") (depends-on "jaded-mode" :git "https://github.com/hlissner/jaded-mode")
;;;; ORGANIZATIONAL/WRITING ;;;;;;;;;;;;
;; Org -- modules/module-org.el
(depends-on "org-plus-contrib")
(depends-on "org-bullets")
(depends-on "ob-go" :git "https://github.com/pope/ob-go")
(depends-on "ob-http")
;; Org Notebook -- modules/module-org-notebook.el
(depends-on "org-download")
(depends-on "ox-pandoc")
;; Writing -- modules/module-write.el
(depends-on "helm-bibtex")
;;;; EXTRA TOOLS ;;;;;;;;;;;;;;;;;;;;;;; ;;;; EXTRA TOOLS ;;;;;;;;;;;;;;;;;;;;;;;
;; Demo --- module-demo.el ;; Demo --- module-demo.el
(depends-on "impatient-mode") (depends-on "impatient-mode")

View file

@ -68,6 +68,7 @@
(Man-mode . emacs) (Man-mode . emacs)
(grep-mode . emacs) (grep-mode . emacs)
(image-mode . normal) (image-mode . normal)
(doc-view-mode . normal)
)) ))
(evil-set-initial-state `,(car mode-map) `,(cdr mode-map))) (evil-set-initial-state `,(car mode-map) `,(cdr mode-map)))

View file

@ -19,6 +19,12 @@
("/Dockerfile$" "__" dockerfile-mode) ("/Dockerfile$" "__" dockerfile-mode)
("/docker-compose.yml$" "__" yaml-mode) ("/docker-compose.yml$" "__" yaml-mode)
;; Org-mode
("\\.org$" "__" org-mode)
("/Work/.+\\.org$" "__project.org" org-mode)
("/Invoices/.+\\.org$" "__invoice.org" org-mode)
("/Contacts/.+\\.org$" "__contact.org" org-mode)
;; C/C++ ;; C/C++
("/Makefile$" "__" makefile-gmake-mode) ("/Makefile$" "__" makefile-gmake-mode)
("/main\\.\\(cc\\|cpp\\)$" "__main.cpp" c++-mode) ("/main\\.\\(cc\\|cpp\\)$" "__main.cpp" c++-mode)

View file

@ -98,10 +98,10 @@
(narf:send-to-tmux (format "cd %s" (shell-quote-argument default-directory))) (narf:send-to-tmux (format "cd %s" (shell-quote-argument default-directory)))
(narf-switch-to-iterm)) (narf-switch-to-iterm))
(defun narf-org-init-for-osx () ;; Open with external programs
;; Reveal files in finder (require 'openwith)
(setq org-file-apps '(("\\.org$" . emacs) (openwith-mode t)
(t . "open -R \"%s\"")))) (setq openwith-associations '(("\\.\\(pdf\\|jpe?g\\|gif\\|docx?\\|pptx?\\|xlsx?\\|zip\\|tar\\(\\.gz\\)?\\|rar\\)$" "open" (file))))
(provide 'core-os-osx) (provide 'core-os-osx)
;;; core-os-osx.el ends here ;;; core-os-osx.el ends here

View file

@ -114,6 +114,14 @@
(after! projectile (after! projectile
(setq projectile-switch-project-action 'neotree-projectile-action)) (setq projectile-switch-project-action 'neotree-projectile-action))
;; Shorter file names for org files
(defun narf*neo-path--file-short-name (orig-fun &rest args)
(let ((file (car args)))
(if (f-ext? file "org")
(s-replace "-" " " (f-base file))
(apply orig-fun args))))
(advice-add 'neo-path--file-short-name :around 'narf*neo-path--file-short-name)
;; A custom and simple theme for neotree ;; A custom and simple theme for neotree
(advice-add 'neo-buffer--insert-fold-symbol :override 'narf*neo-buffer-fold-symbol)) (advice-add 'neo-buffer--insert-fold-symbol :override 'narf*neo-buffer-fold-symbol))

View file

@ -66,6 +66,10 @@
(set-fontset-font "fontset-default" `(,x . ,x) (set-fontset-font "fontset-default" `(,x . ,x)
(font-spec :name "DejaVu Sans" :size 10) nil)) (font-spec :name "DejaVu Sans" :size 10) nil))
'(?➊ ?➋ ?➌ ?➍ ?➎ ?❻ ?➐ ?➑ ?➒ ?➓ )) '(?➊ ?➋ ?➌ ?➍ ?➎ ?❻ ?➐ ?➑ ?➒ ?➓ ))
(mapc (lambda (x)
(set-fontset-font "fontset-default" `(,x . ,x)
(font-spec :name "FontAwesome" :size 13) nil))
'(? ? ? ? ? ? ? ? ?))
(blink-cursor-mode 1) ; do blink cursor (blink-cursor-mode 1) ; do blink cursor
(tooltip-mode -1) ; show tooltips in echo area (tooltip-mode -1) ; show tooltips in echo area

View file

@ -88,9 +88,15 @@
;;module-nim ; look out Abraham ;;module-nim ; look out Abraham
;;module-pony ; Dear Princess Compiler ;;module-pony ; Dear Princess Compiler
;; Organizational/Notes
module-org ; for organized fearless leader
module-org-crm ; org-mode, for keeping tabs on my victims
module-org-notebook ; making org-mode into a modern note-taking solution
;; Extra Tools ;; Extra Tools
module-demo ; allow me to demonstrate... module-demo ; allow me to demonstrate...
module-ansible module-ansible ;
module-write ; yes, I write papers and fiction in Emacs
;; Key bindings & ex commands ;; Key bindings & ex commands
my-bindings my-bindings

View file

@ -1,297 +0,0 @@
;;; helm-deft.el --- helm module for grepping note files over directories
;; Copyright (C) 2014 Derek Feichtinger
;; Author: Derek Feichtinger <dfeich@gmail.com>
;; Keywords: convenience
;; Homepage: https://github.com/dfeich/helm-deft
;; Version: TODO
;; Package-Requires: ((helm "1.7.7") (f "0.17.0") (cl-lib "0.5"))
;; This file is not part of GNU Emacs.
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Helm command to find files fast based on contents and filename. Inspired
;; by the great emacs deft package. It allows defining a list of input directories
;; that can be defined and that are searched recursively.
;;
;; helm-deft is composed of three search sources
;; - file names: simple match of pattern vs. file name
;; - file match: shows file names of files where all of the individual patterns
;; match anywhere in the file
;; - file contents: show the lines where the last word in the search patterns
;; matches
;;; Code:
(require 'helm)
(require 'helm-grep)
(require 'helm-files)
(require 'f)
(require 'cl-lib)
(require 'subr-x)
(defgroup helm-deft nil
"customization group for the helm-deft utility" :group 'helm :version 24.3)
(defcustom helm-deft-dir-list
'("~/Documents")
"List of directories in which to search recursively for candidate files."
:group 'helm-deft
)
(defcustom helm-deft-extension "org"
"Defines file extension for identifying candidate files to be searched for.")
(defvar helm-deft-file-list nil
"Variable to store the list of candidate files.
This is constant over the invocation of one helm-deft.")
(defvar helm-deft-matching-files '()
"Used for building the list of filenames that the grep matched.")
(defvar helm-source-deft-fn
'((name . "File Names")
(header-line . "C-r: rotate pattern C-s/C-d: set/delete (marked) candidates from list")
(init . (lambda ()
(progn (unless helm-deft-file-list
(setq helm-deft-file-list (helm-deft-fname-search)))
(with-current-buffer (helm-candidate-buffer 'local)
(insert (mapconcat 'identity
helm-deft-file-list "\n"))))))
(candidates-in-buffer)
;; matching is done in the buffer when candidates-in-buffer is used
;; We only want against the basename and not the full path
(match-part . (lambda (c) (helm-basename c)))
;;(type . file)
(action . helm-find-files-actions)
;; We want the file list sorted. helm-highlight-files also will
;; transform a filename to a (basename . filename) cons
(candidate-transformer . (lambda (c) (sort (helm-highlight-files c)
(lambda (a b)
(string< (downcase (car a))
(downcase (car b)))))))
(cleanup . (lambda () (setq helm-deft-file-list nil)))
)
"Source definition for matching filenames of the `helm-deft' utility.")
(defun helm-deft-fname-search ()
"Search all preconfigured directories for matching files.
Returns the filenames as a list."
(assert helm-deft-extension nil "No file extension defined for helm-deft")
(assert helm-deft-dir-list nil "No directories defined for helm-deft")
(cl-loop for dir in helm-deft-dir-list
do (assert (file-exists-p dir) nil
(format "Directory %s does not exist. Check helm-deft-dir-list" dir))
collect (f--files dir (equal (f-ext it) helm-deft-extension) t)
into reslst
finally (return (apply #'append reslst)))
)
(defvar helm-source-deft-filegrep
'((name . "File Contents")
(candidates-process . helm-deft-fgrep-search)
;; We use the action from the helm-grep module
(action . helm-grep-action)
(requires-pattern)
(pattern-transformer . (lambda (pattern)
(cl-loop for ptr in (split-string pattern " *" t)
if (string-prefix-p "w:" ptr)
collect (string-remove-prefix "w:" ptr) into cptr
else collect ptr into cptr
finally return (mapconcat 'identity cptr " "))))
(filter-one-by-one . (lambda (candidate)
;; we abuse the filter-one-by-one function
;; for building the candidates list for the
;; matching-files source
(helm-deft-matching-files-search candidate)
;; we borrow the helm-grep filter function
(helm-grep-filter-one-by-one candidate)))
(cleanup . (lambda () (when (get-buffer "*helm-deft-proc*")
(let ((kill-buffer-query-functions nil))
(kill-buffer "*helm-deft-proc*")))))
)
"Source definition for matching against file contents for the `helm-deft' utility.")
(defun helm-deft-build-cmd (ptrnstr filelst)
"Builds a grep command based on the patterns and file list.
PTRNSTR may contain multiple search patterns separated by
spaces. The first pattern will be used to retrieve matching
lines. All other patterns will be used to pre-select files with
matching lines. FILELST is a list of file paths"
(let* ((ptrnlst (reverse (split-string ptrnstr " *" t)))
(firstp (pop ptrnlst))
(firstaddflag (if (string-prefix-p "w:" firstp)
(progn
(setq firstp (string-remove-prefix "w:" firstp))
"-w")
""))
(filelst (mapconcat 'identity filelst " "))
(innercmd (if ptrnlst
(cl-labels ((build-inner-cmd
(ptrnlst filelst)
(let* ((pattern (pop ptrnlst))
(addflags
(if (string-prefix-p "w:" pattern)
(progn
(setq pattern
(string-remove-prefix
"w:" pattern))
"-w")
"")))
(if ptrnlst
(format "$(grep %s -Elie '%s' %s)"
addflags pattern
(build-inner-cmd ptrnlst filelst))
(format "$(grep %s -Elie '%s' %s)"
addflags pattern filelst)))))
(build-inner-cmd ptrnlst filelst))
filelst)))
(format "grep %s -EHine '%s' %s" firstaddflag firstp innercmd))
)
(defun helm-deft-fgrep-search ()
"Greps for the helm search pattern in the configuration defined file list."
(setq helm-deft-matching-files '())
;; need to pass helm-input (the real input line) to the build
;; function since helm-pattern is already cleaned by the
;; pattern-transformer function of helm-source-deft-filegrep
(let* ((shcmd (helm-deft-build-cmd helm-input helm-deft-file-list)))
(helm-log "grep command: %s" shcmd)
;; the function must return the process object
(prog1
(start-process-shell-command "helm-deft-proc" "*helm-deft-proc*"
shcmd)
(set-process-sentinel
(get-process "helm-deft-proc")
(lambda (process event)
(cond
((string= event "finished\n")
(with-helm-window
(setq mode-line-format
'(" " mode-line-buffer-identification " "
(:eval (format "L%s" (helm-candidate-number-at-point))) " "
(:eval (propertize
;; TODO: The count is wrong since it counts all sources
(format
"[Grep process finished - (%s results)] "
(max (1- (count-lines
(point-min)
(point-max)))
0))
'face 'helm-grep-finish))))
(force-mode-line-update))
;; must NOT DO a targeted update here. Seems to call also this source
;; and we end in an infinite loop
;; (helm-update nil helm-source-deft-matching-files)
)
;; Catch error output in log.
(t (helm-log
"Error: Grep %s"
(replace-regexp-in-string "\n" "" event))))
))
)
))
(defvar helm-source-deft-matching-files
'((name . "Matching Files")
(candidates . helm-deft-matching-files)
;;(type . file)
;; introducing the delayed value to always have it scheduled after
;; the async grep process that produces the basis for this source
(delayed . 0.5)
(action . helm-find-files-actions)
;; need to override the file type's match settings
(match . (lambda (candidate) t))
(candidate-transformer . (lambda (c) (sort (helm-highlight-files c)
(lambda (a b)
(string< (downcase (car a))
(downcase (car b)))))))
(requires-pattern)
(volatile)
)
"Source definition for showing matching files from the grep buffer of the `helm-deft' utility.")
(defun helm-deft-matching-files-search (candidate)
"Add entry to helm-deft-matching-files list from a grep CANDIDATE."
(when (string-match "\\([^:]+\\):[0-9]+:" candidate)
(pushnew (match-string 1 candidate) helm-deft-matching-files :test #'equal)))
;; (defun helm-deft-matching-files-search ()
;; (when (get-buffer "*helm-deft-proc*")
;; (with-current-buffer "*helm-deft-proc*"
;; (beginning-of-buffer)
;; (while (and
;; (looking-at "^\\([^:]+\\):[0-9]+:")
;; (not (equal (forward-line) 1)))
;; (push (match-string 1) helm-deft-matching-files)))
;; (cl-remove-duplicates helm-deft-matching-files :test #'equal))
;; )
(defun helm-deft-rotate-searchkeys ()
"Rotate the words of the search pattern in the helm minibuffer."
(interactive)
(helm-log "Executing helm-deft-rotate-searchkeys")
(let ((patlst (split-string helm-pattern " *")))
(when (and (>= (length patlst) 1)
(> (length (car patlst)) 0))
(delete-minibuffer-contents)
(insert (mapconcat #'identity
(append (cdr patlst) (list (car patlst)))
" "))
(helm-update)))
)
(defun helm-deft-remove-candidate-file ()
"Remove the file under point from the list of candidates."
(interactive)
;; helm-get-selection returns current item under point
;; helm-marked-candidates returns all marked candidates or the item under point
(dolist (selection (helm-marked-candidates))
(when (string-match "\\([^:]+\\):[0-9]+:" selection)
(setq selection (match-string 1 selection)))
(setq helm-deft-file-list (delete selection helm-deft-file-list)))
(helm-unmark-all)
(helm-force-update))
(defun helm-deft-set-to-marked ()
"Set the filelist to the marked files."
(interactive)
(setq helm-deft-file-list (helm-marked-candidates))
(helm-unmark-all)
(helm-force-update))
(defvar helm-deft-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "C-r") 'helm-deft-rotate-searchkeys)
(define-key map (kbd "C-d") 'helm-deft-remove-candidate-file)
(define-key map (kbd "C-s") 'helm-deft-set-to-marked)
(delq nil map))
"Helm keymap used for helm deft sources.")
;;;###autoload
(defun helm-deft ()
"Preconfigured `helm' module for locating matching files.
Either the filename or the file contents must match the query
string. Inspired by the Emacs `deft' extension"
(interactive)
(helm :sources '(helm-source-deft-fn helm-source-deft-matching-files
helm-source-deft-filegrep)
:keymap helm-deft-map))
(provide 'helm-deft)
;;; helm-deft.el ends here

120
modules/contrib/openwith.el Normal file
View file

@ -0,0 +1,120 @@
;;; openwith.el --- Open files with external programs
;; Copyright (C) 2007, 2013 Markus Triska
;; Author: Markus Triska <markus.triska@gmx.at>
;; Keywords: files, processes
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This lets you associate external applications with files so that
;; you can open them via C-x C-f, with RET in dired, etc.
;; Copy openwith.el to your load-path and add to your .emacs:
;; (require 'openwith)
;; (openwith-mode t)
;; To customize associations etc., use:
;;
;; M-x customize-group RET openwith RET
;;
;; To prevent openwith-mode from interfering with attachments when
;; writing a message in Gnus, add the following to your .emacs:
;;
;; (require 'mm-util)
;; (add-to-list 'mm-inhibit-file-name-handlers 'openwith-file-handler)
;;; Code:
(defconst openwith-version "0.8g")
(defgroup openwith nil
"Associate external applications with file name patterns."
:group 'files
:group 'processes)
(defcustom openwith-associations
'(("\\.pdf\\'" "acroread" (file))
("\\.mp3\\'" "xmms" (file))
("\\.\\(?:mpe?g\\|avi\\|wmv\\)\\'" "mplayer" ("-idx" file))
("\\.\\(?:jp?g\\|png\\)\\'" "display" (file)))
"Associations of file patterns to external programs.
File pattern is a regular expression describing the files to
associate with a program. The program arguments are a list of
strings and symbols and are passed to the program on invocation,
where the symbol 'file' is replaced by the file to be opened."
:group 'openwith
:type '(repeat (list (regexp :tag "Files")
(string :tag "Program")
(sexp :tag "Parameters"))))
(defcustom openwith-confirm-invocation nil
"Ask for confirmation before invoking external programs."
:group 'openwith
:type 'boolean)
(defun openwith-file-handler (operation &rest args)
"Open file with external program, if an association is configured."
(when (and openwith-mode (not (buffer-modified-p)) (zerop (buffer-size)))
(let ((assocs openwith-associations)
(file (car args))
oa)
;; do not use `dolist' here, since some packages (like cl)
;; temporarily unbind it
(while assocs
(setq oa (car assocs)
assocs (cdr assocs))
(when (save-match-data (string-match (car oa) file))
(let ((params (mapcar (lambda (x) (if (eq x 'file) file x))
(nth 2 oa))))
(when (or (not openwith-confirm-invocation)
(y-or-n-p (format "%s %s? " (cadr oa)
(mapconcat #'identity params " "))))
(apply #'start-process "openwith-process" nil (cadr oa) params)
(kill-buffer nil)
;; inhibit actions that would follow the regular
;; insertion of file contents
(let (debug-on-error)
(error "Opened %s in external program"
(file-name-nondirectory file)))))))))
;; when no association was found, relay the operation to other handlers
(let ((inhibit-file-name-handlers
(cons 'openwith-file-handler
(and (eq inhibit-file-name-operation operation)
inhibit-file-name-handlers)))
(inhibit-file-name-operation operation))
(apply operation args)))
;;;###autoload
(define-minor-mode openwith-mode
"Automatically open files with external programs."
:lighter ""
:global t
(if openwith-mode
(progn
;; register `openwith-file-handler' for all files
(put 'openwith-file-handler 'safe-magic t)
(put 'openwith-file-handler 'operations '(insert-file-contents))
(add-to-list 'file-name-handler-alist '("" . openwith-file-handler)))
(setq file-name-handler-alist
(delete '("" . openwith-file-handler) file-name-handler-alist))))
(provide 'openwith)
;;; openwith.el ends here

View file

@ -0,0 +1,113 @@
;;; defuns-org-notebook.el
;; Keep track of attachments
(defvar narf-org-attachments-list '() "A list of attachments for the current buffer")
(make-variable-buffer-local 'narf-org-attachments-list)
;;;###autoload
(defun narf/org-start ()
(interactive)
(narf:workgroup-new nil "*ORG*" t)
(cd org-directory)
(let ((helm-full-frame t))
(helm-find-files nil))
(save-excursion
(neotree-show)))
;;;###autoload
(defun narf/org-notebook-new ()
(interactive)
(projectile-invalidate-cache nil)
(let* ((default-directory org-directory)
(dir (projectile-complete-dir))
(narf-org-quicknote-dir dir))
(when dir
(narf/org-notebook-quick-note))))
;;;###autoload
(defun narf/org-notebook-quick-note ()
(interactive)
(let (text)
(when (evil-visual-state-p)
(setq text (buffer-substring-no-properties evil-visual-beginning evil-visual-end)))
(switch-to-buffer (generate-new-buffer "*quick-note*"))
(setq default-directory narf-org-quicknote-dir)
(erase-buffer)
(insert text)))
;;;###autoload
(defun narf/org-download-dnd (uri action)
(if (and (eq major-mode 'org-mode)
(not (image-type-from-file-name uri)))
(narf:org-attach uri)
(let ((dnd-protocol-alist
(rassq-delete-all 'narf/org-download-dnd (copy-alist dnd-protocol-alist))))
(dnd-handle-one-url nil action uri))))
;;;###autoload (autoload 'narf:org-attach "defuns-org-notebook" nil t)
(evil-define-command narf:org-attach (&optional uri)
(interactive "<a>")
(if uri
(let* ((rel-path (org-download--fullname uri))
(new-path (f-expand rel-path)))
(cond ((string-match-p (concat "^" (regexp-opt '("http" "https" "nfs" "ftp" "file")) "://") uri)
(url-copy-file uri new-path))
(t (copy-file uri new-path)))
(unless new-path
(user-error "No file was provided"))
(if (evil-visual-state-p)
(org-insert-link nil (format "./%s" rel-path)
(concat (buffer-substring-no-properties (region-beginning) (region-end))
" " (narf/org-attach-icon rel-path)))
(insert (format "%s [[./%s][%s]]"
(narf/org-attach-icon rel-path)
rel-path (f-filename rel-path))))
(when (string-match-p (regexp-opt '("jpg" "jpeg" "gif" "png")) (f-ext rel-path))
(org-toggle-inline-images)))
(let ((attachments (narf-org-attachments)))
(unless attachments
(user-error "No attachments in this file"))
(helm :sources (helm-build-sync-source "Attachments" :candidates attachments)))))
;;;###autoload
(defun narf/org-attach-icon (path)
(char-to-string (pcase (downcase (f-ext path))
("jpg" ?) ("jpeg" ?) ("png" ?) ("gif" ?)
("pdf" ?)
("ppt" ?) ("pptx" ?)
("xls" ?) ("xlsx" ?)
("doc" ?) ("docx" ?)
("ogg" ?) ("mp3" ?) ("wav" ?)
("mp4" ?) ("mov" ?) ("avi" ?)
("zip" ?) ("gz" ?) ("tar" ?) ("7z" ?) ("rar" ?)
(t ?))))
;;;###autoload
(defun narf/org-attachments ()
(let ((attachments '())
element
file)
(save-excursion
(goto-char (point-min))
(while (progn (org-next-link) (not org-link-search-failed))
(setq element (org-element-lineage (org-element-context) '(link) t))
(when element
(setq file (expand-file-name (org-element-property :path element)))
(when (and (string= (org-element-property :type element) "file")
(string= (concat (f-base (f-dirname file)) "/") org-attach-directory)
(file-exists-p file))
(push file attachments)))))
(-distinct attachments)))
;;;###autoload
(defun narf/org-cleanup-attachments ()
(let* ((attachments (narf/org-attachments))
(to-delete (-difference narf-org-attachments-list attachments)))
(mapc (lambda (f)
(message "Deleting attachment: %s" f)
(delete-file f t))
to-delete)
(setq narf-org-attachments-list attachments)))
(provide 'defuns-org-notebook)
;;; defuns-org-notebook.el ends here

View file

@ -0,0 +1,300 @@
;;; defuns-org.el
;;;###autoload
(defun narf/org-find-file-in-notes ()
(interactive)
(in! (f-slash org-directory)
(helm-projectile-find-file)))
;;;###autoload
(defun narf/org-find-file ()
(interactive)
(in! (f-slash org-directory)
(helm-find-files nil)))
;;;###autoload
(defun narf/org-find-exported-file ()
(interactive)
(in! (f-slash narf-org-export-directory)
(helm-find-files nil)))
;;;###autoload
(defun narf/org-get-property (name)
(interactive)
(save-excursion
(goto-char 1)
(re-search-forward (format "^#\\+%s:[ \t]*\\([^\n]+\\)" (upcase name)) nil t)
(buffer-substring-no-properties (match-beginning 1) (match-end 1))))
;;;###autoload
(defun narf/org-insert-item (direction)
"Inserts a new heading or item, depending on the context."
(interactive)
(let* ((context (org-element-lineage
(org-element-context)
'(table table-row headline inlinetask item plain-list)
t))
(type (org-element-type context)))
(cond ((eq type 'item)
(cl-case direction
('below
(org-end-of-line)
(org-insert-heading))
('above
(evil-first-non-blank)
(org-insert-heading)))
(when (org-element-property :checkbox context)
(insert "[ ] ")))
((memq type '(table table-row))
(cl-case direction
('below
(org-table-insert-row))
('above
(narf/org-table-prepend-row-or-shift-up))))
(t
(cl-case direction
('below
(org-insert-heading-after-current))
('above
(org-back-to-heading)
(org-insert-heading)))
(when (org-element-property :todo-type context)
(org-todo 'todo))))
(evil-append-line 1)))
;;;###autoload
(defun narf/org-toggle-checkbox ()
(interactive)
(let ((context (org-element-lineage (org-element-context) '(item) t)))
(when context
(org-end-of-line)
(org-beginning-of-line)
(if (org-element-property :checkbox context)
(when (search-backward-regexp "\\[[ +-]\\]" (line-beginning-position) t)
(delete-char 4))
(insert "[ ] ")))))
;;;###autoload
(defun narf/org-dwim-at-point ()
(interactive)
(let* ((scroll-pt (window-start))
(context (org-element-context))
(type (org-element-type context))
(value (org-element-property :value context)))
(cond
((memq type '(table table-row))
(if (org-element-property :tblfm (org-element-property :parent context))
(org-table-recalculate t)
(org-table-align)))
((and (memq type '(item))
(org-element-property :checkbox context))
(org-toggle-checkbox))
((and (memq type '(headline))
(org-element-property :todo-type context))
(org-todo
(if (eq (org-element-property :todo-type context) 'done) 'todo 'done)))
((and (memq type '(headline))
(string= "ARCHIVE" (car-safe (org-get-tags))))
(org-force-cycle-archived))
((memq type '(headline))
(org-remove-latex-fragment-image-overlays)
(org-preview-latex-fragment '(4)))
((memq type '(babel-call))
(org-babel-lob-execute-maybe))
((memq type '(src-block inline-src-block))
(org-babel-execute-src-block))
((memq type '(latex-fragment latex-environment))
(org-preview-latex-fragment))
((memq type '(link))
(let ((path (org-element-property :path (org-element-lineage (org-element-context) '(link) t))))
(if (and path (image-type-from-file-name path))
(narf/org-refresh-inline-images)
(org-open-at-point))))
(t (narf/org-refresh-inline-images)))
(set-window-start nil scroll-pt)))
;;;###autoload
(defun narf/org-refresh-inline-images ()
(interactive)
(if (> (length org-inline-image-overlays) 0)
(org-remove-inline-images)
(org-display-inline-images
t t
(if (org-before-first-heading-p)
(line-beginning-position)
(save-excursion (org-back-to-heading) (point)))
(if (org-before-first-heading-p)
(line-end-position)
(save-excursion (org-end-of-subtree) (point))))))
;; Formatting shortcuts
;;;###autoload
(defun narf/org-surround (delim)
(if (region-active-p)
(save-excursion
(goto-char (region-beginning))
(insert delim)
(goto-char (region-end))
(insert delim))
(insert delim)
(save-excursion (insert delim))))
;;;###autoload
(defun narf/org-word-count (beg end &optional count-footnotes?)
"Report the number of words in the Org mode buffer or selected region.
Ignores:
- comments
- tables
- source code blocks (#+BEGIN_SRC ... #+END_SRC, and inline blocks)
- hyperlinks (but does count words in hyperlink descriptions)
- tags, priorities, and TODO keywords in headers
- sections tagged as 'not for export'.
The text of footnote definitions is ignored, unless the optional argument
COUNT-FOOTNOTES? is non-nil."
(interactive "r")
(unless mark-active
(setf beg (point-min)
end (point-max)))
(let ((wc 0))
(save-excursion
(goto-char beg)
(while (< (point) end)
(cond
;; Ignore comments.
((or (org-at-comment-p) (org-at-table-p))
nil)
;; Ignore hyperlinks. But if link has a description, count
;; the words within the description.
((looking-at org-bracket-link-analytic-regexp)
(when (match-string-no-properties 5)
(let ((desc (match-string-no-properties 5)))
(save-match-data
(incf wc (length (remove "" (org-split-string
desc "\\W")))))))
(goto-char (match-end 0)))
((looking-at org-any-link-re)
(goto-char (match-end 0)))
;; Ignore source code blocks.
((org-between-regexps-p "^#\\+BEGIN_SRC\\W" "^#\\+END_SRC\\W")
nil)
;; Ignore inline source blocks, counting them as 1 word.
((save-excursion
(backward-char)
(looking-at org-babel-inline-src-block-regexp))
(goto-char (match-end 0))
(setf wc (+ 2 wc)))
;; Ignore footnotes.
((and (not count-footnotes?)
(or (org-footnote-at-definition-p)
(org-footnote-at-reference-p)))
nil)
(t
(let ((contexts (org-context)))
(cond
;; Ignore tags and TODO keywords, etc.
((or (assoc :todo-keyword contexts)
(assoc :priority contexts)
(assoc :keyword contexts)
(assoc :checkbox contexts))
nil)
;; Ignore sections marked with tags that are
;; excluded from export.
((assoc :tags contexts)
(if (intersection (org-get-tags-at) org-export-exclude-tags
:test 'equal)
(org-forward-same-level 1)
nil))
(t
(incf wc))))))
(re-search-forward "\\w+\\W*")))
(message (format "%d words in %s." wc
(if mark-active "region" "buffer")))))
;;;###autoload
(defun narf/org-remove-link ()
"Replace an org link by its description or if empty its address"
(interactive)
(if (org-in-regexp org-bracket-link-regexp 1)
(let ((remove (list (match-beginning 0) (match-end 0)))
(description (if (match-end 3)
(org-match-string-no-properties 3)
(org-match-string-no-properties 1))))
(apply 'delete-region remove)
(insert description))))
;;;###autoload
(defun narf/org-table-next-row ()
(interactive)
(if (org-at-table-p) (org-table-next-row) (org-down-element)))
;;;###autoload
(defun narf/org-table-previous-row ()
(interactive)
(if (org-at-table-p) (narf--org-table-previous-row) (org-up-element)))
;;;###autoload
(defun narf/org-table-next-field ()
(interactive)
(if (org-at-table-p) (org-table-next-field) (org-end-of-line)))
;;;###autoload
(defun narf/org-table-previous-field ()
(interactive)
(if (org-at-table-p) (org-table-previous-field) (org-beginning-of-line)))
;;;###autoload
(defun narf/org-table-append-field-or-shift-right ()
(interactive)
(org-shiftmetaright)
(when (org-at-table-p) (org-metaright)))
;;;###autoload
(defun narf/org-table-prepend-field-or-shift-left ()
(interactive)
(if (org-at-table-p)
(org-shiftmetaright)
(org-shiftmetaleft)))
;;;###autoload
(defun narf/org-table-append-row-or-shift-down ()
(interactive)
(org-shiftmetadown)
(when (org-at-table-p) (org-metadown)))
;;;###autoload
(defun narf/org-table-prepend-row-or-shift-up ()
(interactive)
(if (org-at-table-p)
(org-shiftmetadown)
(org-shiftmetaup)))
(defun narf--org-table-previous-row ()
"Go to the previous row (same column) in the current table. Before doing so,
re-align the table if necessary. (Necessary because org-mode has a
`org-table-next-row', but not `org-table-previous-row')"
(interactive)
(org-table-maybe-eval-formula)
(org-table-maybe-recalculate-line)
(if (and org-table-automatic-realign
org-table-may-need-update)
(org-table-align))
(let ((col (org-table-current-column)))
(beginning-of-line 0)
(when (or (not (org-at-table-p)) (org-at-table-hline-p))
(beginning-of-line))
(org-table-goto-column col)
(skip-chars-backward "^|\n\r")
(when (org-looking-at-p " ") (forward-char))))
(provide 'defuns-org)
;;; defuns-org.el ends here

View file

@ -0,0 +1,45 @@
;;; macros-org.el
;;;###autoload
(defmacro define-org-section! (type directory &optional id-func link-glob)
(setq directory (f-slash directory))
(let* ((type-str (symbol-name type))
(link-sym (intern (format "narf/org-link-%s" type-str)))
(dir-var (intern (format "org-directory-%s" type-str))))
`(progn
;; Variable containing directory: `org-directory-%s'
(defvar ,dir-var ,(expand-file-name directory org-directory))
;; Open helm in directory: `narf/helm-org-%s'
(evil-define-command ,(intern (format "narf:org-search-%s" type-str)) ()
(interactive)
(let ((default-directory (concat ,dir-var "/" (format-time-string "%Y") "/")))
(helm-find-files nil)))
;; Open helm in directory: `narf/helm-org-%s'
(defun ,(intern (format "narf/helm-org-find-file-in-%s" type-str)) ()
(interactive)
(helm-do-ag (f-slash ,dir-var)))
;; Org link handler
(defun ,link-sym (id)
(let ((path (f-glob (format (or ,link-glob "%s.org") id) ,dir-var)))
(unless path
(error "ID not found: %s" id))
(org-open-file (car path) t)))
(org-add-link-type ,type-str ',link-sym)
;; Org completion handler
(defun ,(intern (format "org-%s-complete-link" type-str)) ()
(let* ((default-directory (f-slash ,dir-var))
(file (org-iread-file-name "> "))
(relpath (f-relative file ,dir-var)))
(when (and (not (file-exists-p file))
(y-or-n-p (format "Create %s?" relpath)))
(write-region "" nil file)
(message "Created %s" file))
(format "%s:%s" ,type-str ,(if id-func `(funcall ,id-func relpath) '(f-no-ext relpath)))
)))))
(provide 'macros-org)
;;; macros-org.el ends here

22
modules/module-org-crm.el Normal file
View file

@ -0,0 +1,22 @@
;;; module-org-crm.el
(defun narf|org-crm-init ()
(define-org-section! cproject "Work")
(define-org-section! project "Projects")
(define-org-section! contact "Contacts")
)
(defun narf/org-crm-new (type name)
)
(defun narf/org-crm-visit-project (&optional name)
)
(defun narf/org-crm-visit-contact (&optional name)
)
(defun narf/org-crm-visit-invoice (&optional name)
)
(provide 'module-org-crm)
;;; module-org-crm.el ends here

View file

@ -0,0 +1,107 @@
;;; module-org-notebook.el
;; This transforms Emacs+org-mode into a notebook application with:
;; + Custom links for class notes
;; + Shortcuts for searching org files
;; + Shortcuts for creating new notes (there's org-capture, but this is suited to my
;; workflow).
;; + A simpler attachment system with support for drag-and-drop attachments into org.
;; + A simpler, pandoc-powered, export system.
(add-hook 'org-load-hook 'narf|org-notebook-init t)
(add-hook 'org-load-hook 'narf|org-attach-init t)
(add-hook 'org-load-hook 'narf|org-export-init t)
(defvar narf-org-export-directory (concat org-directory ".export"))
(defvar narf-org-quicknote-dir (concat org-directory "Inbox/"))
(defvar org-attach-directory ".attach/")
;; Tell helm to ignore these directories
(mapc (lambda (r) (add-to-list 'helm-boring-file-regexp-list r))
(list "\\.attach$" "\\.export$"))
;;
(defun narf|org-notebook-init ()
(define-org-section! course "Classes"
(lambda (path) (substring path 0 (s-index-of " " path))) "%s*.org")
(exmap "ocl[ass]" 'narf:org-search-course))
;;
(defun narf|org-attach-init ()
;; Drag-and-drop support
(require 'org-download)
(setq-default org-download-image-dir org-attach-directory
org-download-heading-lvl nil
org-download-timestamp "_%Y%m%d_%H%M%S")
(when IS-MAC
(setq org-download-screenshot-method "screencapture -i %s"))
;; Write download paths relative to current file
(defun org-download--dir-2 () nil)
(defun narf*org-download--fullname (path)
(f-relative path (f-dirname (buffer-file-name))))
(advice-add 'org-download--fullname :filter-return 'narf*org-download--fullname)
;; Add another drag-and-drop handler that will handle anything but image files
(setq dnd-protocol-alist `(("^\\(https?\\|ftp\\|file\\|nfs\\):\\(//\\)?" . narf/org-download-dnd)
,@dnd-protocol-alist))
;; ...auto-delete attachments once all references to it have been deleted.
(add-hook 'org-mode-hook 'narf|org-attach-track-init)
(defun narf|org-attach-track-init ()
(setq narf-org-attachments-list (narf/org-attachments))
(add-hook 'after-save-hook 'narf/org-cleanup-attachments nil t)))
;;
(defun narf|org-export-init ()
(setq org-export-backends '(ascii html latex md opml)
org-export-with-toc t
org-export-with-author t)
(use-package ox-pandoc)
(setq org-pandoc-options '((standalone . t) (mathjax . t) (parse-raw . t)))
;; Export to a central directory (why isn't this easier?)
(unless (file-directory-p narf-org-export-directory)
(mkdir narf-org-export-directory))
(defun narf*org-export-output-file-name (args)
(unless (nth 2 args)
(setq args (append args (list narf-org-export-directory))))
args)
(advice-add 'org-export-output-file-name :filter-args 'narf*org-export-output-file-name))
;;
;; (defvar narf-org-tags '())
;; (defun narf|org-tag-init ()
;; (async-start
;; `(lambda ()
;; (let ((default-directory (narf/project-root))
;; (data (s-trim (shell-command-to-string "ag --nocolor --nonumbers '^#\\+TAGS:'")))
;; (alist '()))
;; (unless (zerop (length data))
;; (mapc (lambda (l)
;; (let* ((parts (s-split ":" l))
;; (file (car parts))
;; (tags (s-trim (nth 2 parts))))
;; (mapc (lambda (tag)
;; (setq tag (substring tag 1))
;; (unless (assoc tag alist)
;; (push (cons tag (list)) alist))
;; (push file (cdr (assoc tag alist))))
;; (s-split " " tags))))
;; (s-lines data))
;; alist)))
;; (lambda (_)
;; (load (concat php-extras-eldoc-functions-file ".el"))
;; (message "PHP eldoc updated!")))
;; )
;;
(provide 'module-org-notebook)
;;; module-org-notebook.el ends here

326
modules/module-org.el Normal file
View file

@ -0,0 +1,326 @@
;;; module-org.el
(add-hook 'org-load-hook 'narf|org-init t)
(add-hook 'org-load-hook 'narf|org-keybinds t)
(add-hook 'org-mode-hook 'narf|org-hook)
(defvar org-directory (expand-file-name "~/Dropbox/docs/"))
(define-minor-mode evil-org-mode
"Evil-mode bindings for org-mode."
:init-value nil
:lighter " !"
:keymap (make-sparse-keymap) ; defines evil-org-mode-map
:group 'evil-org)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun narf|org-hook ()
(evil-org-mode +1)
(org-indent-mode +1)
(setq line-spacing 1)
;; Highlight plaintext links
(highlight-regexp org-any-link-re 'org-link)
;; If saveplace places the point in a folded position, unfold it on load
(when (outline-invisible-p)
(ignore-errors
(save-excursion
(outline-previous-visible-heading 1)
(org-show-subtree))))
(defun narf|org-update ()
(when (file-exists-p buffer-file-name)
(org-update-statistics-cookies t)
(org-align-all-tags)))
(add-hook 'before-save-hook 'narf|org-update nil t)
(add-hook 'evil-insert-state-exit-hook 'narf|org-update nil t))
(defun narf|org-init ()
(setq-default
org-agenda-files
(f-entries org-directory (lambda (path) (string-suffix-p ".org" path)))
;; Appearance
org-indent-mode-turns-on-hiding-stars t
org-adapt-indentation nil
org-blank-before-new-entry '((heading . nil) (plain-list-item . auto))
org-bullets-bullet-list '("" "" "" "" "" "")
org-cycle-separator-lines 1
org-ellipsis 'hs-face
org-entities-user '(("flat" "\\flat" nil "" "" "266D" "")
("sharp" "\\sharp" nil "" "" "266F" ""))
org-fontify-done-headline t
org-fontify-quote-and-verse-blocks t
org-fontify-whole-heading-line t
org-footnote-auto-label 'plain
org-hide-emphasis-markers t
org-hide-leading-stars nil
org-image-actual-width nil
org-indent-indentation-per-level 2
org-pretty-entities t
org-pretty-entities-include-sub-superscripts nil
org-startup-folded t
org-startup-indented nil
org-startup-with-inline-images nil
org-tags-column 70
org-use-sub-superscripts '{}
;; Behavior
org-catch-invisible-edits nil
org-checkbox-hierarchical-statistics nil
org-completion-use-ido nil ; Use helm for refiling
org-confirm-elisp-link-function nil
org-default-priority ?C
org-hidden-keywords '(title)
org-hierarchical-todo-statistics t
org-log-done t
org-loop-over-headlines-in-active-region t
org-outline-path-complete-in-steps nil
org-refile-use-outline-path t
org-special-ctrl-a/e t
;; Sorting/refiling
org-archive-location (concat org-directory "/Archived/%s::")
org-refile-targets '((nil . (:maxlevel . 2))) ; display full path in refile completion
;; Agenda
org-agenda-restore-windows-after-quit t
org-agenda-skip-unavailable-files t
org-agenda-window-setup 'other-window
org-todo-keywords '((sequence "TODO(t)" "|" "DONE(d)")
(sequence "IDEA(i)" "NEXT(n)" "ACTIVE(a)" "WAITING(w)" "LATER(l)" "|" "CANCELLED(c)"))
;; Babel
org-confirm-babel-evaluate nil ; you don't need my permission
org-src-fontify-natively t ; make code pretty
org-src-preserve-indentation t
org-src-tab-acts-natively t
org-src-window-setup 'current-window
;; Latex
org-format-latex-options (plist-put org-format-latex-options :scale 1.3)
org-highlight-latex-and-related '(latex)
org-latex-create-formula-image-program 'dvipng
org-latex-image-default-width nil
org-latex-preview-ltxpng-directory (concat narf-temp-dir "ltxpng/")
org-latex-remove-logfiles nil
org-startup-with-latex-preview nil
;; org-latex-packages-alist
;; '(("" "gauss" t)
;; ("" "physics" t) TODO Install this)
org-capture-templates
'(("c" "Changelog" entry
(file+headline (concat (narf/project-root) "CHANGELOG.org") "Unreleased")
"* %?")
;; ("p" "Project Notes" entry
;; (file+headline org-default-notes-file "Inbox")
;; "* %u %?\n%i" :prepend t)
;; ("m" "Major-mode Notes" entry
;; (file+headline org-default-notes-file "Inbox")
;; "* %u %?\n%i" :prepend t)
("n" "Notes" entry
(file+headline org-default-notes-file "Inbox")
"* %u %?\n%i" :prepend t)
("v" "Vocab" entry
(file+headline (concat org-directory "topics/vocab.org") "Unsorted")
"** %i%?\n")))
(org-babel-do-load-languages
'org-babel-load-languages
'((python . t) (ruby . t) (sh . t) (js . t) (css . t)
(plantuml . t) (emacs-lisp . t) (matlab . t)
(latex . t) (calc . t) (lisp . t) (lilypond . t)
(go . t) (http . t)
(rust . t)))
(let ((ext-regexp (regexp-opt '("GIF" "JPG" "JPEG" "SVG" "TIF" "TIFF" "BMP" "XPM"
"gif" "jpg" "jpeg" "svg" "tif" "tiff" "bmp" "xpm"))))
(setq iimage-mode-image-regex-alist
`((,(concat "\\(`?file://\\|\\[\\[\\|<\\|`\\)?\\([-+./_0-9a-zA-Z]+\\."
ext-regexp "\\)\\(\\]\\]\\|>\\|'\\)?") . 2)
(,(concat "<\\(http://.+\\." ext-regexp "\\)>") . 1))))
;; Don't open separate windows
(add-to-list 'org-link-frame-setup '(file . find-file))
;; Reveal files in finder
(setq org-file-apps '(("\\.org$" . emacs) (t . "open -R \"%s\"")))
;; Custom faces
(defface org-list-bullet '((t ())) "Face for list bullets")
(defvar narf-org-font-lock-keywords
`(("^ *\\([-+]\\|[0-9]+[).]\\) "
(1 'org-list-bullet))
("^ *\\(-----+\\)$"
(1 'org-meta-line))))
(font-lock-add-keywords 'org-mode narf-org-font-lock-keywords)
;; Enable encryption
(require 'epa-file)
(epa-file-enable)
(require 'org-crypt)
(org-crypt-use-before-save-magic)
(setq org-tags-exclude-from-inheritance '("crypt")
org-crypt-key user-mail-address
epa-file-encrypt-to user-mail-address)
;; Don't track attachments
(push (format "/%s.+$" (regexp-quote org-attach-directory)) recentf-exclude)
;; Don't clobber recentf with agenda files
(defun org-is-agenda-file (filename)
(find (file-truename filename) org-agenda-files :key 'file-truename
:test 'equal))
(pushnew 'org-is-agenda-file recentf-exclude)
;; Evil integration
(progn
(advice-add 'evil-force-normal-state :before 'org-remove-occur-highlights)
;; Add element delimiter text-objects so we can use evil-surround to
;; manipulate them.
(define-text-object! "$" "\\$" "\\$")
(define-text-object! "*" "\\*" "\\*")
(define-text-object! "/" "/" "/")
(define-text-object! "_" "_" "_")
(define-text-object! "=" "=" "=")
(define-text-object! "~" "~" "~")))
(defun narf|org-keybinds ()
(define-key org-mode-map (kbd "RET") nil)
(define-key org-mode-map (kbd "C-j") nil)
(define-key org-mode-map (kbd "C-k") nil)
(map! (:map org-mode-map
:i [remap narf/inflate-space-maybe] 'org-self-insert-command
:i "RET" 'org-return-indent)
(:map evil-org-mode-map
:ni "A-l" 'org-metaright
:ni "A-h" 'org-metaleft
:ni "A-k" 'org-metaup
:ni "A-j" 'org-metadown
;; Expand tables (or shiftmeta move)
:ni "A-L" 'narf/org-table-append-field-or-shift-right
:ni "A-H" 'narf/org-table-prepend-field-or-shift-left
:ni "A-K" 'narf/org-table-prepend-row-or-shift-up
:ni "A-J" 'narf/org-table-append-row-or-shift-down
:i "C-L" 'narf/org-table-next-field
:i "C-H" 'narf/org-table-previous-field
:i "C-K" 'narf/org-table-previous-row
:i "C-J" 'narf/org-table-next-row
:i "C-e" 'org-end-of-line
:i "C-a" 'org-beginning-of-line
:nv "j" 'evil-next-visual-line
:nv "k" 'evil-previous-visual-line
:v "<S-tab>" 'narf/yas-insert-snippet
:i "M-a" (λ! (evil-visual-state) (org-mark-element))
:n "M-a" 'org-mark-element
:v "M-a" 'mark-whole-buffer
:ni "<M-return>" (λ! (narf/org-insert-item 'below))
:ni "<S-M-return>" (λ! (narf/org-insert-item 'above))
:i "M-b" (λ! (narf/org-surround "*")) ; bold
:i "M-u" (λ! (narf/org-surround "_")) ; underline
:i "M-i" (λ! (narf/org-surround "/")) ; italics
:i "M-`" (λ! (narf/org-surround "+")) ; strikethrough
:v "M-b" "S*"
:v "M-u" "S_"
:v "M-i" "S/"
:v "M-`" "S+"
(:leader
:n ";" 'helm-org-in-buffer-headings
:n "oa" 'narf/org-attachment-reveal)
(:localleader
:n "/" 'org-sparse-tree
:n "?" 'org-tags-view
:n "n" (λ! (if (buffer-narrowed-p) (widen) (org-narrow-to-subtree)))
:n "e" 'org-edit-special
:n "=" 'org-align-all-tags
:nv "l" 'org-insert-link
:n "L" 'org-store-link
:n "x" 'narf/org-remove-link
;; :n "w" 'writing-mode
:n "v" 'variable-pitch-mode
:n "SPC" 'narf/org-toggle-checkbox
:n "RET" 'org-archive-subtree
:n "a" 'org-agenda
:n "A" 'narf:org-attachment-list
:n "d" 'org-time-stamp
:n "D" 'org-time-stamp-inactive
:n "i" 'narf/org-toggle-inline-images-at-point
:n "t" (λ! (org-todo (if (org-entry-is-todo-p) 'none 'todo)))
:n "T" 'org-todo
:n "s" 'org-schedule
:n "r" 'org-refile
:n "R" (λ! (org-metaleft) (org-archive-to-archive-sibling)) ; archive to parent sibling
)
;; TODO Improve folding bindings
:n "za" 'org-cycle
:n "zA" 'org-shifttab
:n "zm" (λ! (outline-hide-sublevels 1))
:n "zr" 'outline-show-all
:n "zo" 'outline-show-subtree
:n "zO" 'outline-show-all
:n "zc" 'outline-hide-subtree
:n "zC" (λ! (outline-hide-sublevels 1))
:n "zd" (lambda (&optional arg) (interactive "p") (outline-hide-sublevels (or arg 3)))
:m "]]" (λ! (call-interactively 'org-forward-heading-same-level) (org-beginning-of-line))
:m "[[" (λ! (call-interactively 'org-backward-heading-same-level) (org-beginning-of-line))
:m "]l" 'org-next-link
:m "[l" 'org-previous-link
:n "RET" 'narf/org-dwim-at-point
:m "gh" 'outline-up-heading
:m "gj" 'org-forward-heading-same-level
:m "gk" 'org-backward-heading-same-level
:m "gl" (λ! (call-interactively 'outline-next-visible-heading) (show-children))
:n "go" 'org-open-at-point
:n "gO" (λ! (let ((org-link-frame-setup (append '((file . find-file-other-window)) org-link-frame-setup))
(org-file-apps '(("\\.org$" . emacs)
(t . "open \"%s\""))))
(call-interactively 'org-open-at-point)))
:n "gQ" 'org-fill-paragraph
:m "$" 'org-end-of-line
:m "^" 'org-beginning-of-line
:n "<" 'org-metaleft
:n ">" 'org-metaright
:v "<" (λ! (org-metaleft) (evil-visual-restore))
:v ">" (λ! (org-metaright) (evil-visual-restore))
:n "-" 'org-cycle-list-bullet
:n [tab] 'org-cycle)
(:map org-src-mode-map
:n "<escape>" (λ! (message "Exited") (org-edit-src-exit)))
(:after org-agenda
(:map org-agenda-mode-map
:e "<escape>" 'org-agenda-Quit
:e "C-j" 'org-agenda-next-item
:e "C-k" 'org-agenda-previous-item
:e "C-n" 'org-agenda-next-item
:e "C-p" 'org-agenda-previous-item))))
(provide 'module-org)
;;; module-org.el ends here

135
modules/module-write.el Normal file
View file

@ -0,0 +1,135 @@
;; module-write.el
;; This library offers the following:
;; + Write-mode: a mode that turns Emacs into an app for writing notes, papers, or
;; fiction: it adds eye-candy to org-mode, switches to a light color theme and
;; to a more readable font.
;; + Bibtex integration
;; Write-mode settings
(defconst write-mode nil)
(defconst write-mode-font (font-spec :family "Hack" :size 12))
(defconst write-mode-biblio-dir "~/Dropbox/docs/biblio")
(defconst write-mode--last-mode-line mode-line-format)
(defconst write-mode--last-line-spacing line-spacing)
;; (defvar write-mode-org-font-lock-keywords
;; `(("[-+*] \\[X\\] \\([^$\n\r]+\\)"
;; (1 'org-headline-done))
;; ("^ *\\([-+]\\|[0-9]+[).]\\)\\( \\)+[^$\n\r]"
;; (1 'org-list-bullet))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(setq-default visual-fill-column-center-text nil
visual-fill-column-width 80)
(defun write-mode|org-hook ()
"A hook that runs everytime an org-mode buffer is visited/created while `write-mode' is
active."
;; (font-lock-add-keywords nil write-mode-org-font-lock-keywords)
)
(defun write-mode-toggle ()
"Enable write-mode, this is not a [global] minor mode because it mixes some frame-local
functionality with buffer-local ones, which can be buggy in a minor-mode."
(interactive)
(let* ((mode-p write-mode)
(on-off (if mode-p -1 +1)))
;; (scroll-bar-mode on-off)
(narf/load-font (if mode-p narf-default-font write-mode-font))
(when (featurep 'volatile-highlights)
(volatile-highlights-mode (not on-off)))
(when IS-MAC
(setq mouse-wheel-scroll-amount
(if mode-p '(5 ((shift) . 2)) '(3 ((shift) . 2)))))
(if write-mode
(remove-hook 'org-mode-hook 'write-mode|org-hook)
(add-hook 'org-mode-hook 'write-mode|org-hook))
(mapc (lambda (b)
(with-current-buffer b
(setq line-spacing (if mode-p write-mode--last-line-spacing '2))
(when (eq major-mode 'org-mode)
(unless write-mode
;; (font-lock-remove-keywords nil write-mode-org-font-lock-keywords)
(write-mode|org-hook))
(org-bullets-mode on-off))))
(narf/get-buffers-in-modes '(org-mode markdown-mode)))
(setq write-mode (not write-mode))))
(evil-define-command narf:set-columns (&optional bang columns)
"Adjusts visual-fill-column-width on the fly."
(interactive "<!><a>")
(if (or (= (length columns) 0) bang)
(progn
(setq visual-fill-column-width 80)
(when visual-fill-column-mode
(visual-fill-column-mode -1)))
(setq columns (string-to-number columns))
(when (> columns 30)
(setq visual-fill-column-width columns)))
(if visual-fill-column-mode
(visual-fill-column--adjust-window)
(visual-fill-column-mode 1)))
(when (>= emacs-major-version 25)
;; From <https://github.com/joostkremers/visual-fill-column/pull/6>
;; Splitting windows while visual-fill-column makes Emacs go crazy. This prevents that
;; by simply disabled VFC before splitting.
(after! visual-fill-column
(advice-add 'split-window :around #'visual-fill-column--disable-on-split-window))
(defun visual-fill-column--disable-on-split-window (fn window &rest args)
"Undo the effects of `visual-fill-column-mode' for splitting window."
(if (and (or (not window) (window-live-p window))
(buffer-local-value 'visual-fill-column-mode
(window-buffer (or window (selected-window)))))
(let ((inhibit-redisplay t))
(set-window-fringes (or window (selected-window)) nil)
(set-window-margins (or window (selected-window)) 0 0)
(unwind-protect (apply fn window args)
(save-selected-window
(when window (select-window window 'norecord))
(visual-fill-column--adjust-window))))
(apply fn window args))))
;;; LaTeX
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq bibtex-dialect 'biblatex)
(setq bibtex-align-at-equal-sign t)
(setq bibtex-text-indentation 20)
(add-hook! bibtex-mode
(local-set-key (kbd "C-c \\") 'bibtex-fill-entry)
(setq fill-column 140))
(add-hook! latex-mode 'turn-on-auto-fill)
(add-hook! LaTeX-mode 'turn-on-auto-fill)
(use-package reftex
:config
(add-hook 'latex-mode-hook 'turn-on-reftex)
(add-hook 'LaTeX-mode-hook 'turn-on-reftex)
(setq reftex-plug-into-AUCTeX t
reftex-ref-style-default-list '("Cleveref" "Hyperref" "Fancyref")
reftex-default-bibliography
`(,(expand-file-name "phys.bib" write-mode-biblio-dir))))
;;; Bibtex
;; NOTE: http://bibdesk.sourceforge.net/
(use-package helm-bibtex
:defer t
:config
(setq helm-bibtex-bibliography
`(,(expand-file-name "phys.bib" write-mode-biblio-dir))
helm-bibtex-library-path
`(,(expand-file-name "phys-pdf" write-mode-biblio-dir))
helm-bibtex-notes-path (expand-file-name "notes" write-mode-biblio-dir)
helm-bibtex-notes-extension ".org"
helm-bibtex-pdf-open-function
(lambda (fpath) (async-start-process "open-pdf" "/usr/bin/open" nil fpath))))
(provide 'module-write)
;;; module-write.el ends here

View file

@ -161,14 +161,12 @@
:n "T" 'os-switch-to-term-and-cd) :n "T" 'os-switch-to-term-and-cd)
;; Org notes ;; Org notes
:n "X" 'narf/org-start
(:prefix "x" (:prefix "x"
:n "." 'narf/helm-org-find-files :n "." 'narf/org-find-file
:n "/" 'narf/helm-org :n "/" 'narf/org-find-file-in-notes
:n "x" 'narf/org-open-notes :n "e" 'narf/org-find-exported-file
:n "p" 'narf/helm-org-crm-projects ))
:n "c" 'narf/helm-org-crm-contacts
:n "i" 'narf/helm-org-crm-invoices
:n "w" 'narf/helm-org-writing))
(:localleader (:localleader
:n "k" 'narf/helm-descbinds-localleader :n "k" 'narf/helm-descbinds-localleader

View file

@ -72,6 +72,9 @@
(exmap "tabp[rev]" 'narf:switch-to-tab-left) (exmap "tabp[rev]" 'narf:switch-to-tab-left)
(exmap "tabl[ast]" 'narf:switch-to-tab-last) (exmap "tabl[ast]" 'narf:switch-to-tab-last)
;; Org-mode
(exmap "att[ach]" 'narf:org-attach)
;; Plugins ;; Plugins
(after! flycheck (after! flycheck
(exmap "er[rors]" (λ! (flycheck-buffer) (flycheck-list-errors)))) (exmap "er[rors]" (λ! (flycheck-buffer) (flycheck-list-errors))))

View file

@ -0,0 +1,6 @@
# -*- mode: snippet -*-
# name: Org template
# --
#+TITLE:${1:`(f-base buffer-file-name)`}
$0