Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
3856 lines (3290 sloc) 139 KB

Build a Machine That Understands You - an Attempt via Emacs

magit:~/git/.emacs.d

https://github.com/yitang/.emacs.d

(setq yt-sphinx/proj-dir "~/git/.emacs.d")
(setq yt-sphinx/docs-dir "~/git/.emacs.d/docs")
(setq yt-sphinx/proj-badge-md (list "[![Documentation Status](https://readthedocs.org/projects/emacs/badge/?version=latest)](https://readthedocs.org/projects/emacs/?badge=latest)"))
(yt-sphinx/update-documentation)

About This Document

[2015-01-23 Fri 10:58]

The road to Emacs is not easy: I have tried to use Emacs for many years, and started using on daily basis from Jun 2014. The transition is difficulty, and full of tears and bloody, and every day I feel like being doomed in the dark. About Jan 2015, I start to the light. And conquered Emacs, and it now becomes a symbol of me, and I use it does most of productive work.

As the configuration grows bigger and bigger, a single init.el is not suitable for organising, testing, and expanding any more. Previously, I have about 7 .el files, for example, setup-org.el, setup-email.el, and I document on each file. Inspired by Sachua’s new posts, I think it would be a brilliant idea to org Emacs configuration code into one single org file, letting along the convince of organising and share my settings, the precious thing I would appreciate is it provide a way I could start with a long comments, thoughts or workflow. In this way, the code becomes less important as it should be.

My configuration file is initially separated by different purpose or mode, but as it growths, it became probelmatic in tracking, and, As for other Emacs user, my configuration is keep growing, and This documents is first combined by 5 configuration files, and it keeps expanding, I use literate programming to include all the notes, and keep a log of how I use them

This Emacs configuration is free of bug and fully tested on Ubuntu and OS X.

Normally you could tangle an org file to extract all the source code into one file, that you could use. But I would like to push literate programming further in two aspects: 1) the source code takes input from this org file, I.e. table. 2) it facility Babel Library to integrate not only Emacs Lisp, but also sh and R functions that could be run in Emacs, and I found it particular useful.

Licence

[2015-01-23 Fri 10:58]
Copyright (C)  2015  Yi Tang
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.

Code in this document is free software: you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either
version 3 of the License, or (at your option) any later version.

This code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

This document http://yitang.github.io/emacs.d/init.html (either in its HTML format or in its Org format) is licensed under the GNU Free Documentation License version 1.3 or later (http://www.gnu.org/copyleft/fdl.html).

How to Use This Document

[2015-01-20 Tue 08:09]

Add the following scripts to your .emacs

(load-file "~/git/.emacs.d/load_config.el")

Emacs Configuration

[2015-01-19 Mon 11:42]

Install Packages

[2015-03-18 Wed 15:32]

All the packages used in this configuration are available the major Emacs repositories. it is recommended to install them via Emacs’s package management tool, and by the following snippets. Note the initial installation may takes a while to finish, depends on how many are already in the ~/emacs.d/elpa/ folder.

(setq my-package-list '(ess
                        ssh
                        auto-complete
                        ac-R
                        nyan-mode
                        yasnippet
                        projectile
                        magit
                        helm-swoop
                        nyan-mode
                        org-plus-contrib
                        helm-projectile
                        rainbow-delimiters
                        zenburn-theme
                        htmlize
                        nanowrimo
                        golden-ratio
                        artbollocks-mode
                        langtool
                        flycheck
                        expand-region
                        guide-key
                        exec-path-from-shell
                        smart-mode-line
                        smart-mode-line-powerline-theme
                        powerline
                        synosaurus
                        hydra
                        w3m
                        ace-window
                        calfw
                        multiple-cursors
                        org-download
                        paradox
                        smartparens
                        ace-jump-mode
                        voca-builder
                        sunshine
                        keyfreq
                        pretty-mode
                        olivetti
                        helm-mu
                        hl-sentence
                        eval-in-repl
                        auctex
                        elpy
                        git-timemachine
                        snakemake-mode
                        mu4e-alert
                        counsel
                        restart-emacs
                        snakemake-mode
                        tldr
                        yaml-mode
                        markdown-mode
                        ledger-mode
                        ))

(require 'package)
(setq package-archives '(("melpa" . "http://melpa.milkbox.net/packages/")
                         ("org" . "http://orgmode.org/elpa/")
                         ("gnu" . "http://elpa.gnu.org/packages/")
                         ("marmalade" . "http://marmalade-repo.org/packages/")))
(package-initialize)

;; fetch the list of packages available 
(unless package-archive-contents
  (package-refresh-contents))
;; install 
(dolist (i-package my-package-list)
  (unless (package-installed-p i-package)
    (package-install i-package)))

General

Remove Keybind

(global-unset-key (kbd "C-x b"))
(global-unset-key (kbd "C-x C-b"))

Assorted Pieces

[2015-01-19 Mon 12:21]

Define an auto-save feature, the backup files are saved in ~.emacs.d/backup/ folder. I’ve used it several times to recover the most recent, but un-saved version, after power off.

;; ref: http://stackoverflow.com/questions/151945/how-do-i-control-how-emacs-makes-backup-files
;; save all backup files (foo~) to this directory.
(setq backup-directory-alist '(("." . "~/.emacs.d/backup"))
      backup-by-copying t    ; Don't delink hardlinks
      version-control t      ; Use version numbers on backups
      delete-old-versions t  ; Automatically delete excess backups
      kept-new-versions 20   ; how many of the newest versions to keep
      kept-old-versions 5    ; and how many of the old
      auto-save-timeout 20   ; number of seconds idle time before auto-save (default: 30)
      auto-save-interval 200 ; number of keystrokes between auto-saves (default: 300)
      )

