Skip to content

Latest commit

 

History

History
4240 lines (3582 loc) · 151 KB

init.org

File metadata and controls

4240 lines (3582 loc) · 151 KB

Yet Another Emacs Configuration

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.

General

Utilities

[2015-01-19 Mon 12:14]

Firstly, define a function for reloading Emacs configuration, need this function in debugging this configuration file.

(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!"))
(setq confirm-kill-emacs 'y-or-n-p)

Life is too short to type “yes” or “no”. ‘y’ or ‘n’ is enough.

(fset 'yes-or-no-p 'y-or-n-p)

Remove Keybind

(global-unset-key (kbd "C-x b"))
(global-unset-key (kbd "C-x C-b"))
(global-unset-key (kbd "C-x C-c"))  ;; save-buffers-kill-terminal
(global-unset-key (kbd "C-x o"))  ;; other window. replace by f2 - ace-window.

Assorted Pieces

[2015-01-19 Mon 12:21]

Automatically backup buffers/files into the working directory and the ~.emacs.d/backup// directory.

;; 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) 

;; use company for all except few modes
(require 'company)
(add-hook 'after-init-hook 'global-company-mode)
;; Don't enable company-mode in below major modes, OPTIONAL
(setq company-global-modes '(not eshell-mode comint-mode erc-mode rcirc-mode))

;; config company mode
(setq company-selection-wrap-around t
      company-tooltip-align-annotations t
      company-idle-delay 0.36
      company-minimum-prefix-length 2
      company-tooltip-limit 10)

(setq company-ddabbrev-code-everywhere t)
(setq company-dabbrev-code-modes t)
(setq company-dabbrev-code-other-buffers 'all)
(setq company-dabbrev-ignore-buffers "\\`\\'")
(setq company-dabbrev-char-regexp "\\(\\sw\\|\\s_\\|_\\|-\\)")

;; config company for ESS mode
(defun yt/ess_company_mode_setup ()
  ;; this is really important. to source vairbales defined in the scripts.
     (make-local-variable 'company-backends)
     (add-to-list 'company-backends 'company-dabbrev-code)
     )
(add-hook 'ess-mode-hook 'yt/ess_company_mode_setup)


(defun text-mode-hook-setup ()
  (make-local-variable 'company-backends)
  (add-to-list 'company-backends 'company-ispell)
  ;; (setq company-ispell-dictionary (file-truename "~/git/.emacs.d/english_words.txt"))
  )

(add-hook 'text-mode-hook 'text-mode-hook-setup)
(company-quickhelp-mode 1)
(define-key company-active-map (kbd "M-h") #'company-quickhelp-manual-begin)
(define-key company-active-map (kbd "M-h") 'company-show-doc-buffer)

(setq company-dabbrev-downcase nil)
(setq company-show-numbers t)

Configure recent opened files. 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)

Shows an notication for invalid operations.

(setq visible-bell nil) 
(setq ring-bell-function 'ignore)

Disable startup message

(setq inhibit-startup-message t)        

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)
(add-to-list 'yas/snippet-dirs "~/git/.emacs.d/snippets" t)
(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 F2.

(require 'ace-window)
(global-set-key (kbd "<f2>") 'ace-window)
(global-set-key (kbd "M-o") '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)

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.

[2016-06-20 Mon 21:43] helm-find-files has open with default tool functionality. This block is no longer needed.

;; (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)

Modern display is widen. Like many of the Emacs users, I prefer to have the text wrapper inside a small region rather than have a stretch across the whole screen. It’s easier to read in this way.

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.

[2016-06-20 Mon 21:47] Can’t remember when was the last time I use unfill. This snippet is not long used.

(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

Let Emacs remember what I’ve typed, so I don’t need to tediously type the whole thing. Most of the time, I could just select using helm.

(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 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.

Recently I found menu-bar is really useful, it shows commonly used functions for a particular mode. Occasionally I found something useful.

(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.

leuven theme is highly customised for org-mode and I like to use it when my eyes are tired of the zenburn theme.

;; (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)

(defun yt/helm-copy-unmarked-to-buffer ()
  (interactive)
  (with-helm-buffer
    (helm-mark-all)
    (cl-loop for cand in (helm-marked-candidates)
             do (with-helm-current-buffer
                  (insert cand "\n")))))
;; by default, Cc Ci copy marked to buffer.
(define-key helm-map (kbd "C-c C-i") 'helm-copy-unmmarked-to-buffer)

(setq helm-ff-guess-ffap-urls nil)

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->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)

;; (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)))))
      (kill-new file-truename))))

Open a file as a root user 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
open with _e_xternal application
_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)
  ("e" prelude-open-with)
  ("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)
(projectile-mode +1)
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
(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:remote_host:/remote_directory")
;;   ;; (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 t)

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 "~/tmp"
  "temporay folders")

(defun yt/open-tmp-R ()
  (interactive)
  (find-file (expand-file-name "tmp.R" yt/temp-dir)))
(defun yt/open-tmp-el ()
  (interactive)
  (find-file (expand-file-name "tmp.el" yt/temp-dir)))
(defun yt/open-tmp-org ()
  (interactive)
  (find-file (expand-file-name "tmp.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" (find-file "~/git/career/Profession/R.org") "R.org")
  ("p" (find-file "~/git/career/Profession/Python.org") "Python.org")
  ("E" (find-file "~/git/career/Profession/Emacs.org") "Emacs.org") 
  ("l" (find-file "~/git/org/life/life.org") "life.org")
  ("i" (find-file "~/git/.emacs.d/init.org" t) "init.org")
  ("e" (find-file "~/.emacs" t) ".emacs")
  ("d" (yt/org-find-file "dournal/diary.org") "diary.org")
  ("r" (yt/org-find-file "life/review.org") "review.org")
  ("f" (yt/org-find-file "finance/ledger_transaction_2019.org") "ledger.org")
  )
(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)


(define-key ess-r-mode-map "_" #'ess-insert-assign)
(define-key inferior-ess-r-mode-map "_" #'ess-insert-assign)

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)

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]

Define in auto-complete section.

Run R script using subprocess

(defun yt/bash_run_R ()
     (interactive)
     (let* ((args (concat "R --no-save --no-restore < " (file-name-nondirectory (buffer-file-name))))
            (output-buf-name (concat "*R:" (file-name-nondirectory (buffer-file-name)) "*"))
            )
       (async-shell-command args output-buf-name)
       (with-current-buffer output-buf-name
         (inferior-ess-mode))
       ))

Code navigation

;; (visit-tags-table "~/R_tags")

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.

(require 'flyspell)
(add-hook 'text-mode-hook 'flyspell-mode)
(add-hook 'org-mode-hook 'flyspell-mode)
(define-key flyspell-mode-map (kbd "C-.") 'helm-flyspell-correct)

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
mailme[email protected]aboutme
twitterme@yi_tang_ukaboutme
eqtequivalent toenglish
iifif and only ifmaths
wrtwith respect toEnglish
stsuch thatEnglish
d/ndistributionStats
obsobservationstats
obssobservationsstats

:value 2

;; (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@/!)" "RUNNING(r)" "|" "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)
	       ("RUNNING" :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/life//refile.org")
               "* TODO %?\n\n" :clock-in t :clock-resume t) ;; TODO: %? %U %a, what does these means??? %: %c
              ("o" "org" entry (file "~/git/org/life//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/life//refile.org")
              ;;  "* To %? about :RESPONSE:  \nSCHEDULED: %t\n%U\n%a" :clock-in t :clock-resume t)
              ("r" "read" entry (file "~/git/org/life//refile.org")
               "* TODO %? :READ:\n%U\n" :clock-in t :clock-resume t)
              ("n" "note" entry (file "~/git/org/life//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_transaction_2019.org")
	       "%(org-read-date) * %^{Payee}\n\t%^{Account}\t£ %^{Amount}\n\tAssets:%^{Checking}" )
              ("v" "Vocabulary" entry (file "~/git/org/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")
               "* %?\n%U\n" :clock-in t :clock-resume t)
	      ("jf" "Finance" entry (file+datetree "~/git/org/journal/Finance.org")
               "* %?\n%U\n" :clock-in t :clock-resume t)
	      ("jc" "Career" entry (file+datetree "~/git/org/journal/Career.org")
               "* %?\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
      '((nil :maxlevel . 3)
        (org-agenda-files :maxlevel . 3)))
(setq org-outline-path-complete-in-steps nil)

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)

remove empty clock entrys at checkout

(add-hook 'org-clock-out-hook 'org-clock-remove-empty-clock-drawer 'append)

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))
(global-set-key (kbd "<f9> t") 'bh/insert-inactive-timestamp)

(defun yt/insert-ts-as-file ()
    (interactive)
  (insert (format-time-string "%Y-%m-%d--%H-%M-%S"))
  )

(global-set-key (kbd "<f9> T") 'yt/insert-ts-as-file)

(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\\'" . emacs)
                            ("\\.svg\\'" . system)
                            ("\\.mm\\'" . system)
                            ("\\.x?html?\\'" . system)
                            ("\\.pdf\\'" . system))))
                                        ; 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]

  ;; recursively find .org files in provided directory
  ;; modified from an Emacs Lisp Intro example
  (defun sa-find-org-file-recursively (&optional directory filext)
    "Return .org and .org_archive files recursively from DIRECTORY.
  If FILEXT is provided, return files with extension FILEXT instead."
    (interactive "DDirectory: ")
    (let* (org-file-list
           (case-fold-search t)         ; filesystems are case sensitive
           (file-name-regex "^[^.#].*") ; exclude dot, autosave, and backup files
           (filext (or filext "org$\\\|org_archive"))
           (fileregex (format "%s\\.\\(%s$\\)" file-name-regex filext))
           (cur-dir-list (directory-files directory t file-name-regex)))
      ;; loop over directory listing
      (dolist (file-or-dir cur-dir-list org-file-list) ; returns org-file-list
        (cond
         ((file-regular-p file-or-dir) ; regular files
          (if (string-match fileregex file-or-dir) ; org files
              (add-to-list 'org-file-list file-or-dir)))
         ((file-directory-p file-or-dir)
          (dolist (org-file (sa-find-org-file-recursively file-or-dir filext)
                            org-file-list) ; add files found to result
            (add-to-list 'org-file-list org-file)))))))

  (setq org-agenda-files (append (sa-find-org-file-recursively "~/git/org")
                                 (sa-find-org-file-recursively "~/git/career")))

  (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 ()  ;; FIXME: path broken.
    (helm :sources '(((name . "Add directories to org-agenda-files variable")
                      (candidates . ("~/git/org/" "~/git/career" "~/git/org/finance"))
                      (action . yt/org-agenda-files--choose)))))

(defun yt/org-agenda-files-set ()
  (interactive)
  (setq org-agenda-files (list))
  (dolist (dir (yt/org-agenda-files-set-helm))
    (mapcar (lambda (arg)
	      (add-to-list 'org-agenda-files arg))
	    (sa-find-org-file-recursively dir))    
	    ))   


	    ;; (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 "<C-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 require-timed)
 (800 1000 1200 1400 1600 1800 2000)
 "......" "----------------")))

;; (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)

agenda reminder

;; Erase all reminders and rebuilt reminders for today from the agenda
(defun bh/org-agenda-to-appt ()
  (interactive)
  (setq appt-time-msg-list nil)
  (setq appt-display-format 'window) ;; YT: show notification in separate window
  (org-agenda-to-appt))

                                        ; Rebuild the reminders everytime the agenda is displayed
(add-hook 'org-finalize-agenda-hook 'bh/org-agenda-to-appt 'append)

                                        ; This is at the end of my .emacs - so appointments are set up when Emacs starts
(bh/org-agenda-to-appt)

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

External Links

(global-set-key (kbd "C-c l") 'org-store-link)

Babel

[2015-01-29 Thu 14:16]

;;;; * org-babel 
(setq org-src-window-setup 'current-window)
(setq org-src-fontify-natively nil)
(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)
	 (ipython .t)
         (octave . t)
         (latex . t)
	 (ipython . t)
         (sql . t))))

(setq org-babel-default-header-args (append org-babel-default-header-args '((:colnames . "yes"))))

;; (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 t
      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}
\\hypersetup{
     colorlinks   = true,
     citecolor    = gray
}
\\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}
\\usepackage{amsthm}

\\theoremstyle{definition}
\\newtheorem{definition}{Definition}[section]% Conjecture is numbered
                                % within \section
\\newtheorem{lemma}[definition]{Lemma}
\\newtheorem{theorem}[definition]{Theorem}

\\newcommand{\\twodots}{\\mathinner {\\ldotp \\ldotp}}

%% \\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")

(add-to-list 'org-latex-classes
             '("beamer"
               "\\documentclass\[presentation\]\{beamer\}
\\usepackage[T1]{fontenc}
\\usepackage{fontspec}
\\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{minted}
[NO-DEFAULT-PACKAGES]
[NO-PACKAGES]
"
               ("\\section\{%s\}" . "\\section*\{%s\}")
               ("\\subsection\{%s\}" . "\\subsection*\{%s\}")
               ("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}")))

(require 'ox-beamer)

;; 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 nil)
(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:[email protected]\">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_export html
---
layout: post
title: %s
excerpt: 
categories:
  -  
tags:
  -
comments: true 
---
#+END_export

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

# #+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_export html
{%% highlight %s %%}"
  "%s will be replaced by the language identifier")

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

(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"))))

(add-hook 'LaTeX-mode-hook #'outline-minor-mode)
(require 'company-auctex)
(company-auctex-init)
;;; 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  '(("/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 "[email protected]"
         user-mail-address "[email protected]"
         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: [email protected]\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 "[email protected]"
          
          user-mail-address "[email protected]" 
          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")))

(setq yt/email-account-list
      '(
        ("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 <[email protected]>\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)
(add-hook 'python-mode-hook 'elpy-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-statement-and-step)
(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)
(setq python-shell-interpreter "ipython"
      python-shell-interpreter-args "--simple-prompt --pprint")

;; (setq python-shell-interpreter "ipython3"
;;       python-shell-interpreter-args "-i")


;; (setq python-shell-interpreter "jupyter"
;;       python-shell-interpreter-args "console --simple-prompt"
;;       python-shell-prompt-detect-failure-warning nil)
;; (add-to-list 'python-shell-completion-native-disabled-interpreters
;;              "jupyter")

;; for new elpy version
(setq elpy-shell-starting-directory 'current-directory)
(setq elpy-rpc-virtualenv-path 'current)

Python for data analysis

this allows me to run multiple python process and switch between them.

 (setq elpy-dedicated-shells nil)   ; Ensure no conflict with dedicated shells

 (defvar elpy-shell-python-shell-names '("Python")
	 "List of existing python shell names.")

 (defun elpy-shell-switch-python-shell (&optional dont-display)
	 "Switch to another Python shell.

 Create a new one if it does not exist.
 If DONT-DISPLAY is non nil, do not display the python shell afterwards."
	 (interactive)
	 (let ((shell-name (completing-read "Python shell name: "
										'elpy-shell-python-shell-names)))
	   (setq python-shell-buffer-name shell-name)
	   (add-to-list 'elpy-shell-python-shell-names shell-name t)
	   (when (not dont-display)
		 (elpy-shell-display-buffer))))

 (define-key elpy-mode-map (kbd "C-c C-s") 'elpy-shell-switch-python-shell)

Sphinx-doc for documentation

[2016-06-03 Fri 15:33]

(cl-defstruct sphinx-doc-doc
  (summary "FIXME: briefly describe function") ; summary line that fits on the first line
  before-fields                                ; list of comments before fields
  after-fields                                 ; list of comments after fields
  fields)                                      ; list of field objects

(add-hook 'python-mode-hook (lambda ()
                              ;; (require 'sphinx-doc)
                              (sphinx-doc-mode t)))

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)

open this gnome-terminal here

(defun yt/open-terminal ()
  (interactive)
  (shell-command (concat "gnome-terminal "
                         "--working-directory="
                         (file-truename default-directory)
                         )))
;; (global-set-key (kbd "<f5>") 'yt/open-terminal)

use swiper to replace default isearch

(global-set-key "\C-s" 'swiper)

use snakemake-mode for smake file.

(add-to-list 'auto-mode-alist '("sfile" . snakemake-mode))
(defun yt/sh-chunk-args ()
(interactive)
(replace-string " -" " \\\n -")
)

insert git sha1 value into current point.

(defun yt/insert-git-hash-value ()
  (interactive)
  (insert (shell-command-to-string (concat "git rev-parse HEAD"))))
(global-set-key (kbd "<f9> s") 'yt/insert-git-hash-value)

open buffer with external application

[2016-06-20 Mon 16:34]

(defun prelude-open-with (arg)
  "Open visited file in default external program.

With a prefix ARG always prompt for command to use."
  (interactive "P")
  (when buffer-file-name
    (shell-command (concat
                    (cond
                     ((and (not arg) (eq system-type 'darwin)) "open")
                     ((and (not arg) (member system-type '(gnu gnu/linux gnu/kfreebsd))) "xdg-open")
                     (t (read-shell-command "Open current file with: ")))
                    " "
                    (shell-quote-argument buffer-file-name)))))

C++

eshell

(defalias 'open 'find-file)


;; from emacs-reddit
;; (defun eshell-here ()
;;   "Opens up a new shell in the directory associated with the current buffer's file."
;;   (interactive)
;;   (let* ((parent (file-name-directory (buffer-file-name)))
;;          (name   (car
;;                   (last
;;                    (split-string parent "/" t)))))
;;     (split-window-vertically)
;;     (other-window 1)
;;     (eshell "new")
;;     (rename-buffer (concat "*eshell: " name "*"))

;;     (insert (concat "ls"))
;;     (eshell-send-input)))

(defun eshell-here ()
  "Opens up a new shell in the directory associated with the current buffer's file."
  (interactive)
  (let* ((parent (if (buffer-file-name)
                     (file-name-directory (buffer-file-name))
                   default-directory))
         (name (car (last (split-string parent "/" t)))))
    (split-window-vertically)
    (other-window 1)
    (eshell "new")
    (rename-buffer (concat "*eshell: " name "*"))

    (insert (concat "ls"))
    (eshell-send-input)))

(global-set-key (kbd "C-!") 'eshell-here)

(defun delete-single-window (&optional window)
  "Remove WINDOW from the display.  Default is `selected-window'.
If WINDOW is the only one in its frame, then `delete-frame' too."
  (interactive)
  (save-current-buffer
    (setq window (or window (selected-window)))
    (select-window window)
    (kill-buffer)
    (if (one-window-p t)
        (delete-frame)
      (delete-window (selected-window)))))

(defun eshell/x (&rest args)
  (delete-single-window))


move region/line up or donw/

[2019-03-24 Sun 19:51]

(defun move-line-up ()
  "Move up the current line."
  (interactive)
  (transpose-lines 1)
  (forward-line -2)
  (indent-according-to-mode))

(defun move-line-down ()
  "Move down the current line."
  (interactive)
  (forward-line 1)
  (transpose-lines 1)
  (forward-line -1)
  (indent-according-to-mode))

(global-set-key [(meta up)]  'move-line-up)
(global-set-key [(meta down)]  'move-line-down)

agenda

[2019-03-24 Sun 19:52]

(setq yt/org_folder '("~/git/org/" "~/git/career"))

(setq yt/kaggle_competition_folders '(;; "~/kaggle"
				      "~/quickdraw-doodle-recognition/notebook"
				      "~/two_sigma_financial_news/notebooks"))

(setq yt/org_agenda_folder_candidates (append yt/org_folder yt/kaggle_competition_folders))


(defun yt/org-agenda-files-set-helm ()  ;; FIXME: path broken.
  (helm :sources '(((name . "Add directories to org-agenda-files variable")
		    (candidates . yt/org_agenda_folder_candidates)   ;; ("~/git/org/" "~/git/career"))
		    (action . yt/org-agenda-files--choose)))))
   

running Emacs in terminal

[2019-04-01 Mon 21:43]

later i found that Emacs runs much faster in Terminal. for the reason i don’t know but I really enjoy the lightning speed. here’s a selection of confugratino for working Emacs in terminal.

(add-hook 'suspend-hook
	     (lambda () (or (y-or-n-p "Really suspend? ")
			    (error "Suspend canceled"))))
(add-hook 'suspend-resume-hook (lambda () (message "Resumed!")
				    (sit-for 2)))

then fg to bring back emacs.

highlight TODO, IMP in text mode

[2019-10-13 Sun 04:46]

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

move region up/down

[2019-11-09 Sat 11:52]

(defun move-text-internal (arg)
   (cond
    ((and mark-active transient-mark-mode)
     (if (> (point) (mark))
            (exchange-point-and-mark))
     (let ((column (current-column))
              (text (delete-and-extract-region (point) (mark))))
       (forward-line arg)
       (move-to-column column t)
       (set-mark (point))
       (insert text)
       (exchange-point-and-mark)
       (setq deactivate-mark nil)))
    (t
     (beginning-of-line)
     (when (or (> arg 0) (not (bobp)))
       (forward-line)
       (when (or (< arg 0) (not (eobp)))
            (transpose-lines arg))
       (forward-line -1)))))

(defun move-text-down (arg)
   "Move region (transient-mark-mode active) or current line
  arg lines down."
   (interactive "*p")
   (move-text-internal arg))

(defun move-text-up (arg)
   "Move region (transient-mark-mode active) or current line
  arg lines up."
   (interactive "*p")
   (move-text-internal (- arg)))

(global-set-key [\M-\S-up] 'move-text-up)
(global-set-key [\M-\S-down] 'move-text-down)

End

[2015-01-19 Mon 11:43]

End of Emacs configuration. The initalisetion stop here.

Update Emacs library

cask install --path ~/git/.emacs.d
cask upgrade-cask --path ~/git/.emacs.d
git add -A 
git commit -m "cask update $(date)"
git push 
#+call: UpdateEmacsPackages()

#+results:
: [master 3f5c750] cask update Sat Nov  8 18:06:08 GMT 2014
:  2 files changed, 7 insertions(+), 3 deletions(-)
:  delete mode 120000 .#yi.babel.org