Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
3867 lines (2964 sloc) 120 KB

Jay Dixit’s GNU Emacs setup

file settings

#+ TODO: TODO PLEASE-TEST TESTING PLEASE-DEBUG | DONE

About

environment settings

Handle Emacs UTF-8 input

(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
(setenv "LANG" "en_US.UTF-8")

Sticky windows

(global-set-key [(control x) (?0)] 'delete-other-windows)
(global-set-key [(control x) (?9)] 'sticky-window-keep-window-visible)
(global-set-key  (kbd "s-0") 'delete-window)
(global-set-key  (kbd "s-1") 'delete-other-windows)
(global-set-key  (kbd "s-9") 'sticky-window-keep-window-visible)
(global-set-key  (kbd "s-2") 'split-window-vertically)
(global-set-key  (kbd "s-3") 'split-window-horizontally)

abbreviations

Automatically load abbreviations table:

(setq-default abbrev-mode t)
(read-abbrev-file "/Users/jay/emacs/aquamacs-jay/.abbrev_defs")
(setq abbrev-file-name "/Users/jay/emacs/aquamacs-jay/.abbrev_defs")

(setq save-abbrevs t)
(setq save-abbrevs 'silently)
(setq only-global-abbrevs t)

reflash-indentation

(defun reflash-indentation ()
"Fix spacing on the screen."
  (interactive)
  (org-indent-mode 1)
(recenter-top-bottom)
  )

org predicates

(require 'org-element) 

  (defun org-checkbox-p ()
  "Predicate: Checks whether the current line org-checkbox"
    (and
;; (org-or-orgalist-p)
      (string-match "^\s*\\([-+*]\\|[0-9]+[.\\)]\\)\s\\[.?\\]\s" (or (thing-at-point 'line) ""))))

  (defun org-plain-text-list-p ()
  "Predicate: Checks whether the current line org-plain-text-list"
    (and
;; (org-or-orgalist-p)
      (string-match "^\s*\\([-+]\\|\s[*]\\|[0-9]+[.\\)]\\)\s" (or (thing-at-point 'line) ""))))

org-mode hooks

(setq org-hierarchical-todo-statistics nil)

fullscreen settings

(Source)

(defvar maxframe-maximized-p nil "maxframe is in fullscreen mode")

(defun toggle-maxframe ()
  "Toggle maximized frame"
  (interactive)
  (setq maxframe-maximized-p (not maxframe-maximized-p))
  (cond (maxframe-maximized-p (maximize-frame))
        (t (restore-frame))))

(define-key global-map [(s-return)] 'toggle-maxframe)
;; make it easy to go fullscreen
(defun toggle-fullscreen ()
  "Toggle full screen"
  (interactive)
  (set-frame-parameter
   nil 'fullscreen
   (when (not (frame-parameter nil 'fullscreen)) 'fullboth)))

;; and the keybinding
(unless (fboundp 'toggle-frame-fullscreen)
  (global-set-key (kbd "<f11>") 'toggle-fullscreen))
(unless (fboundp 'toggle-frame-fullscreen)
  (global-set-key (kbd "<f13>") 'toggle-fullscreen))

  (global-set-key (kbd "<f13>") 'toggle-fullscreen)

directory settings

There is probably a lot of redundancy here, I don’t understand this stuff too well.

;; (require 'dired-details+)



;; (defadvice dired-readin
;;     (after dired-after-updating-hook first () activate)
;;   "Sort dired listings with directories first before adding marks."
;;   (mydired-sort)
;;   (let ((dired-details-internal-overlay-list  ())) (dired-details-hide)))

(defcustom dired-details-hidden-string ""
  "*This string will be shown in place of file details and symbolic links."
  :group 'dired-details
  :type 'string)

(defcustom dired-details-initially-hide t
  "*Hide dired details on entry to dired buffers."
  :group 'dired-details
  :type 'boolean)

other functions

Manually remove the scrollbar if default setting fails when creating a new frame:

(defun scrollbar-init ()
  (interactive)
  (scroll-bar-mode -1)
  )

(defun scrollbar-mode-turn-off-scrollbar ()
  (interactive)
  (scroll-bar-mode -1)
  )

(defun scrollbar-mode-turn-on-scrollbar ()
  (interactive)
  (scroll-bar-mode 1)
  )

Forgot what this does, I think it’s in case Emacs crashes maybe to recover autosaves?

(defadvice recover-session (around disable-dired-omit-for-recover activate)
  (let ((dired-mode-hook dired-mode-hook))
    (remove-hook 'dired-mode-hook 'enable-dired-omit-mode)
    ad-do-it))

isolate Emacs kill ring from the OSX system pasteboard (clipboard).

Very important, I use this all the time. These are custom functions to separate the OSX clipboard from Emacs’ kill ring, effectively giving me two separate clipboards to work from. The below are the traditional OSX keybindings for cut/copy/paste, and they will now work with the OSX clipboard. The yank and pop functions still work, and use the Emacs kill ring instead.

pasteboard setup

(setq interprogram-cut-function nil)
(setq interprogram-paste-function nil)

pasteboard-copy

(defun pasteboard-copy ()
  "Copy region to OS X system pasteboard."
  (interactive)
  (let* ((txt (buffer-substring (region-beginning) (region-end)))
         (txt-updated-links
          (replace-regexp-in-string
           "\\[\\[\\([^]]*\\)\\]\\(\\[\\([^]]*\\)\\]\\)?\\]"
           (lambda (m)
             (concat "[" (or (match-string 3 m)
                             (match-string 1 m))
                     "](" (match-string 1 m) ")"))
           txt)))
;; (message "Copied: %s" txt-updated-links)
    (shell-command-to-string
     (format "echo -n %s | pbcopy" (shell-quote-argument txt-updated-links)))))

pasteboard-paste

pasteboard-paste (with smart quotes by default)

(defun pasteboard-paste ()
  "Paste from OS X system pasteboard via `pbpaste' to point."
  (interactive)
  (let ((start (point))
        (end (if mark-active
                (mark)
                (point)))
        (ins-text
         (replace-regexp-in-string
          "\\[\\([^][]*\\)\\](\\([^)]*\\))"
          (lambda (m)
             (let ((m1 (match-string 1 m))
                   (m2 (match-string 2 m)))
                (if (string= m1 m2)
                  (concat "[[" m1 "]]")
                  (concat "[[" m2 "][" m1 "]]"))))
          (shell-command-to-string "pbpaste | perl -p -e 's/\r$//' | tr '\r' '\n'"))))
    (delete-region start end)
    (insert ins-text)
    (my/fix-space)
    (save-excursion
     (goto-char start)
     (my/fix-space)))
  ; (reflash-indentation)
  ) 

pasteboard-paste-without-smart-quotes (and without spaces)

(defun pasteboard-paste-without-smart-quotes ()
  (interactive)
  (let ((beg (point)))
    (pasteboard-paste)
    (replace-smart-quotes beg (point))))

pasteboard-paste-spaces-maybe

(defun pasteboard-paste-spaces-maybe ()
(interactive)
;; begin if
(if
(or
(looking-back "'")
(looking-back ":")
(looking-at "'")
(looking-back "(")
(looking-back "'")
(looking-at ")")
(looking-at "|")
(looking-back "|")
(looking-back "\\[")
(looking-at "\\]")
(looking-at "\\/")
(looking-at "\\/")
(looking-at "\\\\")
(looking-back "\\\\")
(looking-back "\/")
(looking-back "\"")
(looking-at "\"")
(looking-back "\"")
(looking-back "=")
(looking-at "<")
(looking-back "<")
(looking-at "<")
(looking-back ">")
(looking-at "{")
(looking-back "{")
(looking-at "}")
(looking-back "}")
)
;; end if

    (pasteboard-paste-no-spaces) ; then
  (pasteboard-paste-without-smart-quotes))   ; else
  )

pasteboard-paste-no-spaces - original working version

(defun pasteboard-paste-no-spaces ()
  "Paste from OS X system pasteboard via `pbpaste' to point."
  (interactive)
  (let ((start (point))
	(end (if mark-active
		 (mark)
	       (point))))
    (shell-command-on-region start end
			     "pbpaste | perl -p -e 's/\r$//' | tr '\r' '\n'"
			     nil t)
    (save-excursion
      )))

pasteboard-cut

(defun pasteboard-cut ()
  "Cut region and put on OS X system pasteboard."
  (interactive)
  (pasteboard-copy)
  (delete-region (region-beginning) (region-end))
  (my/fix-space)
  )

(defun pasteboard-cut-and-capitalize ()
  "Cut region and put on OS X system pasteboard."
  (interactive)
  (pasteboard-copy)
  (delete-region (region-beginning) (region-end))
  (my/fix-space)
  (save-excursion
    (when (my/beginning-of-sentence-p)
      (capitalize-unless-org-heading))))

wrapped-search-forward

(defvar-local failed-search nil)

(defun wrapped-search-forward (str)
  (interactive "sWrappedSearch:")
  (if (and
       failed-search
       (>= (car failed-search) (point))
       (string-equal (cdr failed-search) str))
      (let ((p (save-excursion
                 (goto-char 0)
                 (search-forward str nil t))))
        (if p
            (progn
              (goto-char p)
              (setq-local failed-search nil))
          (message "WrappedSearch: Not found.")))
    (let ((p (search-forward str nil t)))
      (unless p
        (setq-local failed-search (cons (point) str))
        (message "Search: Not found.")))))

pasteboard-search-for-clipboard-contents

(defun pasteboard-search-for-clipboard-contents ()
  (interactive)
  (let ((search-term
         (with-temp-buffer
           (pasteboard-paste-no-spaces)
           (buffer-string))))
    (wrapped-search-forward search-term)))

kill ring to pasteboard functions

push kill ring to OSX pasteboard

(setq x-select-enable-clipboard t)
(defun push-kill-ring-pasteboard-to-clipboard ()
  (interactive)
  (x-select-text (current-kill 0)))

gist-buffer-to-pasteboard

(defun gist-buffer-to-pasteboard ()
  (interactive)
  (gist-buffer)
  (push-kill-ring-pasteboard-to-clipboard)
  )

keybindings

Create custom keybinding prefix

I have an unconventional approach to this that I recommend highly. I have redefined the C-l (‘ell’) key to be a prefix key, and I use that to prefix my favorite commands. This key is very easy to type and it is bound to a function (‘recenter) that isn’t used that much. Well, I don’t use ‘recenter much, but even if you did, it can be assigned to C-l C-l which is almost as easy to type, and a small price to pay for the possibilities opened up by the Ctrl-L-map. (Actually I prefer ‘redraw-display to ‘recenter, so I gave that the place of honor.)

Source: LenW’s answer on keyboard - What are good custom keybindings in emacs? - Stack Overflow

Use ⌘-m as prefix for my own custom keybindings:

(global-unset-key (kbd "s-j"))
(defvar s-j-map (make-keymap)
  "Keymap for local bindings and functions, prefixed by (Command-M)")
(define-key global-map (kbd "s-j") 's-j-prefix)
(fset 's-j-prefix s-j-map)

TODO Custom keybindings

Eventually replace these with this? https://github.com/noctuid/general.el

;; create a custom minor mode to override other keybindings and use mine instead
(defvar key-minor-mode-map (make-keymap) "key-minor-mode keymap.")
(define-minor-mode key-minor-mode
  "A minor mode so that my key settings override annoying major modes."
  t " key" 'key-minor-mode-map)
(key-minor-mode 1)
(defun my-minibuffer-setup-hook ()
  (key-minor-mode 0))
(add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook)

;; unbind some existing keybindings
;; (define-key undo-tree-map (kbd "C-x r") nil)

;; and the keybindings
;; mk - mykeybindings

(define-key key-minor-mode-map (kbd "s-J") 'dired-jump)

(define-key key-minor-mode-map (kbd "s-j n s") 'yas/new-snippet)
(define-key key-minor-mode-map (kbd "s-j y n") 'yas/new-snippet)

(define-key help-mode-map (kbd "C-s-]") 'help-go-back)
(define-key key-minor-mode-map (kbd "C-s-]") 'help-go-forward)


(define-key key-minor-mode-map (kbd "s-j c m") 'css-mode)
;; (define-key css-mode-map (kbd "s-j c s") 'css-mode)
(define-key key-minor-mode-map (kbd "s-j s h") 'sh-mode)
(define-key key-minor-mode-map (kbd "s-j s m") 'sh-mode)

(define-key key-minor-mode-map (kbd "s-k") 'kill-buffer)

(define-key key-minor-mode-map (kbd "s-i") 'avy-goto-char)
(define-key key-minor-mode-map (kbd "s-p") 'org-html-export-to-html-and-open)


(define-key key-minor-mode-map (kbd "M-y") 'helm-show-kill-ring)

(define-key key-minor-mode-map (kbd "M-h M-k") 'describe-key)

(define-key key-minor-mode-map (kbd "s-M") 'visit-messages-buffer)

(defun visit-messages-buffer ()
(interactive)
()
  (interactive)
  (view-echo-area-messages)
(other-window 1)
)


(define-key key-minor-mode-map (kbd "s-p") 'move-region-to-other-window)

(defun visit-messages-buffer-full-screen ()
  (interactive)
  (with-current-buffer (messages-buffer)
  (goto-char (point-max))
  (switch-to-buffer (current-buffer)))
  )

(define-key key-minor-mode-map (kbd "<s-backspace>") 'kill-region)

(define-key key-minor-mode-map (kbd "s-j t c") 'org-table-create)

(define-key key-minor-mode-map (kbd "C-;") 'org-def)
(require 'flyspell)
(define-key flyspell-mode-map (kbd "C-;") 'org-def)

(define-key key-minor-mode-map (kbd "s-j u p") 'unfill-paragraph)

(define-key key-minor-mode-map (kbd "C-w") 'copy-region-as-kill)

;; (define-key key-minor-mode-map (kbd "=") 'insert-equals-sign)

(define-key key-minor-mode-map (kbd "s-j w s") 'isearch-forward-word)

(define-key key-minor-mode-map (kbd "s-f") 'isearch-forward-ignore-case)

(define-key key-minor-mode-map (kbd "s-j w m") 'whitespace-mode)

(define-key key-minor-mode-map (kbd "s-j h l") 'spacemacs/toggle-highlight-current-line-globally-off)

(define-key key-minor-mode-map (kbd "s-j r b") 'revert-buffer)

(define-key key-minor-mode-map (kbd "s-j s b") 'scrollbar-mode-turn-off-scrollbar)

(define-key key-minor-mode-map (kbd "s-j i l") 'imenu-list)
(define-key key-minor-mode-map (kbd "s-j i m") 'imenu-list)

(define-key key-minor-mode-map (kbd "s-j g t") 'google-translate-at-point)

(define-key key-minor-mode-map (kbd "M-?") 'insert-question-mark)


(define-key key-minor-mode-map (kbd "<s-S-down>") 'scratch)


(define-key key-minor-mode-map (kbd "s-j g a") 'adobe-garamond-pro)
(define-key key-minor-mode-map (kbd "s-j ag") 'adobe-garamond-pro)
(define-key key-minor-mode-map (kbd "s-j gf") 'adobe-garamond-pro)
(define-key key-minor-mode-map (kbd "s-j mf") 'monaco-font)
(define-key key-minor-mode-map (kbd "s-j mo") 'monaco-font)

(define-key key-minor-mode-map (kbd "s-j t t") 'toggle-between-src-and-example-block)

;; working with an external monitor
(define-key key-minor-mode-map (kbd "s-n") 'make-frame)
(define-key key-minor-mode-map (kbd "s-~") 'other-frame)
(define-key key-minor-mode-map (kbd "s-`") 'other-window)

(define-key key-minor-mode-map (kbd "C-x C-d") 'dired)

(define-key key-minor-mode-map (kbd "s-j c p") 'path-copy-path-to-kill-ring)


(define-key org-mode-map (kbd "s-j c s") 'org-clone-subtree)
(define-key key-minor-mode-map (kbd "s-j p s") 'org-paste-subtree)
(define-key key-minor-mode-map (kbd "s-j v") 'org-paste-subtree)
(define-key key-minor-mode-map (kbd "s-j x") 'org-cut-subtree)
(define-key key-minor-mode-map (kbd "s->") 'org-mark-subtree)


(define-key key-minor-mode-map (kbd "M-'") 'insert-one-double-quote)
(define-key key-minor-mode-map (kbd "M-s-.") 'mark-paragraph)

(define-key key-minor-mode-map (kbd "M-_") 'em-dash)

(define-key key-minor-mode-map (kbd "s-/") 'rgrep)

(define-key key-minor-mode-map (kbd "C-v") 'kdm/html2org-clipboard)


(define-key key-minor-mode-map (kbd "s-r") 'counsel-recentf)

(define-key key-minor-mode-map (kbd "M-.") 'insert-period)
(define-key key-minor-mode-map (kbd "M-,") 'insert-comma)


(define-key key-minor-mode-map (kbd "s-j g b") 'gist-buffer-to-pasteboard)

;; (define-key key-minor-mode-map (kbd "<M-s-up>") 'scroll-down-command)
;; (define-key key-minor-mode-map (kbd "<M-s-down>") 'scroll-up-command)


(define-key key-minor-mode-map (kbd "M-s b") 'book-search)
(define-key key-minor-mode-map (kbd "M-s c") 'current-buffers-search)


(define-key key-minor-mode-map (kbd "s-;") 'helm-resume)
(define-key key-minor-mode-map (kbd "s-j o m") 'org-mode)
(define-key key-minor-mode-map (kbd "s-j f m") 'fundamental-mode)
(define-key key-minor-mode-map (kbd "s-j e l") 'emacs-lisp-mode)


(define-key key-minor-mode-map (kbd "s-j w c") 'wc-mode)
(define-key key-minor-mode-map (kbd "s-j o c") 'org-wc-count-subtrees)
(define-key key-minor-mode-map (kbd "s-j o c") 'org-wc-display)

(global-set-key (kbd "C-c m") 'compose-mail)
;; (global-set-key (kbd "C-c m") 'yale-or-vivovii-compose)


(define-key key-minor-mode-map (kbd "s-j m b") 'menu-bar-mode)

(define-key key-minor-mode-map (kbd "s-m") 'mc/mark-all-like-this-dwim)

(define-key key-minor-mode-map (kbd "s-j d c") 'org-table-delete-column)
(define-key key-minor-mode-map (kbd "s-j i c") 'org-table-insert-column)
(define-key key-minor-mode-map (kbd "s-j i r") 'org-table-insert-row)


;; mu4e-gmail
;; (define-key key-minor-mode-map (kbd "s-L") 'mu4e-gmail)
(define-key key-minor-mode-map (kbd "]gi") 'mu4e-gmail)
(define-key key-minor-mode-map (kbd "]gm") 'mu4e-gmail)



;; don't know why this stopped working
(define-key key-minor-mode-map (kbd "C-c C-x <C-i>") 'org-clock-in)
(define-key key-minor-mode-map (kbd "C-c C-x <C-i>") 'org-clock-in)


(define-key key-minor-mode-map (kbd "M-s-=") 'calc-eval-region)

(define-key key-minor-mode-map (kbd "s-j p m") 'poetry-mode)

(define-key key-minor-mode-map (kbd "s-p") 'zin/org-checkbox-next)

(define-key key-minor-mode-map (kbd "<f20>") 'pomodoro-start-jay)
(define-key key-minor-mode-map (kbd "s-j p o") 'pomodoro-start-jay)



(define-key key-minor-mode-map (kbd "<C-s-left>") 'work-on-book)



(define-key key-minor-mode-map (kbd "s-j t d") 'jd-org-today)
(define-key key-minor-mode-map (kbd "s-j c i") 'jd-clock-in)



(define-key key-minor-mode-map (kbd "s-.") 'org-select-line)
(define-key key-minor-mode-map (kbd "C-.") 'searchlink)


;; (define-key key-minor-mode-map (kbd "s-p") 'jay-refile-region)

(define-key key-minor-mode-map (kbd "M-0") 'move-region-to-other-window)

(define-key key-minor-mode-map (kbd "s-b") 'narrow-or-widen-dwim)
                                        ; org-narrow-to-subtree

(define-key key-minor-mode-map (kbd "s-B") 'helm-mini)


(define-key key-minor-mode-map (kbd "C-x <return> RET") 'mc/mark-all-dwim)

(define-key key-minor-mode-map (kbd "s-H") 'hyperbole)

(define-key key-minor-mode-map (kbd "M-e") 'smart-forward-sentence)

(define-key key-minor-mode-map (kbd "M-q") 'prelude-switch-to-previous-buffer)

(define-key key-minor-mode-map (kbd "s-]") 'org-forward-heading-same-level)
(define-key key-minor-mode-map (kbd "s-[") 'org-backward-heading-same-level)


(define-key key-minor-mode-map (kbd "C-M-]") 'org-next-subtree-and-narrow)
(define-key key-minor-mode-map (kbd "C-M-[") 'org-previous-subtree-and-narrow)

(define-key key-minor-mode-map (kbd "C-]") 'org-next-subtree-same-level-and-narrow)

(define-key key-minor-mode-map (kbd "ESC ESC") 'org-previous-subtree-same-level-and-narrow)


(define-key key-minor-mode-map (kbd "s-F") 'pasteboard-search-for-clipboard-contents)

(define-key key-minor-mode-map (kbd "M-\"") 'open-abbrevs)

(define-key key-minor-mode-map (kbd "s-|") 'path-copy-path-to-clipboard)

(define-key key-minor-mode-map (kbd "<s-return>") 'toggle-fullscreen)

;; (define-key key-minor-mode-map (kbd "s-v") 'pasteboard-paste-without-smart-quotes)
;; (define-key orgalist-mode-map (kbd "s-v") 'pasteboard-paste-without-smart-quotes)
(global-set-key (kbd "s-v") 'pasteboard-paste-no-spaces)
(define-key org-mode-map (kbd "s-v") 'pasteboard-paste-spaces-maybe)
;; (define-key orgalist-mode-map (kbd "s-v") 'pasteboard-paste-spaces-maybe)
;; (define-key fundamental-mode-map (kbd "s-v") 'pasteboard-paste-without-smart-quotes)
(define-key text-mode-map (kbd "s-v") 'pasteboard-paste-without-smart-quotes)
;; (define-key markdown-mode-map (kbd "s-v") 'pasteboard-paste-without-smart-quotes)

;; (define-key sh-mode-map (kbd "s-v") 'pasteboard-paste-no-spaces)
(define-key emacs-lisp-mode-map (kbd "s-v") 'pasteboard-paste-no-spaces)
(define-key key-minor-mode-map (kbd "C-s-v") 'kdm/html2org-clipboard)
(define-key key-minor-mode-map (kbd "C-s-c") 'ox-clip-formatted-copy)
(define-key key-minor-mode-map (kbd "M-v") 'kdm/html2org-clipboard)


(define-key key-minor-mode-map (kbd "s-x") 'pasteboard-cut-and-capitalize)
(define-key key-minor-mode-map (kbd "s-c") 'pasteboard-copy)
(define-key key-minor-mode-map (kbd "s-V") 'pasteboard-paste-no-spaces)


(define-key emacs-lisp-mode-map (kbd "s-v") 'pasteboard-paste-no-spaces)
;; (define-key rebuilder-mode-map (kbd "s-v") 'pasteboard-paste-no-spaces)


(define-key key-minor-mode-map (kbd "s-h") 'replace-string)

(global-unset-key (kbd "C-S-r"))
(define-key key-minor-mode-map (kbd "C-S-r") nil)
(define-key org-mode-map (kbd "C-S-r") nil)

(define-key key-minor-mode-map (kbd "M-s-g") 'gnugol-word-at-point)
(define-key key-minor-mode-map (kbd "M-s-d") 'define-word-at-point)


(define-key key-minor-mode-map (kbd "C-s-o") 'dired-jump)

;; (define-key org-mode-map (kbd "s-O") 'uo-byword-file)


(define-key org-mode-map (kbd "s-O") 'reveal-in-finder)


;; pop mark
(define-key key-minor-mode-map (kbd "C-x p")'pop-to-mark-command)

;; projectile
;; (define-key key-minor-mode-map (kbd "s-P") 'projectile-commander)

(define-key key-minor-mode-map (kbd "s-E") 'new-email-from-subtree-no-signature)

;; and make it work in the minibuffer too
(define-key minibuffer-local-map (kbd "s-v") 'pasteboard-paste-no-spaces)
(define-key minibuffer-local-map (kbd "s-x") 'pasteboard-cut)
(define-key minibuffer-local-map (kbd "s-c") 'copy-minibuffer-contents)
(define-key minibuffer-local-map (kbd "s-a") 'copy-minibuffer-contents)

(defun copy-minibuffer-contents (arg)
  (interactive "p")
  (beginning-of-visual-line)
  (end-of-buffer)
  (copy-region-as-kill (mark) (point))
  (push-kill-ring-pasteboard-to-clipboard)
  )




(define-key key-minor-mode-map (kbd "C-c C-v") 'refile-region)

;; (define-key key-minor-mode-map (kbd "s-0") 'widen)

(define-key key-minor-mode-map (kbd "s-0") 'copy-region-to-other-window)

(define-key emacs-lisp-mode-map (kbd "C-c e") 'eval-buffer)
(define-key org-mode-map (kbd "C-c e") 'eval-subtree)

(define-key key-minor-mode-map (kbd "C-c r") 'eval-region)


(define-key key-minor-mode-map (kbd "C-9") 'goto-last-change-reverse) ; super useful when editing
(define-key key-minor-mode-map (kbd "C--") 'goto-last-change) ; super useful when editing

;; (define-key key-minor-mode-map (kbd "s-=") 'zoom-in-and-disable-menu-bar-mode)

(define-key key-minor-mode-map (kbd "M-=") 'er/expand-region)
(define-key key-minor-mode-map (kbd "C-=") 'er/expand-region)
;; (define-key key-minor-mode-map (kbd "C-8") 'embolden-or-bold)
;; replaced it with multiple-cursors-hydra/body for now

;; (define-key key-minor-mode-map (kbd "C-8") '(lambda (arg) (interactive "p") (wrap-region-trigger arg "*"))) ; wow this was a stroke of genius

(define-key key-minor-mode-map (kbd "s-j r e") 'set-rectangular-region-anchor)

(define-key key-minor-mode-map (kbd "C-d") 'kill-word-correctly-and-capitalize)
;; (define-key key-minor-mode-map (kbd "m-d") 'kill-word-correctly-and-capitalize)

;; (define-key key-minor-mode-map (kbd "m-D") 'org-shiftleft)



(define-key key-minor-mode-map (kbd "C-l") 'reflash-indentation)
;; (define-key org-mode-map (kbd "C-l") 'reflash-indentation)


(define-key key-minor-mode-map (kbd "=") 'smex) ; call any function with easiest keystroke possible
;; (define-key key-minor-mode-map (kbd "=") 'counsel-M-x) ; call any function with easiest keystroke possible
(define-key key-minor-mode-map (kbd "M-x") 'helm-M-x) ; call helm-M-x instead of regular M-x
;; (define-key key-minor-mode-map (kbd "\|") 'deft)

(define-key org-mode-map (kbd "M-K") 'kill-clause)
(define-key emacs-lisp-mode-map (kbd "M-K") 'kill-sexp)

(define-key key-minor-mode-map (kbd "C-M-8") 'org-toggle-heading) ; i.e. subheading


(define-key key-minor-mode-map (kbd "M-8") 'org-toggle-heading-same-level)
(define-key key-minor-mode-map (kbd "M-*") 'org-toggle-todo-heading)
;; (define-key key-minor-mode-map (kbd "C-M-*") 'org-toggle-todo-subheading)


(define-key key-minor-mode-map (kbd "M-t") 'transpose-words)

(define-key key-minor-mode-map (kbd "M--") 'cycle-hyphenation-or-toggle-item)

(define-key key-minor-mode-map (kbd "s-'") 'refile-region-or-subtree)

(define-key key-minor-mode-map (kbd "C-c j") 'helm-org-headlines) ; also bound to keychord jj
(define-key key-minor-mode-map (kbd "C-x b") 'helm-mini) ; shows recent files; also bound to ⌘-r
(define-key key-minor-mode-map (kbd "M-b M-d") 'book-dired) ; show directory of my book folder
(define-key key-minor-mode-map (kbd "M-b r") 'read-a-book) ; show directory of my PDF books
(define-key key-minor-mode-map (kbd "M-b j") 'read-jd) ; show PDF books I have annotated
(define-key key-minor-mode-map (kbd "M-b M-b") 'work-on-book) ;

(define-key key-minor-mode-map (kbd "M-b M-w") 'work-on-book) ;

(define-key key-minor-mode-map (kbd "M-b lc") 'book-load-current) ;

;; (define-key key-minor-mode-map (kbd "M-b ho") 'spacemacs/toggle-highlight-current-line-globally)


;; book bindings
(define-key key-minor-mode-map (kbd "M-b M-p") 'book-proposal-directory)
(define-key key-minor-mode-map (kbd "M-b M-m") 'book-mistakes-directory)

(define-key key-minor-mode-map (kbd "M-b M-r") 'book-helm-strict) ; this is a smart function, show recent files in my book folder

;; can't get this to work. for some reason GNU Emacs interprets ⌘-shift-d as s-c
(define-key key-minor-mode-map (kbd "s-D") 'bjm/ivy-dired-recent-dirs)

;; own structure editing
(define-key key-minor-mode-map (kbd "s-o") 'move-region-to-other-window) ; very useful when working with a split frame
(define-key org-mode-map (kbd "s-o") 'move-region-to-other-window)


(define-key key-minor-mode-map (kbd "s-j o l") 'olivetti-mode)
(define-key key-minor-mode-map (kbd "] ol") 'olivetti-mode)
(define-key key-minor-mode-map (kbd "s-j o e") 'olivetti-expand)
(define-key key-minor-mode-map (kbd "s-+") 'olivetti-expand)
(define-key key-minor-mode-map (kbd "s-_") 'olivetti-shrink)

(define-key key-minor-mode-map (kbd "s-l") 'org-insert-link)


;; For extracting content from my browser

(define-key key-minor-mode-map (kbd "s-W") 'org-mac-chrome-insert-frontmost-url)
;; (define-key key-minor-mode-map (kbd "s-V") 'kdm/html2org-clipboard) ; paste HTML content that I've copied from the web, automatically converting to proper org-mode syntax


;; indirect buffer
(define-key key-minor-mode-map (kbd "s-I") 'clone-indirect-buffer-other-window)



;; and the keybinding
(define-key org-mode-map (kbd "C-k") 'my/kill-line-dwim)
(define-key key-minor-mode-map (kbd "C-k") 'my/kill-line-dwim)

;; use OSX standard keybindings ⌘-up and ⌘-down to go to top or bottom of buffer
(define-key key-minor-mode-map [s-up] 'beginning-of-buffer)
(define-key key-minor-mode-map [s-down] 'end-of-buffer)

(define-key key-minor-mode-map (kbd "S-s-SPC") 'set-mark-command)

;; mark commands 
(define-key key-minor-mode-map (kbd "C-M-SPC") 'set-mark-command)
(define-key key-minor-mode-map (kbd "C-M-x") 'exchange-point-and-mark)


(define-key key-minor-mode-map (kbd "C-s-SPC") 'helm-all-mark-rings)

; (define-key key-minor-mode-map (kbd "s-+") 'set-mark-command)

;; (define-key key-minor-mode-map (kbd "s-_") 'avy-pop-mark)
;; use OSX standard keybinding for "Redo"
(define-key key-minor-mode-map (kbd "s-y") 'undo-tree-redo)

;; use OSX standard keybinding to increase or decrease font size
;; (define-key key-minor-mode-map (kbd "s-=") 'text-scale-increase)
;; (define-key key-minor-mode-map (kbd "s--") 'text-scale-decrease)

(define-key key-minor-mode-map (kbd "s-=") 'embiggen-text)
(define-key key-minor-mode-map (kbd "s--") 'ensmallen-text)


;; rebind global help command so that I can use C-h for backspace
(define-key key-minor-mode-map (kbd "M-h") 'help-command)

;; very useful when encountering names and other unfamiliar words
(define-key key-minor-mode-map (kbd "M-+") 'add-word-to-personal-dictionary)

(define-key key-minor-mode-map (kbd "s-j s w") 'crux-swap-windows)

(define-key key-minor-mode-map (kbd "s-j l a") 'jay-load-latex)
(define-key key-minor-mode-map (kbd "s-j l t") 'jay-load-latex)
(define-key key-minor-mode-map (kbd "s-j k a") 'load-koma-letter)
(define-key key-minor-mode-map (kbd "s-j k o") 'load-koma-letter)

(define-key key-minor-mode-map (kbd "M-s-v") 'kdm/html2org-clipboard)


;; navigate between buffers, including uninteresting ones that are hidden by default
(define-key key-minor-mode-map (kbd "M-s-<right>") 'switch-to-next-buffer)
(define-key key-minor-mode-map (kbd "M-s-<left>") 'previous-buffer)

;; deleting things
;; (define-key key-minor-mode-map (kbd "<backspace>") 'my/delete-backward)
(define-key key-minor-mode-map (kbd "<backspace>") 'my/delete-backward-and-capitalize)

;; a keybinding for "delete" in addition to "backspace"
(define-key key-minor-mode-map (kbd "C-<backspace>") 'delete-char)
(define-key key-minor-mode-map (kbd "M-<backspace>") 'backward-kill-word-correctly-and-capitalize)

;; pomodoro
(define-key key-minor-mode-map (kbd "C-c C-x pi") 'pomodoro-start)
(define-key key-minor-mode-map (kbd "C-c C-x po") 'pomodoro-stop)

;; find files using helm
(define-key key-minor-mode-map (kbd "C-x C-f") 'helm-find-files)

;; search using helm-swoop
(global-set-key (kbd "M-I") 'helm-swoop-back-to-last-point)
(global-set-key (kbd "C-c M-i") 'helm-multi-swoop)
(global-set-key (kbd "C-x M-i") 'helm-multi-swoop-all)
(global-set-key (kbd "M-i") 'helm-multi-swoop-all)

;; edit Emacs preferences using standard OSX keybinding for preferences
(define-key key-minor-mode-map (kbd "s-,") 'customize-group)

;; grep, using current project as default
(define-key key-minor-mode-map (kbd "s-G") 'helm-projectile-grep)

;; ag, using current folder as default
;; (define-key key-minor-mode-map (kbd "C-u s-g") 'helm-ag)
;; does that keyvinding work?

;; some custom functions

(define-key key-minor-mode-map (kbd "C-c v i") 'org-insert-src-block)

;; org-mime
;; (define-key org-mode-map (kbd "M-n") 'new-email-from-subtree-no-signature)
;; (define-key key-minor-mode-map (kbd "M-N") 'new-email-from-subtree)

sentences

Make kill-sentence work in a more intuitive way:

(defun kill-sentence-to-period ()
  "Leave the period in there."
  (interactive)
  (kill-sentence)
  (push-mark)
  (insert ".")
  (backward-char)
)

Source

(defun my/forward-to-sentence-end ()
  "Move point to just before the end of the current sentence."
  (forward-sentence)
  (backward-char)
  (unless (looking-back "[[:alnum:]]")
    (backward-char)))

(defun my/beginning-of-sentence-p ()
  "Return  t if point is at the beginning of a sentence."
  (let ((start (point))
        (beg (save-excursion (forward-sentence) (forward-sentence -1))))
    (eq start beg)))

(defun my/kill-sentence-dwim ()
  "Kill the current sentence up to and possibly including the punctuation.
When point is at the beginning of a sentence, kill the entire
sentence. Otherwise kill forward but preserve any punctuation at the sentence end."
  (interactive)
(smart-expand)
  (if (my/beginning-of-sentence-p)
      (progn
        (kill-sentence)
        (just-one-space)
        (when (looking-back "^[[:space:]]+") (delete-horizontal-space)))
      (kill-region (point) (progn (my/forward-to-sentence-end) (point)))
      (just-one-space 0))

;; don't leave two periods in a row
(when
(or
(looking-at "\\.\\. ")
(and
(looking-at "\\.")
(looking-back "\\.")
)
)
(delete-forward-char 1))

(when
    (and
     (looking-at ".")
     (looking-back ",")
     )
  (delete-backward-char 1)
  (forward-char 1)
  )

)

my/kill-line-dwim

(defun my/kill-line-dwim ()
  "Kill the current line."
  (interactive)
;; don't leave stray stars behind when killing a line
(when
(or
(looking-back "\\[")
(looking-back "\* ")
(looking-back "\* TODO ")
(looking-back "^\*+")
(looking-back "- ")
(looking-back "# ")
)
(beginning-of-line)
)
;;  (expand-abbrev)
  (org-kill-line)
;;  (save-excursion
;;    (when (my/beginning-of-sentence-on)
;;      (capitalize-unless-org-heading)))
)

kill-sentence-maybe-else-kill-line

(defun kill-sentence-maybe-else-kill-line ()
  (interactive)
(when
    (not (looking-at "$"))
  (my/kill-sentence-dwim))
  (when
      (looking-at "$")
    (my/kill-line-dwim))
)
;; and the keybinding
(global-set-key (kbd "M-k") 'kill-sentence-maybe-else-kill-line)

Browsing

(setq browse-url-browser-function 'browse-url-default-macosx-browser)

spacecraft-mode - superior handling of whitespace for writing and editing prose

smart-space

(defun smart-period-or-smart-space ()
"double space adds a period!"
(interactive)
  (if
(looking-back "[A-Za-z0-9] ")
(smart-period)
(smart-space)
))

(defun smart-space ()
  "Insert space and then clean up whitespace."
  (interactive)
(cond (mark-active
 (progn (delete-region (mark) (point)))))

;; (if (org-at-heading-p)
 ;;    (insert-normal-space-in-org-heading)

  (unless
      (or
(let ((case-fold-search nil)
(looking-back "\\bi\.e[[:punct:][:punct:]]*[ ]*") ; don't add extra spaces to ie.
)
(looking-back "\\bvs.[ ]*") ; don't add extra spaces to vs.
(looking-back "\\be\.\g[[:punct:]]*[ ]*") ; don't add extra spaces to eg.

(looking-back "^[[:punct:]]*[ ]*") ; don't expand previous lines - brilliant!

(looking-back ">") ; don't expand days of the week inside timestamps

(looking-back "][\n\t ]*") ; don't expand past closing square brackets ]
       ))
  (smart-expand))

(insert "\ ")
(just-one-space)
)




;; this is probably convuluted logic to invert the behavior of the SPC key when in org-heading
(defun insert-smart-space-in-org-heading ()
 "Insert space and then clean up whitespace."
 (interactive)
(unless
   (or
(looking-back "\\bvs.[ ]*") ; don't add extra spaces to vs.
(looking-back "\\bi\.e[[:punct:][:punct:]]*[ ]*") ; don't add extra spaces to ie.
(looking-back "\\be\.\g[[:punct:][:punct:]]*[ ]*") ; don't add extra spaces to eg.

(looking-back "^[[:punct:][:punct:]]*[ ]*") ; don't expand previous lines---brilliant!

(looking-back ">") ; don't expand days of the week inside timestamps

(looking-back "][\n\t ]*") ; don't expand past closing square brackets ]
    )
 (smart-expand))
(insert "\ ")
 (just-one-space))



; (define-key org-mode-map (kbd "<SPC>") 'smart-period-or-smart-space) ; I disabled this for DragonSpeak 
(define-key org-mode-map (kbd "<SPC>") 'smart-space)
;; (define-key orgalist-mode-map (kbd "<SPC>") 'smart-period-or-smart-space)
(global-set-key (kbd "M-SPC") 'insert-space)
(define-key org-mode-map (kbd "<M-SPC>") 'insert-space)
;; (define-key orgalist-mode-map (kbd "<M-SPC>") 'insert-space)

my/fix-space

;;; I changed this a)) bunch, not sure if it still works correctly.
;; (defun my/fix-space ()
;;   "Delete all spaces and tabs around point, leaving one space except at the beginning of a line and before a punctuation mark."
;;   (interactive)
;;   (just-one-space)
;;
;;     (when (or
;;            (looking-back "^[[:space:]]+")
;;            (looking-back "-[[:space:]]+")
;;            (looking-at "[.,:;!?»)-]")
;;            (looking-back"( ")
;;            (looking-at " )")
;;            ))
;;       (unless
;;       (looking-back "^-[[:space:]]+")
;;   (delete-horizontal-space))
;;
;; (unless
;;  (looking-back "^")
;; (just-one-space)
;; )
;;
;; )

(defun my/fix-space ()
  "Delete all spaces and tabs around point, leaving one space except at the beginning of a line and before a punctuation mark."
  (interactive)
  (just-one-space)
  (when (and (or
              (looking-back "^[[:space:]]+")
              (looking-back "-[[:space:]]+")
              (looking-at "[.,:;!?»)-]")
              (looking-back"( ")
              (looking-at " )")
              )
             (not (looking-back "^-[[:space:]]+"))
             (not (looking-back " - "))

)
    (delete-horizontal-space)))

. This.

insert-space

(defun insert-space ()
  (interactive) 
(if (org-at-heading-p)
(insert-smart-space-in-org-heading)
(cond (mark-active
   (progn (delete-region (mark) (point)))))
  (insert " ")
)) 

(defun insert-normal-space-in-org-heading ()
 (interactive)
(cond (mark-active
 (progn (delete-region (mark) (point))))) 
 (insert " ")
)

;; this is probably convuluted logic to invert the behavior of the SPC key when in org-heading


(defun insert-period ()
"Inserts a fuckin' period!"
 (interactive)
(cond (mark-active
   (progn (delete-region (mark) (point)))))

 (insert ".")
)


(defun insert-comma ()
 (interactive)
(cond (mark-active
   (progn (delete-region (mark) (point))))) 
 (insert ",")
)

(defun insert-exclamation-point ()
 (interactive)
(cond (mark-active
  (progn (delete-region (mark) (point)))))
 (insert "!")
)


(defun insert-colon ()
"Insert a goodamn colon!"
 (interactive)
(cond (mark-active
  (progn (delete-region (mark) (point))))) 
 (insert ":")
) 

(defun insert-question-mark ()
"Insert a freaking question mark!!"
 (interactive)
(cond (mark-active
 (progn (delete-region (mark) (point))))) 
 (insert "?")
) 

smart insertion of headings and subheadings

smart-org-meta-return-dwim

(setq org-blank-before-new-entry
      '((heading . always)
       (plain-list-item . always)))

(defun call-rebinding-org-blank-behaviour (fn)
  (let ((org-blank-before-new-entry
         (copy-tree org-blank-before-new-entry)))
    (when (org-at-heading-p)
      (rplacd (assoc 'heading org-blank-before-new-entry) nil))
    (call-interactively fn)))

(defun smart-org-meta-return-dwim ()
  (interactive)

(if

    (and
     (looking-back "^")
     (looking-at ".+")
     )                               ; if
    (org-toggle-heading-same-level) ; then
 (call-rebinding-org-blank-behaviour 'org-meta-return)) ; else
)

smart-org-insert-heading-respect-content-dwim

(defun smart-org-insert-heading-respect-content-dwim ()
(interactive)
  (call-rebinding-org-blank-behaviour 'org-insert-heading-respect-content)
)

smart-org-insert-todo-heading-dwim

(defun smart-org-insert-todo-heading-dwim ()
  (interactive)
  (let ((listitem-or-checkbox (org-plain-text-list-p)))
    (call-rebinding-org-blank-behaviour 'org-insert-heading)
    (if listitem-or-checkbox
        (insert "[ ] ")
        (insert "TODO ")))
)

smart-org-insert-todo-heading-respect-content-dwim

(defun smart-org-insert-todo-heading-respect-content-dwim ()
  (interactive)
  (call-rebinding-org-blank-behaviour 'org-insert-todo-heading-respect-content)
)

smart-org-insert-subheading

(defun smart-org-insert-subheading ()
  (interactive)
(call-rebinding-org-blank-behaviour 'org-meta-return)
(org-demote-subtree)
)

smart-org-insert-todo-subheading

(defun smart-org-insert-todo-subheading ()
  (interactive)
(call-rebinding-org-blank-behaviour 'org-insert-todo-subheading)
)

keybindings

(define-key org-mode-map (kbd "M-<return>") 'smart-org-meta-return-dwim)
(define-key org-mode-map (kbd "M-S-<return>") 'smart-org-insert-todo-heading-dwim)
(define-key org-mode-map (kbd "C-<return>") 'return-insert-blank-line-before)
(define-key org-mode-map (kbd "C-S-<return>") 'smart-org-insert-todo-heading-respect-content-dwim)
(define-key org-mode-map (kbd "C-M-<return>") 'smart-org-insert-subheading)
(define-key org-mode-map (kbd "<C-S-M-return>") 'smart-org-insert-todo-subheading)
(define-key org-mode-map (kbd "<C-s-return>") 'smart-org-insert-todo-subheading)
(define-key key-minor-mode-map (kbd "<s-S-return>") 'smart-org-insert-todo-heading-dwim)
(define-key key-minor-mode-map (kbd "<s-return>") 'toggle-fullscreen) 

length of previous line

(defun length-of-previous-line ()
 (save-excursion
  (forward-line -1)
  (end-of-line)
  (current-column)))

smart-return

(defun smart-return ()
  (interactive)

  ;; don't leave stray stars or links
  (when
      (or
       (looking-back "\\[")
       ;; (looking-back "\* ")
       (looking-back "^\*+[ ]*") ; hopefully this means: at the beginning of the line, 1 or more asterisks followed by zero or more spaces
       (looking-back "^# ")
       ;; (looking-back "* TODO ") ; actually I don't think I want this
       ;; (looking-back "^*+")
       ;; (looking-back "- ")

       )
    (beginning-of-line)
    )
  ;;
  (cond (mark-active
         (progn (delete-region (mark) (point))
                (newline)))
        ;; Shamefully lifted from `org-return'. Why isn't there an
        ;; `org-at-link-p' function?!
        ((and 
;; (org-or-orgalist-p)
              org-return-follows-link
              (org-in-regexp org-any-link-re))
         (cond
          ((or
            ;;(looking-at "\\[\\[.*")
            (looking-back ">")
            (looking-back "\\]\\]")
            (and (thing-at-point 'url)
                 (let ((bnds (bounds-of-thing-at-point 'url)))
                   (or (>= (car bnds) (point))
                       (<= (cdr bnds) (point))))))
           (newline))
          ((char-equal (string-to-char "]") (following-char))
           (progn (forward-char 2)
                  (newline)))
          (t (call-interactively 'org-open-at-point))))

   ((and 
;; (org-or-orgalist-p)
              (let ((el (org-element-at-point)))
                (and el
                     ;; point is at an item
                     (eq (first el) 'item)
                     ;; item is empty
                     (eql (getf (second el) :contents-begin)
                          (getf (second el) :contents-end)))))
    (message "at 1")
    (beginning-of-line)
         (let ((kill-whole-line nil))
           (kill-line))
         (newline))
        ((and 
;; (org-or-orgalist-p)
              (let ((el (org-element-at-point)))
                (and el
                     (or (member (first el) '(item plain-list))
                         (let ((parent (getf (second el) :parent)))
                           (and parent
                                (member (first parent) '(item plain-list))))))))
         (let ((is-org-chbs (org-checkbox-p)))
           (org-run-like-in-org-mode (lambda () (interactive) (call-interactively 'org-meta-return)))
           (when is-org-chbs
             (insert "[ ] "))))
        ((and
;; (org-or-orgalist-p)
          (not (and
                org-return-follows-link
                (looking-back ">"))))
         (org-run-like-in-org-mode (lambda () (interactive) (call-interactively 'org-return))))
        (t (newline))))

(define-key org-mode-map (kbd "<return>") 'smart-return)
;; (define-key orgalist-mode-map (kbd "<return>") 'smart-return)

kill word correctly

(defun kill-word-correctly ()
  "Kill word."
  (interactive)
  (smart-expand)
  (if (or (re-search-forward "\\=[ 	]*\n" nil t)
          (re-search-forward "\\=\\W*?[[:punct:]]+" nil t)) ; IF there's a sequence of punctuation marks at point
      (kill-region (match-beginning 0) (match-end 0)) ; THEN just kill the punctuation marks
    (kill-word 1))                                    ; ELSE kill word
  (my/fix-space)
;; don't leave two periods in a row
(when 
(or
(looking-at "\\,\\, ")

(and 
(looking-at "\\,")
(looking-back "\\,") 
)
)
(delete-forward-char 1))
)

kill word correctly and capitalize

(defun kill-word-correctly-and-capitalize ()
  "Check to see if the point is at the beginning of the sentence. If yes, then kill-word-correctly and endless/capitalize to capitalize the first letter of the word that becomes the first word in the sentence. Otherwise simply kill-word-correctly."
  (interactive)
(when (looking-at "[ ]")
         (forward-char 1)
          )
;; capitalize correctly if there's point is before the space at the beginning of a sentence 
 
  (let ((fix-capitalization (my/beginning-of-sentence-p)))
    (call-interactively 'kill-word-correctly)
    (when fix-capitalization
      (save-excursion (capitalize-unless-org-heading)))))

character movement

(defun jay/left-char ()
  "Move point to the left or the beginning of the region.
 Like `backward-char', but moves point to the beginning of the region
provided the (transient) mark is active."
  (interactive)
  (let ((this-command 'left-char)) ;; maintain compatibility
    (let ((left (min (point)
                     ;; `mark' returning nil is ok; we'll only use this
                     ;; if `mark-active'
                     (or (mark t) 0))))
      (if (and transient-mark-mode mark-active)
          (progn
            (goto-char left)
            (setq deactivate-mark t))
        (call-interactively 'left-char)))))


(defun jay/right-char ()
  "Move point to the right or the end of the region.
 Like `right-char', but moves point to the end of the region
provided the (transient) mark is active."
  (interactive)
  (let ((this-command 'right-char)) ;; maintain compatibility
    (let ((right (max (point)
                      ;; `mark' returning nil is ok; we'll only use this
                      ;; if `mark-active'
                      (or (mark t) 0))))
      (if (and transient-mark-mode mark-active)
          (progn (goto-char right)
		 (setq deactivate-mark t))
	(call-interactively 'right-char)))))

(define-key org-mode-map (kbd "<left>") 'jay/left-char)
(define-key org-mode-map (kbd "<right>") 'jay/right-char)

code not currently in use

keybindings not currently in use

(define-key key-minor-mode-map (kbd “DEL”) ‘new-org-delete-backward-char) (global-set-key (kbd “C-c s”) ‘org-copy-subtree) (define-key key-minor-mode-map (kbd “C-v s”) ‘org-paste-subtree) ;; (define-key key-minor-mode-map (kbd “s-l”) ‘org-insert-link) (define-key key-minor-mode-map (kbd “C-c C-l”) ‘org-insert-link) (define-key key-minor-mode-map (kbd “s-i”) ‘markdown-insert-image) (define-key key-minor-mode-map (kbd “s-\”) ‘org-ctrl-c-ctrl-c) (define-key key-minor-mode-map (kbd “s-u”) ‘ido-dired) (define-key key-minor-mode-map (kbd “H-n”) ‘org-narrow-to-subtree)

(define-key key-minor-mode-map (kbd “H-G”) ‘prelude-google) (define-key key-minor-mode-map (kbd “s-G”) ‘osx-browse-guess)

(define-key key-minor-mode-map (kbd “s-“) ‘google-define-word-or-phrase) (define-key key-minor-mode-map (kbd “C-c C-x C-o”) ‘org-pomodoro) (define-key key-minor-mode-map (kbd “s-R”) ‘web-research)

;; (define-key key-minor-mode-map (kbd “<right>”) ‘aquamacs-right-char) ;; (define-key key-minor-mode-map (kbd “<right>”) ‘switch-to-next-buffer) ;; (define-key key-minor-mode-map (kbd “<right>”) ‘switch-to-next-buffer) ;; (define-key key-minor-mode-map (kbd “<down>”) ‘aquamacs-next-line)

experiments - tested

words - some interesting utilities for text in Emacs

The idea is a command called words that will be run interactively. It will grab the word at point, or operate on a selected region, and then offer a menu to lookup the definition, find it in a thesaurus, google it, etc.

We structure the code so you can add functions to it later, without directly modifying this code. The only limitation of this code is that the functions must have a signature with no arguments. That does not seem terribly limiting, as we can check for a region, and use it if we want (see the words-google function).

(defun words-dictionary ()
  (interactive)
  (browse-url
   (format
    "http://dictionary.reference.com/browse/%s?s=t"
    (thing-at-point 'word))))

(defun words-thesaurus ()
  (interactive)
  (browse-url
   (format
    "http://www.thesaurus.com/browse/%s"
    (thing-at-point 'word))))

(defun words-google ()
  (interactive)
  (browse-url
   (format
    "http://www.google.com/search?q=%s"
    (if (region-active-p)
	(url-hexify-string (buffer-substring (region-beginning)
					     (region-end)))
      (thing-at-point 'word)))))


(defvar words-funcs '()
 "functions to run in `words'. Each entry is a list of (key menu-name function).")

(setq words-funcs
  '(("d" "ictionary" words-dictionary)
    ("t" "hesaurus" words-thesaurus)
    ("g" "oogle" words-google)))


(defun words ()
  (interactive)
   (message
   (concat
    (mapconcat
     (lambda (tup)
       (concat "[" (elt tup 0) "]"
	       (elt tup 1) " "))
     words-funcs "") ": "))
   (let ((input (read-char-exclusive)))
     (funcall
      (elt
       (assoc
	(char-to-string input) words-funcs)
       2))))

This works nicely. Now, let us add a new function that looks up the word or selection on twitter. We just define a new function, and add the menu selection to the words-func variable.

(defun words-twitter ()
  (interactive)
  (browse-url
   (format
    "https://twitter.com/search?q=%s"
    (if (region-active-p)
	(url-hexify-string (buffer-substring (region-beginning)
					     (region-end)))
      (thing-at-point 'word)))))

(add-to-list 'words-funcs
  '("w" "twitter" words-twitter)
  t) ; append

Finally, the most complicated idea: spelling and grammar. I know there is flyspell, and such, but they are build on an ancient dictionary. Here, for fun, we explore a web api. This next function is not a trivial one, and I will not explain it here beyond saying it sends a selection of text to a url, gets an xml response back, and that response is parsed and printed to a buffer by this function. The main point is to illustrate we can do interesting things with a selection of text!

(defun words-atd ()
  "Send paragraph at point to After the deadline for spell and grammar checking."
  (interactive)

  (let* ((url-request-method "POST")
	 (url-request-data (format
			    "key=some-random-text-&data=%s"
			    (url-hexify-string
			     (thing-at-point 'paragraph))))
	 (xml  (with-current-buffer
		   (url-retrieve-synchronously
		    "http://service.afterthedeadline.com/checkDocument")
		 (xml-parse-region url-http-end-of-headers (point-max))))
	 (results (car xml))
	 (errors (xml-get-children results 'error)))

    (switch-to-buffer-other-frame "*ATD*")
    (erase-buffer)
    (dolist (err errors)
      (let* ((children (xml-node-children err))
	     ;; for some reason I could not get the string out, and had to do this.
	     (s (car (last (nth 1 children))))
	     ;; the last/car stuff doesn't seem right. there is probably
	     ;; a more idiomatic way to get this
	     (desc (last (car (xml-get-children children 'description))))
	     (type (last (car (xml-get-children children 'type))))
	     (suggestions (xml-get-children children 'suggestions))
	     (options (xml-get-children (xml-node-name suggestions) 'option))
	     (opt-string  (mapconcat
			   (lambda (el)
			     (when (listp el)
			       (car (last el))))
			   options
			   " ")))

	(insert (format "** %s ** %s
Description: %s
Suggestions: %s

" s type desc opt-string))))))

(add-to-list 'words-funcs
  '("s" "spell/grammar" words-atd)
  t) ; append

My final words menu looks like:

./images/final-menu.png

If I have the cursor in the previous paragraph, run the words command and select “s” I get a buffer with these contents:

*** flyspell ** (spelling)
Description: (Spelling)
Suggestions: flywheel flyball

*** are build on ** (grammar)
Description: (Auxiliary Verb Agreement)
Suggestions: are built on

*** api ** (spelling)
Description: (Spelling)
Suggestions: app ape apt ai ami

*** url ** (spelling)
Description: (Spelling)
Suggestions: urn ure curl hurl burl

*** xml ** (spelling)
Description: (Spelling)
Suggestions: xl ml

*** selection ** (suggestion)
Description: (Complex Expression)
Suggestions: choice

*** an xml ** (grammar)
Description: (Wrong article)
Suggestions: a xml

*** a selection of ** (grammar)
Description: (Hidden Verbs)
Suggestions:

*** is parsed ** (grammar)
Description: (Passive voice)
Suggestions:

*** selection ** (suggestion)
Description: (Complex Expression)
Suggestions: choice

*** a selection of ** (grammar)
Description: (Hidden Verbs)
Suggestions:

It might be nice to link back to those words, so you could click on them and fix them, but that is a beyond today’s goal. In summary, today we looked at a framework to create a user-modifiable menu of commands that are launched from a single command. Here we called the command words, and then built up some different things we might want to do with the word or selection at point. While you can of course just remember the individual commands, remembering one command and then being prompted might have some advantages.

Source: tk

invisible text in Emacs

Source: invisible text in Emacs

Making org-mode links to files in Emacs packages

Today I will make a new org-mode link that lets me make links to files inside of Emacs packages. These files may be installed in different places on different systems (e.g. in the system directory, in ELPA directories, or in custom directories), so we need a way to construct paths to them. The application of this is eventually I hope to have some emacs packages of documentation, and I would like to have links between the packages that work no matter how they are installed.

I want a syntax that looks like pkg:rainbow-mode==rainbow-mode-pkg.el. We will have a function that parses that to get the package, and the path to the file in the package. Emacs has a function to find the path to the file that defines a library. I chose == because it seems unlikely that would be a string in a package or path.

(locate-library "rainbow-mode")

#+RESULTS:
: c:/Users/jkitchin/Dropbox/kitchingroup/jmax/elpa/rainbow-mode-0.9/rainbow-mode.elc

We can use that to construct the path to where we want. Say we want the file named "rainbow-mode-pkg.el"

(expand-file-name
 "rainbow-mode-pkg.el"
 (file-name-directory (locate-library "rainbow-mode")))

#+RESULTS:
: c:/Users/jkitchin/Dropbox/kitchingroup/jmax/elpa/rainbow-mode-0.9/rainbow-mode-pkg.el

In org-mode links, the link path gets passed to a function. We can split the string like this to get the package and relative path we are referring to.

(split-string "rainbow-mode==rainbow-mode-pkg.el" "==")

#+RESULTS:
| rainbow-mode | rainbow-mode-pkg.el |

That is all of the pieces we need to construct the link function. Here it is.

(org-add-link-type
 "pkg"
 (lambda (path)
   (let ((pkg) (relpath)
	 (splitpath (split-string path "==")))
     (setq pkg (car splitpath))
     (setq relpath (nth 1 splitpath))
     (find-file (expand-file-name
		 relpath
		 (file-name-directory (locate-library pkg)))))))

#+RESULTS:

pkg:rainbow-mode==rainbow-mode-pkg.el

This works too, but you have to use auctex-pkg as the package name.

pkg:auctex-pkg==doc/intro.texi

I think that is because locate-library looks for the /file/ a library is defined in. That is not quite the same as the root directory of a package. It turns out to be a little more complicated to find that. Below is some code I hacked up looking at the package.el code. First let us examine some pieces.

This gives us information about an installed package.

(assq 'auctex package-alist)

#+RESULTS:
: (auctex . [(11 87 2) nil Integrated environment for *TeX*])

We can get the version of the package like this

(package-version-join (package-desc-vers (cdr (assq 'auctex package-alist))))

#+RESULTS:
: 11.87.2

Ok, finally, we get the directory where it is installed like this:

(package--dir "auctex" "11.87.2")

#+RESULTS:
: c:/Users/jkitchin/Dropbox/kitchingroup/jmax/elpa/auctex-11.87.2

Note that in some places we use a package symbol, and in other places a string name.Putting that together, we have this block to get the install-dir of a package. If we have a package symbol we can get the path like this.

(let* ((pkg 'auctex)
       (pkg-name (symbol-name pkg)) ; convert symbol to string
       (desc (cdr (assq pkg package-alist)))
       (version (package-version-join (package-desc-vers desc)))
       (pkg-dir (package--dir pkg-name version)))
  pkg-dir)

#+RESULTS:
: c:/Users/jkitchin/Dropbox/kitchingroup/jmax/elpa/auctex-11.87.2

Usually, we will have a string though. We just have to make it a symbol with the =intern= function.

(setq pkg-name "auctex")
(setq pkg (intern pkg-name))
(setq desc (cdr (assq pkg package-alist)))

#+RESULTS:
: [(11 87 2) nil "Integrated environment for *TeX*"]

Now, we have all the pieces to get the path from a package name in a string:

(let* ((pkg-name "auctex")
       (pkg (intern pkg-name))
       (desc (cdr (assq pkg package-alist)))
       (version (package-version-join (package-desc-vers desc)))
       (pkg-dir (package--dir pkg-name version)))
  pkg-dir)

#+RESULTS:
: c:/Users/jkitchin/Dropbox/kitchingroup/jmax/elpa/auctex-11.87.2

Let us use that to rewrite the link, and address a few other limitations. We will  use =org-open-link-from-string= so we can use org-link syntax in the path part of the link, e.g. to open a file at a line, or headline. Here is our new link.

(org-add-link-type
 "pkg2"
 (lambda (path)
   (let ((pkg) (relpath) (pkg-dir) (link-string)
	 (splitpath (split-string path "==")))
     (setq pkg-name (car splitpath))
     (setq relpath (nth 1 splitpath))
     (setq pkg-dir (let* ((pkg-symbol (intern pkg-name)) ;convert string to pkg
			  (desc (cdr (assq pkg-symbol package-alist)))
			  (version (package-version-join (package-desc-vers desc)))
			  (pkg-dir (package--dir pkg-name version)))
		     pkg-dir))
     (setq link-string (format "[[file:%s/%s]]" pkg-dir relpath))
     (message "link: %s" link-string)
     (org-open-link-from-string link-string))))

Now, we can do all of these:
pkg2:auctex==doc/faq.texi
pkg2:auctex==doc/faq.texi::should
pkg2:auctex==doc/faq.texi::10
[[pkg2:auctex==doc/faq.texi::first place]]

Awesome!

Just for fun, I made a toy package called =package1= in my elpa directory. That package has an org file in it. Now, I can test out the following links:

pkg2:package1==intro.org

pkg2:package1==intro.org::*Miscellaneous

[[pkg2:package1==intro.org::*subheading with words]]

pkg2:package1==intro.org::#install-section

pkg2:package1==intro.org::intro-target

They all work! That works for packages installed via the package manager. However, when I try this with my custom installed org-mode, it does not work. If I run (describe-package 'org) I see that org is a build in package, and that there is an alternate version avalable. It does not point to my org-installation.

pkg2:org==doc/library-of-babel.org

(princ (locate-library "org"))

#+RESULTS:
: c:/Users/jkitchin/Dropbox/kitchingroup/jmax/org-mode/lisp/org.elc

(princ (package-installed-p "org"))

#+RESULTS:
: nil

Obviously, we need to check if the package is installed via package.el, or if we should look somewhere else. Let us take a final stab at this. Let us review the challenge.

(print (locate-library "auctex"))
(print (locate-library "auctex-autoloads"))

#+RESULTS:
:
: nil
:
: "c:/Users/jkitchin/Dropbox/kitchingroup/jmax/elpa/auctex-11.87.2/auctex-autoloads.el"

We may have to check for a package-autoloads. Ww can wrap that in an =or= macro, which will return the first non-nil result.

(let ((pkg-name "auctex"))
   (file-name-directory
    (or (locate-library pkg-name)
	(locate-library (format "%s-autoloads" pkg-name)))))

#+RESULTS:
: c:/Users/jkitchin/Dropbox/kitchingroup/jmax/elpa/auctex-11.87.2/

Doing this on the org package shows that this points to a lisp directory.
(let ((pkg-name "org"))
   (file-name-directory
    (or (locate-library pkg-name)
	(locate-library (format "%s-autoloads" pkg-name)))))

#+RESULTS:
: c:/Users/jkitchin/Dropbox/kitchingroup/jmax/org-mode/lisp/

So, let's try a final link function.

(org-add-link-type
 "pkg3"
 (lambda (path)
   (let ((pkg-name) (relpath)(pkg-dir) (link-string)
	 (splitpath (split-string path "==")))
     (setq pkg-name (car splitpath))
     (setq relpath (nth 1 splitpath))
     (setq pkg-dir (file-name-directory
		    (or (locate-library pkg-name)
			(locate-library (format "%s-autoloads" pkg-name)))))
(setq link-string (format "[[file:%s/%s]]" pkg-dir relpath))
     (message "link: %s" link-string)
     (org-open-link-from-string link-string))))

#+RESULTS:

Now, we just have to make sure to use the right relative path. This link opens up an org-file in my installed version of org-mode: pkg3:org==../doc/library-of-babel.org

I don't know if there is a more clever way to create these links. There are two parts to them: 1) the package, and 2) the relative path. The link syntax isn't that rich to do it without parsing the linkpath.

Send email to a list of users

I have a need to send a lot of emails to users in my class. I have to send each student an email containing there userid and a password assigned to them. I have a list of these, so the strategy is to create a function that will email that information to one user, and then use mapc to apply the function to each pair in a list. First, we work out a function that will send one email to one user.

(defun send-mail (userid password)
  "send email to sunjaydixit@gmail.com containing their password"
  (interactive)
  (mail)
  (mail-to)
  (insert (format "%s@jaydixit.com" userid))
  (mail-subject)
  (insert "[06-640] account information")
  (mail-text)
  (insert (format "
An account has been created on jaydixit.com
userid: %s
password: %s" userid password))
  (mail-send-and-exit))

;; (send-mail "jkitchin" "trustme99")

That worked well. I ran the block and got the email.

Now, suppose I have this data:

useridpassword
user1trustme99
user2foolme99
user3blameme99

We can pass that to a source block as a list of lists that will look like this:

((user1 trustme99) (user2 foolme99) (user3 blameme99))

Then, we can use a mapc to process each element. Here I use a dummy function with two arguments. If I substitute the function above, each of these users would get an email.

;; (defun fun (a b) (princ (format "user: %s\npassword: %s\n" a but)))

;; (mapc (lambda (x) (fun (car x) (cadr x))) data)

I am not sure that is the best way to get the first and second elements in the list element. It looks funny to me, but it works fine. the alternative is not much prettier:

;; (defun fun (a b) (princ (format "user: %s\npassword: %s\n" a but)))

;; (mapc (lambda (x) (fun (nth 0 x) (nth 1 x))) data)

Source: The Kitchin Research Group

videos

macro to create defuns?

(defmacro make-my-function (name) (list ‘defun (intern (format “my-%s-function” name)) () (list ‘interactive) (list (intern (format “mark-%s” name))) (list ‘do-more-stuff) (list (intern (format “modify-%s” name)))))

saveplace

;; Save point position between sessions

;; Save point position between sessions
(use-package saveplace
 :init (save-place-mode)) 

The saveplace package is part of Emacs, and remembers the position of point - even between emacs sessions.

The last line sets the path to where saveplace stores your position data. Change it at your peril!

embolden next word

(define-minor-mode embolden-next-word
    "Make the next word you type bold."
  nil
  :lighter " EMBOLDEN"
  :keymap (let ((map (make-sparse-keymap)))
            (define-key map (kbd "SPC") (lambda ()
                      (interactive)
                      (expand-abbrev)
                      (save-excursion
                        (goto-char (get-register 'p))
                        (insert "*"))
                      (insert "* ")
                      (embolden-next-word -1)))
        (define-key map (kbd ".") (lambda ()
                    (interactive)
                    (expand-abbrev)
                    (save-excursion
                      (goto-char (get-register 'p))
                      (insert "*"))
                    (insert "*. ")
                    (embolden-next-word -1)))
            map)
  (if embolden-next-word
      (set-register 'p (point))
    (set-register 'p nil)))

(global-set-key "\C-o" 'embolden-or-bold)
(define-key key-minor-mode-map (kbd "C-o") 'embolden-or-bold)

no-abbrev-slash

Doesn’t work.

(define-minor-mode insert-slash-no-abbrev
    "Make the next word you type bold."
  nil
  :lighter " don't abbreviate"
  :keymap (let ((map (make-sparse-keymap)))
            (define-key map (kbd "SPC") (lambda ()
                      (interactive)
(insert "/ ")
))
            map)
  (if insert-slash-no-abbrev
      (set-register 'p (point))
    (set-register 'p nil)))
;; (global-set-key "/" 'insert-slash-no-abbrev)

ideas

C-d on an empty line in the shell terminates the process.

(defun comint-delchar-or-eof-or-kill-buffer (arg) (interactive “p”) (if (null (get-buffer-process (current-buffer))) (kill-buffer) (comint-delchar-or-maybe-eof arg)))

(add-hook ‘shell-mode-hook (lambda () (define-key shell-mode-map (kbd “C-d”) ‘comint-delchar-or-eof-or-kill-buffer))) With this snippet, another press of C-d will kill the buffer.

It’s pretty nice, since you then just tap C-d twice to get rid of the shell and go on about your merry way.

Do you program any elisp, at all, ever?

;; Elisp go-to-definition with M-. and back again with M-, (autoload ‘elisp-slime-nav-mode “elisp-slime-nav”) (add-hook ‘emacs-lisp-mode-hook (lambda () (elisp-slime-nav-mode t))) (eval-after-load ‘elisp-slime-nav ‘(diminish ‘elisp-slime-nav-mode)) Then you need to M-x package-install elisp-slime-nav-mode.

It lets you jump to the definition of a function with M-., and back again afterwards with M-,.

That last line says that we want elisp-slime-nav-mode to continue doing its work for us, but we no longer want to be reminded of it.

source code blocks: org-insert-src-block

Emacs:insert source code block in org-mode | 肉山博客 (Wenshan’s Blog)

(defun org-insert-src-block (src-code-type)
  "Insert a `SRC-CODE-TYPE' type source code block in org-mode."
  (interactive
   (let ((src-code-types
          '("emacs-lisp" "sh" "css" "dot" "latex" "fountain")))
     (list (ido-completing-read "Source code type: " src-code-types))))
  (progn
    (newline-and-indent)
    (insert (format "#+BEGIN_SRC %s\n" src-code-type))
    (newline-and-indent)
    (insert "#+END_SRC\n")
    (previous-line 2)
    (org-edit-src-code)))

(local-set-key (kbd "C-c v e")
               'org-edit-src-code)
;; keybinding for inserting code blocks

experiments - new/untested

include the output of a shell command in org-mode source code block?

org export - How to include the output of a shell command in org-mode source code block? - Emacs Stack Exchange

play mp3

(defun play-mp3 ()
  (interactive)
  (let ((file (buffer-file-name)))
    (kill-buffer (current-buffer))
    (ora-dired-start-process (format "rhythmbox \"%s\"" file))))
(add-to-list 'auto-mode-alist '("\\.mp3\\'" . ora-mp3))

Source: elisp - What’s a good way to run a command instead of opening a file? - Emacs Stack Exchange

shareeditflag answered 6 hours ago

sds 6258

Thanks, I already bound “r” in dired to do that years ago. My interest is in making it work everywhere, for example from a locate or a find-file completion session, or from a bookmark etc. – abo-abo 5 hours ago add a comment

I stopped using openwith when I started using Helm, as I find typing C-c C-x from helm-find-files convenient enough. (Also nowadays, I only unconditionally open audio and video files outside of Emacs, so most of the time I like being able to either open a file in Emacs or in an external program.)

openwith

;; (require ‘openwith) (openwith-mode t) (setq openwith-associations ‘((“\.pdf\’” “Skim.app” (file))))

Source: find file - How to use an external program as the default way to open PDFs from Emacs? - Emacs Stack Exchange

PDF-tools

find file - How to use an external program as the default way to open PDFs from Emacs? - Emacs Stack Exchange

http://tuhdo.github.io/static/emacs-read-pdf.gif

defun syntax

A Lisp function becomes a command when its body contains, at top level, a form that calls the special form `<code>(interactive…)</code>’. This special form does nothing when executed, but its presence in the function definition indicates that interactive calling is permitted. Its argument controls the reading of the function arguments in an interactive call.

Here is a simple example defining a command that displays a message:

(defun hello ()
      "Hello World and you can call it via M-x hello."
      (interactive)
      (message "Hello World!"))

Example of a command that reads a string argument:

(defun hello (someone)
      "Say hello to SOMEONE via M-x hello."
      (interactive "sWho do you want to say hello to? ")
      (message "Hello %s!" someone))

To use multiple arguments, separate their `interactive’ entries with a newline:

(defun multiple-hello (someone num)
      "Say hello to SOMEONE via M-x hello, for NUM times."
      (interactive "sWho do you want to say hello to? \nnHow many times? ")
      (dotimes (i num)
        (insert (format "Hello %s!\n" someone))))

Instead of passing a literal string argument to `interactive’, you can pass it an EmacsLisp sexp that is evaluated when the command is called, to produce a list of the actual arguments.

This is useful when you need to do more than is offered by the predefined `interactive’ string constructs.

To get the effect of the string constructs `P’ and `p’, respectively, use variable `current-prefix-arg’ and function `prefix-numeric-value’ applied to that variable.

To get the effect of `interactive’ string codes that read user input, use Lisp functions that read input, such as `read-buffer’, `read-string’, and `completing-read’.

The following pairs of `interactive’ specs are equivalent:

(defun bar (arg) (interactive “p”) …)

(defun bar (arg) (interactive (list (prefix-numeric-value current-prefix-arg)) …)

(defun foo (arg buf) (interactive “P\nbBuffer: “) …)

(defun foo (arg buf) (interactive (list current-prefix-arg (read-buffer “Buffer: ” (current-buffer) t))) …)

lisp functions from John Kitchin

helm actions when there is no match

Sometimes you run out of matches in a helm selection buffer, and all that is left is the pattern you have typed in. It turns out you can perform some action on that pattern! Why would you do that? Suppose you are searching your bibliography, and you do not find what you are looking for. Then, you may want to send the pattern to Google, or some other search engine to see what comes up.

The key to handling this situation is to use two sources in your helm session. One that works on the candidates and deals with actions on them, and one that has no candidates, and works on the pattern. The variable helm-pattern contains what you typed in. We call the second source the Fallback option. The second source has no candidates, and we use (dummy) in place of the candidates.

It easy to add two sources. Here we define the sources as variables, and use the variables in the :sources list to the helm command.

(defun some-action (arg) (message-box “%s\n%s” (helm-get-selection) (helm-marked-candidates)))

(defun default-action (candidate) (browse-url (format “http://www.google.com/search?q=%s” (url-hexify-string helm-pattern))))

(defvar source1 ‘((name . “HELM”) (candidates . (1 2 3 4)) (action . ((“open” . some-action)))))

(defvar fallback-source ‘((name . “fallback”) (dummy) (action . ((“Google” . default-action)))))

(helm :sources ‘(source1 fallback-source))

When you run this, if you run out of search candidates, all that will be left is the fallback option, and when you press enter, it will launch a browser pointing to the google search for your pattern.

Source: helm actions when there is no match

how to write helm functions

How to write helm extensions - WikEmacs Anatomy of a helm source

dwiw-auto-capitalize

I have been using auto-capitalize.el for a short time to automatically capitalize the beginning of sentences. I mostly like what it does, but in org-mode I tend to write short code blocks while still in org-mode, and it is pretty irritating for auto-capitalize to “fix” the capitalization of your code. Of course, I can type C-c ’ to edit the block in its native mode, but I do not always want to do that.

Below, I illustrate an approach to turn off auto-capitalize-mode when the cursor is inside a code-block. Basically, we write a function that checks if you are in a src-block, and if auto-capitalize is on, turn it off. If you are not in the code-block, we turn auto-capitalize on if it is not on. Then we hook the function into post-command-hook, which will run it after every emacs command, including cursor movements.

Here is that code:

(defun dwiw-auto-capitalize ()
  (if (org-in-block-p '("src"))
      (when auto-capitalize
	(auto-capitalize-mode -1))
    (unless auto-capitalize
      (auto-capitalize-mode 1))))

;; (add-hook 'post-command-hook dwiw-auto-capitalize)

It works! Now the minor mode turns on and off depending on where the cursor is in my org document.

Source: auto capitalization in org buffers

Better integration of org-mode and email

I like to email org-mode headings and content to people. It would be nice to have some records of when a heading was sent, and to whom. We store this information in a heading. It is pretty easy to write a simple function that emails a selected region.

(defun email-region (start end)
  "Send region as the body of an email."
  (interactive "r")
  (let ((content (buffer-substring start end)))
    (compose-mail)
    (message-goto-body)
    (insert content)
    (message-goto-to)))

that function is not glamorous, and you still have to fill in the email fields, and unless you use gnus and org-contacts, the only record keeping is through the email provider.

What I would like is to send a whole heading in an email. The headline should be the subject, and if there are TO, CC or BCC properties, those should be used. If there is no TO, then I want to grab the TO from the email after you enter it and store it as a property. You should be able to set OTHER-HEADERS as a property (this is just for fun. There is no practical reason for this yet). After you send the email, it should record in the heading when it was sent.

It turned out that is a relatively tall order. While it is easy to setup the email if you have everything in place, it is tricky to get the information on TO and the time sent after the email is sent. Past lispers had a lot of ideas to make this possible, and a day of digging got me to the answer. You can specify some “action” functions that get called at various times, e.g. after sending, and a return action when the compose window is done. Unfortunately, I could not figure out any way to do things except to communicate through some global variables.

So here is the code that lets me send org-headings, with the TO, CC, BCC properties, and that records when I sent the email after it is sent.

(defvar *email-heading-point* nil
  "global variable to store point in for returning")

(defvar *email-to-addresses* nil
  "global variable to store to address in email")

(defun email-heading-return ()
  "after returning from compose do this"
  (switch-to-buffer (marker-buffer  *email-heading-point*))
  (goto-char (marker-position  *email-heading-point*))
  (setq *email-heading-point* nil)
  (org-set-property "SENT-ON" (current-time-string))
  ;; reset this incase you added new ones
  (org-set-property "TO" *email-to-addresses*)
  )

(defun email-send-action ()
  "send action for compose-mail"
  (setq *email-to-addresses* (mail-fetch-field "To")))

(defun email-heading ()
  "Send the current org-mode heading as the body of an email, with headline as the subject.

use these properties
TO
OTHER-HEADERS is an alist specifying additional
header fields.  Elements look like (HEADER . VALUE) where both
HEADER and VALUE are strings.

save when it was sent as s SENT property. this is overwritten on
subsequent sends. could save them all in a logbook?
"
  (interactive)
  ; store location.
  (setq *email-heading-point* (set-marker (make-marker) (point)))
  (org-mark-subtree)
  (let ((content (buffer-substring (point) (mark)))
	(TO (org-entry-get (point) "TO" t))
	(CC (org-entry-get (point) "CC" t))
	(BCC (org-entry-get (point) "BCC" t))
	(SUBJECT (nth 4 (org-heading-components)))
	(OTHER-HEADERS (eval (org-entry-get (point) "OTHER-HEADERS")))
	(continue nil)
	(switch-function nil)
	(yank-action nil)
	(send-actions '((email-send-action . nil)))
	(return-action '(email-heading-return)))

    (compose-mail TO SUBJECT OTHER-HEADERS continue switch-function yank-action send-actions return-action)
    (message-goto-body)
    (insert content)
    (when CC
      (message-goto-cc)
      (insert CC))
    (when BCC
      (message-goto-bcc)
      (insert BCC))
    (if TO
	(message-goto-body)
      (message-goto-to))
    ))

This works pretty well for me. Since I normally use this to send tasks to people, it keeps the task organized where I want it, and I can embed an org-id in the email so if the person replies to it telling me the task is done, I can easily navigate to the task to mark it off. Pretty handy.

Source: better integration of org-mode and email

pandoc

org-mode does pandocc and word now!

new stuff / experimental

;; Also auto refresh dired, but be quiet about it
;; (setq global-auto-revert-non-file-buffers t)
;; (setq auto-revert-verbose nil)


;; Move files to trash when deleting
(setq delete-by-moving-to-trash t)

Helm Org Wiki

I’m using an extremely simplistic approach: just dump all the org files into one directory. The name of each org file should be concise but descriptive, e.g. Makefile.org describes Makefiles, and git.org describes git.

This simplicity completely alleviates organization effort: there’s nothing to organize, since there’s only one directory to put the files in. At the same time, it’s very accessible by means of two `helm` wrappers:

  • globally, “C-0” runs the command helm-org-wiki (the code is below)
  • in org-mode, “g” runs the command wspecial-worf-goto (the code is at

https://github.com/abo-abo/worf)

It’s like a two-stage personal Google: the first stage is to find an org-file, the second stage is to search within an org-file.

For example, here’s the sequence of key bindings when I want to look up how git bisect works, assuming that I’m in some random buffer, like `ansi-term`:

C-0 gi RET g bis RET

Done. Note that “gi” was enough to match “git.org”, since all my other pages don’t contain “gi”. Same thing for “bis” being able to match uniquely the heading “git bisect”. I think that it’s quite optimal that I’m able to find the topic “git bisect” by using only 10 key presses, which is the same as the amount of characters in “git bisect”. Compare this to `helm-google-suggest` (bound to “C-p g”):

C-p g git bi RET TAB RET

That’s 12 key presses (10 in Emacs, 2 in Firefox).

New wiki pages can be created with “C-0” as well, just type in the name of the new file and hit RET.

That’s it, the code is below. It’s very similar to `org-switchb`, except that the files need not be opened to appear in the completion list, and new files are created if there’s no match.

regards, Oleh (Source: http://lists.gnu.org/archive/html/emacs-orgmode/2014-04/msg01134.html)

(defgroup helm-org-wiki nil
  "Simple jump-to-org-file package."
  :group 'org
  :prefix "helm-org-wiki-")
(defcustom helm-org-wiki-directory "~/nd/"
  "Directory where files for `helm-org-wiki' are stored."
  :group 'helm-org-wiki
  :type 'directory)
(defun helm-org-wiki-files ()
  "Return .org files in `helm-org-wiki-directory'."
  (let ((default-directory helm-org-wiki-directory))
    (mapc #'file-name-sans-extension
            (file-expand-wildcards "*.txt"))))
(defvar helm-source-org-wiki
  `((name . "Projects")
    (candidates . helm-org-wiki-files)
    (action . ,(lambda (x)
                  (find-file (expand-file-name
                              (format "%s.txt" x)
                              helm-org-wiki-directory))))))
(defvar helm-source-org-wiki-not-found
  `((name . "Create org-wiki")
    (dummy)
    (action . (lambda (x)
                (helm-switch-to-buffer
                 (find-file
                  (format "%s/%s.org"
                          helm-org-wiki-directory x)))))))
;;;###autoload
(defun helm-org-wiki ()
  "Select an org-file to jump to."
  (interactive)
  (helm :sources
        '(helm-source-org-wiki
          helm-source-org-wiki-not-found)))
(provide 'helm-org-wiki)

Emacs Lisp Mode

(defun turn-on-autocomplete-mode ()
   (auto-complete-mode 1))
(add-hook 'emacs-lisp-mode-hook 'turn-on-autocomplete-mode )

Reference for cleaning up whitespace around sentences:

regex - Redefining “sentence” in Emacs? (single space between sentences, but ignoring abbreviations) - Stack Overflow

cycle-hyphenation

(defun cycle-hyphenation ()
  (interactive)
  (cond ((re-search-forward "\\=\\w*\\(-\\)\\w+" nil t)
         (save-excursion (replace-match " " t t nil 1)))
        ((re-search-forward "\\=\\w*\\( +\\)\\w+" nil t)
         (save-excursion (replace-match "-" t t nil 1)))))

cycle-punctuation

(defvar *punctuation-markers-to-cycle-between*  ".?!")

(defun cycle-punctuation ()
  (interactive)
  (save-excursion
    (forward-sentence)
    (when (re-search-backward (format "\\>\\([%s]\\)[[:space:]]*\\="
                                      *punctuation-markers-to-cycle-between*)
                              nil t)
      (let ((next (elt *punctuation-markers-to-cycle-between*
                       ;; circular string; should be abstracted
                       (mod (1+ (position (elt (match-string 1) 0)
                                          *punctuation-markers-to-cycle-between*))
                            (length *punctuation-markers-to-cycle-between*)))))
        (replace-match (format "%c" next) t t nil 1)))))

;; (define-key key-minor-mode-map (kbd "M-.") 'cycle-punctuation)

clone subtree

(defun org-clone-subtree ()
  (interactive)
  (org-clone-subtree-with-time-shift 1)
  (save-excursion
    (org-goto-sibling)
    ;; This part was lifted partly and adapted from
    ;; http://orgmode.org/worg/org-hacks.html#orgheadline10.
    ;; There should be a better way to change the contents of an org heading
    ;; though...
    (when (org-at-heading-p)
      (let ((hl-text (nth 4 (org-heading-components)))
            (buffer-undo-list))
        (when hl-text
          (beginning-of-line)
          (search-forward hl-text (point-at-eol))
          (replace-match (format "%s" hl-text) nil t)
;; (org-align-tags-here org-tags-column)
)))))

smart punctuation

kill-clause

This version kill org-mode headings by ‘kill-line’

;; Identify the end of sentences globally.
(setq sentence-end-base "[][.?!…}]+[\"”]?")
(defun kill-clause ()
  (interactive)
  (smart-expand)
  (if (let ((sm (string-match "[*]+\s" (thing-at-point 'line)))) (and sm (= sm 0)))
      (kill-line)
    (progn
      (let ((old-point (point))
            (kill-punct (my/beginning-of-sentence-p)))
        (when (re-search-forward "--\\|[][,;:?!…\"”()}]+\\|\\.+ " nil t)
          (kill-region old-point
                       (if kill-punct
                           (match-end 0)
                         (match-beginning 0)))))

      (my/fix-space)
      (save-excursion
        (when (my/beginning-of-sentence-p)
          (capitalize-unless-org-heading)))

;; below is my own hack to fix the ", , " issue
(when

(or

(looking-back ", , ")
(looking-back ",, ")
(looking-back ",, ")
(looking-back ": : ")
)
(new-org-delete-backward-char 2) 
(my/fix-space)


(when
(and
(looking-back "----")
(looking-at "-"))

(delete-backward-char 4)
(delete-char 1)
(insert-space))


t)))

This old version leaves a rogue comma:

;; Identify the end of sentences globally.
(setq sentence-end-base "[][.?!…}]+[\"”]?")
(defun kill-clause ()
  (interactive)
  (smart-expand)
  (let ((old-point (point))
        (kill-punct (my/beginning-of-sentence-p)))
    (when (re-search-forward "--\\|[][,;:?!…\"”()}]+\\|\\.+ " nil t)
      (kill-region old-point
                   (if kill-punct
                       (match-end 0)
                     (match-beginning 0)))))
  (my/fix-space)
  (save-excursion
    (when (my/beginning-of-sentence-p)
      (capitalize-unless-org-heading))))

Old version that I retrieved:

(defun kill-clause ()
  (interactive)
  (smart-expand)

(if
(let ((sm (string-match "*+\s" (thing-at-point 'line)))) (and sm (= sm 0)))
(kill-line)


  (let ((old-point (point))
        (kill-punct (my/beginning-of-sentence-p)))
    (when (re-search-forward "--\\|[][,;:?!…\"”()}]+\\|\\.+ " nil t)
      (kill-region old-point
                   (if kill-punct
                       (match-end 0)
                     (match-beginning 0)))))
  (my/fix-space)
  (save-excursion
    (when (my/beginning-of-sentence-p)
      (capitalize-unless-org-heading)))

(when
(or    (looking-back ", , ")
     (looking-back ":: ")
     )
(new-org-delete-backward-char 2)
(my/fix-space)
t)

;; fix a bug that leaves this: " : "
(when (looking-back " : ")
(progn
(left-char 2)
(new-org-delete-backward-char 1)
(right-char 2)
))


;; fix a bug that leaves this: " , "
(when (looking-back " , ")
(progn
(left-char 2)
(my/fix-space)
(right-char 2)
))


;; fix a bug that leaves this: ",."
(when (looking-back ",. ")
(left-char 2)
(delete-backward-char 1)
(right-char 2)
)


;; fix a bug that leaves this: ", . "
(when (looking-back ", . ")
(left-char 2)
(delete-backward-char 2)
(right-char 2)
)

(when
(and
(looking-back "----")
(looking-at "-"))

(delete-backward-char 4)
(delete-char 1)
(insert-space))



))

smart-punctuation exceptions

(defvar *smart-punctuation-marks*
  ".,;:!?-")

(setq *smart-punctuation-exceptions*
  (list "?!" ".." "..." "............................................." "---" ";;" "!!" "!!!" "??" "???" "! :" ". :" ") ; "))

;; How do I add an exception for ") ; "?
;; e.g. if I want to add a comment after a line of lisp?

smart-punctuation (auxiliary)

  (defun smart-punctuation (new-punct &optional not-so-smart)
    (smart-expand)
    (save-restriction
      (when (and (eql major-mode 'org-mode)
                 (org-at-heading-p))
        (save-excursion
          (org-beginning-of-line)
          (let ((heading-text (fifth (org-heading-components))))
            (when heading-text
              (search-forward heading-text)
              (narrow-to-region (match-beginning 0) (match-end 0))))))
      (cl-flet ((go-back (regexp)
                  (re-search-backward regexp nil t)
                  (ignore-errors      ; might signal `end-of-buffer'
                    (forward-char (length (match-string 0))))))
        (if not-so-smart
            (let ((old-point (point)))
              (go-back "[^ \t]")
              (insert new-punct)
              (goto-char old-point)
              (forward-char (length new-punct)))
          (let ((old-point (point)))
            (go-back (format "[^ \t%s]\\|\\`" *smart-punctuation-marks*))
            (let ((was-after-space (and (< (point) old-point)
                                        (find ?  (buffer-substring (point) old-point)))))
              (re-search-forward (format "\\([ \t]*\\)\\([%s]*\\)"
                                         *smart-punctuation-marks*)
                                 nil t)
              (let* ((old-punct (match-string 2))
                     (was-after-punct (>= old-point (point))))
                (replace-match "" nil t nil 1)
                (replace-match (or (when (and was-after-punct
                                              (not (string= old-punct "")))
                                     (let ((potential-new-punct (concat old-punct new-punct)))
                                       (find-if (lambda (exception)
                                                  (search potential-new-punct exception))
                                                *smart-punctuation-exceptions*)))
                                   new-punct)
                               nil t nil 2)
                (if was-after-space
                    (my/fix-space)
                  (when (looking-at "[ \t]*\\<")
                    (save-excursion (my/fix-space))))))))))
    (when (and (eql major-mode 'org-mode)
               (org-at-heading-p))
; (org-align-tags-here org-tags-column)
))

smart-period

(defun smart-period ()
  (interactive)
(cond (mark-active
 (progn (delete-region (mark) (point))))) 
(unless
      (or
(looking-back "\\bvs.[ ]*") ; Don't add extra periods to vs.
(looking-back "\\bi\.e[[:punct:]]*[ ]*") ; don't add extra periods to ie.
(looking-back "\\be\.\g[[:punct:]]*[ ]*") ; don't add extra periods to eg.

       )
  (smart-punctuation "."))
  (save-excursion
    (unless
        (or
         (looking-at "[ ]*$")
         (looking-at "\][[:punct:]]*[ ]*$")
         (looking-at "[[:punct:]]*[ ]*$")
         (looking-at "\"[[:punct:]]*[ ]*$")
         (looking-at "\)[ ]*$")
         (looking-at "\)")
         ) ; or
    (capitalize-unless-org-heading)
      ) ; unless
) ; save excursion

;; if two periods or two commas in a row, delete the second one 
(when 
(or
(and
(looking-at "\\.")
(looking-back "\\.")
) 
(and
(looking-at ",")
(looking-back ",")
))
(delete-char 1)
)

  ) ; defun


(define-key org-mode-map (kbd ".") 'smart-period)
;; (define-key orgalist-mode-map (kbd ".") 'smart-period)

smart-comma

(defun smart-comma ()
  (interactive)
(cond (mark-active
 (progn (delete-region (mark) (point))))) 

  (smart-punctuation ",")
(unless
(or

(looking-at "\]*[[:punct:]]*[ ]*$")
(looking-at "[[:punct:]]*[ ]*$")
(looking-at "[ ]*I\\b")          ; never downcase the word "I"
(looking-at "[ ]*I\'")          ; never downcase the word "I'
(looking-at "[[:punct:]]*[ ]*\"")          ; beginning of a quote
)

(save-excursion (downcase-word 1)))
(when

;; if two periods or two commas in a row, delete the second one
(or
(and
(looking-at "\\.")
(looking-back "\\.")
) 
(and
(looking-at ",")
(looking-back ",")
))
(delete-char 1)
)

)


(define-key org-mode-map (kbd ",") 'comma-or-smart-comma)
;; (define-key orgalist-mode-map (kbd ",") 'comma-or-smart-comma)

smart-question-mark

(defun smart-question-mark ()
  (interactive)
  (cond (mark-active
         (progn (delete-region (mark) (point))))) 

  (smart-punctuation "?")
  (save-excursion
    (unless
        (or
         (looking-at "[ ]*$")
         (looking-at "\][[:punct:]]*[ ]*$")
         (looking-at "[[:punct:]]*[ ]*$")
         (looking-at "\"[[:punct:]]*[ ]*$")
         (looking-at "\)[ ]*$")
         (looking-at "\)")
         ) ; or
    (capitalize-unless-org-heading)
      ) ; unless
    ) ; save excursion
  ) ; defun

;; works!!

(define-key org-mode-map (kbd "?") 'smart-question-mark)
;; (define-key orgalist-mode-map (kbd "?") 'smart-question-mark)

smart-exclamation-point

(defun smart-exclamation-point ()
  (interactive)
(cond (mark-active
 (progn (delete-region (mark) (point))))) 

  (smart-punctuation "!")
(save-excursion
(unless (looking-at "[ ]*$")
(capitalize-unless-org-heading))
))

(define-key org-mode-map (kbd "!") 'smart-exclamation-point)
;; (define-key orgalist-mode-map (kbd "!") 'smart-exclamation-point)

smart-hyphen

(defun smart-hyphen () (interactive) (smart-punctuation “-“))

(define-key org-mode-map (kbd “-“) ‘smart-hyphen) ;; (define-key orgalist-mode-map (kbd “-“) ‘smart-hyphen)

smart-semicolon

(defun smart-semicolon ()
  (interactive)
(cond (mark-active
 (progn (delete-region (mark) (point))))) 
  (smart-punctuation ";")
(unless
(or
(looking-at "[[:punct:]]*[ ]*$")
(looking-at "[ ]*I\\b")     ; never downcase the word "I"
(looking-at "[ ]*I\'")     ; never downcase the word "I'
(looking-at "[[:punct:]]*[ ]*\"")     ; beginning of a quote
)

(save-excursion (downcase-word 1))))

(define-key org-mode-map (kbd ";") 'smart-semicolon)
;; (define-key orgalist-mode-map (kbd ";") 'smart-semicolon)

smart-colon

(defun smart-colon ()
  (interactive)
(cond (mark-active
  (progn (delete-region (mark) (point))))) 
  (smart-punctuation ":")
(unless
(or
(looking-at "[[:punct:]]*[ ]*$")
(looking-at "[ ]*I\\b")     ; never downcase the word "I"
(looking-at "[ ]*I\'")     ; never downcase the word "I'
(looking-at "[[:punct:]]*[ ]*\"")     ; beginning of a quote
)

;; (save-excursion (downcase-word 1))
))


(define-key org-mode-map (kbd ":") 'colon-or-smart-colon)
(define-key org-mode-map (kbd ",") 'comma-or-smart-comma)
;; (define-key orgalist-mode-map (kbd ":") 'smart-colon) 

comma-or-smart-comma

(defun comma-or-smart-comma ()
(interactive) 
(if 
(or
(bolp)
(org-at-heading-p)
(looking-at " \"")
) 
(insert ",")
(smart-comma))
) 

colon-or-smart-colon

(defun colon-or-smart-colon ()
(interactive)
(if
(or
(bolp)
(org-at-heading-p)
)
(insert ":")
(smart-colon))
)

TODO [#A] check my changes to backward-kill-word-correctly?

Rúdi: desired behavior is that when invoking backward-kill-word-correctly to delete words backwards, Emacs should leave a space after the word to the left of the point UNLESS point is at the beginning of the line or after “—”

I tried to implement this myself, below. My hack seems to work, but it seems slow… Is it possible to make it faster or no? maybe just than a look at the below and see if you think I implemented it in the best way.

(defun backward-kill-word-correctly ()
  "Kill word."
  (interactive)
  (if (re-search-backward "\\>\\W*[[:punct:]]+\\W*\\=" nil t)
      (kill-region (match-end 0) (match-beginning 0))
    (backward-kill-word 1))
  (my/fix-space)

;; I added this ↓↓↓ #######################
(when (and
(not (looking-back "---")) ; I added this
(not (looking-back "^"))) ; I added this
;; I added this ↑↑↑ #######################

(smart-space)
)
)

Question

Since backward-kill-word-correctly already calls my/fix-space, isn’t a call to smart-space redundant? What was the use case you were thinking of when you originally added it? Note that if you remove the whole (when ...) block, it apparently works as you intend it to work…

NOTE-TO-SERJ Answer

Good question. The answer is that there should never be a space after “—”

Example:

Alice was tired---tired as hell. ^

Say the point is the carat, and I invoke backward-kill-word-correctly 4 times.

Output if I remove the whole (when ...) block:

Alice was tired--- ^

Note the space after “—”

Desired output:

Alice was tired---^

No space. Does that make sense? Thanks!

[#B] my-delete-backward

(defun my/delete-backward ()
  "When there is an active region, delete it and then fix up the whitespace"
  (interactive)
  (if (use-region-p)
      (delete-region (region-beginning) (region-end))
    (delete-backward-char 1))
  (save-excursion
    (when (or (looking-at "[[:space:]]")
              (looking-back "[[:space:]]"))
(unless (looking-back "\\w ")
      (my/fix-space)))))

my-delete-backward-and-capitalize

(defcustom capitalize-after-deleting-single-char nil
  "Determines whether capitalization should occur after deleting a single character.")

(defun my/delete-backward-and-capitalize ()
  "When there is an active region, delete it and then fix up the whitespace"
  (interactive)
(when (looking-back "^[*]+ ")
(kill-line 0)
(insert " ") ; this line is super hacky I put it here because when I tried to use "unless", the rest of the function, and then this at the end, it didn't work; however, this does produce the behavior I desire
)

  (let ((capitalize capitalize-after-deleting-single-char))
    (if (use-region-p)
        (progn
          (delete-region (region-beginning) (region-end))
          (setf capitalize t))
      (new-org-delete-backward-char 1))
    (save-excursion
      (when (or (looking-at "[[:space:]]")
    (looking-back "[[:space:]]"))
;; unless there's already exactly one space between words, since I need to be able to delete backward past spaces
(unless (and
(looking-back "\\w ")
(looking-at "\\w")
)
  (my/fix-space))))
    (when (and capitalize (my/beginning-of-sentence-p))
      (save-excursion
        (capitalize-unless-org-heading))))
(when

(or
(and
(looking-at "\\.")
(looking-back "\\.")
) 
(and
(looking-at ",")
(looking-back ",")
))
(delete-char 1)
)
) 

backward-kill-word-correctly-and-capitalize

(defun backward-kill-word-correctly-and-capitalize ()
  "Backward kill word correctly. Then check to see if the point is at the beginning of the sentence. If yes, then kill-word-correctly and endless/capitalize to capitalize the first letter of the word that becomes the first word in the sentence. Otherwise simply kill-word-correctly."
  (interactive)
(call-interactively 'backward-kill-word-correctly)
  (let ((fix-capitalization (my/beginning-of-sentence-p)))
    (when fix-capitalization
      (save-excursion (capitalize-unless-org-heading)))))

defadvice capitalize-word

(defadvice capitalize-word (after capitalize-word-advice activate)
  "After capitalizing the new first word in a sentence, downcase the next word which is no longer starting the sentence."

  (unless
 
      (or
       (looking-at "[ ]*\"")          ; if looking at a quote? Might not work

       (looking-at "[[:punct:]]*[ ]*I\\b")          ; never downcase the word "I"
       (looking-at "[[:punct:]]*[ ]*I'")          ; never downcase words like I'm, I'd
       (looking-at "[[:punct:]]*[ ]*\"*I'")    ; never downcase words like I'm, I'd 

(looking-at "[ ]*I\'")   ; never downcase the word "I'

       (looking-at "[[:punct:]]*[ ]*\"I\\b")          ; never downcase the word "I"
       (looking-at "[[:punct:]]*[ ]*OK\\b")          ; never downcase the word "OK"

       ;; (looking-at "\\") ; how do you search for a literal backslash?
       (looking-at (sentence-end))

       (looking-at "[[:punct:]]*[ ]*$") ; don't downcase past line break 

       (looking-at "[[:punct:]]*[ ]*\"$") ; don't downcase past quotation then line break 
       (looking-at "[[:punct:]]*[ ]*)$") ; don't downcase past a right paren then line break 
       (looking-at "[[:punct:]]*[ ]*\")$") ; don't downcase past a quotation then a right paren then a line break 

       (looking-at "[[:punct:]]*[ ]*http") ; never capitalize http 

(looking-at "\"[[:punct:]]*[ ]*$") ; a quotation mark followed by "zero or more whitespace then end of line?"

(looking-at "\)[ ]*$") ; a right paren followed by "zero or more" whitespace, then end of line 

(looking-at ")[ ]*$") ; a right paren followed by "zero or more" whitespace, then end of line 
(looking-at ")$") ; a right paren followed by "zero or more" whitespace, then end of line 

(looking-at "[ ]*-*[ ]*$") ; dashes at the end of a line 


       (looking-at (user-full-name))

       )

    (save-excursion
      (downcase-word 1))))

I tried to add exceptions for “line-end” and also for user-full name.

capitalize-unless-org-heading

(defun capitalize-unless-org-heading ()
  (interactive)
  (unless
      (or
       (looking-at "[[:punct:]]*[\n\t ]*\\*")
       ;; (looking-at "\\* TODO"); redundant
       (let ((case-fold-search nil))
         (looking-at "[ ]*[\n\t ]*[[:punct:]]*[\n\t ]*[A-Z]")
         (looking-at "[A-Z].*"))
       (looking-at "[\n\t ]*[[:punct:]]*[\n\t ]*#\\+")
       (looking-at "[\n\t ]*[[:punct:]]*[\n\t ]*\(")
       (looking-at "[\n\t ]*[[:punct:]]*[\n\t ]*<")
       (looking-at "[\n\t ]*[[:punct:]]*[\n\t ]*file:")
       (looking-at "[\n\t ]*\\[fn")
       (looking-at "[\n\t ]*)$")
       (looking-at "[\n\t ]*\"$")
       (looking-at "\"[\n\t ]*$")
       (looking-at "[[:punct:]]*[ ]*http")
       (looking-at "[[:punct:]]*[ ]*\")$"); don't capitalize past
       (looking-at "[ ]*I\'")
       (looking-at
        (concat
         "\\("
         (reduce (lambda (a b) (concat a "\\|" b))
                 auto-capitalize-words)
         "\\)")))
    (capitalize-word 1)))

downcase-save-excursion

(defun downcase-save-excursion ()
  (interactive)
(unless
(or
(looking-at "[[:punct:]]*[ ]*$") 
(looking-at "[ ]*I\\b") ; never downcase the word "I"
(looking-at "[[:punct:]]*[ ]*[[:punct:]]*I'")  ; never downcase I'm I've etc.
(looking-at "[[:punct:]]*[ ]*$") ; zero or more whitespaces followed by zero or more punctuation followed by zero or more whitespaces followed by a line break
(looking-at "\"[[:punct:]]*[ ]*$") ; a quotation mark followed by "zero or more whitespace then end of line?"
(looking-at "\)[ ]*$") ; a quotation mark followed by "zero or more whitespace then end of line?"
(looking-at (sentence-end)) ; quotation mark followed by "zero or more whitespace then end of line?"
       (looking-at (user-full-name))


)
  (save-excursion
      (downcase-word 1))
  ))

smart-expand

Don’t expand past certain delimiters, e.g. line break, ), and ”

(defun smart-expand ()
  (interactive)

  (unless

    (or
       (looking-back "\)\n*")
(looking-back "[[:punct:]]*\)[ ]*[[:punct:]]*[\n\t ]*[[:punct:]]*>*")
(looking-back ":t[ ]*")
(looking-back "][\n\t ]*[[:punct:]]*[\n\t ]*") ; don't expand past closing square brackets ]

(looking-back ">[\n\t ]*[[:punct:]]*[\n\t ]*") ; don't expand past closing email addresses]


;; (looking-back "\\\w") ; for some reason this matches all words, not just ones that start with a backslash
)
    (expand-abbrev)
)
)

(defun smart-expand () (interactive)

(unless

(or (looking-back “\)\n*”) (looking-back “\)[ ]*”) (looking-back “:t[ ]*”)

;; (looking-back “\\w”) ; for some reason this matches all words, not just ones that start with a backslash ) (expand-abbrev) ) )

fountain

;; (load-file "/Users/jay/emacs/emacs-settings/fountain-mode.el")
;; (require 'fountain-mode)

;; (add-hook 'fountain-mode-hook 'turn-on-olivetti-mode)
(add-hook 'fountain-mode-hook '(lambda () (orgalist-mode 1)))
(add-hook 'fountain-mode-hook 'turn-on-auto-capitalize-mode 'append)

(defcustom fountain-export-default-command
  'fountain-export-shell-script
  "\\<fountain-mode-map>Default function to call with \\[fountain-export-default]."
  :type '(radio (function-item fountain-export-shell-script)
                (function-item fountain-export-buffer-to-html))
  :group 'fountain-export)

(defcustom fountain-export-shell-script
  "afterwriting --config ~/.config/afterwriting/config.json --source %s --pdf --overwrite"
  "Shell command string to convert Fountain source to ouput.
\"%s\" will be substituted with `buffer-file-name'"
  :type 'string
  :group 'fountain-export)

(defun fountain-export-shell-script (&optional buffer)
  "Call shell script defined in `fountain-export-shell-script'."
  (interactive)
  (let* ((buffer (or buffer (current-buffer)))
         (file (shell-quote-argument (buffer-file-name buffer)))
         (command (format fountain-export-shell-script file)))
    (async-shell-command command "*Fountain Export Process*")))

(setq fountain-export-include-title-page nil)
(setq fountain-export-html-replace-alist
   (quote
    (("&" "&amp;")
     ("<" "&lt;")
     (">" "&gt;")
     ("\\\\ " "&nbsp;")
     ("^\\\\$" "<br>")
     ("\\\\_" "&#95;")
     ("\\\\\\*" "&#42;")
     ("\\\\`" "&#96;")
     ("\\\\'" "&apos;")
     ("``" "&ldquo;")
     ("''" "&rdquo;")
     ("`" "&lsquo;")
     ("'" "&rsquo;")
     ("\\*\\*\\*\\(.+?\\)\\*\\*\\*" "<span class=\"underline\">\\1</span>")
     ("\\*\\*\\(.+?\\)\\*\\*" "<span class=\"underline\">\\1</span>")
     ("\\*\\(.+?\\)\\*" "<span class=\"underline\">\\1</span>")
     ("^~ *\\(.+?\\)$\\*\\*" "<i>\\1</i>")
     ("_\\(.+?\\)_" "<span class=\"underline\">\\1</span>")
     ("

+" "<br><br>")
     ("
" "<br>")))) 

display file name

How can I modify the titlebar to contain the current file name?

The contents of an Emacs frame’s titlebar is controlled by the variable frame-title-format, which has the same structure as the variable mode-line-format. (Use C-h v or M-x describe-variable to get information about one or both of these variables.)

By default, the titlebar for a frame does contain the name of the buffer currently being visited, except if there is a single frame. In such a case, the titlebar contains Emacs invocation name and the name of the machine at which Emacs was invoked. This is done by setting frame-title-format to the default value of

(multiple-frames “%b” (“” invocation-name “@” system-name)) To modify the behavior such that frame titlebars contain the buffer’s name regardless of the number of existing frames, include the following in your .emacs:

(setq frame-title-format (concat "Hey bro, just FYI, this file is called %b or something like that."))

keybindings for terminal

(define-key key-minor-mode-map (kbd "M-(") 'backward-word)
(define-key key-minor-mode-map (kbd "M-)") 'forward-word)

capitalize sentence

(defun capitalize-sentence ()
  (interactive)
(unless (my/beginning-of-sentence-p)
(org-backward-sentence))
  (endless/capitalize)
(org-forward-sentence 1)
(jay/right-char)
)
(define-key key-minor-mode-map (kbd "M-C") 'capitalize-word)

downcase sentence

(defun downcase-sentence ()
  (interactive)
(unless (my/beginning-of-sentence-p)
(org-backward-sentence))
  (downcase-word 1)
(org-forward-sentence 1)
(jay/right-char)
)

(define-key key-minor-mode-map (kbd "M-L") 'downcase-sentence)

return-insert-blank-line-before

(defun return-insert-blank-line-before ()
  (interactive)
  (beginning-of-line)
(newline)
  )

disable color themes

(defadvice load-theme (before theme-dont-propagate activate)
 (mapc #'disable-theme custom-enabled-themes))

toggle item or hyphenation

(defun toggle-item-or-hyphenation ()
(interactive "P")
(if

    (region-active-p)                               ; if
    (org-toggle-item) ; then
    (cycle-hyphenation); else
)
)

my-forward-sentence

(defun smart-forward-sentence ()
  (interactive)
  (org-forward-sentence)
  (my/fix-space)
  )

replace-inner

(defun replace-inner ()
  (interactive)
(change-inner)
  (pasteboard-paste-no-spaces)
  )

doesn’t work.

smex

;; (require 'smex)
;; (setq smex-completion-method 'ivy) 

bjm-swiper

;;advise swiper to recenter on exit
(defun bjm-swiper-recenter (&rest args)
  "recenter display after swiper"
  (recenter)
  )
(advice-add 'swiper :after #'bjm-swiper-recenter)

available keybindings

s-i s-N s-: s-. searchlink s-u m-,

s-i C-> C-< M-1 to 9

keep cursor at same position when scrolling

(setq scroll-preserve-screen-position 1)
;;scroll window up/down by one line
(define-key key-minor-mode-map (kbd "M-n") (kbd "C-u 1 C-v"))
(define-key key-minor-mode-map (kbd "M-p") (kbd "C-u 1 M-v"))

embolden-or-bold

*

(defun embolden-or-bold (arg)
  (interactive "p")
  (if (region-active-p)
      ;;      (wrap-region-trigger arg "*")
      (let ((s (replace-regexp-in-string
                "[*]" "" (delete-and-extract-region (region-beginning) (region-end)))))
        (insert "*")
        (insert s)
        (insert "*"))
    (embolden-next-word)))

save buffer to sent-emails-org-file

(defvar *sent-emails-org-file* "/Users/jay/Dropbox/writing/notationaldata/sent-emails.org")

(defun save-buffer-to-sent-emails-org-file ()
  ;; header

(write-region
   (concat "\n\n\n* "
(format-time-string "%F %l:%M%P\n\n")
           "\n\n")
   0 *sent-emails-org-file* t)
  ;; buffer
  (write-region nil 0 *sent-emails-org-file* t))

send message without bullets

(defun send-message-without-bullets ()
  (interactive)
  (remove-hook 'org-mode-hook 'org-bullets-mode)
;; (notmuch-mua-send-and-exit)
(message-send-and-exit) 
  (add-hook 'org-mode-hook 'org-bullets-mode))

(add-hook 'message-mode-hook
          (lambda ()
            (local-set-key "\C-c\C-c" 'send-message-without-bullets)
            (local-set-key "\C-c\C-l" 'org-insert-link)
))

sign current email

(defvar *mail-signature* "\n---\nJay Dixit\n(646) 355-8001\njaydixit.com")

(defun sign-current-email ()
  (save-excursion
    (end-of-buffer)
    (insert *mail-signature*)))

custom-send-message

(defun custom-send-message (arg)
  (interactive "p")
  (when (and arg (= 0 (mod arg 4)))
    (sign-current-email))
  (save-buffer-to-sent-emails-org-file)
  (send-message-without-bullets))

orgalist-mode-map

(define-key orgalist-mode-map (kbd "<M-return>") 'smart-org-meta-return-dwim)
(define-key mu4e-compose-mode-map (kbd "<M-return>") 'smart-org-meta-return-dwim)
; (define-key orgalist-mode-map (kbd "<return>") 'message-mode-smart-return)
(define-key orgalist-mode-map (kbd "\C-c\C-c") 'custom-send-message)
(define-key mu4e-compose-mode-map (kbd "\C-c\C-c") 'custom-send-message)


(define-key orgalist-mode-map (kbd "C-c .") 'org-time-stamp)

message-mode-map

(add-hook 'message-mode-hook
          (lambda ()
            (local-set-key "\C-c\C-c" 'custom-send-message)
; (local-set-key (kbd "<return>") 'orgalist-mode-smart-return)
))

fountain-mode-map

(add-hook 'fountain-mode-hook
     (lambda ()
(local-set-key (kbd ".") 'smart-period) 
(local-set-key (kbd ",") 'smart-comma) 
(local-set-key (kbd "\`") 'flyspell-auto-correct-word)
(local-set-key (kbd "<SPC>") 'smart-space) 


))

color theme advice

(defadvice load-theme (after load-theme-advice activate)
(custom-set-faces
'(bold ((t (:inherit font-lock-warning-face :weight bold))))
'(org-quote ((t (:inherit default))))
;; '(org-link ((t (:underline nil))))
'(org-done ((,class (:weight bold :box (:line-width 1 :color "#BBBBBB") :foreground "#BBBBBB" :background "green"))))



(org-mode)
  ))

reformat email

(defun reformat-email (begin end)
  (interactive "r")
(xah-replace-pairs-region begin end
 '(
 ["> " ""]
))
  (unfill-region begin end)
  (fill-region begin end)
  (xah-replace-pairs-region begin end
 '(
 ["\n" "\n> "]
)))

leader key, doesn’t need a special mode

(define-key key-minor-mode-map (kbd "] i t") 'org-inlinetask-insert-task) 
(define-key key-minor-mode-map (kbd "] c[") 'load-shared-functions)
(define-key key-minor-mode-map (kbd "] c]") 'load-gnu-startup)
(define-key key-minor-mode-map (kbd "] ]") 'insert-right-bracket)

fix image links

(defun fix-image-links ()
(interactive)
(goto-char 1)
(while (search-forward-regexp "[[\(.*?\).jpg][\(.*?\).jpg]]" nil t)
  (replace-match "[[" (match-string 1) ".jpg]]"  t nil))

(while (search-forward-regexp "[[\(.*?\).png][\(.*?\).png]]" nil t)
  (replace-match "[[" (match-string 1) ".png]]"  t nil))
)

replace garbage characters

Òembedding-

“embedding”

(defun replace-garbage-chars ()
"Replace goofy MS and other garbage characters with latin1 equivalents."
(interactive)
(save-excursion				;save the current point
  (replace-string "  " " " nil (point-min) (point-max))
  (replace-string "" "" nil (point-min) (point-max))
  (replace-string "΄" "\"" nil (point-min) (point-max))
  (replace-string "" "\"" nil (point-min) (point-max))
  (replace-string "" "'" nil (point-min) (point-max))
  (replace-string "" "\"" nil (point-min) (point-max))
  (replace-string "" "--" nil (point-min) (point-max)) ; multi-byte
  (replace-string "��" "'" nil (point-min) (point-max))
  (replace-string "��" "'" nil (point-min) (point-max))
  (replace-string "��" "\"" nil (point-min) (point-max))
  (replace-string "��" "\"" nil (point-min) (point-max))
  (replace-string "��" "\"" nil (point-min) (point-max))
  (replace-string "��" "\"" nil (point-min) (point-max))
  (replace-string "" "\"" nil (point-min) (point-max))
  (replace-string "" "'" nil (point-min) (point-max))
  (replace-string "�¡\"" "\"" nil (point-min) (point-max))
  (replace-string "¡­" "..." nil (point-min) (point-max))
  (replace-string "" "..." nil (point-min) (point-max))
  (replace-string "" " " nil (point-min) (point-max)) ; M-SPC
  (replace-string "" "`" nil (point-min) (point-max))  ; \221
  (replace-string "" "'" nil (point-min) (point-max))  ; \222
  (replace-string "" "``" nil (point-min) (point-max))
  (replace-string "" "''" nil (point-min) (point-max))
  (replace-string "" "*" nil (point-min) (point-max))
  (replace-string "" "--" nil (point-min) (point-max))
  (replace-string "" "--" nil (point-min) (point-max))
  (replace-string " " " " nil (point-min) (point-max)) ; M-SPC
  (replace-string "¡" "\"" nil (point-min) (point-max))
  (replace-string "´" "\"" nil (point-min) (point-max))
  (replace-string "»" "<<" nil (point-min) (point-max))
  (replace-string "Ç" "'" nil (point-min) (point-max))
  (replace-string "È" "\"" nil (point-min) (point-max))
  (replace-string "é" "e" nil (point-min) (point-max)) ;; &eacute;
  (replace-string "ó" "-" nil (point-min) (point-max))

  (replace-string " Ñ " "---" nil (point-min) (point-max))


  (replace-string "á" "-" nil (point-min) (point-max))
(replace-string "     " "" nil (point-min) (point-max))
(replace-string "    " "" nil (point-min) (point-max))
(replace-string " " " " nil (point-min) (point-max))
(replace-string " " "" nil (point-min) (point-max))


(replace-string "Õ" "'" nil (point-min) (point-max))
(replace-string "Ò" "\"" nil (point-min) (point-max))
(replace-string "Ó" "\"" nil (point-min) (point-max))



))

replace missing PDF ligatures

different → different

(defun replace-missing-ligatures ()
"Replace goofy MS and other garbage characters with latin1 equivalents."
(interactive)
(save-excursion				; save the current point

  (replace-string "de cit" "deficit" nil (point-min) (point-max))
  (replace-string "di eren" "differen" nil (point-min) (point-max))
  (replace-string "e ective" "effective" nil (point-min) (point-max))
  (replace-string "de ne" "define" nil (point-min) (point-max))
  (replace-string "re ect" "reflect" nil (point-min) (point-max))
  (replace-string "o er" "offer" nil (point-min) (point-max))
  (replace-string "con den" "confiden" nil (point-min) (point-max))
  (replace-string "con ict" "conflict" nil (point-min) (point-max))
;(replace-string "nd" "find" nil (point-min) (point-max)); whole word only
;(replace-string "ve" "five" nil (point-min) (point-max)); this one should be whole word only 
; (replace-string "ve" "they" nil (point-min) (point-max)); this one should be whole word only 
; (replace-string "ve" "the" nil (point-min) (point-max)); this one should be whole word only 
  (replace-string "scientifc" "scientific" nil (point-min) (point-max))



))

web-mode

    (use-package web-mode

:init
 (add-hook 'web-mode-hook
      (lambda ()
       (rainbow-mode)
       (rspec-mode)
       (setq web-mode-markup-indent-offset 2)))

;; (setq web-mode-load-hook (quote ((lambda nil (abbrev-mode -1)))))

(add-hook 'web-mode-hook (lambda () (abbrev-mode -1)))

    :bind (:map web-mode-map 


  ("s-O" . prelude-open-with)))

flyspell fix

(setq flyspell-abbrev-p t)
(setq flyspell-use-global-abbrev-table-p t)
(setq global-flyspell-mode t)

mw-thesaurus

;; (require 'mw-thesaurus)
(load "/Users/jay/emacs/emacs-settings/secret-codes.el")
(define-key key-minor-mode-map (kbd "M-s-t") 'mw-thesaurus--lookup-at-point)
You can’t perform that action at this time.