Find files provided by the installed package

dpkg -L emacs # Debian/Ubuntu
pacman -Ql emacs # ArchLinux
rpm -qlp emacs # Redhat/Centos
cygcheck -l emacs # Cygwin
brew ls --verbose emacs # Homebrew
equery f emacs # Gentoo Linux, you need install gentoolkit
gem contents zurb-foundation # Ruby gem

Moving focus and buffer between Emacs window

Please read the excellent article Moving between Emacs windows for basic setup.

Here is my summary of that article:

  • you can use windmove.el (embedded in Emacs). Its hotkey is Shift+Arrow
  • switch-window.el is great. The default hot key is C-x o

I also use other packages which is more efficient.


window-numbering.el is great. It uses hot key M-number to switch window (for example, M-3 to select window with number 3). So I can press only one key to switch window. Besides, it has some extra features like M-0 to jump to the minibuffer.

Here is my configuration for window-numbering.el:

(require 'window-numbering)
;; highlight the window number in pink color
(custom-set-faces '(window-numbering-face ((t (:foreground "DeepPink" :underline "DeepPink" :weight bold)))))
(window-numbering-mode 1)


Evil is a vim-emulation. It use vim's keybindings C-w h/j/k/l to move. Please note C-w h is more efficient than C-x o. It's because w key is more close than x key and h/j/k/l is easy to press.


buffer-move.el moves the buffer instead of focus between windows. It can be installed through MELPA.

Here is my configuration:

(global-set-key (kbd "C-c C-b C-k") 'buf-move-up)
(global-set-key (kbd "C-c C-b C-j") 'buf-move-down)
(global-set-key (kbd "C-c C-b C-h") 'buf-move-left)
(global-set-key (kbd "C-c C-b C-l") 'buf-move-right)


I use keyfreq to record all my key pressing for more than six months.

According to the data collected by keyfreq, more than 99 percent of my moving focus between windows is done through window-numbering.el.

So it's necessary to optimize window-numbering.el further. By default, window-numbering.el uses M-num key to select window which is already efficient. But as a geek, I have a tendency to push the efficiency to the extreme end.

Finally I use hotkey ,1, ,2, and ,3 to switch to the window numbering 1, 2, and 3.

Here is the code:

(define-key evil-normal-state-map ",1" 'select-window-1)
(define-key evil-normal-state-map ",2" 'select-window-2)
(define-key evil-normal-state-map ",3" 'select-window-3)
(define-key evil-normal-state-map ",4" 'select-window-4)

Check my setup at github.

Comment/uncomment line(s) is easy in Emacs

It's easy if you use evil-nerd-commenter because commenting/uncommenting line(s) is only pressing ",ci" in evil-mode.

You can also select text and press M-; to comment the lines in the region. If part of the line is not in the selected, the whole line will still be commented out. This saves your extra key pressing for moving cursor to the beginning of the first line or moving the cursor to the end of the last line.

The reason to make commenting efficient is that I need comment/uncomment code for debug purpose.

Some people say comment out the code is not a right way to debug. The right way is using debugger.

In some huge projects, debugger makes no sense for many reasons:

  • The debugger for that Domain Specific Language simply does not exist
  • Bugs can be reproduced ONLY on production server where debugger is not installed
  • Too much overhead to set up debugger


原创日期: 2013-01-31 四

2012年1月31日我写了一年成为Emacs高手(像神一样使用编辑器) (后文简称<一年>),到今天(2013年1月31日)正好一周年.











这是我的twittergoogle plus以及微博,也可以通过我的email<chenbin DOT sh AT GMAIL DOT COM>联系我.我也在新浪weibo.com上开通账号emacsguru.

Open url in Emacs with external browser

Here is some handy elisp function which use browse-url-generic to open the url in external browser (firefox, for example).

The key point is how to detect the url. If we are in w3m-mode, we will use the link under cursor or the URI of current web page. Or else, we will let browse-url-generic to detect the url.

(defun w3mext-open-link-or-image-or-url ()
  "Opens the current link or image or current page's uri or any url-like text under cursor in firefox."
  (let (url)
    (if (string= major-mode "w3m-mode")
        (setq url (or (w3m-anchor) (w3m-image) w3m-current-url)))
    (browse-url-generic (if url url (car (browse-url-interactive-arg "URL: "))))
(global-set-key (kbd "C-c b") 'w3mext-open-link-or-image-or-url)

To specify the external browser like firefox, add below code into ~/.emacs:

;; `C-h v browse-url-generic-program RET` to see the documentation

;; *is-a-mac* and *linux* is the boolean constants defined by me

(setq browse-url-generic-program
       (*is-a-mac* "open")
       (*linux* (executable-find "firefox"))

Simplest workflow on email git commit in Emacs (No magit needed)

Sometimes I just want to email my trivial patch to the original author and forget it. In this case "github fork" or "git format-patch" is too heavy weight for me.

So here is the simplest workflow I can figure out:

  • Step 1, command "M-x vc-dir" whose hotkey is "C-x v d"
  • Step 2, command "M-x git-print-log" whose hotkey is "C-x v l"
  • Step 3, Move focus to the specific commit and run command "M-x log-view-diff" whose hotkey is "d".
  • Step 4, Yank the commit/diff
  • Step 5, Compose new email (command "M-x compose-mail" whose hotkey is "C-x m")
  • Step 6, Make sure the subject of email start with "[PATCH]". See this patch sumbit guide for reasons.
  • Step 7, Paste the content of commit/diff into email body.
  • Step 8, Send the email by command "M-x message-send-and-exit" whose hotkey is "C-c C-c"

Please note:

  • Step 1 is usually necessary unless you only need the diff of current file.
  • Step 2 and step 3 could be replaced with command "M-x vc-diff" or hotkey "C-x v =" if you want to email the diff of work directory.

Import Gmail contacts into BBDB

  • Go to, click the menu "More>>Export…>>vCard format (blah, blah …)".
  • Click "Export" button. Download the contacts.vcf.
  • Make sure bbdb-vcard.el installed.
  • In Emacs run "M-x bbdb-vcard-import-file" and input the full path of contacts.vcf
  • In Emacs run "M-x bbdb-save"
  • Remove contacts whose names are empty. These are Google Plus people inserted automatically by Gmail:

Run the command in shell:

# the orginal ~/.bbdb will be saved as ~/.bbdb.bak
sed -i.bak '/\["" ""/d' ~/.bbdb

Search at both stackoverflow and google code in Emacs

Two programming sites are most valuable to me:
solution design and code prototype
google code search
code sample from real product

So I write some elisp code w3mext-hacker-search to automate the workflow.

Copy the into ~/.emacs and you can use hotkey "C-c ; s" to open search results in external browser (firefox, for example):

; external browser should be firefox
(setq browse-url-generic-program
       (*is-a-mac* "open")
       (*linux* (executable-find "firefox"))

;; use external browser to search

(defun w3mext-hacker-search ()
  "search word under cursor in google code search and"
  (require 'w3m)
  (let ((keyword (w3m-url-encode-string (thing-at-point 'symbol))))
    (browse-url-generic (concat "" keyword))
    (browse-url-generic (concat "" keyword "" )))

(add-hook 'prog-mode-hook '( lambda () (local-set-key (kbd "C-c ; s") 'w3mext-hacker-search)) )

Toggle http proxy in emacs-w3m

emacs-w3m is a browser which handles all my basic web surfing needs.

For some reason, I need switch my http proxy frequently.

The solution is to set/unset the environment variable "http_proxy" in elisp code. Restarting the w3m session after change the environment variable is not needed at all.

Here is my code:

(defun toggle-env-http-proxy ()
  "set/unset the environment variable http_proxy which w3m uses"
  (let ((proxy ""))
    (if (string= (getenv "http_proxy") proxy)
        ;; clear the proxy
          (setenv "http_proxy" "")
          (message "env http_proxy is empty now"))
      ;; set the proxy
      (setenv "http_proxy" proxy)
      (message "env http_proxy is %s now" proxy))))

Use POPFile at Linux

CREATED: <2012-12-28 Fri>

UPDATED: <2017-03-12 Sun>

POPFile automatically sorts emails.

Install POPFile

Install third party packages


cpan DBD::SQLite DBI Date::Format Date::Parse HTML::Tagset HTML::Template IO::Socket::SSL Net::IDN::Encode Mozilla::CA Encode:IMAPUTF7

When being asked by cpan, say you prefer installing local lib.

My cpan configuration ~/.cpan/CPAN/,

$CPAN::Config = {
  'applypatch' => q[],
  'auto_commit' => q[0],
  'build_cache' => q[100],
  'build_dir' => q[/home/cb/.cpan/build],
  'build_dir_reuse' => q[0],
  'build_requires_install_policy' => q[yes],
  'bzip2' => q[/bin/bzip2],
  'cache_metadata' => q[1],
  'check_sigs' => q[0],
  'colorize_output' => q[0],
  'commandnumber_in_prompt' => q[1],
  'connect_to_internet_ok' => q[1],
  'cpan_home' => q[/home/cb/.cpan],
  'ftp_passive' => q[1],
  'ftp_proxy' => q[],
  'getcwd' => q[cwd],
  'gpg' => q[/usr/bin/gpg],
  'gzip' => q[/bin/gzip],
  'halt_on_failure' => q[0],
  'histfile' => q[/home/cb/.cpan/histfile],
  'histsize' => q[100],
  'http_proxy' => q[],
  'inactivity_timeout' => q[0],
  'index_expire' => q[90],
  'inhibit_startup_message' => q[0],
  'keep_source_where' => q[/home/cb/.cpan/sources],
  'load_module_verbosity' => q[none],
  'make' => q[/usr/bin/make],
  'make_arg' => q[],
  'make_install_make_command' => q[/usr/bin/make],
  'mbuild_arg' => q[--install-dirs site],
  'mbuild_install_arg' => q[./Build],
  'mbuild_install_build_command' => q[./Build],
  'mbuildpl_arg' => q[--installdirs site],
  'no_proxy' => q[],
  'pager' => q[/usr/bin/less],
  'patch' => q[/usr/bin/patch],
  'perl5lib_verbosity' => q[none],
  'prefer_external_tar' => q[1],
  'prefer_installer' => q[MB],
  'prefs_dir' => q[/home/cb/.cpan/prefs],
  'prerequisites_policy' => q[follow],
  'recommends_policy' => q[1],
  'scan_cache' => q[atstart],
  'shell' => q[/bin/bash],
  'show_unparsable_versions' => q[0],
  'show_upload_date' => q[0],
  'show_zero_versions' => q[0],
  'suggests_policy' => q[0],
  'tar' => q[/bin/tar],
  'tar_verbosity' => q[none],
  'term_is_latin' => q[1],
  'term_ornaments' => q[1],
  'test_report' => q[0],
  'trust_test_report_history' => q[0],
  'unzip' => q[/usr/bin/unzip],
  'urllist' => [q[]],
  'use_prompt_default' => q[0],
  'use_sqlite' => q[0],
  'version_timeout' => q[15],
  'wget' => q[/usr/bin/wget],
  'yaml_load_code' => q[0],
  'yaml_module' => q[YAML],

cpan will append setup into ~/.bashrc,

PATH="$HOME/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="$HOME/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_MB_OPT="--install_base \"$HOME/perl5\""; export PERL_MB_OPT;

Double check installed packages:

perl -MDBI -e 'print $MIME::DBI::VERSION'

If there is any error:

perl -V
rm -rf ~/perl5/*
cpan DBD::SQLite DBI Date::Format Date::Parse HTML::Tagset HTML::Template IO::Socket::SSL Net::IDN::Encode MOZILLA::CA


I only use IMAP. The purpose of tweak POP3 port is only to make the program executable without root permission.

See for details.

Run the below command to fix the root issue.

sed -i 's/pop3_port \+110/pop3_port 1110/g' ~/bin/popfile/popfile.cfg

Davmail is a gateway to convert Outlook/Exchange service to IMAP/POP3). It's required if and only if you use Microsoft's Exchange/Outlook.

If you don't use Davmail and fetch mails directly, you'd better set imap_expunge 1 to fix Microsoft Office 365 issue.

Please disable ssl if running local Davmail Server only. Or else, ssl should be enabled.

My popfile setup,

bayes_bad_sqlite_version 4.0.0
bayes_corpus corpus
bayes_database popfile.db
bayes_dbconnect dbi:SQLite:dbname=$dbname
bayes_nihongo_parser kakasi
bayes_sqlite_journal_mode delete
bayes_sqlite_tweaks 4294967295
bayes_subject_mod_left [
bayes_subject_mod_pos 1
bayes_subject_mod_right ]
bayes_unclassified_weight 100
bayes_xpl_angle 0
config_pidcheck_interval 5
config_piddir ./
GLOBAL_debug 1
GLOBAL_last_update_check 1407715200
GLOBAL_message_cutoff 100000
GLOBAL_msgdir messages/
GLOBAL_ssl_verify_peer_certs 0
GLOBAL_timeout 60
GLOBAL_update_check 1
history_archive 0
history_archive_classes 0
history_archive_dir archive
history_history_days 2
html_cache_templates 0
html_column_characters 0
html_columns +inserted,+from,+to,-cc,+subject,-date,-size,+bucket
html_language English
html_last_reset Sat Dec  1 11:06:48 2012
html_local 0
html_page_size 20
html_password b6b3637136ad630eba43aa5ee7106780
html_port 8888
html_search_filter_highlight 0
html_send_stats 1
html_session_dividers 1
html_show_bucket_help 1
html_show_training_help 0
html_skin simplyblue
html_strict_templates 0
html_test_language 0
imap_bucket_folder_mappings job-->job-->geek-->geek-->business-->business-->ad-->ad-->unclassified-->INBOX-->work-->work-->
imap_enabled 1
imap_expunge 1
imap_hostname localhost
imap_login binc1
imap_password password1
imap_port 1143
imap_training_mode 0
imap_uidnexts work-->749-->job-->5914-->INBOX-->20736-->geek-->5009-->ad-->1296-->business-->15-->
imap_uidvalidities job-->98-->work-->107-->ad-->100-->business-->106-->geek-->99-->INBOX-->2-->
imap_update_interval 1000
imap_use_ssl 0
imap_watched_folders INBOX-->INBOX-->
logger_format default
logger_level 0
logger_logdir ./
nntp_enabled 0
nntp_force_fork 1
nntp_headtoo 0
nntp_local 1
nntp_port 119
nntp_separator :
nntp_socks_port 1080
nntp_welcome_string NNTP POPFile (v1.1.3) server ready
pop3_enabled 0
pop3_force_fork 1
pop3_local 1
pop3_port 1110
pop3_secure_port 110
pop3_separator :
pop3_socks_port 1080
pop3_toptoo 0
pop3_welcome_string POP3 POPFile (v1.1.3) server ready
smtp_chain_port 25
smtp_enabled 0
smtp_force_fork 1
smtp_local 1
smtp_port 25
smtp_socks_port 1080
smtp_welcome_string SMTP POPFile (v1.1.3) welcome
xmlrpc_enabled 0
xmlrpc_local 1
xmlrpc_port 8081

The only remaining issue is user name. If it contains "\", you should replace it with "\\" when inputting in Popfile!

Run the program

See for details.

cd ~/bin/popfile;perl

Start the POPFile automatically when bash login

Insert below code in ~/.bashrc:

OS_NAME=`uname -s`
if [ $OS_NAME == Linux ]; then
   # start popfile
   if [ -f $HOME/bin/popfile/ ]; then
      # @see
      pop_pid=`ps -ef | grep perl | grep | gawk '{print $2}'`
      if [ "${pop_pid}" = "" ] ; then
         cd $HOME/bin/popfile
         perl >> /dev/null 2>&1 &
      cd $HOME

Start the POPFile systemd service as a user (OPTIONAL)

My user name is cb. Put popfile.service in usr/lib/systemd/system. Then run `systemctl enable popfile` to install service. Run `systemctl start popfile` to start the service. My Linux distribution is ArchLinux.

here is content of popfile.service.

Description=POPFile (Automatic Email Classification) Service




Please backup popfile.cfg and popfile.db.

See for details.


  • Portable
  • No root privilege needed
  • No X windows needed. I can manage mails in remote shell