#+TITLE: My Dotfiles in Org mode #+CATEGORY: dotfiles * Table of Contents :TOC_1: - [[#meta][Meta]] - [[#passwords][Passwords]] - [[#bash][Bash]] - [[#isync][isync]] - [[#offlineimap][OfflineIMAP]] - [[#notmuch][Notmuch]] - [[#git][Git]] - [[#ssh][SSH]] - [[#gnupg][GnuPG]] - [[#nano][nano]] - [[#wget][Wget]] * Meta :dotfiles: ** How to use this file? - To extract dotfiles (such as ~~/.bash_profile~) from this file, type ~C-c C-v t~ (~org-babel-tangle~) in Emacs. - To propagate changes in dotfiles (such as ~~/.bash_profile~) to this file, type ~M-x org-babel-detangle~ in Emacs. ** DONE Safer ~org-babel-tangle~ Use the following command instead of ~org-babel-tangle~ to avoid overriding exist files. Notes that - it doesn't respect :tangle-mode if the exiting file has different mode bits with :tangle-mode. - it might not work with remote file #+BEGIN_SRC emacs-lisp :results silent :lexical yes (defun chunyang-org-babel-tangle (&optional arg target-file lang) "Like `org-babel-tangle' but don't override without permission." (declare (interactive-only org-babel-tangle)) (interactive "P") (require 'ob-tangle) (require 'seq) (require 'cl-lib) (save-some-buffers) (let* ((tmpdir (let ((dir "/tmp/org-babel-tangle/")) (or (file-exists-p dir) (make-directory dir)) dir)) (mkbak (lambda (filename) (expand-file-name (replace-regexp-in-string "/" "!" (expand-file-name filename)) tmpdir))) (diffp (lambda (file-a file-b) (/= 0 (call-process diff-command nil nil nil (expand-file-name file-a) file-b)))) (swap (lambda (file-a file-b) (let ((tmp (make-temp-name tmpdir))) (copy-file file-a tmp t t t t) (copy-file file-b file-a t t t t) (copy-file tmp file-b t t t t)))) deleted-files tangled-files (advice (define-advice delete-file (:around (old-fun filename &rest args) dont-delete) (push filename deleted-files) (copy-file filename (funcall mkbak filename) t t t t) (apply old-fun filename args)))) (unwind-protect (progn (setq tangled-files (org-babel-tangle arg target-file lang) deleted-files (nreverse deleted-files)) (cl-loop for f in (seq-intersection deleted-files tangled-files) for bak = (funcall mkbak f) do (funcall swap f bak) (if (funcall diffp f bak) (with-current-buffer (find-file-noselect f) (message "Diff %s..." f) (delete-region (point-min) (point-max)) (insert-file-contents bak)) (message "Skip %s..." f)) finally (save-some-buffers))) (advice-remove 'delete-file advice)))) #+END_SRC ** Resources - [[https://dotfiles.github.io/][GitHub does dotfiles - dotfiles.github.io]] - [[https://github.com/webpro/awesome-dotfiles][webpro/awesome-dotfiles: A curated list of dotfiles resources.]] - [[https://github.com/mathiasbynens/dotfiles][mathiasbynens/dotfiles: .files, including ~/.macos — sensible hacker defaults for macOS]] * Passwords :passwords: :PROPERTIES: :CRYPTKEY: mail@xuchunyang.me :END: To view and edit these passwords, type ~M-x org-encrypt-entries~. During ~org-babel-tangle~, it might be too annoying by asking for which key to use for encryption each time, use the following work-around to bypass it. #+BEGIN_SRC emacs-lisp :results silent :lexical yes (require 'org-crypt) (setq org-crypt-key "mail@xuchunyang.me") (define-advice org-babel-tangle (:around (old-fun &rest r) shutup-epa-file) "Shut up epa-file. `epa-file' will prompt for which key to use for encryption each time if `epa-file-encrypt-to' is not set locally, however it looks like local variables embedded in comment will not applied during org-tangle." (with-current-buffer (current-buffer) (cl-assert (eq major-mode 'org-mode)) (let (before-save-hook return) (org-decrypt-entries) (save-buffer) (define-advice write-region (:before (&rest r) set-epa-file-encrypt-to) (setq-local epa-file-encrypt-to org-crypt-key)) (unwind-protect (setq return (apply old-fun r)) (advice-remove 'write-region #'write-region@set-epa-file-encrypt-to)) (org-encrypt-entries) (save-buffer) return))) #+END_SRC ** ~/.authinfo.gpg :crypt: :PROPERTIES: :header-args: :tangle ~/.authinfo.gpg :comments link :tangle-mode '#o600 :END: -----BEGIN PGP MESSAGE----- Version: GnuPG v2 hQIMA+LcwErZWE+CARAAkDKQp7aAUKRDjy3cRYyG+FfVZCSBWG4yYz41kXa51mfV Qd21dUflyoCxnT1XizaXhzHnuIXEShxXzdJOUyTD8aL1Bc2GexZUs/jWZiZpGESq nuYvfNTeOUbXQW3Ub8Q4NngjR+xoOrupt64DVYPaFi5LsQeDYDHdoUHszjLuilCF 1pkkwowOBKrIxpRbznNts+4dD6TGdFyfIlowcds9PoNKWV6iFzqARmgVkKvyAv54 F7neoaMbIcdbymj+euR/abE4pTH0Su/mHmm1oat9vh9RWFlH4RF1rrsJgjXkxX0F NWmPJgb9thYVEY7Ooijj+10Pd1NGWpNCE9+3HUsVKONDMW/PvX29Ve4QFqIdMmte fqFlE/SVBAkdMLmVB9y53lcZxrpE22LVsv4GQrzPw5K77AnO8sWzxEd8k/ijqJco Jvox/jOm0XaZO2bUa7KUnz1J1l/aDvnfHw/iWeg25S5/86sU3QXXbN2heuHq46NL b0GkCb06EL2Xq/b3BSDoJXY57BuROl2FQXhBxPNYzmjKKbEL4qQ98j49ny2hWtSd gud9IDxIVwqU1pfKSQ2eUm9kBzYWzhbKa8zHcHpYr4GnLoeK6tdZclvcmThqbOu8 pcoW4e4ouTxGLmH2E91XACrSV1AUcm1hKrAaozsStlP+o6WJuCj9h8AQJVG/3MDS wFUBbA/dWHGZl4ZXIq6JqRRPqSqA9JzxpA/xJCLy+USav7U7G9lABDbSR0GUeSI+ dlnSjFHa01pIkgrb26rWThYnGVBeEJPQyqp7rwfDX2nLX2AZA/EErMeNQCCaAzFk PI5hTOkFME3G00wyWnczBTbfVjXUWbBYfqtJLYpN12ZvNG0z2sy4TWQb3YWcSNIa dyxXsmGyIXYWCUpfh21qqCPm+KxeVg6CmXPgESmUWb31Y3aC5YvmR2ABYyTCqqby 6XlsI00xj9YeTK5xmqchSXcjHdHWUGAq9IEVSgL3hp9ET33r1l42zd3aHJqmiaFm xmMzK1KWgt5jJYKKz1snAgCCFdGq3fx6Dh4fcIv40HwTa/yDGvVV =PH15 -----END PGP MESSAGE----- * Bash :bash: :PROPERTIES: :header-args:bash: :tangle ~/.bash_profile :comments link :END: ** Meta *** TODO 学习 Bash 变量(全局本地)、判断、控制结构、函数。 [[https://github.com/javier-lopez/learn/tree/master/sh][learn/sh at master · javier-lopez/learn]] *** Resources **** Style Guides - [[https://google.github.io/styleguide/shell.xml][Google Shell Style Guide]] - [[https://github.com/bahamas10/bash-style-guide][bahamas10/bash-style-guide: A style guide for writing safe, predictable, and portable bash scripts (not sh!)]] **** Guides - [[http://tldp.org/LDP/abs/html/][Advanced Bash-Scripting Guide]] - [[http://wiki.bash-hackers.org/start][The Bash Hackers Wiki {Bash Hackers Wiki}]] **** Tools - [[https://github.com/Bash-it/bash-it][Bash-it/bash-it: A community Bash framework.]] - [[https://github.com/koalaman/shellcheck][koalaman/shellcheck: ShellCheck, a static analysis tool for shell scripts]] ** ~~/.bashrc~ vs ~~/.bash_profile~ Don't use [[file:~/.bashrc][file:~/.bashrc]] to keep configuration, use [[file:~/.bash_profile][file:~/.bash_profile]] instead. #+BEGIN_SRC bash :tangle ~/.bashrc :comments link # The variable PS1 is unset in non-interactive shells: # [[https://www.gnu.org/software/bash/manual/html_node/Is-this-Shell-Interactive_003f.html][Bash Reference Manual: Is this Shell Interactive?]] if [ -z "$PS1" ]; then # This shell is not interactive source ~/.path else # This shell is interactive source ~/.bash_profile fi #+END_SRC ** OS detection #+BEGIN_SRC bash function is_mac () { [[ "$OSTYPE" =~ ^darwin ]] } function is_gnu_linux () { [[ "$OSTYPE" == linux-gnu ]] } #+END_SRC ** Helper #+BEGIN_SRC bash function source_maybe () { local file="$1" [ -r "$file" ] && [ -f "$file" ] && source "$file" } #+END_SRC ** Startup #+BEGIN_SRC bash # Add `~/bin` to the `$PATH` export PATH="$HOME/bin:$PATH" # Load the shell dotfiles, and then some: # * ~/.path can be used to extend `$PATH`. # * ~/.extra can be used for other settings you don’t want to commit. for file in ~/.{path,bash_prompt,exports,aliases,functions,extra}; do source_maybe "$file" done unset file #+END_SRC ** ~$PATH~ in [[file:~/.path][file:~/.path]] Here’s an example ~~/.path~ file that adds ~/usr/local/bin~ to the ~$PATH~: #+BEGIN_SRC bash :tangle no export PATH="/usr/local/bin:$PATH" #+END_SRC ** Prompt #+BEGIN_SRC bash # Looks like "~$ " in $HOME ("~" is in blue) PS1="\[\e[34m\]\w\[\e[m\]\\$ " #+END_SRC ** Other Environment variables in [[file:~/.exports][file:~/.exports]] #+NAME: exports #+BEGIN_SRC bash :tangle ~/.exports :comments link :shebang "#!/usr/bin/env bash" :tangle-mode (identity #o644) # Make Emacs the default editor. export EDITOR='emacsclient' export VISUAL='emacsclient' # Enable support of searching Chinese for Notmuch export XAPIAN_CJK_NGRAM=1 #+END_SRC ** Aliases in [[file:~/.aliases][file:~/.aliases]] #+NAME: aliases #+BEGIN_SRC bash :tangle ~/.aliases :comments link :shebang "#!/usr/bin/env bash" :tangle-mode (identity #o644) # Detect which `ls` flavor is in use if ls --color > /dev/null 2>&1; then # GNU `ls` colorflag="--color=auto" export LS_COLORS='no=00:fi=00:di=01;31:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.ogg=01;35:*.mp3=01;35:*.wav=01;35:' else # macOS `ls` colorflag="-G" export LSCOLORS='BxBxhxDxfxhxhxhxhxcxcx' fi # List all files colorized in long format alias l="ls -lF ${colorflag}" # List all files colorized in long format, including dot files alias la="ls -laF ${colorflag}" # List only directories alias lsd="ls -lF ${colorflag} | grep --color=never '^d'" # Always use color output for `ls` alias ls="command ls ${colorflag}" # Enable aliases to be sudo’ed alias sudo='sudo ' # Stopwatch alias timer='echo "Timer started. Stop with Ctrl-D." && date && time cat && date' # Reload the shell (i.e. invoke as a login shell) alias reload="exec $SHELL -l" # Print each PATH entry on a separate line alias path='echo -e ${PATH//:/\\n}' # Use color with Grep alias grep="command grep --color=auto" # Cat with syntax highlight alias e2ansi-cat="$HOME/src/e2ansi/bin/e2ansi-cat" #+END_SRC ** Completion #+BEGIN_SRC bash # Add tab completion for many Bash commands (MacPorts) if is_mac && [ -f /opt/local/etc/profile.d/bash_completion.sh ]; then . /opt/local/etc/profile.d/bash_completion.sh elif is_gnu_linux && [ -f /usr/share/bash-completion/bash_completion ]; then . /usr/share/bash-completion/bash_completion fi #+END_SRC *** Personal bash completion in [[file:~/.bash_completion][file:~/.bash_completion]] #+NAME: personal_bash_completion #+BEGIN_SRC bash :tangle ~/.bash_completion :comments link command -v pandoc &>/dev/null && eval "$(pandoc --bash-completion)" # Use a custom version: 1) enable git-ls-files 2) support the alias dotfiles # cp /usr/share/bash-completion/completions/git ~/.git-completion.bash source_maybe "~/.git-completion.bash" source_maybe "/Applications/Docker.app/Contents/Resources/etc/docker.bash-completion" _emacs () { local cur prev opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" opts='--help --version -L --directory --l --load --script --daemon --debug-init -Q --reverse-video --no-desktop --no-window-system --batch --eval --funcall' case $prev in --help|--version) return ;; -L|--directory) COMPREPLY=( $(compgen -d ${cur}) ) return ;; -l|--load|--script) COMPREPLY=( $(compgen -f ${cur}) ) return ;; esac COMPREPLY=( $(compgen -f -W "${opts}" -- ${cur}) ) } complete -F _emacs emacs _emacsclient () { local cur prev opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" opts=' --version --help --tty --create-frame --eval --no-wait --quiet --socket-name --server-file --alternate-editor ' COMPREPLY=( $(compgen -f -W "${opts}" -- ${cur}) ) } complete -F _emacsclient emacsclient #+END_SRC ** History The following settings of Bash history is copied from [[https://sanctum.geek.nz/arabesque/better-bash-history/][Better Bash history | Arabesque]]. #+BEGIN_SRC bash # Append history instead of rewriting it shopt -s histappend # Allow a larger history file HISTFILESIZE=1000000 HISTSIZE=1000000 # Don’t store specific lines HISTCONTROL='ignorespace:ignoredups' HISTIGNORE='pwd:ls:bg:fg:history' # Record timestamps HISTTIMEFORMAT='%F %T ' # Use one command per line shopt -s cmdhist # Store history immediately PROMPT_COMMAND='history -a;' #+END_SRC Select history with [[https://github.com/peco/peco][peco]] (base on [[http://qiita.com/comutt/items/f54e755f22508a6c7d78][bash/zsh のヒストリを peco で便利にする - Qiita]]): #+BEGIN_SRC bash peco-select-history () { declare l=$(HISTTIMEFORMAT= history | tac | peco --query "$READLINE_LINE" | cut -c 8-) READLINE_LINE="$l" READLINE_POINT=${#l} } bind -x '"\C-r": peco-select-history' #+END_SRC See also [[https://github.com/junegunn/fzf/wiki/examples#command-history][Examples · junegunn/fzf Wiki]] and [[https://github.com/peco/peco/wiki/Sample-Usage][Sample Usage · peco/peco Wiki]]. *** TODO Read [[https://sanctum.geek.nz/arabesque/better-bash-history/][Better Bash history | Arabesque]] again ** Change directory #+BEGIN_SRC bash # Enable some Bash 4 features when possible: # * `autocd`, e.g. `**/qux` will enter `./foo/bar/baz/qux` # * Recursive globbing, e.g. `echo **/*.txt` for option in autocd globstar; do shopt -s "$option" 2> /dev/null done #+END_SRC Setup [[https://github.com/rupa/z][rupa/z: z - jump around]]: #+BEGIN_SRC bash if is_mac; then file=/opt/local/etc/profile.d/z.sh elif is_gnu_linux; then file=/etc/profile.d/z.sh fi if [ -f "$file" ]; then source "$file" else echo "Can't source $file, install it from " fi unset file #+END_SRC ** Emacs [[file:~/.emacs.d/misc/emacs.sh][file:~/.emacs.d/misc/emacs.sh]] includes shell functions to launch Emacs's functions (such as Magit and ~C-x C-f~) inside Shell/Terminal. #+BEGIN_SRC bash source ~/.emacs.d/misc/emacs.sh #+END_SRC ** iTerm2 With [[https://www.iterm2.com/documentation-shell-integration.html][iTerm2 Shell Integration]], iTerm2 can - track recent used directories - capture command results - set mark - view command exit status - view command history - switch profile automatically To install, first downlaod the script: #+BEGIN_SRC bash :tangle no curl -L https://iterm2.com/misc/bash_startup.in -o ~/.iterm2_shell_integration.bash #+END_SRC Then load it: #+BEGIN_SRC bash [ "$TERM_PROGRAM" == "iTerm.app" ] && source_maybe "$HOME/.iterm2_shell_integration.bash" #+END_SRC * Readline [[info:bash#Readline%20Init%20File][info:bash#Readline Init File]] #+BEGIN_SRC conf :tangle ~/.inputrc :comments link # This file controls the behaviour of line input editing for # programs that use the GNU Readline library. Existing # programs include FTP, Bash, and GDB. # # You can re-read the inputrc file with C-x C-r. # Lines beginning with '#' are comments. # # First, include any system-wide bindings and variable # assignments from /etc/Inputrc $include /etc/Inputrc $if Bash # edit the path "\C-xp": "PATH=${PATH}\e\C-e\C-a\ef\C-f" # prepare to type a quoted word -- # insert open and close double quotes # and move to just after the open quote "\C-x\"": "\"\"\C-b" # Quote the current or previous word "\C-xq": "\eb\"\ef\"" $endif # For FTP $if Ftp "\C-xg": "get \M-?" "\C-xt": "put \M-?" "\M-.": yank-last-arg $endif #+END_SRC * isync :email: OfflineImap 报 "Too many read 0" 错误 #+BEGIN_EXAMPLE abort: command: FETCH => socket error: - Too many read 0 #+END_EXAMPLE 转而用 [[http://isync.sourceforge.net/][isync]] 。下面的配置是从 [[https://wiki.archlinux.org/index.php/Isync][isync - ArchWiki]] 抄来的,其中的 "gmail" 懒得改了。 #+BEGIN_SRC conf :tangle ~/.mbsyncrc :comments link IMAPAccount main # Address to connect to Host imap.migadu.com User mail@xuchunyang.me # gem install netrc PassCmd "ruby -r netrc -e 'print (Netrc.read(File.expand_path(\"~/.authinfo.gpg\"))[\"imap.migadu.com\"]).password'" # # Use SSL SSLType IMAPS CertificateFile /opt/local/share/curl/curl-ca-bundle.crt IMAPStore main-remote Account main MaildirStore main-local # The trailing "/" is important Path ~/.mail/ Inbox ~/.mail/INBOX Channel main Master :main-remote: Slave :main-local: # Or include everything Patterns * # Automatically create missing mailboxes, both locally and on the server Create Both # Save the synchronization state files in the relevant directory SyncState * #+END_SRC * OfflineIMAP :email: Write a Python Script [[file:~/.offlineimap.py][file:~/.offlineimap.py]] to extract IMAP password from [[file:~/.authinfo.gpg][file:~/.authinfo.gpg]]. I don't know Python, the following is based on [[http://quotenil.com/OfflineIMAP-with-Encrypted-Authinfo.html][Gábor Melis' () blog - OfflineIMAP with Encrypted Authinfo]]. #+BEGIN_SRC python :tangle ~/.offlineimap.py :comments link :shebang "#!/usr/bin/env python2" :tangle-mode (identity #o644) import re, os from distutils.spawn import find_executable def get_authinfo_password(machine, login): s = "machine %s login %s password ([^ ]*)\n" % (machine, login) p = re.compile(s) if find_executable("gpg2"): authinfo = os.popen("gpg2 -q --no-tty -d ~/.authinfo.gpg").read() else: authinfo = os.popen("gpg -q --no-tty -d ~/.authinfo.gpg").read() return p.search(authinfo).group(1) #+END_SRC #+BEGIN_SRC conf :tangle ~/.offlineimaprc :comments link [general] pythonfile = ~/.offlineimap.py accounts = Personal [Account Personal] localrepository = Local remoterepository = Remote [Repository Local] type = Maildir localfolders = ~/Maildir [Repository Remote] type = IMAP remotehost = imap.migadu.com remoteuser = mail@xuchunyang.me remotepasseval = get_authinfo_password("imap.migadu.com", "mail@xuchunyang.me") sslcacertfile = /opt/local/etc/openssl/cert.pem #+END_SRC ** Resources - [[https://wiki.archlinux.org/index.php/OfflineIMAP][OfflineIMAP - ArchWiki]] * Notmuch :email: ** Hooks #+BEGIN_SRC sh :tangle ~/.mail/.notmuch/hooks/pre-new :mkdirp yes :shebang "#!/usr/bin/env bash" :comments link set -x mbsync -V -a echo "pre-new hook Done!" #+END_SRC #+BEGIN_SRC sh :tangle ~/.mail/.notmuch/hooks/post-new :mkdirp yes :shebang "#!/usr/bin/env bash" :comments link # [[man:notmuch-hooks][Manpage for notmuch-hooks]] # # [[https://notmuchmail.org/initial_tagging/][initial tagging]] # [[https://notmuchmail.org/pipermail/notmuch/2010/001691.html][{notmuch} Initial tagging]] set -x # notmuch tag +to-me -- to:mail@xuchunyang.me and not tag:to-me # notmuch tag +sent -- from:mail@xuchunyang.me and not tag:sent # notmuch tag +org -- to:emacs-orgmode@gnu.org and not tag:org # notmuch tag +emacs -- to:emacs-devel@gnu.org and not tag:emacs # notmuch tag +emacs -- to:help-gnu-emacs@gnu.org and not tag:emacs # notmuch tag +notmuch -- to:notmuch@notmuchmail.org and not tag:notmuch echo "post-new hook Done!" #+END_SRC * Git :git: ** ~/.gitignore #+BEGIN_SRC gitignore :tangle ~/.gitignore :comments link # Folder view configuration files .DS_Store #+END_SRC ** ~/.gitconfig #+BEGIN_SRC gitconfig :tangle ~/.gitconfig :comments link [user] name = Chunyang Xu email = mail@xuchunyang.me signingkey = A952083AF6D0A8BF [gpg] program = gpg [credential] helper = osxkeychain [http] proxy = socks5://localhost:1086 [core] # Restroe Terminal after quitting # # See [[man:git-config][Manpage for git-config]] and [[man:less][Manpage for less]] # # Git defaults to less FRX # # -F or --quit-if-one-screen # -R or --RAW-CONTROL-CHARS # -X or --no-init # # XXX: -F doesn't work without -X, see # https://unix.stackexchange.com/questions/107315/less-quit-if-one-screen-without-no-init # # Thus deactivate X to restore terminal, and deactivate F to work with # it. pager = less -+X -+F [include] path = .gitconfig_local #+END_SRC * SSH :ssh: ** ~/.ssh/id_rsa :crypt: :PROPERTIES: :header-args: :tangle ~/.ssh/id_rsa :mkdirp yes :tangle-mode '#o600 :END: -----BEGIN PGP MESSAGE----- Version: GnuPG v2 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 =X/y7 -----END PGP MESSAGE----- ** ~/.ssh/id_rsa.pub #+BEGIN_SRC text :mkdirp yes :tangle ~/.ssh/id_rsa.pub ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDHOci6JWgdNE8oxyuGOSSt2Ekn2VIhWMv9ipCAlBa+b+KDneA8kFOo2CdtvEywyv0/z7++DVA0j6Y7QMK4vh1H6PdD+N84ZL2wHXGlWCliYl2wlGhvefOaV3YVgTz4L3TQCsXnmCAWiFNzWAp+dHibgYuy0Sk2+vftcCpwgWFvMYZ5e/8HMNaAYA/aNauWivci1k6VzSmr2XToxOfyeXfkhmPsM3rnHxQbmW2CZJ4L5y0P8innLJSC8MC4zzddbqazHB+KbZYGGXFrJ4BPXN9zst+Q+mNZGCEg/fz8X6X92+C8zyvNgHM6sLPRqsKqpTIjqjGnIbuVCT7E8J8AzwiIUcRIjpeyYeJl5dnh1d1GQcFoa6ZRdhfZ7hMLUvxSsEPflrwdw8UqE6SOIOGi7r2C8FTnoXYkOipff6u0fngSq9CFQ7WQHqgIA1ABnq243EojimwARqcSHbhrWyUxY0D6Q7rs51nHXTOawnFr/46na0CI6sxTv3h6uGfjt5KBn56Y8meHHQlpsk1NR3R2P5UAOA0+xu7MsJUN3b4/xmALUIO6Eiz1ph25umEJC9sWuE6dMm9Wta+s6yLREdHZtV5YnTr1b/79lGLrbJlavTqf2jnBQAewRpMvRpSzVzbtRY8Ucq1+fL3/0eJTXUCAIrOiTAnRhfVqmzcFgftHnXdYuQ== mail@xuchunyang.me #+END_SRC ** ~/.ssh/config #+BEGIN_SRC conf :mkdirp yes :tangle ~/.ssh/config :comments link Host * # If the network connection is down, don't hang ServerAliveInterval 5 # Master Connection # https://unix.stackexchange.com/questions/2857/ssh-easily-copy-file-to-local-system ControlMaster auto ControlPath ~/.ssh/control:%h:%p:%r Host vps HostName xuchunyang.me User root Host elpa HostName elpa.emacs-china.org User root Host pc Hostname 192.168.0.105 User xcy #+END_SRC * GnuPG :gpg: I have made a backup for my GPG keys in my USB disk with #+BEGIN_SRC sh mkdir -v -p /Volumes/USB/backup/gnupg cp -v ~/.gnupg/*.gpg /Volumes/USB/backup/gnupg #+END_SRC To resture these keys, use #+BEGIN_SRC sh cp /Volumes/USB/backup/gnupg/*.gpg ~/.gnupg #+END_SRC This method is from [[https://gist.github.com/chrisroos/1205934][Instructions for exporting/importing (backup/restore) GPG keys]]. * nano 参考 [[file:/opt/local/share/doc/nano/sample.nanorc][file:/opt/local/share/doc/nano/sample.nanorc]] #+BEGIN_SRC conf :tangle ~/.nanorc :comments link ## Use the blank line below the titlebar as extra editing space. set morespace ## Switch on multiple file buffers (inserting a file will put it into ## a separate buffer). set multibuffer ## Remember the cursor position in each file for the next editing session. set positionlog ## Use smooth scrolling as the default. set smooth ## Allow nano to be suspended. set suspend ## Syntax highlight. include "/opt/local/share/nano/*.nanorc" ## Key bindings. ## See nanorc(5) (section REBINDING KEYS) for more details on this. bind ^S savefile main bind M-Q findprevious main bind M-W findnext main #+END_SRC * Wget #+BEGIN_SRC conf :tangle ~/.wgetrc :comments link # Set this to on to use timestamping by default: # timestamping = on # It is a good idea to make Wget send your email address in a `From:' # header with your request (so that server administrators can contact # you in case of errors). Wget does *not* send `From:' by default. header = From: Chunyang Xu #+END_SRC ** Tips *** Redirect wget to standard output 用 ~--output-document/-O~ 选项 #+BEGIN_SRC bash wget --quiet --output-document=- xuchunyang.me wget -q -O - xuchunyang.me #+END_SRC 也可以写成更短的,不知道参数本来就可以这么写,又或者只是 Wget 的一个特例? #+BEGIN_SRC bash wget -qO- xuchunyang.me #+END_SRC * Hammerspoon :mac: #+BEGIN_SRC lua :tangle ~/.hammerspoon/init.lua :mkdirp yes :comments link -- http://www.hammerspoon.org/ hs.hotkey.bind({"ctrl", "cmd"}, "left", function() local win = hs.window.focusedWindow() local f = win:frame() local screen = win:screen() local max = screen:frame() f.x = max.x f.y = max.y f.w = max.w / 2 f.h = max.h win:setFrame(f) end) hs.hotkey.bind({"ctrl", "cmd"}, "right", function() local win = hs.window.focusedWindow() local f = win:frame() local screen = win:screen() local max = screen:frame() f.x = max.x + (max.w / 2) f.y = max.y f.w = max.w / 2 f.h = max.h win:setFrame(f) end) hs.hotkey.bind({"ctrl", "cmd"}, "up", function() local win = hs.window.focusedWindow() win:maximize() end) hs.hotkey.bind({"ctrl", "cmd"}, "down", function() local win = hs.window.focusedWindow() win:centerOnScreen() end) hs.alert.show("init.lua reloaded") #+END_SRC