;; guide-key package 
;; (require 'guide-key)
;; (setq guide-key/guide-key-sequence t) ;; on for all key-bindings 
;; (guide-key-mode 1) 

;; start auto-complete with emacs
(require 'auto-complete)
;; do default config for auto-complete
(require 'auto-complete-config)
(ac-config-default)
(setq ac-delay 0.1)       
(setq ac-auto-show-menu 0.2)
(setq ac-quick-help-delay 0.2)
(setq ac-quick-help-height 10)
(setq ac-candidate-limit 100)

I use helm-mini to navigate between files, which is a lot convenient and faster than actually locate the file path.

(recentf-mode 1)
(setq recentf-max-saved-items 200
      recentf-max-menu-items 15)
(setq inhibit-startup-message t)        ; Disable startup message

Shows an notication for invalid operations.

(setq visible-bell nil) 

yasnippet is a powerful package that I’d like to explore in the future, and this stage, I turned if off since it will slow down the start-up.

(require 'yasnippet)
(yas/global-mode 1)
(setq yas-default-snippets (concat (file-name-directory (pkg-info-library-source "yasnippet")) "snippets" ))
(setq yas/snippet-dirs '(yas-default-snippets "~/git/.emacs.d/snippets"))
(yas/reload-all)

Window Layout/Navigation

[2015-01-19 Mon 12:13]

Quickly jump between windows using ace-window, I used it frequently and bind it F1.

(require 'ace-window)
(global-set-key (kbd "<f2>") 'ace-window)
(setq aw-scope 'frame)

Instead of equally split the window size, it make a lot sense to have the current window, the one I am working one, has bigger size.

(require 'golden-ratio)
(golden-ratio-mode 1)
(add-to-list 'golden-ratio-extra-commands 'ace-window) ;; active golden ratio when using ace-window

Some actions will add/remove windows, and sometimes I’d like to cycle tough the window layout/changes. In the following settings, C-c <left> to undo window layout changes, and C-c <right> to redo.

(winner-mode 1)
;; winner-undo -> C-c <left>
;; winner-redo -> C-c <right>

I’d like to use two frames, one for doing and logging, and other for reference/searching.

(defun yt/ref-frame ()
  (interactive)
  ;;   (frame-parameter (car (frame-list)) 'name)
  (if (eq 1 (length (frame-list)))
      (new-frame '((name . "***********************REFERENCE*******************")))
    nil))
(global-set-key (kbd "M-`") 'other-frame)

Utilities

[2015-01-19 Mon 12:14]

;; Change "yes or no" to "y or n"
(fset 'yes-or-no-p 'y-or-n-p)

(defun yt/reload-dot-emacs ()
  "Save the .emacs buffer if needed, then reload .emacs."
  (interactive)
  (let ((dot-emacs "~/.emacs"))
    (and (get-file-buffer dot-emacs)
         (save-buffer (get-file-buffer dot-emacs)))
    (load-file dot-emacs))
  (message "Re-initialized!"))

Use keyfreq package to record the commands I use in Emacs.

(require 'keyfreq)
(keyfreq-mode 1)
(keyfreq-autosave-mode 1)

System Path/Keyboard

[2015-01-19 Mon 12:15]

Solve the PATH issues for the software installed via Homebrew in OS X. Uncomment the setenv for CYGWIN since I am not using Windows any more.

(defun set-exec-path-from-shell-PATH ()
  (let ((path-from-shell 
         (replace-regexp-in-string "[[:space:]\n]*$" "" 
                                   (shell-command-to-string "$SHELL -l -c 'echo $PATH'"))))
    (setenv "PATH" path-from-shell)
    (setq exec-path (split-string path-from-shell path-separator))))
(when (equal system-type 'darwin) (set-exec-path-from-shell-PATH))
;; windows path convention
;; (setenv "CYGWIN" "nodosfilewarning")

Modify the Mac keyboard: unset the C-z just in case I run Emacs in terminal and C-z won’t stop the program without asking.

;; modify mac keyboard 
(cond ((eq system-type 'darwin)
       (setq mac-command-modifier 'meta)
       (fset 'insertPound "#")
       (global-set-key (kbd "M-3") 'insertPound)       
       (global-unset-key (kbd "M-`"))
       (global-set-key (kbd "M-`") 'other-frame)
       (global-set-key (kbd "C-Z") nil)
       ))

(prefer-coding-system 'utf-8)
(when (display-graphic-p)
  (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)))

Open PDF files using external program.

;; (require 'openwith)
;; (openwith-mode t)
;; (if (string= system-type "darwin")
;;     (setq openwith-associations '(("\\.pdf\\'" "Skim" (file))))
;;   (setq openwith-associations '(("\\.pdf\\'" "evince" (file)))))

General Editing

There are a set of characters that are more likely to occur as a pair, for example, quote and brackets. smartparens mode allows me to define such set of pairing characters.

(smartparens-global-mode 1)
(sp-pair "(" ")" :wrap "C-(")
;; |foobar
;; hit C-(
;; becomes (|foobar)
(sp-pair "'" nil :actions :rem)

It is a terrible idea to have lines of context that expand the whole screen, especially nowadays we have wide-screens, which just make it is hard to read. A well accepted rule is to set the width of lines to 80 characters, and force a logical line breaks. This funcitonality is called auto-fill in Emacs, and I can do the filling by call fill-paragraph.

(add-hook 'text-mode-hook 'turn-on-auto-fill) ;; 

Just in case I need to reverse the auto-fill process.

(defun yt/unfill-paragraph ()
  (interactive)
  (let ((fill-column (point-max)))
    (fill-paragraph nil)))
(defun yt/unfill-region ()
  (interactive)
  (let ((fill-column (point-max)))
    (fill-region (region-beginning) (region-end) nil)))

Minibuffer history

savehist is an very powerful mode.

(setq savehist-file "~/git/.emacs.d/personal/emacs-history")
(savehist-mode 1)

GUI - Emacs Looks Cool

[2015-01-19 Mon 12:16]

Fonts

[2015-07-20 Mon 11:46]

I use the Adobe’s Source Code Pro font, it is Monospaced font and claimed to be suitable for coding environments. But I use it for all modes.

;; (set-default-font "Source Code Pro-14" nil t)
;; (set-face-attribute 'default nil :height 100)

Minimalists GUI

[2015-07-20 Mon 11:46]

I never click any buttons in the menu-bar/tool-bar, nor need the scroll-bar to tell me the cursor position the in the buffer, so I removed all of them to have minimalist GUI of Emacs.

(tool-bar-mode -1)
(menu-bar-mode -1)
(scroll-bar-mode -1)

Theme

[2015-07-20 Mon 11:46]

I have been using zenburn theme for a while. It is a popular low contrast colour theme and easy on the eye. Occasionally I apply tsdh-dark theme on the top when I really need to focus on.

;; (load-theme 'zenburn t) 
(load-theme 'leuven t)

Mode Line

[2015-07-20 Mon 11:46]

The mode line is at the bottom of every Emacs Window aside from MiniBuffer windows. It has most of the relevant information about the buffer, including Git status, Major mode, clock info, etc.

The smart-mode-line packages can make mode-line “smart and sexy”. There are many options to tweak.

(require 'smart-mode-line)
(setq powerline-arrow-shape 'curve)
(setq powerline-default-separator-dir '(right . left))
(setq sml/theme 'powerline)
(sml/setup)

There are too much information cluttered at the bottom. I disable the display of minor modes, there are just too many and almost all are irrelevant.

(rich-minority-mode 1)
(setf rm-blacklist "")

This will leave empty spaces which can be removed by

(setq sml/mode-width 0)
(setq sml/name-width 20)

Finally, show the current time in the mode-line.

(display-time-mode)

Completion and Selection

[2015-01-23 Fri 18:44]

Helm - Fuzzy Match

[2015-02-22 Sun 11:40]

Helm and fuzzy match makes selection a lot easier. in

(require 'helm)
(require 'helm-config)

;; The default "C-x c" is quite close to "C-x C-c", which quits Emacs.
;; Changed to "C-c h". Note: We must set "C-c h" globally, because we
;; cannot change `helm-command-prefix-key' once `helm-config' is loaded.
(global-set-key (kbd "C-c h") 'helm-command-prefix)
(global-unset-key (kbd "C-x c"))

;; (define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action) ; rebind tab to run persistent action
;; (define-key helm-map (kbd "C-i") 'helm-execute-persistent-action) ; make TAB works in terminal
;; (define-key helm-map (kbd "C-z")  'helm-select-action) ; list actions using C-z

(global-set-key (kbd "M-x") 'helm-M-x)
(global-set-key (kbd "C-x C-f") 'helm-find-files)

(setq helm-M-x-fuzzy-match t) ;; optional fuzzy matching for helm-M-x

(global-set-key (kbd "M-y") 'helm-show-kill-ring)
;;(global-set-key (kbd "C-x b") 'helm-mini)
(global-set-key (kbd "M-l") 'helm-mini) 
(setq helm-buffers-fuzzy-matching t
      helm-recentf-fuzzy-match    t)
(global-set-key (kbd "C-c h o") 'helm-occur)
(global-set-key (kbd "C-h a") 'helm-apropos)
(setq helm-apropos-fuzzy-match t)
(setq helm-semantic-fuzzy-match t
      helm-imenu-fuzzy-match    t)

(helm-autoresize-mode t)
(defun pl/helm-alive-p ()
  (if (boundp 'helm-alive-p)
      (symbol-value 'helm-alive-p)))
(add-to-list 'golden-ratio-inhibit-functions 'pl/helm-alive-p)
(helm-mode 1)

Multi-Cursor & Helm-swoop - Multiple Selection

[2015-01-19 Mon 12:10]

When refactoring code, I need to rename a variable or function names, the normal way to do that is via searching and replacing. multiple-cursors provides function to select all the words/symbols that is highlighted and then modify all of them at the same time.

(require 'multiple-cursors)
(global-set-key (kbd "C-S-<right>") 'mc/mark-next-like-this)
(global-set-key (kbd "C-S-<left>") 'mc/mark-previous-like-this)
;; (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
;; (global-set-key (kbd "C->") 'mc/mark-next-like-this)
;; (global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
;; (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
;; (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)

I usually use multi-cursor with helm-swoop, which allows me to search, and then narrow down all the occurrences in a temporary buffer, and then start to edit.

(require 'helm-swoop)
;; Change the keybinds to whatever you like :)
;; (global-set-key (kbd "M-i") '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 "<C-f1>") 'helm-swoop)
;; When doing isearch, hand the word over to helm-swoop
;; (define-key isearchp-mode-map (kbd "M-i") 'helm-swoop-from-isearch)
;; From helm-swoop to helm-multi-swoop-all
;; (define-key helm-swoop-map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop)
;; When doing evil-search, hand the word over to helm-swoop
;; (define-key evil-motion-state-map (kbd "M-i") 'helm-swoop-from-evil-search)
;; Save buffer when helm-multi-swoop-edit complete
(setq helm-multi-swoop-edit-save t)
;; If this value is t, split window inside the current window
(setq helm-swoop-split-with-multiple-windows nil)
;; Split direcion. 'split-window-vertically or 'split-window-horizontally
(setq helm-swoop-split-direction 'split-window-vertically)
;; If nil, you can slightly boost invoke speed in exchange for text color
(setq helm-swoop-speed-or-color nil)
;; ----------------------------------------------------------------------

ace-jump

Instead of moving into the place I want, ace-jump provides a way to jump directly to there places, just by pressing 4-5 keys. The places can be a character, line, or word. Personally I found it is really efficient to jump to a word when editing.

(global-set-key (kbd "C-c w") 'ace-jump-word-mode)

Expand-Region - Incremental Selection

[2015-01-20 Tue 07:47]

expand-region provides smart way of sectioning, by expanding the scope one at a time. for example,

S = "A B C"

If the cursor in inside of the quote, I press C-=, everything inside of the quote is selected, press it again, the quotes are also selected, press it again, the whole line/region is selected. It saves a lot of keystrokes in highlighting the area.

It works well with smartparens mode, if I want to apply markup syntax around a word, I press C-= to select it, then insert quote or forward slash, the whole word will be warped inside of quote or forward flash.

(require 'expand-region)
(global-set-key (kbd "C-=") 'er/expand-region)

File Management

[2015-01-23 Fri 18:52]

Alternative to shell

[2015-01-28 Wed 07:46]

For the file management tasks like rename and delete, I’d like to wrapper it as a Lisp function and call it directly in Emacs.

Rename the buffer-visiting file, and also rename the buffer. Similar to the save as idea but will remove the older file.

;; rename current buffer-visiting file
(defun yt/rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        (error "Buffer '%s' is not visiting a file!" name)
      (let ((new-name (read-file-name "New name: " filename)))
        (if (get-buffer new-name)
            (error "A buffer named '%s' already exists!" new-name)
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil)
          (message "File '%s' successfully renamed to '%s'"
                   name (file-name-nondirectory new-name)))))))

Another useful Lisp function is to copy the file path to clipboard for cross reference.

;; full path of current buffer
(defun yt/copy-full-path-to-kill-ring ()
  "copy buffer's full path to kill ring"
  (interactive)
  (when buffer-file-name
    (let* ((file-truename buffer-file-name)
	   (rel-name (file-relative-name file-truename "~/")))  ; BUG: if filename is not relative to home directory.
      (kill-new (concat "~/" rel-name)))))

Open a file as a rooter in Emacs, very handy.

(defun yt/sudo-find-file (file-name)
  "Like find file, but opens the file as root."
  (interactive "FSudo Find File: ")
  (let ((tramp-file-name (concat "/sudo::" (expand-file-name file-name))))
    (find-file tramp-file-name))) 

Find out the last modified date for current buffer, I need this often when updating a blog post or documents.

(defun yt/last-updated-date ()
  "return modification time of current file-visitng buffer"
  (interactive)
  (let* ((mtime (visited-file-modtime))) 
    (unless (integerp mtime)
      (concat "/Last UPdated/: "
              (format-time-string "%d %b %Y" mtime)))))

Remove current buffer-visiting file, and kill the buffer. I use this function often in testing and trying out.

(defun yt/delete-this-buffer-and-file ()
  "Removes file connected to current buffer and kills buffer."
  (interactive)
  (let ((filename (buffer-file-name))
        (buffer (current-buffer))
        (name (buffer-name)))
    (if (not (and filename (file-exists-p filename)))
        (error "Buffer '%s' is not visiting a file!" name)
      (when (yes-or-no-p "Are you sure you want to remove this file? ")
        (delete-file filename)
        (kill-buffer buffer)
        (message "File '%s' successfully removed" filename)))))

It is a good practise to group all the file management related commands together using hydra.

(defhydra hydra-file-management (:color red
                                        :hint nil)
  "
_o_pen file
_O_pen file as Sudo user 
copy file _P_ath to kill ring
_r_ename buffer-visiting file 
_d_elete buffer-visiting file
_g_it sync"
  ("o" find-file)
  ("O" yt/sudo-find-file)
  ("P" yt/copy-full-path-to-kill-ring)
  ("r" yt/rename-current-buffer-file)
  ("c" yt/copy-file-to)
  ("d" yt/delete-this-buffer-and-file)
  ("g" yt/git-up))
(global-set-key [f3] 'hydra-file-management/body)

Open the file manager at the default directory.

;; http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html
(defun yt/open-file-manager ()
  "Show current file in desktop (OS's file manager)."
  (interactive)
  (cond
   ((string-equal system-type "windows-nt")
    (w32-shell-execute "explore" (replace-regexp-in-string "/" "\\" default-directory t t)))
   ((string-equal system-type "darwin") (shell-command "open ."))
   ((string-equal system-type "gnu/linux")
    (let ((process-connection-type nil)) (start-process "" nil "xdg-open" "."))
    ;; (shell-command "xdg-open .") ;; 2013-02-10 this sometimes froze emacs till the folder is closed. ⁖ with nautilus
    )))

Projectile - Directory Access

[2015-01-19 Mon 12:08]

Projectile is an powerful Emacs package but I only use projectile to jump between different git folders, so there isn’t much configuration except using helm for selection.

(require 'projectile)
(helm-projectile-on)
(require 'helm-projectile)
(projectile-global-mode)
(setq projectile-enable-caching t)
(setq projectile-switch-project-action 'projectile-dired)
(setq projectile-remember-window-configs t )
(setq projectile-completion-system 'helm)
(setq projectile-switch-project-action 'helm-projectile)
(setq projectile-project-root-files-bottom-up '(".git" ".projectile")) ;; .projectile comes first

There are many things work out of box. For example, use C-p p to choose which project to jump to, but I can type M-g to invoke Magit or M-e to invoke Eshell for that project.

Remote (SSH)

[2015-01-22 Thu 23:11]

I can work on the remote files in Emacs via ssh or tramp, both are build-in packages.

(require 'tramp)
(require 'ssh)

I’d like catch the password so that I don’t need to type it every time to open a file.

(setq password-cache-expiry nil)

I mainly run R on a remote machine. Sometimes I want to copy the charts I created to local to include them in my report. This workfow is suspended because it fails when the file size is large.

;; (defun yt/sync-local-remote ()
;;   (interactive)
;;   "copy all files in remote:~/LR_share to local:~/LR_share,
;; does not support the ther way"
;;   (find-file "/ssh:JBA28:/home/local/JBANORTHWEST/yitang/LR_share")
;;   ;; (mark-whole-buffer)
;;   (dired-mark-subdir-files)
;;   ;; (find-file "~/LR_share")
;;   ;; (setq-local dirqed-dwim-target t)
;;   (dired-do-copy))

Git Sync

[2015-01-19 Mon 12:09]

I use git and Github a lot, and usually in shell-mode, but I just can’t remember all the commands. Magit provides an interface to Git, and it is really pleasant to use. So I don’t need to remmeber all the commands, also it comes with excellent manual and cheatsheet.

(require 'magit)
(setq magit-last-seen-setup-instructions "1.4.0")
(setq magit-auto-revert-mode nil)
(global-set-key (kbd "<f9> g") 'magit-status)
(global-auto-revert-mode)

Occasionally my office machine goes down because I run R with big data, and it consumes all the memory. If that happens, I potentially lose the newsiest version of scripts, which is bit annoy. The following snippets will save all buffers in every hours.

(defun yt/save-all-buffers ()
  "save all files-visiting buffers without user confirmation"
  (interactive)
  (save-some-buffers t nil)
  (message "save all buffers... done"))
(run-at-time "05:59" 3600 'yt/save-all-buffers)

Sometimes I have to leave at the last minutes, then what I do is call a functions that commits and upload to the repo so that I can continue work at home.

The yt/git-up function will do

  1. pull from the remote repo, and make sure the local repo is always up-to-date.
  2. add everything and commit with a timesamp.
  3. push local changes to the remote repo.

Here is the snippets.

(defun yt/git-backup ()
  (let ((git-sh-scripts "
echo Start to Sync: $(date) 

REPOS=\"org\"
for REPO in $REPOS
do
    echo
    echo \"Repository: $REPO\"
    cd ~/git/$REPO
    # update
    git pull 
    # Remove deleted files
    git ls-files --deleted -z | xargs -0 git rm >/dev/null 2>&1
    # Add new files
    git add -A . >/dev/null 2>&1
    git commit -m \"$(date)\"
    git push origin master 
done

echo Finished Sync: $(date)
"))
    (async-shell-command git-sh-scripts))
  (message "all git sync... done"))

(defun yt/git-up ()
  (interactive)
  (yt/save-all-buffers)
  (yt/git-backup))

Few times I did some important work over the weenend, but once I arrived office I realised I forgot uploading, These situations are quick frustrating. The following snippets will start to uploads once every three hours on my MacbookPro, but I don’t use it anymore, since I can get most of my work done in the office.

Note this workflow is suspended for it’s unsafe.

;; (cond ((eq system-type 'darwin)
;;        (run-at-time "05:59" 10800 'yt/git-up)))

Testing Buffers

[2015-07-20 Mon 11:39]

scratch buffer is usually used for testing Emacs lisp functions. I also need temporary buffers for testing R code and org-mode. In the following settings, I can use F9-f to select temporal buffers.

(defvar yt/temp-dir "~/git/org/temp"
  "temporay folders")

(defun yt/open-tmp-R ()
  (interactive)
  (find-file (expand-file-name "temp.R" yt/temp-dir)))
(defun yt/open-tmp-el ()
  (interactive)
  (find-file (expand-file-name "temp.el" yt/temp-dir)))
(defun yt/open-tmp-org ()
  (interactive)
  (find-file (expand-file-name "temp.org" yt/temp-dir)))
(global-set-key (kbd "<f9> f r") 'yt/open-tmp-R)
(global-set-key (kbd "<f9> f e") 'yt/open-tmp-el)
(global-set-key (kbd "<f9> f o") 'yt/open-tmp-org)

Frequently visiting buffers

[2016-05-17 Tue 17:14]

(defun yt/org-find-file (filepath)
  (interactive)
  (find-file (expand-file-name filepath "~/git/org") nil))

(defhydra hydra/open-common-files (:color blue)
  "Open file:
      "
  ("R" (yt/org-find-file "Profession/R.org") "R.org")
  ("p" (yt/org-find-file "python.org") "python.org")
  ("l" (yt/org-find-file "life.org") "life.org")
  ("i" (find-file "~/git/.emacs.d/init.org" t) "init.org")
  ("e" (find-file "~/.emacs" t) ".emacs")
  )
(global-set-key (kbd "<f6>") 'hydra/open-common-files/body)

ESS - Emacs Speaks Statistics

As Statistician, coding in R and writing report is what I do most of the day. I have been though a long way of searching the perfect editor for me, tried Rstudio, SublimeText, TextMate and settled down happily with ESS/Emacs, for both coding and writing.

There three features that have me made the decision:

  1. Auto Formatting

    Scientists has reputation of being bad programmers, who wrote the code that is unreadable and therefore incomprehensible to others. I have intention to become top level programmer and followed a style guide strictly. It means I have to spent sometime in adding and removing space in the code.

    To my surprise, Emacs will do it for me automatically, just by hitting the TAB and it also indent smartly, which make me conformable to write long function call and split it into multiple lines. Here’s an example. Also if I miss placed a ‘)’ or ‘]’ the formatting will become strange and it reminders me to check.

    rainfall.subset <- data.table(rainfall.london,
                                 rainfall.pairs,
                                 rainfall.dublin)
        
  2. Search Command History

    I frequently search the command history. Imaging I was produce a plot and I realised there was something miss in the data, so I go back and fix the data first, then run the ggplot command again, I press Up/Down bottom many times, or just search once/two times. M-x ggplot( will gives me the most recent command I typed containing the keyword ggplot(, then I press RET to select the command, which might be ggplot(gg.df, aes(lon, lat, col = city)) + geom_line() + ...... If it is not I want, I press C-r again to choose the second most recent one and repeat until I find right one.

  3. Literate Programming

    I am an supporter of literate statistical analysis and believe we should put code, results and discoveries together in developing models. Rstudio provides an easy to use tool for this purpose, but it does not support different R sessions, so if I need to generate a report, I have to re-run all the code from beginning, which isn’t particle for me with volumes data because it will take quit long.

    ESS and org-mode works really well via Babel, which is more friendly to use. I can choose to run only part of the code and have the output being inserted automatically, no need to copy/paste. Also, I can choose where to execute the code, on my local machine or the remote server, or both at the same time.

    These are only the surface of ESS and there are lot more useful features like spell checking for comments and documentation templates, that makes me productive and I would recommend anyone use R to learn ESS/Emacs. The following is my current setting.

;; Adapted with one minor change from Felipe Salazar at
;; http://www.emacswiki.org/emacs/EmacsSpeaksStatistics
(require 'ess-site)
(setq ess-ask-for-ess-directory nil) ;; start R on default folder
(setq ess-local-process-name "R")
(setq ansi-color-for-comint-mode 'filter) ;;
;; (setq comint-scroll-to-bottom-on-input t)
;; (setq comint-scroll-to-bottom-on-output nil)
;; (setq comint-move-point-for-output nil)
(setq ess-eval-visibly-p 'nowait) ;; no waiting while ess evalating
(defun my-ess-start-R ()
  (interactive)
  (if (not (member "*R*" (mapcar (function buffer-name) (buffer-list))))
      (progn
        (delete-other-windows)
        (setq w1 (selected-window))
        (setq w1name (buffer-name))
        (setq w2 (split-window w1))
        (R)
        (set-window-buffer w2 "*R*")
        (set-window-buffer w1 w1name))))
(defun my-ess-eval ()
  (interactive)
  (my-ess-start-R)
  (if (and transient-mark-mode mark-active)
      (call-interactively 'ess-eval-region)
    (call-interactively 'ess-eval-line-and-step)))
(add-hook 'ess-mode-hook
          '(lambda()
             (local-set-key [(shift return)] 'my-ess-eval)))
(add-hook 'ess-mode-hook
          (lambda ()
            (flyspell-prog-mode)
            (run-hooks 'prog-mode-hook)
            ))
(add-hook 'ess-R-post-run-hook (lambda () (smartparens-mode 1)))

;; REF: http://stackoverflow.com/questions/2901198/useful-keyboard-shortcuts-and-tips-for-ess-r
;; Control and up/down arrow keys to search history with matching what you've already typed:
(define-key comint-mode-map [C-up] 'comint-previous-matching-input-from-input)
(define-key comint-mode-map [C-down] 'comint-next-matching-input-from-input)
(setq ess-history-file "~/.Rhisotry")
(setq ess-indent-with-fancy-comments nil)

Start-up

[2015-05-20 Wed 13:42]

when R start, it will load few local settings, one of them is the user-setting, which is R scripts saved in ~/RProfile. I’d like to have same settings on both my local, and remote server. and this can be achieved by using ess-post-run-hook.

(setq yt/ess--RProfile-string "
#### change this file name to .Rprofile and place to ~/userName so when R starts, the following command will be processed automatically

## http://stackoverflow.com/questions/1189759/expert-r-users-whats-in-your-rprofile
options(\"width\"=160)                # wide display with multiple monitors
options(\"digits.secs\"=3)            # show sub-second time stamps
options(\"repos\" = c(CRAN = \"http://www.stats.bris.ac.uk/R/\")) # hard code the UK repo for CRAN
options(\"max.print\" = 200)
## from the AER book by Zeileis and Kleiber
options(prompt=\"R> \", digits=4, show.signif.stars=FALSE)

.Libs <- function(){
    library(data.table)
    library(ggplot2)
    library(gridExtra)
##    library(sp)
##    library(geosphere)
##    library(rgeos)
##    library(sp)
##    library(dragonfly)
}

.libPaths(\"~/R/x86_64-pc-linux-gnu-library/3.2\")
## improved list of objects
.ls.objects <- function (pos = 1, pattern, order.by,
                 decreasing=FALSE, head=FALSE, n=5)
    {
        napply <- function(names, fn) sapply(names, function(x)
            fn(get(x, pos = pos)))
        names <- ls(pos = pos, pattern = pattern)
        obj.class <- napply(names, function(x) as.character(class(x))[1])
        obj.mode <- napply(names, mode)
        obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
        obj.prettysize <- napply(names, function(x) {
                                    capture.output(print(object.size(x), units = \"auto\")) })
        obj.size <- napply(names, object.size)
        obj.dim <- t(napply(names, function(x)
            as.numeric(dim(x))[1:2]))
        vec <- is.na(obj.dim)[, 1] & (obj.type != \"function\")
        obj.dim[vec, 1] <- napply(names, length)[vec]
        out <- data.frame(obj.type, obj.size, obj.prettysize, obj.dim)
        names(out) <- c(\"Type\", \"Size\", \"PrettySize\", \"Rows\", \"Columns\")
        if (!missing(order.by))
            out <- out[order(out[[order.by]], decreasing=decreasing), ]
        if (head)
            out <- head(out, n)
        out
    }
## shorthand
lsos <- function(..., n=10) {
    .ls.objects(..., order.by=\"Size\", decreasing=TRUE, head=TRUE, n=n)
}")

(add-hook 'ess-post-run-hook
          (lambda ()
            (goto-char (point-max))
            (insert yt/ess--RProfile-string)
            (inferior-ess-send-input) ;; execuate the R scripts 
            ;; clean up
            ;; (search-backward "Type 'q()' to quit R.")
            ;; (next-line)
            (delete-region (point) (point-max))
            (inferior-ess-send-input)
            ))

Syntax highlight

In Emacs, syntax highlighting is known as font-locking. You can customize the amount of syntax highlighting that you want to see. At the top of the Emacs window, click on the ESS menu and select “Font Lock”. This will display a menu of buttons corresponding to language elements that you can syntax highlight.

(setq ess-R-font-lock-keywords
    '((ess-R-fl-keyword:modifiers . t)
     (ess-R-fl-keyword:fun-defs . t)
     (ess-R-fl-keyword:keywords . t)
     (ess-R-fl-keyword:assign-ops)
     (ess-R-fl-keyword:constants . t)
     (ess-fl-keyword:fun-calls . t)
     (ess-fl-keyword:numbers)
     (ess-fl-keyword:operators)
     (ess-fl-keyword:delimiters)
     (ess-fl-keyword:=)
     (ess-R-fl-keyword:F&T)
     (ess-R-fl-keyword:%op%)))

use pretty mode

(add-hook 'ess-mode-hook 'turn-on-pretty-mode)

Programming Mode

After 2014, Emacs comes a prog-mode, for programming langauge. it is generic mode, just like text-mode, that sits underneth all the programming language, either R, phython, C++ etc. The good thinkg to have this concept is that we can define few things that will apply to all these mode, when we write scripts.

One thing I find particulaar usefull and necessary is to highliht characters in comments that has particullar meaning, like TODO, FIXME or other. which can be particular handy in code reivew, I can navite and jump between the code quickly.

;; highlights FIXME: TODO: and BUG: in prog-mode 
(add-hook 'prog-mode-hook
          (lambda ()
            (font-lock-add-keywords nil
                                    '(("\\<\\(YT\\|FIXME\\|TODO\\|BUG\\):" 1 font-lock-warning-face t)))))

we usually have long scripts, and in Subimetext, one cold folder and unfolder a function. in Emacs, this feature could be extended to furture, by define folder-characters. at this statge, I tented to used the deafault, I.e. folder functions only. in the folliwng setting, I could press F3 to folder/unfolder a function, C-F3 or S-F3 to folder/unfolder all functions.

one potentially solution is to use org-strct-mode, to show/hide the whole section, I havne;t tryied it before, but it sounds a good idea.

;; (add-hook 'prog-mode-hook 'hs-minor-mode)
;; (defalias 'fold-toggle 'hs-toggle-hiding)
;; (global-set-key (kbd "<f4>") 'hs-toggle-hiding)
;; (global-set-key (kbd "S-<f4>") 'hs-show-all) ;; S->show 
;; (global-set-key (kbd "C-<f4>") 'hs-hide-all) 
;; ;;   hs-hide-block                      C-c @ C-h
;; ;;   hs-show-block                      C-c @ C-s
;; ;;   hs-hide-all                        C-c @ C-M-h
;; ;;   hs-show-all                        C-c @ C-M-s
;; ;;   hs-hide-level                      C-c @ C-l
;; ;;   hs-toggle-hiding 
;; ;;   hs-mouse-toggle-hiding             [(shift mouse-2)]
;; ;;   hs-hide-initial-comment-block
(global-set-key (kbd "C-d") 'comment-region) ;; overwite delete-char 
(global-set-key (kbd "C-S-d") 'uncomment-region)

(defhydra hydra-fold (:pre (hs-minor-mode 1))
  "fold"
  ("t" hs-toggle-hiding "toggle")
  ("s" hs-show-all "hide-all")
  ("h" hs-hide-all "show-all")
  ("q" nil "quit"))
(global-set-key (kbd "<f4>") 'hydra-fold/body)

use subword-mode then ThisPhase has two word, and I can use C-DEL it will remove the Phase and left This. Very useful in CamerCase.

(subword-mode 1)

highlights the text that are longer than 80 columns rule.

(require 'whitespace)
(setq whitespace-line-column 120) ;; limit line length
(setq whitespace-style '(face lines-tail))
(add-hook 'prog-mode-hook 'whitespace-mode)

Rainbow-delimiters. constantly have problem with package, and tired of fixing it, so I turned it off at this stage.

(require 'rainbow-delimiters)
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode)
(show-paren-mode t) ;for Emacs
(require 'cl-lib)
(require 'color)
(cl-loop
 for index from 1 to rainbow-delimiters-max-face-count
 do
 (let ((face (intern (format "rainbow-delimiters-depth-%d-face" index))))
   (cl-callf color-saturate-name (face-foreground face) 30)))

use f8 to remove the R process buffer.

(defun yt/prog-previous-output-region ()
  "return start/end points of previous output region"
  (save-excursion
    (beginning-of-line)
    (setq sp (point))
    (comint-previous-prompt 1)
    (next-line)
    (beginning-of-line)
    (setq ep (point))
    (cons sp ep)))
(defun yt/prog-kill-output-backwards ()
  (interactive)
  (save-excursion
    (let ((reg (yt/prog-previous-output-region)))
      (delete-region (car reg) (cdr reg))
      (goto-char (cdr reg))
      (insert "*** output flushed ***\n"))))
(global-set-key (kbd "<f8>") 'yt/prog-kill-output-backwards)

Documentation

[2015-01-23 Fri 17:53]

;; edit roxy template
;; ess-roxy-update-entry
(setq ess-roxy-template-alist '(("description" . " content for description")
                                ("details" . "content for details")
                                ("title" . "")
                                ("param" . "")
                                ("return" . "")
                                ("export" . "")
                                ("author" . "Yi Tang")))

R Style Check - Flycheck

[2015-01-20 Tue 10:49]

https://github.com/jimhester/lintr the default R-style is not meet my with current R project style, has to turn it off.

(require 'flycheck)
;; '(flycheck-lintr-caching nil) ;; need to customised it inside of Emacs
;; (add-hook 'ess-mode-hook
;;           (lambda () (flycheck-mode t)))

Scripts editing

[2015-06-25 Thu 10:02]

R programming

[2015-05-26 Tue 12:41]

clean up the messy R scripts buffer. it will

  1. remove comments lines start with ‘## ’
  2. remove blank lines,
  3. add one blank lines between sections, which defined by ‘#### ‘.
(defun yt/clean-R () 
  (interactive)
  (when (string= major-mode "ess-mode")
    (progn
      (goto-char (point-min))
      (flush-lines "^\\(\\|[[:space:]]+\\)[#]\\{1,3\\} ") ;; remove lines with only commenst and start with #, ##, or ###, but not #### for it's the section heading. 
      (flush-lines "^\\(\\|[[:space:]]+\\)$") ;; blank lines
      (replace-regexp "#### " "\n#### ") ;; add blank lines between sections. 
      (while (search-forward-regexp "##[^']" nil t) ;; remove inline comments start with ## 
        (kill-region (- (point) 3) (line-end-position)))
    (save-buffer))))

apply the clean scripts to the tangled file. also, preappend the date and my name on the tangled file.

;; add author info
(defun yt/ess-author-date ()
  (interactive)
  (when (string= major-mode "ess-mode")
    (goto-char (point-min))
    (insert "##' @author: Yi Tang\n")
    (insert "##' @date: ")
    (insert (format-time-string "%F %T"))
    (insert "\n\n")
    (save-buffer)))
(add-hook 'org-babel-post-tangle-hook 'yt/ess-author-date)
(add-hook 'org-babel-post-tangle-hook 'yt/clean-R)

clean R console

;;;; * clean up ESS or sh buffer 
(defun yt/prog-previous-output-region ()
  "return start/end points of previous output region"
  (save-excursion
    (beginning-of-line)
    (setq sp (point))
    (comint-previous-prompt 1)
    (next-line)
    (beginning-of-line)
    (setq ep (point))
    (cons sp ep)))

(defun yt/prog-kill-output-backwards ()
  (interactive)
  (save-excursion
    (let ((reg (yt/prog-previous-output-region)))
      (delete-region (car reg) (cdr reg))
      (goto-char (cdr reg))
      (insert "*** output flushed ***\n"))))

(global-set-key (kbd "<f8>") 'yt/prog-kill-output-backwards)
(add-hook 'ess-mode-hook '(lambda ()
			      (turn-on-orgstruct)
			      (setq-local orgstruct-heading-prefix-regexp "## ")))

increase readability

(defun yt/ess-chunk-args--line ()
  "sim.gc.table <- data.table(duration = sort(sim.duration, decreasing = TRUE), rp = 1e4 / seq(1, length(sim.duration))) becomes 


sim.gc.table <- data.table(duration = sort(sim.duration,
                                          decreasing = TRUE),
                          rp = 1e4 / seq(1, length(sim.duration)))
"
  (interactive)
  (save-excursion
    (let ((start-point (point)))
      (while (re-search-forward ", \\([a-z]+ =\\)" (line-end-position) t)
	(replace-match (concat ",\n    " (match-string 1))))
      (indent-region start-point (line-end-position))
      (goto-char start-point))))
      
(defun yt/ess-chunk-plus--line ()
  "ggplot(obs.gc.table, aes(rp, duration)) + geom_point() + scale_x_log10() + scale_y_log10() 

becomes 

ggplot(obs.gc.table, aes(rp, duration)) +
    geom_point() +
    scale_x_log10() +
    scale_y_log10()
"
  (interactive)
  (save-excursion
    (let ((start-point (point)))
      (replace-regexp " \\+ " " +\n    " nil (point) (line-end-position))
      (indent-region start-point (line-end-position))
      (goto-char start-point))))

testing

(defun yt/ess-script-variables ()
  (interactive)
  (let ((var-list '())
        (data-list '()))
    (save-excursion
      (while (search-forward-regexp "^[[:space:]]*\\([[:alpha:]]+\\) <- function\(" nil t)
        (add-to-list 'func-list (match-string-no-properties 1))))
    (save-excursion
      (while (search-forward-regexp "^[[:space:]]*\\([a-z\\.]+\\) <- " nil t)
        (add-to-list 'var-list (match-string-no-properties 1))))
    (append (set-difference var-list func-list) data-list)))

(defun yt/ess-remove-variables-not-in-scripts ()
  (interactive)
  (let* ((all-vars (yt/ess-script-variables))
         (all-vars-R (concat "c(\"" (mapconcat 'identity all-vars "\",\"")
                             "\")")))
    (kill-new (concat "rm(list = setdiff\(setdiff\(ls\(\), lsf.str\(\)\), " all-vars-R "\)\)"))))

Auto-complete

[2016-05-13 Fri 14:17]

;; see https://github.com/tavisrudd/emacs.d/blob/master/dss-ess.el
(defun dss/ess-ac-setup ()
  (interactive)
  (require 'ac-R)
  (make-local-variable 'ac-ignore-case)
  (make-local-variable 'ess-use-R-completion)
  (setq ess-use-R-completion nil)
  (setq ac-ignore-case t)
  (setq ac-sources
        '(ac-source-filename                    ;; for file names 
          ac-source-words-in-same-mode-buffers  ;; as it says
          ac-source-R                           ;; for R objects
          ac-source-abbrev                      ;; 
          ac-source-dictionary)))

(add-hook 'ess-mode-hook 'dss/ess-ac-setup)

Writing in Emacs

[2015-01-19 Mon 12:11]

Spell and Grammar

[2015-01-23 Fri 17:43]

Spell checking and correcting are essential in writing. Emacs need third party program do this. There are a couple of programs and I use aspell. It is part of GNU and can be easily installed in OS X and Ubuntu. The following snippet tells Emacs where aspell is installed and use British dictionary.

(if (eq system-type 'darwin)
    (setq ispell-program-name "/usr/local/bin/aspell")
  (setq ispell-program-name "/usr/bin/aspell"))
(setq ispell-dictionary "british"
      ispell-extra-args '() ;; TeX mode "-t"
      ispell-silently-savep t)

I have a personal spelling dictionary, most are abbreviations and jargon. I can tell aspell that they are not misspellings.

(setq ispell-personal-dictionary "~/git/.emacs.d/personal/ispell-dict") ;; add personal dictionary 
(add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
(add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))

Flyspell depends on ispell mode and enables on-the-fly spell checking/correcting. I enable the flyspell mode for text-mode and org-mode.

By default, I use C-, to move the cursor to the next misspelled word, and flycheck will provide a list of candidates for auto-correlection. I press C-. select the first one, and press it again to select the next one.

(add-hook 'text-mode-hook 'flyspell-mode)
(add-hook 'org-mode-hook 'flyspell-mode)

I need an grammar check to let me know that

Have you do ...

is wrong, and also tell me to change do to done, and also why. langtool can do be the job, but currently I don’t understand how to get it works, so I am not using it anymore.

;; check grammar 
(require 'langtool)
(setq langtool-language-tool-jar "~/java/LanguageTool-2.8/languagetool-commandline.jar")
(setq langtool-mother-tongue "en")

Abbreviation

I have been writing in Emacs/org-mode a lot, have been really tired of capitalise i to I, so I use abbrevitation table.

nameexpandCategory
iIwrite
amaxannual maximumstat
gmapgoogle mapwebsite
mailmeyi.tang.uk@me.comaboutme
twitterme@yi_tang_ukaboutme
eqtequivalent toenglish
iifif and only ifmaths
wrtwith respect toEnglish
stsuch thatEnglish
d/ndistributionStats
obsobservationstats
obssobservationsstats
(defun my-text-abbrev-expand-p ()
  "Return t if the abbrev is in a text context, which is: in
 comments and strings only when in a prog-mode derived-mode or
 src block in org-mode, and anywhere else."
  (if (or (derived-mode-p 'prog-mode)
          (and (eq major-mode 'org-mode)
               (org-in-src-block-p 'inside)))
      (nth 8 (syntax-ppss))
    t))

(define-abbrev-table 'my-text-abbrev-table ()
  "Abbrev table for text-only abbrevs. Expands only in comments and strings."
  :enable-function #'my-text-abbrev-expand-p)

(dolist (table (list text-mode-abbrev-table
                     prog-mode-abbrev-table))
  (abbrev-table-put table
                    :parents (list my-text-abbrev-table)))

(defun my-text-abbrev-table-init (abbrevs-org-list)
  "Parse 'name: expansion' pairs from an org list and insert into abbrev table."
  (message "Creating text-abbrev table...")
  (dolist (abbrev abbrevs-org-list)
    (let ((name (nth 0 abbrev))
          (expansion (nth 1 abbrev)))
      ;; (print (cons name expansion))
      (define-abbrev my-text-abbrev-table name expansion nil :system t))))
(my-text-abbrev-table-init my-text-abbrevs)

Style

[2015-05-26 Tue 12:13]

English is my second language, and I am trying to avoid certain guarding term in writing. The following snipts I get it from Sachua will highlight the word like shuold or I think, which reminds to confirm with what I am not sure about, and have more confidence in what I am saying.

(require 'artbollocks-mode)
(add-hook 'text-mode-hook 'artbollocks-mode)
(setq artbollocks-weasel-words-regex
      (concat "\\b" (regexp-opt
                     '("should"
                       "just"
                       "sort of"
                       "a lot"
                       "probably"
                       "maybe"
                       "perhaps"
                       "I think"
                       "really"
                       "nice") t) "\\b"))

add synosaurus

;; [2015-02-12 Thu 21:14]
;; https://github.com/rootzlevel/synosaurus
;; synosaurus-lookup
;; synosaurus-choose-and-replace
;; brew install wordnet
(require 'synosaurus)
(setq synosaurus-choose-method "popup")

;; synosaurus-lookup C-c s l
;; synosaurus-choose-and-replace C-c s r	
(setq synosaurus-backend 'synosaurus-backend-wordnet)
(setq synosaurus-choose-method 'popup)

Title Case

(defun xah-title-case-region-or-linebegin φend)
  "Title case text between nearest brackets, or current line, or text selection.
Capitalize first letter of each word, except words like {to, of, the, a, in, or, and, …}. If a word already contains cap letters such as HTTP, URL, they are left as is.

When called in a elisp program, φbegin φend are region boundaries.
URL `http://ergoemacs.org/emacs/elisp_title_case_text.html'
Version 2015-05-07"
  (interactive
   (if (use-region-p)
       (list (region-beginning) (region-end))
     (let (
           ξp1
           ξp2
           (ξskipChars "^\"<>(){}[]“”‘’‹›«»「」『』【】〖〗《》〈〉〔〕"))
       (progn
         (skip-chars-backward ξskipChars (line-beginning-position))
         (setq ξp1 (point))
         (skip-chars-forward ξskipChars (line-end-position))
         (setq ξp2 (point)))
       (list ξp1 ξp2))))
  (let* (
         (ξstrPairs [
                     [" A " " a "]
                     [" And " " and "]
                     [" At " " at "]
                     [" As " " as "]
                     [" By " " by "]
                     [" Be " " be "]
                     [" Into " " into "]
                     [" In " " in "]
                     [" Is " " is "]
                     [" It " " it "]
                     [" For " " for "]
                     [" Of " " of "]
                     [" Or " " or "]
                     [" On " " on "]
                     [" Via " " via "]
                     [" The " " the "]
                     [" That " " that "]
                     [" To " " to "]
                     [" Vs " " vs "]
                     [" With " " with "]
                     [" From " " from "]
                     ["'S " "'s "]
                     ]))
    (save-excursion 
      (save-restriction
        (narrow-to-region φbegin φend)
        (upcase-initials-region (point-min) (point-max))
        (let ((case-fold-search nil))
          (mapc
           (lambdax)
             (goto-char (point-min))
             (while
                 (search-forward (aref ξx 0) nil t)
               (replace-match (aref ξx 1) 'FIXEDCASE 'LITERAL)))
           ξstrPairs))))))

Write-Mode

[2015-07-20 Mon 10:37]

For about one month, I tried to write at least 500 words per day. I also set up a special write-mode that has different color scheldules that helps me to set the moode.

;; [2014-12-25 Thu 22:21]
(defun yt/write-mode ()
  (interactive)
  (hl-sentence-mode)
  (variable-pitch-mode)
  (nanowrimo-mode))

;; word count
;; https://bitbucket.org/gvol/nanowrimo.el
(require 'org-wc)
(require 'nanowrimo)
(setq nanowrimo-today-goal 500)

;; [2014-12-23 Tue 22:06]
;; Highlight sentence
;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Attribute-Functions.html
(require 'hl-sentence)
(add-hook 'nanowrimo-mode 'hl-sentence-mode)
(set-face-attribute 'hl-sentence-face nil
                    ;; :foreground "black")
                    :foreground "white")
(add-hook 'nanowrimo-mode 'variable-pitch-mode)
(set-face-attribute 'variable-pitch nil
                    :foreground "gray40")

Random Quotes

[2015-01-22 Thu 23:14]

If I run out of idea, and I didn’t write anything for 1 minutes, Emacs will pop a random quote that I collected in the echo area. The random quotes can inspire me sometimes.

(defconst yt/quotes
  '("You can't see paradise, if you don't pedal.  - Chicken Run "
    "He who who says he can and he who says he can’t are both usually right ― Confucius"
    "Why waste time proving over and over how great you are when you could be getting better? - Dweck The Mindset"
    "You’re not a failure until you start to assign blame. - The legendary basketball coach John Wooden"
    "I could hear my heart beating. I could hear everyone's heart. I could hear the human noise we sat there making, not one of us moving, not even when the room went dark. - Raymond Carver"
    "A writer is a sum of their experiences. Go get some - Stuck in Love (2012)"
    "If there is any one secret of success, it lies in the ability to get the other person's point of view and see things from that person's angle as well as from your own. - Henry Ford"
    "People who can put themselves in the place of other people who can understand the workings of their minds, need never worry about what the future has in store for them. - Owen D. Young"
    )
  "Good quotes 
   they can be useful for creative writers as well.")
(defun yt/show-random-quotes ()
  "Show random quotes to minibuffer"
  (interactive)
  (message "%s"
           (nth (random (length yt/quotes))
                yt/quotes)))
(run-with-idle-timer 60 t 'yt/show-random-quotes)

Org mode

I started to learn Emacs by reading Bernt Hansen’s Org Mode - Organize Your Life In Plain Text! .My settings based on Bernt’s

associate org-mode with file with .org, .org_archive, and .txt extension.

(add-to-list 'auto-mode-alist '("\\.\\(org\\|org_archive\\|txt\\)$" . org-mode))

org-todos

[2015-07-20 Mon 14:57]

First, define the TODO keywords.

(setq org-todo-keywords
      (quote ((sequence "TODO(t)" "NEXT(n)" "SOMEDAY" "ORG(o@/!)" "|" "DONE(d)")
              (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)" "MEETING"))))

Then highlight the keywords using different colours.

(setq org-todo-keyword-faces
      (quote (("TODO" :foreground "red" :weight bold)
	      ("NEXT" :foreground "red" :weight bold)
	      ("ORG" :foreground "blue" :weight bold)
              ("DONE" :foreground "forest green" :weight bold)
              ("WAITING" :foreground "orange" :weight bold)
              ("HOLD" :foreground "magenta" :weight bold)
              ("CANCELLED" :foreground "forest green" :weight bold)
              ("MEETING" :foreground "forest green" :weight bold))))

Define an event when a TODO status changes, for example, if changed to HOLD, add HOLD tag and remove WAITING tag. If changed to DONE, remove both HOLD and WAITING tags.

(setq org-todo-state-tags-triggers
      (quote (("CANCELLED" ("CANCELLED" . t))
              ("WAITING" ("WAITING" . t))
              ("HOLD" ("WAITING") ("HOLD" . t))
              (done ("WAITING") ("HOLD"))
              ("TODO" ("WAITING") ("CANCELLED") ("HOLD"))
              ("NEXT" ("WAITING") ("CANCELLED") ("HOLD"))
              ("DONE" ("WAITING") ("CANCELLED") ("HOLD")))))

Especially, when a task is marked as DONE, a timestamp is added to the LOGBOOK drawer.

;; (setq org-log-done (quote time))
;; (setq org-log-into-drawer t)
;; (setq org-log-state-notes-insert-after-drawers nil)

Add a cross line for the headline with DONE status. Note currently it is disabled before of the performance issues in OS X.

(defun my/modify-org-done-face ()
  (setq org-fontify-done-headline t)
  (set-face-attribute 'org-done nil :strike-through t)
  (set-face-attribute 'org-headline-done nil
                      :strike-through t
                      :foreground "light gray"))
(add-hook 'org-mode-hook 'my/modify-org-done-face)
;; (setq org-fontify-done-headline t)
;; (set-face-attribute 'org-done nil :strike-through t)
;; (set-face-attribute 'org-headline-done nil :strike-through t)

org-capture

[2015-07-20 Mon 14:57]

Use C-c c anywhere to quickly create a org headline and save it to a default place.

(global-set-key (kbd "C-c c") 'org-capture)

The capture mode templates.

(setq org-capture-templates
      (quote (("t" "todo" entry (file "~/git/org/refile.org")
               "* TODO %?\n%U\n" :clock-in t :clock-resume t) ;; TODO: %? %U %a, what does these means??? %: %c
              ("o" "org" entry (file "~/git/org/refile.org")
               "* TODO %?General Org\n%U\n" :clock-in t :clock-resume t) ;; TODO: %? %U %a, what does these means??? %: %c 
              ;; ("r" "respond" entry (file "~/git/org/refile.org")
              ;;  "* To %? about :RESPONSE:  \nSCHEDULED: %t\n%U\n%a" :clock-in t :clock-resume t)
              ("r" "read" entry (file "~/git/org/refile.org")
               "* TODO %? :READ:\n%U\n" :clock-in t :clock-resume t)
              ("n" "note" entry (file "~/git/org/refile.org")
               "* %? :NOTE:\n%U\n" :clock-in t :clock-resume t)
              
              ("h" "Habit" entry (file "~/git/org/habits.org")
               "* NEXT %?\nSCHEDULED: %(format-time-string \"<%Y-%m-%d .+1d/3d>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n%U\n")
              ("l" "Ledger Journal" plain (file "~/git/org/Finance/ledger")
               "%(org-read-date) * %^{Payee}\n\t%^{Account}\t£ %^{Amount}\n\tAssets:Checking" :immediate-finish :clock-in t :clock-resume t)
              ("v" "Vocabulary" entry (file "~/git/Learning/Vocabulary.org")
               "* %? :VOCA:\n%U" :clock-in t :clock-resume t)

              ("j" "Journalsing")
              ("jd" "diary" entry (file+datetree "~/git/org/Journal/diary.org")
               "* %?\n%U\n" :clock-in t :clock-resume t)
              ("jk" "Kaggle Competition" entry (file+datetree "~/git/org/Journal/Kaggle.org")
               "* %?\n%U\n" :clock-in t :clock-resume t)
              ("js" "Statistician" entry (file+datetree "~/git/org/Journal/Statistics.org")
               "* %?\n%U\n" :clock-in t :clock-resume t)
              ("jo" "Office" entry (file+datetree "~/git/org/Journal/Office.org")
               "* TODO %?\n%U\n" :clock-in t :clock-resume t)
              )))

Speed up the process by using cache.

(setq org-refile-use-cache t)

org-refile

[2015-07-20 Mon 14:57]

Set the refile targets, they are all level 1 2 3 in current buffer and all the files in org-agenda-files.

(setq org-refile-targets (quote ((nil :maxlevel . 3)
                                 (org-agenda-files :maxlevel . 3))))

but exclude DONE state tasks from refile targets

(defun bh/verify-refile-target ()
  "Exclude todo keywords with a done state from refile targets"
  (not (member (nth 2 (org-heading-components)) org-done-keywords)))
(setq org-refile-target-verify-function 'bh/verify-refile-target)

Provide refile targets as paths. So a level 3 headline will be available as level1/level2/level3.

(setq org-refile-use-outline-path t)

Use helm for matching the target path. a low easier.

(setq org-completion-handler 'helm)

org-clock

[2015-07-20 Mon 14:57]

Save the running clock and all clock history when exiting Emacs, load it on startup

(setq org-clock-persist t)

Resume clocking task when emacs is restarted, and if continue to count on this task.

(org-clock-persistence-insinuate)
(setq org-clock-in-resume t)

;; Do not prompt to resume an active clock
;; (setq org-clock-persist-query-resume nil)
;; Save clock data and state changes and notes in the LOGBOOK drawer
(setq org-clock-into-drawer t)
;; Sometimes I change tasks I'm clocking quickly - this removes clocked tasks with 0:00 duration
(setq org-clock-out-remove-zero-time-clocks t)
;; Clock out when moving task to a done state
(setq org-clock-out-when-done t)

;; Enable auto clock resolution for finding open clocks
(setq org-clock-auto-clock-resolution (quote when-no-clock-is-running))
;; Include current clocking task in clock reports
(setq org-clock-report-include-clocking-task t)

highlight the clocking info in mode line.

(set-face-attribute 'org-mode-line-clock nil
		    :weight 'bold :box '(:line-width 1 :color "#FFBB00") :foreground "white" :background "#FF4040")

List recently clocked headline and clock in.

;; Show lot of clocking history so it's easy to pick items off the C-F11 list
(setq org-clock-history-length 23)
;; http://stackoverflow.com/questions/6156286/emacs-lisp-call-function-with-prefix-argument-programmatically
(defun yt/org-clock-in-select ()
  (interactive)
  (setq current-prefix-arg '(4)) ;; C-u, 
  (call-interactively 'org-clock-in))
(global-set-key (kbd "S-<f11>") 'yt/org-clock-in-select)
(global-set-key (kbd "<f11>") 'org-clock-jump-to-current-clock)

When clock in to a TODO headline, turn the keywords into NEXT.

;; Change tasks to NEXT when clocking in
(setq org-clock-in-switch-to-state 'bh/clock-in-to-next)
(defun bh/clock-in-to-next (kw) 
  "Switch a task from TODO to NEXT when clocking in.
Skips capture tasks"
  (when (not (and (boundp 'org-capture-mode) org-capture-mode))
    (if (member (org-get-todo-state) (list "TODO"))
        "NEXT")))

punch-in into a default org-mode headline.

(defun yt/punch-in ()
  (interactive)
    (org-with-point-at (org-id-find "1b586ec1-fa8a-4bd1-a44c-faf3aa2adf51" 'marker)
    (org-clock-in)
     ))
(global-set-key (kbd "<f9> I") 'yt/punch-in)

use hydra to define a function that use most frequently

;; https://github.com/abo-abo/hydra/wiki/Org-clock
(defhydra hydra-org-clock (:color blue :hint nil)
  "
Clock       In/out^     ^Edit^   ^Summary     (_?_)
---------------------------------------------------
            _i_n         _e_dit   _g_oto entry
_h_istory   _c_ontinue   _q_uit   _d_isplay
_j_ump      _o_ut        ^ ^      _r_eport
      "
  ("i" org-clock-in)
  ("o" org-clock-out)
  ("c" org-clock-in-last)
  ("e" org-clock-modify-effort-estimate)
  ("q" org-clock-cancel)
  ("g" org-clock-goto)
  ("d" org-clock-display)
  ("r" org-clock-report)
  ("j" org-clock-jump-to-current-clock)
  ("h" yt/org-clock-in-select)
  ("?" (org-info "Clocking commands")))

(global-set-key (kbd "<f11>") 'hydra-org-clock/body)

org-tags

[2015-07-20 Mon 14:57]

(setq org-tag-alist (quote ((:startgroup)
                            ("@office" . ?O)
                            ("@home" . ?H)
                            (:endgroup)
                            ("WAITING" . ?w)
                            ("HOLD" . ?h)
                            ("PERSONAL" . ?P)
                            ("WORK" . ?W)
                            ("NOTE" . ?n)
                            ("READ" .?r)
                            ("CANCELLED" . ?c)
                            )))
;; Allow setting single tags without the menu
(setq org-fast-tag-selection-single-key (quote expert))
(setq org-agenda-tags-todo-honor-ignore-options t)

Others

[2015-07-20 Mon 14:57]

;;;; * Custom Key Bindings

(setq org-agenda-clockreport-parameter-plist
      (quote (:link t :maxlevel 5 :fileskip0 t :compact t :narrow 80)))
;; Set default column view headings: Task Effort Clock_Summary
(setq org-columns-default-format "%80ITEM(Task) %10Effort(Effort){:} %10CLOCKSUM")
;; global Effort estimate values
;; global STYLE property values for completion
(setq org-global-properties (quote (("Effort_ALL" . "0:15 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 0:00")
                                    ("STYLE_ALL" . "habit"))))
(setq org-agenda-log-mode-items (quote (closed clock)))

(setq org-use-speed-commands t)
(defun bh/insert-inactive-timestamp ()
  (interactive)
  (org-insert-time-stamp nil t t nil nil nil))
(defun bh/insert-heading-inactive-timestamp ()
  (save-excursion
    (org-return)
    (org-cycle)
    (bh/insert-inactive-timestamp)))
(add-hook 'org-insert-heading-hook 'bh/insert-heading-inactive-timestamp 'append)
(setq org-file-apps (quote ((auto-mode . emacs)
                            ("\\.png\\'" . system)
                            ("\\.svg\\'" . system)
                            ("\\.mm\\'" . system)
                            ("\\.x?html?\\'" . system)
                            ("\\.pdf\\'" . emacs))))
                                        ; Overwrite the current window with the agenda
(setq org-agenda-window-setup 'current-window)

(setq org-time-clocksum-format
      '(:hours "%d" :require-hours t :minutes ":%02d" :require-minutes t))

;; (setq org-agenda-span 'day)
;; (require 'org-habit)

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

Agenda

[2015-01-23 Fri 16:54]

(setq org-agenda-files '("~/git/org/" "~/git/org/Journal" "~/git/org/Profession" "~/git/org/Statistics"))
(setq org-list-allow-alphabetical t)

(defun yt/org-agenda-files--choose (candidate)
  (mapc 'identity (helm-marked-candidates)))
(defun yt/org-agenda-files-set-helm ()
  (helm :sources '(((name . "Add directories to org-agenda-files variable")
                    (candidates . ("~/git/org/" "~/git/org/Journal" "~/git/org/Profession" "~/git/org/statistics"))
                    (action . yt/org-agenda-files--choose)))))
(defun yt/org-agenda-files-set ()
  (interactive)
  (setq org-agenda-files (yt/org-agenda-files-set-helm)))
;; (yt/org-agenda-files-set)

(global-set-key (kbd "<f12>") 'org-agenda)

;; Do not dim blocked tasks
(setq org-agenda-dim-blocked-tasks nil)

;; Compact the block agenda view
(setq org-agenda-compact-blocks nil)



;; Custom agenda command definitions
(defvar bh/hide-scheduled-and-waiting-next-tasks t)
(setq org-agenda-custom-commands
      (quote (("N" "Notes" tags "NOTE"
               ((org-agenda-overriding-header "Notes")
                (org-tags-match-list-sublevels t)))
              ("h" "Habits" tags-todo "STYLE=\"habit\""
               ((org-agenda-overriding-header "Habits")
                (org-agenda-sorting-strategy
                 '(todo-state-down effort-up category-keep))))
	      ("d" "deadline" agenda ""
	       (
		(org-agenda-entry-types '(:deadline))
		(org-agenda-start-day "2016-01-01")
		(org-agenda-span 'year)
		(org-agenda-include-diary nil)
		(org-agenda-show-all-dates nil)))
	      ("s" "scheduled" agenda ""
	       (
		(org-agenda-entry-types '(:scheduled))
		(org-agenda-start-day "2016-01-01")
		(org-agenda-span 'year)
		(org-agenda-include-diary nil)
		(org-agenda-show-all-dates nil)))
              (" " "Agenda"
               ((agenda "" nil)
                (tags-todo "-CANCELLED+WAITING|HOLD/!"
                           ((org-agenda-overriding-header (concat "Waiting and Postponed Tasks (Ask them)"
                                                                  (if bh/hide-scheduled-and-waiting-next-tasks
                                                                      ""
                                                                    " (including WAITING and SCHEDULED tasks)")))
                            (org-agenda-skip-function 'bh/skip-non-tasks)
                            (org-tags-match-list-sublevels nil)
                            (org-agenda-todo-ignore-scheduled bh/hide-scheduled-and-waiting-next-tasks)
                            (org-agenda-todo-ignore-deadlines bh/hide-scheduled-and-waiting-next-tasks)))
                (tags "RESPONSE"
                      ((org-agenda-overriding-header "Response (Make other's life easier)")
                       (org-tags-match-list-sublevels nil)))
                (tags-todo "-CANCELLED/!NEXT"
                           ((org-agenda-overriding-header (concat "Project Next Tasks (Running out of things to do? pick one)"
                                                                  (if bh/hide-scheduled-and-waiting-next-tasks
                                                                      ""
                                                                    " (including WAITING and SCHEDULED tasks)")))
                            (org-agenda-skip-function 'bh/skip-projects-and-habits-and-single-tasks)
                            (org-tags-match-list-sublevels t)
                            (org-agenda-todo-ignore-scheduled bh/hide-scheduled-and-waiting-next-tasks)
                            (org-agenda-todo-ignore-deadlines bh/hide-scheduled-and-waiting-next-tasks)
                            (org-agenda-todo-ignore-with-date bh/hide-scheduled-and-waiting-next-tasks)
                            (org-agenda-sorting-strategy
                             '(todo-state-down effort-up category-keep))))
                (tags-todo "-CANCELLED/!"
                           ((org-agenda-overriding-header "Stuck Projects (Make the project flows, assign Next)")
                            (org-agenda-skip-function 'bh/skip-non-stuck-projects)
                            (org-agenda-sorting-strategy
                             '(category-keep))))
                (tags-todo "-HOLD-CANCELLED/!"
                           ((org-agenda-overriding-header "Projects (on-going)")
                            (org-agenda-skip-function 'bh/skip-non-projects)
                            (org-tags-match-list-sublevels 'indented)
                            (org-agenda-sorting-strategy
                             '(category-keep))))
                (tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!"
                           ((org-agenda-overriding-header (concat "Project Subtasks (Will do in the furture)"
                                                                  (if bh/hide-scheduled-and-waiting-next-tasks
                                                                      ""
                                                                    " (including WAITING and SCHEDULED tasks)")))
                            (org-agenda-skip-function 'bh/skip-non-project-tasks)
                            (org-agenda-todo-ignore-scheduled bh/hide-scheduled-and-waiting-next-tasks)
                            (org-agenda-todo-ignore-deadlines bh/hide-scheduled-and-waiting-next-tasks)
                            (org-agenda-todo-ignore-with-date bh/hide-scheduled-and-waiting-next-tasks)
                            (org-agenda-sorting-strategy
                             '(category-keep))))
                (tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!"
                           ((org-agenda-overriding-header (concat "Standalone Tasks (One-off/Small Tasks to pick)"
                                                                  (if bh/hide-scheduled-and-waiting-next-tasks
                                                                      ""
                                                                    " (including WAITING and SCHEDULED tasks)")))
                            (org-agenda-skip-function 'bh/skip-project-tasks)
                            (org-agenda-todo-ignore-scheduled bh/hide-scheduled-and-waiting-next-tasks)
                            (org-agenda-todo-ignore-deadlines bh/hide-scheduled-and-waiting-next-tasks)
                            (org-agenda-todo-ignore-with-date bh/hide-scheduled-and-waiting-next-tasks)
                            (org-agenda-sorting-strategy
                             '(category-keep))))
                (tags "-REFILE/"
                      ((org-agenda-overriding-header "Tasks to Archive (Two month old)")
                       (org-agenda-skip-function 'bh/skip-non-archivable-tasks)
                       (org-tags-match-list-sublevels nil)))
                (tags "REFILE"
                      ((org-agenda-overriding-header "Tasks to Refile")
                       (org-tags-match-list-sublevels nil)))
                nil)))))

;; Limit restriction lock highlighting to the headline only
(setq org-agenda-restriction-lock-highlight-subtree nil)

;; Always hilight the current agenda line
(add-hook 'org-agenda-mode-hook
          '(lambda () (hl-line-mode 1))
          'append)

;;;; * agenda ignore items 
;; Keep tasks with dates on the global todo lists
(setq org-agenda-todo-ignore-with-date nil)

;; Keep tasks with deadlines on the global todo lists
(setq org-agenda-todo-ignore-deadlines nil)

;; Keep tasks with scheduled dates on the global todo lists
(setq org-agenda-todo-ignore-scheduled nil)

;; Keep tasks with timestamps on the global todo lists
(setq org-agenda-todo-ignore-timestamp nil)

;; Remove completed deadline tasks from the agenda view
(setq org-agenda-skip-deadline-if-done t)

;; Remove completed scheduled tasks from the agenda view
(setq org-agenda-skip-scheduled-if-done t)

;; Remove completed items from search results
(setq org-agenda-skip-timestamp-if-done t)

(setq org-agenda-include-diary nil)
(setq org-agenda-diary-file "~/git/org/diary.org")


(setq org-agenda-insert-diary-extract-time t)

;; Include agenda archive files when searching for things
(setq org-agenda-text-search-extra-files (quote (agenda-archives)))

;; Show all future entries for repeating tasks
(setq org-agenda-repeating-timestamp-show-all t)

;; Show all agenda dates - even if they are empty
(setq org-agenda-show-all-dates t)

;; Sorting order for tasks on the agenda
(setq org-agenda-sorting-strategy
      (quote ((agenda habit-down time-up user-defined-up effort-up category-keep)
              (todo category-up effort-up)
              (tags category-up effort-up)
              (search category-up))))



;; (setq org-agenda-tags-column -102)
;; Use sticky agenda's so they persist
;; (setq org-agenda-sticky t)

Enable display of the time grid so we can see the marker for the current time

(setq org-agenda-time-grid (quote ((daily today remove-match)
                                   #("----------------" 0 16 (org-heading t))
                                   (0700 0800 0900 1000 1100 1200 1200 1300 1400 1500 1600 1700))))

Start the weekly agenda on Monday.

(setq org-agenda-span 'week)
(setq org-agenda-start-on-weekday 1)

use 30 days.

(setq org-deadline-warning-days 30)

check clock entries if some are too long/short.

(setq org-agenda-clock-consistency-checks
      (quote (:max-duration "4:00"                 ;; highligh clock entries longer than 5 hours.
			    :min-duration "00:05"  ;; highlight clock smaller than 5 mins 
			    :max-gap "00:05"       ;; highlight clock gap loger than 5 mins.
			    :gap-ok-around ("4:00")))) 

(setq org-read-date-prefer-future ‘time)

customised

(setq org-reverse-note-order t) ;; refiled headline will be the first under the taget

(setq org-archive-location "::* Archived Tasks") ;;in-file archive 

(require 'org-habit)
(setq org-habit-show-all-today t)
(setq org-habit-show-habits nil)
(setq org-habit-graph-column 80)
;; add the following 
(setq org-time-stamp-custom-formats '("<%A %d %B %Y>" . "<%A %d %B %Y %H:%M>"))
(setq org-agenda-tags-column 120)

(setq org-columns-default-format "%80ITEM(Task) %10Effort(Effort){:} %10CLOCKSUM %10Mindfullness")

Start up options

(setq org-startup-folded t
      org-hide-block-startup t
      org-startup-indented nil)

Deep Configuration

Remove keys

;; remove C-TAB
(define-key org-mode-map (kbd "C-S-<right>") 'mc/mark-next-like-this)
(define-key org-mode-map (kbd "C-S-<left>") 'mc/mark-previous-like-this)
(org-defkey org-mode-map (kbd "C-c [") nil)
(org-defkey org-mode-map (kbd "C-c ]") nil)
(org-defkey org-mode-map (kbd "C-TAB") nil)
(org-defkey org-mode-map (kbd "<f8>") nil)
;; use helm iwth org
;; (setq org-completion-handler 'helm)

Show org-mode bullets as UTF-8 characters.

(require 'org-bullets)
(setq org-bullets-bullet-list '(;;; Large
                                "" "" ;"◎" "◌"
                                "" ""
                                "" ""
                                "" ""
                                "" "" ;"✸"
                                "" "" 
                                "" "" ;"☢" 
                                "" "" "" ""))
(setq org-bullets-bullet-list '("" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""))
;; org ellipsis options, other than the default Go to Node...
;; not supported in common font, but supported in Symbola (my fall-back font) ⬎, ⤷, ⤵
(setq org-ellipsis "⚡⚡⚡");; ⤵ ≫
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))

org-download

(require 'org-download)
(setq-default org-download-image-dir "~/Downloads/img")
(setq-default org-download-heading-lvl nil)
;; (if (eq system-type 'darwin)
;;     "org-download: default download method"
;;     (setq org-download-screenshot-method "gnome-screens
;; hot -w --delay=1 -f %s"))
(setq org-download-image-wdith 400)

;; (setq org-download-screenshot-method "gnome-screenshot -a -f %s")

Add markup wrapper for org-mode. to turn a word into bold, wrapper in a selected region, by using expand-region, which is bound to C-= then type *.

(sp-local-pair 'org-mode "=" "=") ; select region, hit = then region -> =region= in org-mode
(sp-local-pair 'org-mode "*" "*") ; select region, hit * then region -> *region* in org-mode
(sp-local-pair 'org-mode "/" "/") ; select region, hit / then region -> /region/ in org-mode
(sp-local-pair 'org-mode "_" "_") ; select region, hit _ then region -> _region_ in org-mode
(sp-local-pair 'org-mode "+" "+") ; select region, hit + then region -> +region+ in org-mode
(sp-local-pair 'org-mode "$" "$") ; select region, hit $ then region -> $region$ in org-mode

Babel

[2015-01-29 Thu 14:16]

;;;; * org-babel 
(setq org-src-window-setup 'current-window)

(setq org-src-fontify-natively t)
(setq org-structure-template-alist
      (quote (("s" "#+begin_src ?\n\n#+end_src" "<src lang=\"?\">\n\n</src>")
              ("o" "#+begin_src octave\n?\n#+end_src" "<src lang=octave\"?\">\n\n</src>")
              ("R" "#+begin_src R\n?\n#+end_src" "<src lang=R\"?\">\n\n</src>")
              ("Rg" "#+begin_src R :exports results :results graphics :width 400 :height 400 :file (org-babel-temp-file \"figure-\" \".png\") \n?\n#+end_src")
              ("p" "#+begin_src python\n?\n#+end_src" "<src lang=python\"?\">\n\n</src>")
              ("el" "#+begin_src emacs-lisp :results silent \n?\n#+end_src" "<src lang=emacs-lisp\"?\">\n\n</src>")
              ("n" "#+begin_note\n?\n#+end_note" "<note>\n?\n</note>") ;; TOOD: add note tag in html css stylesheet 
              ("e" "#+begin_example\n?\n#+end_example" "<example>\n?\n</example>")
              ("q" "#+begin_quote\n?\n#+end_quote" "<quote>\n?\n</quote>")
              ("v" "#+begin_verse\n?\n#+end_verse" "<verse>\n?\n</verse>")
              ("c" "#+begin_center\n?\n#+end_center" "<center>\n?\n</center>")
              ("l" "#+begin_latex\n?\n#+end_latex" "<literal style=\"latex\">\n?\n</literal>")
              ;;  ("L" "#+latex: " "<literal style=\"latex\">?</literal>")
              ("L" "#+begin_src emacs-lisp \n?\n#+end_src" "<src lang=emacs-lisp\"?\">\n\n</src>")
              ("h" "#+begin_html\n?\n#+end_html" "<literal style=\"html\">\n?\n</literal>")
              ("H" "#+html: " "<literal style=\"html\">?</literal>")
              ("a" "#+begin_ascii\n?\n#+end_ascii")
              ("A" "#+ascii: ")
              ("i" "#+index: ?" "#+index: ?")
              ("ln" "#+begin_latex\n\\begin{note}\n?\n\\end{note}\n#+end_latex")
              ("le" "#+begin_latex\n\\begin{equation}\n?\n\\end{equation}\n#+end_latex")
              ("la" "#+begin_latex\n\\begin{align}\n?\n\\end{align}\n#+end_latex")
              ("lc" "#+begin_latex\n\\begin{cases}\n?\n\\end{cases}\n#+end_latex")
              ("I" "#+include %file ?" "<include file=%file markup=\"?\">"))))
(setq org-src-preserve-indentation nil)
(setq org-edit-src-content-indentation 0)
(setq org-catch-invisible-edits 'error)
(setq org-export-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
(set-charset-priority 'unicode)
(setq default-process-coding-system '(utf-8-unix . utf-8-unix))
(defun bh/display-inline-images ()
  (condition-case nil
      (org-display-inline-images)
    (error nil)))


(add-hook 'org-babel-after-execute-hook 'bh/display-inline-images 'append)

(setq org-babel-results-keyword "results")
(org-babel-do-load-languages
 (quote org-babel-load-languages)
 (quote ((emacs-lisp . t) ;; TODO: simplifiy this list 
         (R . t)
         (shell . t)
         (ledger . t)
         (org . t)
         (plantuml . t)
         (dot . t)
         (python .t)
         (octave . t)
         (latex . t)
         (sql . t))))

;; (add-to-list 'org-babel-default-header-args:R
;;              ;; '(:session . "*R-main*")
;;              '((:width . 640) (:height . 640)))


(setq org-confirm-babel-evaluate nil)

(setq org-plantuml-jar-path "~/git/.emacs.d/java/plantuml.jar") ;; TODO: change the location.. 
;; Use fundamental mode when editing plantuml blocks with C-c '
(setq plantuml-jar-path "~/git/.emacs.d/java/plantuml.jar")
(add-to-list 'org-src-lang-modes (quote ("plantuml" . plantuml)))

Export

[2015-02-04 Wed 12:23]

Add export back-end, I need HTML, PDF, MarkDown, and Ascii.

(require 'ox-html)
(require 'ox-latex)
(require 'ox-ascii)
(require 'ox-md)
(require 'htmlize)
(require 'ox-gfm)

General export options, it applys to all the export-backend.

(setq org-export-with-toc nil
      org-export-with-todo-keywords t
      org-export-with-sub-superscripts nil
      org-export-with-planning nil
      org-export-with-author t
      org-export-with-timestamps nil
      org-export-babel-evaluate nil
      org-export-with-drawers nil)
(setq org-image-actual-width '(400))

Set the default format when exporting table to CSV.

(setq org-table-export-default-format "orgtbl-to-csv")

define the markups.

(setq org-emphasis-alist (quote (("*" bold "<b>" "</b>")
                                 ("/" italic "<i>" "</i>")
                                 ("_" underline "<span style=\"text-decoration:underline;\">" "</span>")
                                 ("=" org-code "<code>" "</code>" verbatim)
                                 ("~" org-verbatim "<code>" "</code>" verbatim))))

PDF Export

[2015-01-19 Mon 15:45]

;; http://emacs-fu.blogspot.co.uk/2011/04/nice-looking-pdfs-with-org-mode-and.html
;; 'djcb-org-article' for export org documents to the LaTex 'article', using
;; XeTeX and some fancy fonts; requires XeTeX (see org-latex-to-pdf-process)
(add-to-list 'org-latex-classes
             '("yt/org-article"
               "
\\documentclass[11pt,a4paper]{article}
\\usepackage{graphicx}    %% demo mode is a must when .img does not exists.
\\usepackage[T1]{fontenc}
\\usepackage{fontspec}
\\usepackage{hyperref}
\\usepackage{amsmath}
\\usepackage{amstext}
\\usepackage{amssymb} %% checkbox
\\usepackage{commath}
\\DeclareMathOperator*{\\argmin}{\\arg\\!\\min} %% use $\argmin_{b}$
\\DeclareMathOperator*{\\argmax}{\\arg\\!\\max} 
%% \\DeclareMathOperator{\\E}{\\mathbb{E}}
\\newcommand{\\E}[1]{{\\mathbb E}\\left[ #1 \\right]}
\\newcommand{\\Var}{\\mathrm{Var}}
\\DeclareMathOperator{\\P}{\\mathbb{Pr}}

\\usepackage{minted}
\\defaultfontfeatures{Mapping=tex-text}
% \\setromanfont[BoldFont={Gentium Basic Bold},
%                 ItalicFont={Gentium Basic Italic}]{Gentium Plus}
\\setsansfont{Charis SIL}
\\setmonofont[Scale=0.8]{DejaVu Sans Mono}
\\usepackage{geometry}
%% \\geometry{a4paper, textwidth=6.5in, textheight=10in,
 %%  marginparsep=7pt,
 %%  marginparwidth=1.2in, %% make sure it less than right=1.5in,
  %% otherwise, will go out of the paper
 %% right=1.5in, left=0.6in}

\\geometry{a4paper, textwidth=6.5in, textheight=10in,
            marginparsep=7pt, marginparwidth=.6in}
\\pagestyle{empty}
 
%% package from org-latex-default-packages-alist
\\usepackage{setspace}
\\onehalfspacing
\\usepackage{textcomp}
\\usepackage{marvosym}
\\usepackage{wasysym}
\\usepackage{ulem}

%% \\renewcommand\\texttt[1]{{\\mint{cl}|#1|}} 


\\usepackage{environ}
\\NewEnviron{note}{\\marginpar{\\footnotesize \\BODY}}

%% algorithm 
\\usepackage{xcolor}
\\usepackage[linesnumbered]{algorithm2e}
\\newcommand\\mycommfont[1]{\\footnotesize\\ttfamily\\textcolor{blue}{#1}}
\\makeatletter
\\renewcommand{\\@algocf@capt@plain}{above}% formerly {bottom}
\\makeatother


\\title{}
      [NO-DEFAULT-PACKAGES]
      [NO-PACKAGES]"
               ("\\section{%s}" . "\\section*{%s}")
               ("\\subsection{%s}" . "\\subsection*{%s}")
               ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
               ("\\paragraph{%s}" . "\\paragraph*{%s}")
               ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
(setq org-latex-default-class "yt/org-article")

;; code highlights using minted package 
(add-to-list 'org-latex-packages-alist '("" "minted"))
(setq org-latex-listings 'minted)
(setq org-latex-minted-options
      '(("frame" "lines")
        ("fontsize" "\\scriptsize")))
;; ("linenos" "")))

;;;; comple pdf 
(setq org-latex-pdf-process
      '("xelatex -shell-escape -interaction=nonstopmode -output-directory %o %f"
        "xelatex -shell-escape -interaction=nonstopmode -output-directory %o %f"
        "xelatex -shell-escape -interaction=nonstopmode -output-directory %o %f"))

HTML Export

[2015-01-19 Mon 15:45]

;; http://sachachua.com/blog/2014/03/emacs-tweaks-export-org-checkboxes-using-utf-8-symbols/
(defun sacha/org-html-checkbox (checkbox)
  "Format CHECKBOX into HTML."
  (case checkbox (on "<span class=\"check\">&#x2611;</span>") ; checkbox (checked)
        (off "<span class=\"checkbox\">&#x2610;</span>")
        (trans "<code>[-]</code>")
        (t "")))
(defadvice org-html-checkbox (around sacha activate)
  (setq ad-return-value (sacha/org-html-checkbox (ad-get-arg 0))))

(setq org-html-head
      "<link rel=\"stylesheet\" type=\"text/css\"
href=\"http://sachachua.com/blog/wp-content/themes/sacha-v3/foundation/css/foundation.min.css\"></link>
<link rel=\"stylesheet\" type=\"text/css\" href=\"http://sachachua.com/org-export.css\"></link>
<link rel=\"stylesheet\" type=\"text/css\" href=\"http://sachachua.com/blog/wp-content/themes/sacha-v3/style.css\"></link>
<script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js\"></script>")
(setq org-html-htmlize-output-type 'css)
(setq org-src-fontify-natively t)
(setq org-html-preamble "<a name=\"top\" id=\"top\"></a>")
(setq org-html-postamble "
<style type=\"text/css\">
.back-to-top {
    position: fixed;
    bottom: 2em;
    right: 0px;
    text-decoration: none;
    color: #000000;
    background-color: rgba(235, 235, 235, 0.80);
    font-size: 12px;
    padding: 1em;
    display: none;
}
.back-to-top:hover {    
    background-color: rgba(135, 135, 135, 0.50);
}
</style>
<div class=\"back-to-top\">
<a href=\"#top\">Back to top</a> | <a href=\"mailto:yi.tang.uk@me.com\">E-mail me</a>
</div>
<script type=\"text/javascript\">
    var offset = 220;
    var duration = 500;
    jQuery(window).scroll(function() {
        if (jQuery(this).scrollTop() > offset) {
            jQuery('.back-to-top').fadeIn(duration);
        } else {
            jQuery('.back-to-top').fadeOut(duration);
        }
    });
</script>")


;; Inline images in HTML instead of producting links to the image
(setq org-html-inline-images t)
;; Do not use sub or superscripts - I currently don't need this functionality in my documents
(setq org-export-with-sub-superscripts nil)
;; Export with LaTeX fragments
(setq org-export-with-LaTeX-fragments t)
;; Increase default number of headings to export
(setq org-export-headline-levels 6)

like the fontified area for key-bindings.

(setq org-html-text-markup-alist
      '((bold . "<b>%s</b>")
        (code . "<kbd>%s</kbd>")
        (italic . "<i>%s</i>")
        (strike-through . "<del>%s</del>")
        (underline . "<span class=\"underline\">%s</span>")
        (verbatim . "<code>%s</code>")))

Beautiful and useful HTML themes

(setq yt/org-html-themes-sacha ;; Sacha's 
      "<link rel=\"stylesheet\" type=\"text/css\"
href=\"http://sachachua.com/blog/wp-content/themes/sacha-v3/foundation/css/foundation.min.css\"></link>
<link rel=\"stylesheet\" type=\"text/css\" href=\"http://sachachua.com/org-export.css\"></link>
<link rel=\"stylesheet\" type=\"text/css\" href=\"http://sachachua.com/blog/wp-content/themes/sacha-v3/style.css\"></link>
<script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js\"></script>")

(setq yt/org-html-themes-readtheorg ;; ReadTheOrg
      "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://www.pirilampo.org/styles/readtheorg/css/htmlize.css\"/>
<link rel=\"stylesheet\" type=\"text/css\" href=\"http://www.pirilampo.org/styles/readtheorg/css/readtheorg.css\"/>
<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js\"></script>
<script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js\"></script>
<script type=\"text/javascript\" src=\"http://www.pirilampo.org/styles/lib/js/jquery.stickytableheaders.js\"></script>
<script type=\"text/javascript\" src=\"http://www.pirilampo.org/styles/readtheorg/js/readtheorg.js\"></script>")

(setq yt/org-html-themes-bigblow ;; Bigblow
      "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://www.pirilampo.org/styles/bigblow/css/htmlize.css\"/>
<link rel=\"stylesheet\" type=\"text/css\" href=\"http://www.pirilampo.org/styles/bigblow/css/bigblow.css\"/>
<link rel=\"stylesheet\" type=\"text/css\" href=\"http://www.pirilampo.org/styles/bigblow/css/hideshow.css\"/>
<script type=\"text/javascript\" src=\"http://www.pirilampo.org/styles/bigblow/js/jquery-1.11.0.min.js\"></script>
<script type=\"text/javascript\" src=\"http://www.pirilampo.org/styles/bigblow/js/jquery-ui-1.10.2.min.js\"></script>
<script type=\"text/javascript\" src=\"http://www.pirilampo.org/styles/bigblow/js/jquery.localscroll-min.js\"></script>
<script type=\"text/javascript\" src=\"http://www.pirilampo.org/styles/bigblow/js/jquery.scrollTo-1.4.3.1-min.js\"></script>
<script type=\"text/javascript\" src=\"http://www.pirilampo.org/styles/bigblow/js/jquery.zclip.min.js\"></script>
<script type=\"text/javascript\" src=\"http://www.pirilampo.org/styles/bigblow/js/bigblow.js\"></script>
<script type=\"text/javascript\" src=\"http://www.pirilampo.org/styles/bigblow/js/hideshow.js\"></script>
<script type=\"text/javascript\" src=\"http://www.pirilampo.org/styles/lib/js/jquery.stickytableheaders.min.js\"></script>")

(setq yt/org-html-themes
      '(("General" . yt/org-html-themes-sacha)
        ("ReadTheOrg" . yt/org-html-themes-readtheorg)
        ("Bigblow" . yt/org-html-themes-bigblow)))

(defun yt/org-set-html-theme ()
  (interactive)
  (let* ((user-input  (completing-read "Theme: " yt/org-html-themes nil t))
         (theme-link  (symbol-value (cdr (assoc user-input yt/org-html-themes)))))
    (setq org-html-head theme-link)
    (format "Use %s HTML Theme" user-input)))

(setq org-html-head (symbol-value (cdr (assoc "Bigblow" yt/org-html-themes)))) ;; default setting

Publish for blogging

[2015-07-20 Mon 16:39]

Blogging with Jekyll

Jeklly have few conventins, like the new, YAML etc, it is better to solve it autoamtilcally and in Emacs, as part of the export process.

First, define a publish project, so that the exported html file will go to certail place, and we can define the styles, and other features for a praticularlly project. but for Jeklly, it is more about to match the constraints.

For managing a blog, it is good idea to keep the original org file inside of the website. Most people using Jeklly write blog in Markdown format, but Org-mode is obvious more powerful in Literate Program. In this case, I have two folders under Jeklly project direcotyr, org/_drafts and org/_posts.

(defvar jekyll-directory (expand-file-name "~/git/myblog/org/")
  "Path to Jekyll blog.")
(defvar jekyll-drafts-dir "_drafts/"
  "Relative path to drafts directory.")
(defvar jekyll-posts-dir "_posts/"
  "Relative path to posts directory.")
(defvar jekyll-post-ext ".org"
  "File extension of Jekyll posts.")

I can quickly scne the folder to see how many outstanding drasfts and which posts is published in in cease I need to edit it. I bind it to C-c j p and C-c j d where j means Jekly, p means posts, and d means drafts.

(global-set-key (kbd "C-c j p") (lambda ()
                                  (interactive)
                                  (find-file "~/git/myblog/org/_posts/")))
(global-set-key (kbd "C-c j d") (lambda ()
                                  (interactive)
                                  (find-file "~/git/myblog/org/_drafts/")))

Jeklyl has a spacial template that requires to add YAML in the front, since it is in org-mode, I can call Babel functions, add table of contents and others etc. This is the template I am using. Note the jekly-ymal-escape function is used just to make sure there is strange characters that jeklly don;t like.

(defvar jekyll-post-template
  " 
#+BEGIN_HTML
---
layout: post
title: %s
excerpt: 
categories:
  -  
tags:
  -
comments: true 
---
#+END_HTML

#+begin_html
<script type=\"text/javascript\"
    src=\"http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML\">
</script>
#+end_html

# #+call: GetLastUpdatedDate[:exports none]()[:results org]

#+TOC: headlines 4
"
  "Default template for Jekyll posts. %s will be replace by the post title.")

(defun jekyll-yaml-escape (s)
  "Escape a string for YAML."
  (if (or (string-match ":" s)
        2  (string-match "\"" s))
      (concat "\"" (replace-regexp-in-string "\"" "\\\\\"" s) "\"")
    s))

Then in starting a blog post, I fill the title, and there file will be served in the org/_drafts folder, and insert the YMAL. Note in jeklly, the title be part of html file name and therefore part of the URL. So strange characters must been removed.

(defun blog-draft-post (title) 
  "Create a new Jekyll blog post."
  (interactive "sPost Title: ")
  (let ((draft-file (concat jekyll-directory jekyll-drafts-dir
                            (jekyll-make-slug title)
                            jekyll-post-ext)))
    (if (file-exists-p draft-file)
        (find-file draft-file)
      (find-file draft-file)
      (insert (format jekyll-post-template (jekyll-yaml-escape title))))))

(defun jekyll-make-slug (s)
  "Turn a string into a slug."
  (replace-regexp-in-string
   " " "-" (downcase
            (replace-regexp-in-string
             "[^A-Za-z0-9 ]" "" s))))

Once I think the article is read to be publish, the blog-publish-post function will move the editing draft into org/_posts folder and prepend the file name with today’s date in %Y-%m-%d format. it is required by Jeklly.

(defun blog-publish-post ()
  "Move a draft post to the posts directory, and rename it so that it
 contains the date."
  (interactive)
  (cond
   ((not (equal
          (file-name-directory (buffer-file-name (current-buffer)))
          (concat jekyll-directory jekyll-drafts-dir)))
    (message "This is not a draft post."))
   ((buffer-modified-p)
    (message "Can't publish post; buffer has modifications."))
   (t
    (let ((filename
           (concat jekyll-directory jekyll-posts-dir
                   (format-time-string "%Y-%m-%d-")
                   (file-name-nondirectory
                    (buffer-file-name (current-buffer)))))
          (old-point (point)))
      (rename-file (buffer-file-name (current-buffer))
                   filename)
      (kill-buffer nil)
      (find-file filename)
      (set-window-point (selected-window) old-point)))))

I bound C-c j n and C-c j P for making a draft and publishing a draft.

(global-set-key (kbd "C-c j n") 'blog-draft-post)
(global-set-key (kbd "C-c j P") 'blog-publish-post)

Then convert all the org files in org/_posts into HTML and save in the _posts/ folder. It is good to define an org-publish-project to automate this. Note in the following, the published HTML has body only, and without TOC, which are again, required by JEKLLY.

;; ref: http://cute-jumper.github.io/emacs/2013/10/06/orgmode-to-github-pages-with-jekyll/
(setq org-publish-project-alist
      '(("myblog"
         :base-directory "~/git/myblog/org"
         :base-extension "org"
         :publishing-directory "~/git/myblog"
         :recursive t
         :publishing-function org-html-publish-to-html
         :with-toc nil
         :headline-levels 4
         :section-numbers nil
         :auto-preamble nil
         :auto-sitemap nil
         :html-extension "html"
         :htmlized-source t
         :body-only t
         :with-toc nil
         )))

code highlight

[2015-01-23 Fri 17:47]

(defvar jekyll-highlight-template-open
  "#+begin_html
{%% highlight %s %%}"
  "%s will be replaced by the language identifier")

(defvar jekyll-highlight-template-close
  "{% endhighlight %}
#+end_html")

(defun yt/org-to-jekyll-highlight ()
  "wrap babel src block with jekyll syntax highlight block"
  (interactive)
  (save-excursion
    (goto-char (point-min))
(org-show-block-all)
    (while (search-forward-regexp "#\\+begin_src \\([a-z]+\\).*$" nil t)
      (replace-match (format jekyll-highlight-template-open (match-string 1)))
      (search-forward-regexp "#\\+end_src") ;; will throew error if src block is not closed. 
      (replace-match jekyll-highlight-template-close t))))

;; (add-hook 'org-export-before-processing-hook 'yt/org-to-jekyll-highlight) ;; won't work. all src blocks are wrapped before execuating. not ideal if i do need them. 
;; (add-hook 'org-export-before-parsing-hook 'yt/org-to-jekyll-highlight)

;;;; TODO: 
;; it won't be good to add a hook yt/org-jekyl-highlight
;; so that it won't effect my other exporting

;; (defun yt/test (html)
;;   (message (concat "I am here: " default-directory)))
;; for /home/itang/git/org/tmp.org, get 
;; I am here: /home/yitang/git/org/

(defun yt/my-blog-pre-process-hook (html) ;; only for html back-end
  (when (equal default-directory
               (concat jekyll-directory jekyll-posts-dir))
    (message "PROCESS SRC BLOCK")
    (goto-char (point-min))
    (yt/org-to-jekyll-highlight)))

;; (setq org-export-before-parsing-hook nil)
(add-hook 'org-export-before-parsing-hook 'yt/my-blog-pre-process-hook)

When publishing, the org-file is firstly exported to html file, and when Jekyll build the website, the html file will be saved in to some folder that depends on the YMAL. Then the relative path to image files are broken. To solve that, according to the Jeklyy web site, is to save all the image or downloade files in assets/ folder. Then those image files are referende by org-mode.

First, define a img link, that when exporting, the image a_img.png will be set to linked to /assets/a_img.png. when I click, it wil open the img file in Emacs.

(defun org-custom-link-img-follow (path)
  (org-open-file-with-emacs
   (format "../../assets/%s" path)))

(defun org-custom-link-img-export (path desc format)
  (cond
   ((eq format 'html)
    (format "<img src=\"/assets/%s\" alt=\"%s\"/>" path desc))))

(org-add-link-type "img" 'org-custom-link-img-follow 'org-custom-link-img-export)

Org-link

[2015-07-18 Sat 09:15]

magit

;; from https://lists.gnu.org/archive/html/emacs-orgmode/2009-08/msg00460.html
;; magit link in org-mode 
(defun org-magit-store-link ()
  "Store a link to a directory to open with magit."
  (when (eq major-mode 'magit-mode)
    (let* ((dir default-directory)
           (link (org-make-link "magit:" dir))
           (desc (abbreviate-file-name dir)))
      (org-store-link-props :type "magit" :link link :description desc)
      link)))
(defun org-magit-open (dir)
  "Follow a magit link to DIR."
  (require 'magit)
  (magit-status dir))
(org-add-link-type "magit" 'org-magit-open nil)
(add-hook 'org-store-link-functions 'org-magit-store-link)

cross reference

[2015-07-21 Tue 10:59]

(defun org-jekyll-post-link-follow (path)
  (org-open-file-with-emacs path))

(defun org-jekyll-post-link-export (path desc format)
  (cond
   ((eq format 'html)
    (format "<a href=\"{%% post_url %s %%}\">%s</a>" path desc))))

(org-add-link-type "jekyll-post" 'org-jekyll-post-link-follow 'org-jekyll-post-link-export)

auctex

[2015-10-03 Sat 13:48]

http://tex.stackexchange.com/questions/50827/a-simpletons-guide-to-tex-workflow-with-emacs

http://tex.stackexchange.com/questions/29813/setup-synctex-with-emacs

http://www.stefanom.org/setting-up-a-nice-auctex-environment-on-mac-os-x/

;; AucTeX
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq-default TeX-master nil)
(add-hook 'LaTeX-mode-hook 'visual-line-mode)
(add-hook 'LaTeX-mode-hook 'flyspell-mode)
(add-hook 'LaTeX-mode-hook 'LaTeX-math-mode)
(add-hook 'LaTeX-mode-hook 'turn-on-reftex)
(setq reftex-plug-into-AUCTeX t)
(setq TeX-PDF-mode t)
;; make latexmk available via C-c C-c
(add-hook 'LaTeX-mode-hook (lambda ()
			     (push
			      '("latexmk" "latexmk -pdf %s" TeX-run-TeX nil t
				:help "Run latexmk on file")
			      TeX-command-list)))
(add-hook 'TeX-mode-hook '(lambda () (setq TeX-command-default "latexmk")))
(setq TeX-view-program-selection '((output-pdf "evince")))
(if (string= system-type "darwin")
    (setq TeX-view-program-selection '((output-dvi "open")
				       (output-pdf "open")
				       (output-html "open"))))
;;; Brent.Longborough's .emacs

;; (global-visual-line-mode 1); Proper line wrapping
;; (global-hl-line-mode 1); Highlight current row
;; (show-paren-mode 1); Matches parentheses and such in every mode
;; (set-fringe-mode '(0 . 0)); Disable fringe because I use visual-line-mode
;; (set-face-background hl-line-face "#f2f1f0"); Same color as greyness in gtk
;; (setq inhibit-splash-screen t); Disable splash screen
;; (setq visible-bell t); Flashes on error
;; (setq calendar-week-start-day 1); Calender should start on Monday
;; (add-to-list 'default-frame-alist '(height . 59)); Default frame height.

;;; AUCTeX
;; Customary Customization, p. 1 and 16 in the manual, and http://www.emacswiki.org/emacs/AUCTeX#toc2
(setq TeX-parse-self t); Enable parse on load.
(setq TeX-auto-save t); Enable parse on save.
(setq-default TeX-master nil)

(setq TeX-PDF-mode t); PDF mode (rather than DVI-mode)

(add-hook 'TeX-mode-hook 'flyspell-mode); Enable Flyspell mode for TeX modes such as AUCTeX. Highlights all misspelled words.
(add-hook 'TeX-mode-hook
          (lambda () (TeX-fold-mode 1))); Automatically activate TeX-fold-mode.
(setq LaTeX-babel-hyphen nil); Disable language-specific hyphen insertion.

;; " expands into csquotes macros (for this to work babel must be loaded after csquotes).
(setq LaTeX-csquotes-close-quote "}"
      LaTeX-csquotes-open-quote "\\enquote{")

;; LaTeX-math-mode http://www.gnu.org/s/auctex/manual/auctex/Mathematics.html
(add-hook 'TeX-mode-hook 'LaTeX-math-mode)

;;; RefTeX
;; Turn on RefTeX for AUCTeX http://www.gnu.org/s/auctex/manual/reftex/reftex_5.html
(add-hook 'TeX-mode-hook 'turn-on-reftex)

(eval-after-load 'reftex-vars; Is this construct really needed?
  '(progn
     (setq reftex-cite-prompt-optional-args t); Prompt for empty optional arguments in cite macros.
     ;; Make RefTeX interact with AUCTeX, http://www.gnu.org/s/auctex/manual/reftex/AUCTeX_002dRefTeX-Interface.html
     (setq reftex-plug-into-AUCTeX t)
     ;; So that RefTeX also recognizes \addbibresource. Note that you
     ;; can't use $HOME in path for \addbibresource but that "~"
     ;; works.
     (setq reftex-bibliography-commands '("bibliography" "nobibliography" "addbibresource"))
                                        ;     (setq reftex-default-bibliography '("UNCOMMENT LINE AND INSERT PATH TO YOUR BIBLIOGRAPHY HERE")); So that RefTeX in Org-mode knows bibliography
     (setcdr (assoc 'caption reftex-default-context-regexps) "\\\\\\(rot\\|sub\\)?caption\\*?[[{]"); Recognize \subcaptions, e.g. reftex-citation
     (setq reftex-cite-format; Get ReTeX with biblatex, see http://tex.stackexchange.com/questions/31966/setting-up-reftex-with-biblatex-citation-commands/31992#31992
           '((?t . "\\textcite[]{%l}")
             (?a . "\\autocite[]{%l}")
             (?c . "\\cite[]{%l}")
             (?s . "\\smartcite[]{%l}")
             (?f . "\\footcite[]{%l}")
             (?n . "\\nocite{%l}")
             (?b . "\\blockcquote[]{%l}{}")))))

;; Fontification (remove unnecessary entries as you notice them) http://lists.gnu.org/archive/html/emacs-orgmode/2009-05/msg00236.html http://www.gnu.org/software/auctex/manual/auctex/Fontification-of-macros.html
(setq font-latex-match-reference-keywords
      '(
        ;; biblatex
        ("printbibliography" "[{")
        ("addbibresource" "[{")
        ;; Standard commands
        ;; ("cite" "[{")
        ("Cite" "[{")
        ("parencite" "[{")
        ("Parencite" "[{")
        ("footcite" "[{")
        ("footcitetext" "[{")
        ;; ;; Style-specific commands
        ("textcite" "[{")
        ("Textcite" "[{")
        ("smartcite" "[{")
        ("Smartcite" "[{")
        ("cite*" "[{")
        ("parencite*" "[{")
        ("supercite" "[{")
                                        ; Qualified citation lists
        ("cites" "[{")
        ("Cites" "[{")
        ("parencites" "[{")
        ("Parencites" "[{")
        ("footcites" "[{")
        ("footcitetexts" "[{")
        ("smartcites" "[{")
        ("Smartcites" "[{")
        ("textcites" "[{")
        ("Textcites" "[{")
        ("supercites" "[{")
        ;; Style-independent commands
        ("autocite" "[{")
        ("Autocite" "[{")
        ("autocite*" "[{")
        ("Autocite*" "[{")
        ("autocites" "[{")
        ("Autocites" "[{")
        ;; Text commands
        ("citeauthor" "[{")
        ("Citeauthor" "[{")
        ("citetitle" "[{")
        ("citetitle*" "[{")
        ("citeyear" "[{")
        ("citedate" "[{")
        ("citeurl" "[{")
        ;; Special commands
        ("fullcite" "[{")))

(setq font-latex-match-textual-keywords
      '(
        ;; biblatex brackets
        ("parentext" "{")
        ("brackettext" "{")
        ("hybridblockquote" "[{")
        ;; Auxiliary Commands
        ("textelp" "{")
        ("textelp*" "{")
        ("textins" "{")
        ("textins*" "{")
        ;; supcaption
        ("subcaption" "[{")))

(setq font-latex-match-variable-keywords
      '(
        ;; amsmath
        ("numberwithin" "{")
        ;; enumitem
        ("setlist" "[{")
        ("setlist*" "[{")
        ("newlist" "{")
        ("renewlist" "{")
        ("setlistdepth" "{")
        ("restartlist" "{")))

Hydra

[2015-06-22 Mon 14:11]
(defhydra yt-hydra/help (:color blue :hint nil)
  "
_f_unction: Documentation for a function
_v_ariable: Documentation for a variable
_i_nfo: info mode 
_G_oogle: search google 
_d_ictionary: search meaning of a word"
  ("f" describe-function)
  ("v" describe-variable)
  ("i" helm-info-org)
  ("G" helm-google-suggest)
  ("d" voca-builder/search-popup))
(global-set-key (kbd "<f1>") 'yt-hydra/help/body)

hydra

(require 'hydra)

(defhydra hydra-search (:color blue
                               :hint nil)
  "
Current Buffer   : _i_search helm-_s_woop _a_ce-jump-word 
Multiple Buffers : helm-multi-_S_woop 
Project Directory: projectile-_g_rep  helm-projectile-_G_rep
"
  ("i" isearch-forward)
  ("s" helm-swoop)
  ("a" ace-jump-word-mode)
  ("S" helm-multi-swoop)
  ("g" projectile-grep)
  ("G" helm-projectile-grep))
(global-set-key [f5] 'hydra-search/body)

Emacs Lisp Programming

[2015-07-05 Sun 19:46]

use org-struct mode for emacs-lisp.

(add-hook 'emacs-lisp-mode-hook '(lambda ()
                              (turn-on-orgstruct)
                              (setq-local orgstruct-heading-prefix-regexp ";;;; ")))

(rep “a” 3) –> “aaa”

(defun yt/lisp-rep (arg n)
  (apply 'concat (make-list n arg)))

Org-Mode API

[2015-07-05 Sun 19:47]

Get the link to current headline as an external link.

(defun yt/org-get-heading-link ()
  (interactive)
  (let* ((file-name (file-truename buffer-file-name))
         (headline (org-heading-components))
         (level (nth 0 headline))
         (title (nth 4 headline))
         (link (concat file-name
                       "::"
                       "*" ;; (yt/lisp-rep "*" level)
                       title)))
    (kill-new (concat "[["
                      link
                      "]["
                      (concat "headline: " title)
                      "]]"))))

mu4e - Email Client

The advantage of use Emacs as an email client:

  1. communication happens at the point where the content is genreated. as a statisician/programmer, most likely I need to mmunicate with numbers, table, graphs, or snippet. I could just copy these results from to email, do an quickly editing.
  2. HTML email with CSS style. I like to formate my email use headingline, fonts, and highlhgit the code, I used to be write a report in Word/LatEx and write an email with only onbe line, please see the attachment. which I don’t like.
  3. search properly I use search all the time, and this functionality is not working at all in outlkooik 2013, it also shows up random info (mail.app in osx did a great job).

Disadvantage and the things it can’t do:

  1. book Meeting/Appointment I didn’t aware that you can do it in emacs, and we need an iterative way to do. Outlook Schedule Asistant do a good job, it list agenda of all attendence, and I could spot oen time slot that suit for all or most people.
  2. don’t expect me to reply immediately this is how does it works: 1. download the email from server, 2) index with head, body, attachment, user name etc. 3) Emacs talk to and show in GUI. I usually update the meail about 30 imnutes. but I helps me out of disrupts.
  3. calendar I don’t know how to integrate Office 365 calendar with Org-mode calandar yet. even it can, I doubt I can download and see other people’s agenda.

This setting need two programms to work: 1) mu, 2) offlineimap.

To install mu on osx,

The basical workflow is:

  1. offlineimap download the Emails from server,
  2. mu index them,
  3. and mu4e package render the emails in Emacs.
  4. smtpmail for senting out emails.
;;----------------------------------------------------------
(add-to-list 'load-path "~/git/.emacs.d/elpa/mu4e")
(require 'mu4e)
;; default

;; don't save message to Sent Messages, Gmail/IMAP takes care of this
(setq mu4e-sent-messages-behavior 'sent)

;; allow for updating mail using 'U' in the main view:
; get mail
(setq mu4e-html2text-command "w3m -T text/html"
      mu4e-update-interval 120
      mu4e-headers-auto-update t
      mu4e-compose-signature-auto-include t)

;; don't keep message buffers around
(setq message-kill-buffer-on-exit t)

;; attempt to show images when viewing messages
(setq mu4e-view-show-images t
      mu4e-show-images t
      mu4e-view-image-max-width 800)


;; (setq mu4e-html2text-command "html2text -utf8 -width 72") ;; nil "Shel command that converts HTML
;; ref: http://emacs.stackexchange.com/questions/3051/how-can-i-use-eww-as-a-renderer-for-mu4e
(defun my-render-html-message ()
  (let ((dom (libxml-parse-html-region (point-min) (point-max))))
    (erase-buffer)
    (shr-insert-document dom)
    (goto-char (point-min))))
(setq mu4e-html2text-command 'my-render-html-message)

;; (setq mu4e-view-prefer-html t) ;; try to render 
(add-to-list 'mu4e-view-actions 
             '("ViewInBrowser" . mu4e-action-view-in-browser) t) ;; read in browser 
;; mu4e as default email agent in emacs
(setq mail-user-agent 'mu4e-user-agent)
(require 'org-mu4e)
                                        ;== M-x org-mu4e-compose-org-mode==
(setq org-mu4e-convert-to-html t) ;; org -> html
                                        ; = M-m C-c.= 

;; give me ISO(ish) format date-time stamps in the header list
(setq  mu4e-headers-date-format "%Y-%m-%d %H:%M")

;; customize the reply-quote-string
;; M-x find-function RET message-citation-line-format for docs
(setq message-citation-line-format "%N @ %Y-%m-%d %H:%M %Z:\n")
(setq message-citation-line-function 'message-insert-formatted-citation-line)

;; the headers to show in the headers list -- a pair of a field
;; and its width, with `nil' meaning 'unlimited'
;; (better only use that for the last field.
;; These are the defaults:
(setq mu4e-headers-fields
      '( (:date          .  25)
         (:flags         .   6)
         (:from          .  22)
         (:subject       .  nil)))

;; don't keep message buffers around
(setq message-kill-buffer-on-exit t)
;; attachments go here
(setq mu4e-attachment-dir  "~/Downloads")

;; should mu4e use fancy utf characters? NO. they're ugly.
;;(setq mu4e-use-fancy-chars 't)

;; sending mail -- replace USERNAME with your gmail username
;; also, make sure the gnutls command line utils are installed
;; package 'gnutls-bin' in Debian/Ubuntu
(require 'smtpmail)
(setq smtpmail-default-smtp-server "smtpserver") ; needs to be specified before the (require)
(setq send-mail-function 'smtpmail-send-it)
(setq smtpmail-stream-type 'starttls)

use helm-mu to search emails

(global-set-key (kbd "<f9> e") 'helm-mu)
(add-to-list 'mu4e-bookmarks
             '("date:20100930..now"       "All Messages"     ?a))
(add-to-list 'mu4e-bookmarks
             '("flag:flagged" "Flagged messages" ?f))
;; use helm-style completion for jumpping mail directory.
;; https://github.com/djcb/mu/issues/286
(defun pyl-helm-mu-compl-read (prompt maildirs-list &optional ignore1 ignore2 ignore3)
  (helm-comp-read prompt maildirs-list
		  :name prompt
		  :must-match t))
(setq mu4e-completing-read-function 'pyl-helm-mu-compl-read)

Account

[2015-01-23 Fri 17:32]

set up email account, use office 365 in the office, and iCloud at macbook por.

(setq  mu4e-maildir-shortcuts  '(("/JBA/INBOX"    . ?j)
                                 ("/iCloud/INBOX" . ?a)
                                 ("/Gmail/INBOX" . ?g)))


(defun yt/email-icloud ()
  (push '("/iCloud/INBOX" . ?i) mu4e-maildir-shortcuts)
  (setq  mu4e-get-mail-command "mbsync iCloud Gmail; mu index --maildir=~/Maildir/personal"
         mu4e-maildir "~/Maildir/personal"
         smtpmail-default-smtp-server "smtp.mail.me.com"
         smtpmail-smtp-server "smtp.mail.me.com"
         smtpmail-smtp-service 587
         smtpmail-smtp-user "yi.tang.uk@me.com"
         user-mail-address "yi.tang.uk@me.com"
         user-full-name  "Yi Tang"
         mu4e-drafts-folder "/iCloud/Drafts"
         mu4e-sent-folder   "/iCloud/Sent Messages"
         mu4e-trash-folder  "/iCloud/Deleted Messages"
         mu4e-compose-signature (concat
                                 "唐毅 (Yi Tang)\n"
                                 "Email: yi.tang.uk@me.com\n"
                                 "\n")))

(defun yt/email-gmail ()
  (push '("/Gmail/[Google Mail].All Mail" . ?i) mu4e-maildir-shortcuts)
  ;; sent emails 
  (setq   mu4e-get-mail-command "mbsync iCloud Gmail; mu index --maildir=~/Maildir/personal"
          mu4e-maildir "~/Maildir/personal"
          smtpmail-starttls-credentials '(("smtp.gmail.com" 587 nil nil))
          smtpmail-default-smtp-server "smtp.gmail.com"
          smtpmail-smtp-server "smtp.gmail.com"
          smtpmail-smtp-service 587
          smtpmail-smtp-user "yi.tang.uni@gmail.com"
          
          user-mail-address "yi.tang.uni@gmail.com" 
          user-full-name  "Yi Tang"
          mu4e-drafts-folder "/Gmail/[Google Mail].Drafts" 
          mu4e-sent-folder   "/Gmail/[Google Mail].Sent Messages" 
          mu4e-trash-folder  "/Gmail/[Google Mail].Trash"

          mu4e-compose-signature (concat
                                  "Yi Tang\n"
                                  "Statistician\n"
                                  "T: 07445510033\n")))

(defun yt/email-jba ()
  (interactive)
  ;; setup for smtp 
  (setq   mu4e-get-mail-command "mbsync JBA; mu index --maildir=~/Maildir/work"
          mu4e-maildir "~/Maildir/work"
          smtpmail-default-smtp-server "smtp.office365.com"
          smtpmail-smtp-server "smtp.office365.com"
          smtpmail-smtp-service 587
          smtpmail-smtp-user "yi.tang@jbarisk.com"
          ;; account info 
          user-mail-address "yi.tang@jbarisk.com"
          user-full-name  "Yi Tang"
          ;; mu4e 
          mu4e-drafts-folder "/JBA/Drafts"
          mu4e-sent-folder   "/JBA/Outbox"
          mu4e-trash-folder  "/JBA/Trash"

          mu4e-compose-signature (concat
                                  "Yi Tang\n"
                                  "Statistician\n"
                                  "T: +44 (0) 1756 799919\n")))

(setq yt/email-account-list
      '(("JBA" . yt/email-jba)
        ("Gmail" . yt/email-gmail)
        ("iCloud" . yt/email-icloud)))

(defun yt/email-switch-account (&optional account)
  (interactive)
  (let* ((account (if (equal account nil)
                      (completing-read "Choose Email Account: " yt/email-account-list nil t)
                    account))
         (email-setup  (cdr (assoc account yt/email-account-list))))
    (funcall email-setup)
    (format "User %s email account" account)))
(yt/email-switch-account "Gmail")

when I sent an email, it will promote and ask for email, I only need type once per Emacs session, also, I can save the password to an .authoty file.

Contacts

[2015-01-23 Fri 17:28]

have problem with BBDB installtion, and use org-contact.el to manage contact. add contactor very easy. I cna use tab to completet contacts, which is really handy.

(require 'org-contacts)
(setq org-contacts-files '("~/git/org/contacts.org"))
(setq mu4e-org-contacts-file "~/git/org/contacts.org")
(add-to-list 'mu4e-headers-actions
             '("add-org-contact" . mu4e-action-add-org-contact) t)
(add-to-list 'mu4e-view-actions
             '("add-org-contact" . mu4e-action-add-org-contact) t)

(defun yt/mu4e-show-org-contact (msg)
  "show the first sender in the org-contact file"
  (let* ((sender (car-safe (mu4e-message-field msg :from))))
    (find-file  mu4e-org-contacts-file)
    (search-forward (car sender))))
(add-to-list 'mu4e-headers-actions
             '("show-org-contact" . yt/mu4e-show-org-contact) t)
(add-to-list 'mu4e-view-actions
             '("show-org-contact" . yt/mu4e-show-org-contact) t)
(defun GetContactGroup (contact-file search-tag contact-type)
  (interactive)
  (let ((name-address (org-map-entries (lambda()
                                 (cons (elt (org-heading-components) 4)  ;; get headline (name) 
                                       (org-entry-get nil contact-type))) ;; get Email/phone etc property 
                               search-tag
                               contact-file)))
    (mapconcat (lambda (a-list)
                  (concat (car a-list) " <" (cdr a-list) ">"))
               name-address ", ")))
(defun yt/get-email-group (search-tag)
  (GetContactGroup org-contacts-files search-tag "EMAIL"))

Workflow

[2015-01-23 Fri 17:28]

I am trying to avoid use C-x m to write/sent email directy, unless it is really short. otherwise, if it relates to a project, I will make an org headline to keep track the project communciation, to do that, I compose email/message in org mode, then sent the whole subtree by C-c M-o.

(require 'org-mime)
(setq org-mime-library 'mml)
(add-hook 'message-mode-hook
          (lambda ()
            (local-set-key "\C-c\M-o" 'org-mime-htmlize)))
;; (add-hook 'org-mode-hook
;;           (lambda ()
;;             (local-set-key "\C-c\M-o" 'org-mime-org-buffer-htmlize)))
(add-hook 'org-mime-html-hook
          (lambda ()
            (insert-file-contents "~/git/.emacs.d/personal/css/office.css")
            ;; (goto-char 5)
            )
          t)


;; (add-hook 'org-mode-hook
;;           (lambda ()
;;             (local-set-key (kbd "C-c M-o") 'org-mime-subtree))
;;           'append)

(add-hook 'org-mode-hook
          (lambda ()
            (local-set-key (kbd "C-c M-o") 'yt/org-mime-subtree)))

(defun yt/mu4e-cc-myself ()
  (goto-char (point-min))
  (search-forward "Subject: ")
  (beginning-of-line)
  (insert "Cc: Yi Tang <yi.tang@jbarisk.com>\n")
  (search-forward "--text follows this line--")
  (forward-char 1))
(defun yt/org-mime-subtree ()
  (interactive)
  (org-mime-subtree)
  (yt/mu4e-cc-myself))

just in case I didn’t get the format right at the first place and need some quick fix in message mode, save me few seconds in going back to org-mode.

(add-hook 'message-mode-hook 'orgstruct++-mode 'append)
(add-hook 'message-mode-hook 'turn-on-auto-fill 'append)
;; (add-hook 'message-mode-hook 'bbdb-define-all-aliases 'append)
(add-hook 'message-mode-hook 'orgtbl-mode 'append)
(add-hook 'message-mode-hook 'turn-on-flyspell 'append)
;; (add-hook 'message-mode-hook
;;           '(lambda () (setq fill-column 270))
;;           'append)

Comprehensive Email

[2015-01-23 Fri 14:36]

Attach and Inline Image I got an email from an estate agency where there are few images are inlined, but also in the attachment. why not just save the attachment online and inline the image as a normal HTML do?

  1. add an png attachment, display it as inline image.

Render LaTeX code as image currently it is broken. the error message is the path issues, and seems the file is not generated.

SNS Client

[2015-08-14 Fri 10:07]

Twitter

[2015-08-14 Fri 10:07]

(setq twittering-use-master-password t)
(setq twittering-icon-mode t)
;; (setq twittering-convert-fix-size 48)
(setq twittering-use-icon-storage t)
;; (setq twittering-retweet-format '(nil _ " %u RT @%s: %t"))

use V to swtich timline, to show replies or direst messages.

when the cursr is in a twitter:

enter
- reply.
d
to sent direct message
u
to post a tweet

Python

[2015-07-05 Sun 19:49]

(add-hook 'python-mode-hook 'flyspell-prog-mode)
(setq python-fill-docstring-style 'django)
(require 'elpy)
(elpy-enable)
(elpy-use-ipython "ipython3")
(setq elpy-rpc-python-command "python3")
(global-set-key (kbd "M-*") 'pop-tag-mark)
(setq elpy-test-discover-runner-command '("python3" "-m" "unittest"))
(setq elpy-rpc-backend "jedi")

;; make elpy more like ESS
(define-key elpy-mode-map (kbd "<C-return>") 'elpy-shell-send-current-statement)
(define-key elpy-mode-map (kbd "<C-c C-f>") 'python-shell-send-defun)
(define-key elpy-mode-map (kbd "<C-c C-b>") 'elpy-shell-send-region-or-buffer)

Refile

voca-builde

(require 'voca-builder)
(setq voca-builder/voca-file "~/git/org/vocabulary.org")
(setq voca-builder/current-tag "General")
;; (global-set-key (kbd "<f4>") 'voca-builder/search-popup)
(setq sentence-end-double-space nil)

weather forecasting

;; sunshine: weather forcaste service
(setq sunshine-units 'metric)
(setq sunshine-location "Keighley, GB")

quickly filter out non-work tasks in org-agenda.

(defun yt/filter-life-agenda (tag)
  (concat "-" "life"))
(defun yt/filter-office-agenda (tag)
  (concat "-" "@office"))
(if (eq system-type 'darwin)
    (setq org-agenda-auto-exclude-function 'yt/filter-office-agenda)
  (setq org-agenda-auto-exclude-function 'yt/filter-life-agenda))

shell mode

;; execute line/region of shell scripts.
;; http://stackoverflow.com/questions/6286579/emacs-shell-mode-how-to-send-region-to-shell
; (require 'shell)

(defun sh-send-line-or-region (&optional step)
  (interactive ())
  (let ((proc (get-process "shell"))
        pbuf min max command)
    (unless proc
      (let ((currbuff (current-buffer)))
        (shell)
        (switch-to-buffer currbuff)
        (setq proc (get-process "shell"))
        ))
    (setq pbuff (process-buffer proc))
    (if (use-region-p)
        (setq min (region-beginning)
              max (region-end))
      (setq min (point-at-bol)
            max (point-at-eol)))
    (setq command (concat (buffer-substring min max) "\n"))
    (with-current-buffer pbuff
      (goto-char (process-mark proc))
      (insert command)
      (move-marker (process-mark proc) (point))
      ) ;;pop-to-buffer does not work with save-current-buffer -- bug?
    (process-send-string  proc command)
    (display-buffer (process-buffer proc) t)
    (when step 
      (goto-char max)
      (next-line))
    ))

(defun sh-send-line-or-region-and-step ()
  (interactive)
  (sh-send-line-or-region t))
(defun sh-switch-to-process-buffer ()
  (interactive)
  (pop-to-buffer (process-buffer (get-process "shell")) t))

(defun yt/sh-script-editing-keybinds ()
  (interactive)
  (local-set-key [(control return)] 'sh-send-line-or-region-and-step)
  ; (local-set-key (kbd "C-c C-z") ''sh-switch-to-process-buffer)         
  )
(add-hook 'sh-mode-hook 'yt/sh-script-editing-keybinds)

End

[2015-01-19 Mon 11:43]

End of Emacs configuration. The initalisetion stop here.