├── .zshenv
├── .hammerspoon
├── caffeine-active.png
├── caffeine-inactive.png
├── utils.lua
├── init.lua
└── Spoons
│ └── SpoonInstall.spoon
│ └── init.lua
├── .gitconfig
├── .latexmkrc
├── .mpdconf
├── .emacs.d
├── lisp
│ ├── init-locales.el
│ ├── setup-flycheck.el
│ ├── setup-yasnippet.el
│ ├── setup-hydra.el
│ ├── setup-jump.el
│ ├── init-fonts.el
│ ├── setup-spellcheck.el
│ ├── setup-company.el
│ ├── init-utils.el
│ ├── init-mac.el
│ ├── setup-music.el
│ ├── setup-pdf.el
│ ├── init-package.el
│ ├── setup-git.el
│ ├── init-core.el
│ ├── init-frames.el
│ ├── setup-projectile.el
│ ├── setup-ivy.el
│ ├── setup-tex.el
│ ├── init-evil.el
│ ├── init-editor.el
│ ├── init-theme.el
│ ├── init-ui.el
│ ├── init-keybindings.el
│ ├── init-windows.el
│ └── setup-org.el
├── early-init.el
└── init.el
├── .config
├── imapnotify
│ ├── anand.iyer.p@gmail.com.js
│ ├── bmail.js
│ └── anand.padmanabha.iyer@gmail.com.js
├── afew
│ └── config
└── yabai
│ └── yabairc
├── .msmtprc
├── .tmux.conf
├── .notmuch-config
├── .chunkwmrc
├── .dotfiles
└── README.md
├── .vimrc
├── .mbsyncrc
├── .gitignore
└── .zshrc
/.zshenv:
--------------------------------------------------------------------------------
1 | export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
2 | export PATH="$HOME/.cargo/bin:$PATH"
3 |
--------------------------------------------------------------------------------
/.hammerspoon/caffeine-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anandpiyer/.dotfiles/HEAD/.hammerspoon/caffeine-active.png
--------------------------------------------------------------------------------
/.hammerspoon/caffeine-inactive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anandpiyer/.dotfiles/HEAD/.hammerspoon/caffeine-inactive.png
--------------------------------------------------------------------------------
/.gitconfig:
--------------------------------------------------------------------------------
1 | [user]
2 | email = anand.iyer@berkeley.edu
3 | [credential]
4 | helper = osxkeychain
5 | [core]
6 | excludesfile = /Users/api/.gitignore
7 | editor = emacsclient -c
8 |
--------------------------------------------------------------------------------
/.latexmkrc:
--------------------------------------------------------------------------------
1 | # Generate pdf using pdflatex (-pdf)
2 | $pdf_mode = 1;
3 |
4 | # Use bibtex if a .bib file exists
5 | $bibtex_use = 1;
6 |
7 | $pdflatex = 'pdflatex -shell-escape -synctex=1 %O %S';
8 | $pdf_previewer = 'open -a skim';
9 | $clean_ext = "bbl rel out synctex.gz log %R-blx.bib %R.synctex.gz";
10 |
--------------------------------------------------------------------------------
/.mpdconf:
--------------------------------------------------------------------------------
1 | music_directory "~/Music/beets"
2 | playlist_directory "~/Music/beets"
3 | db_file "~/.mpd/mpd.db"
4 | log_file "~/.mpd/mpd.log"
5 | pid_file "~/.mpd/mpd.pid"
6 | state_file "~/.mpd/mpd.state"
7 | sticker_file "~/.mpd/sticker.sql"
8 |
9 | bind_to_address "127.0.0.1"
10 | port "6600"
11 | user "api"
12 |
13 | auto_update "yes"
14 | auto_update_depth "2"
15 | follow_outside_symlinks "yes"
16 | follow_inside_symlinks "yes"
17 |
18 | audio_output {
19 | type "osx"
20 | name "CoreAudio"
21 | mixer_type "software"
22 | }
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-locales.el:
--------------------------------------------------------------------------------
1 | ;;; init-locales.el --- locales settings -*- lexical-binding: t; -*-
2 | ;;; Commentary:
3 | ;;; Code:
4 |
5 | ;;------------------------------------------------------------------------------
6 | ;; Prefer UTF-8 everywhere.
7 | ;;------------------------------------------------------------------------------
8 | (set-language-environment 'utf-8)
9 | (prefer-coding-system 'utf-8)
10 | (set-default-coding-systems 'utf-8)
11 | (setq locale-coding-system 'utf-8)
12 | (set-terminal-coding-system 'utf-8)
13 | (set-keyboard-coding-system 'utf-8)
14 | (set-selection-coding-system 'utf-8)
15 | (setq-default buffer-file-coding-system 'utf-8)
16 |
17 | (provide 'init-locales)
18 | ;;; init-locales.el ends here
19 |
--------------------------------------------------------------------------------
/.hammerspoon/utils.lua:
--------------------------------------------------------------------------------
1 | -- Merge two tables, overwriting entires in the first one
2 | -- in case of a conflict.
3 | function table_merge(t1, t2)
4 | for k,v in pairs(t2) do
5 | if type(v) == "table" then
6 | if type(t1[k] or false) == "table" then
7 | table_merge(t1[k] or {}, t2[k] or {})
8 | else
9 | t1[k] = v
10 | end
11 | else
12 | t1[k] = v
13 | end
14 | end
15 | return t1
16 | end
17 |
18 | function table_concat(t1, t2)
19 | for i=1,#t2 do
20 | t1[#t1+1] = t2[i]
21 | end
22 | return t1
23 | end
24 |
25 | function table_length(t)
26 | local count = 0
27 | for _ in pairs(t) do count = count + 1 end
28 | return count
29 | end
30 |
--------------------------------------------------------------------------------
/.config/imapnotify/anand.iyer.p@gmail.com.js:
--------------------------------------------------------------------------------
1 | var child_process = require('child_process');
2 |
3 | function getStdout(cmd) {
4 | var stdout = child_process.execSync(cmd);
5 | return stdout.toString().trim();
6 | }
7 |
8 | exports.host = "imap.gmail.com";
9 | exports.port = 993;
10 | exports.tls = true;
11 | exports.tlsOptions = { "rejectUnauthorized": false };
12 | exports.username = "anand.iyer.p@gmail.com";
13 | exports.password = getStdout("security find-generic-password -s emacs-email -a anand.iyer.p@gmail.com -w")
14 | exports.onNotify = "afew -m; mbsync -q anand.iyer.p@gmail.com";
15 | exports.onNotifyPost = {"mail": "terminal-notifier -message 'has new mail.' -title 'anand.iyer.p@gmail.com'; notmuch new; emacsclient -e '(mu4e-update-index)'"};
16 | exports.boxes = ["INBOX"];
17 |
--------------------------------------------------------------------------------
/.config/imapnotify/bmail.js:
--------------------------------------------------------------------------------
1 | var child_process = require('child_process');
2 |
3 | function getStdout(cmd) {
4 | var stdout = child_process.execSync(cmd);
5 | return stdout.toString().trim();
6 | }
7 |
8 | exports.host = "imap.gmail.com";
9 | exports.port = 993;
10 | exports.tls = true;
11 | exports.tlsOptions = { "rejectUnauthorized": false };
12 | exports.username = "anand.iyer@berkeley.edu";
13 | exports.password = getStdout("security find-generic-password -s emacs-email -a anand.iyer@berkeley.edu -w")
14 | exports.onNotify = "afew -m && mbsync --push -q bmail && mbsync --pull -q bmail";
15 | exports.onNotifyPost = {"mail": "notmuch new && emacsclient -e '(mu4e-update-index)' && terminal-notifier -message 'has new mail.' -title 'berkeley.edu'"};
16 | exports.boxes = ["INBOX"];
17 |
--------------------------------------------------------------------------------
/.config/imapnotify/anand.padmanabha.iyer@gmail.com.js:
--------------------------------------------------------------------------------
1 | var child_process = require('child_process');
2 |
3 | function getStdout(cmd) {
4 | var stdout = child_process.execSync(cmd);
5 | return stdout.toString().trim();
6 | }
7 |
8 | exports.host = "imap.gmail.com";
9 | exports.port = 993;
10 | exports.tls = true;
11 | exports.tlsOptions = { "rejectUnauthorized": false };
12 | exports.username = "anand.padmanabha.iyer@gmail.com";
13 | exports.password = getStdout("security find-generic-password -s emacs-email -a anand.padmanabha.iyer@gmail.com -w")
14 | exports.onNotify = "afew -m; mbsync -q anand.padmanabha.iyer@gmail.com";
15 | exports.onNotifyPost = {"mail": "terminal-notifier -message 'has new mail.' -title 'anand.padmanabha.iyer@gmail.com'; notmuch new; emacsclient -e '(mu4e-update-index)'"};
16 | exports.boxes = ["INBOX"];
17 |
--------------------------------------------------------------------------------
/.emacs.d/early-init.el:
--------------------------------------------------------------------------------
1 | (unless noninteractive
2 | (defvar api--file-name-handler-alist file-name-handler-alist)
3 | (unless after-init-time
4 | (setq gc-cons-threshold (* 512 1024 1024)
5 | gc-cons-percentage 0.6
6 | file-name-handler-alist nil
7 | auto-window-vscroll nil)
8 | (defun api|reset-gc ()
9 | (setq gc-cons-threshold (* 16 1024 1024)
10 | gc-cons-percentage 0.1
11 | file-name-handler-alist api--file-name-handler-alist))
12 | (add-hook 'emacs-startup-hook #'api|reset-gc)))
13 |
14 | (setq user-emacs-directory (file-name-directory load-file-name)
15 | package-enable-at-startup nil
16 | ;;package-quickstart t
17 | load-prefer-newer noninteractive)
18 |
19 | (if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
20 | (if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
21 | (if (fboundp 'tooltip-mode) (tooltip-mode -1))
22 | (unless (display-graphic-p) (menu-bar-mode -1))
23 |
--------------------------------------------------------------------------------
/.config/afew/config:
--------------------------------------------------------------------------------
1 | [ArchiveSentMailsFilter]
2 |
3 | [InboxFilter]
4 |
5 | [MailMover]
6 | folders = anand.ebiz@gmail.com/inbox anand.ebiz@gmail.com/all anand.padmanabha.iyer@gmail.com/inbox anand.padmanabha.iyer@gmail.com/all bmail/inbox bmail/all anand.iyer.p@gmail.com/inbox anand.iyer.p@gmail.com/all
7 | rename = True
8 |
9 | # rules
10 | anand.ebiz@gmail.com/inbox = 'tag:trash':anand.ebiz@gmail.com/trash 'NOT tag:inbox':anand.ebiz@gmail.com/all
11 | anand.ebiz@gmail.com/all = 'tag:trash':anand.ebiz@gmail.com/trash
12 | anand.padmanabha.iyer@gmail.com/inbox = 'tag:trash':anand.padmanabha.iyer@gmail.com/trash 'NOT tag:inbox':anand.padmanabha.iyer@gmail.com/all
13 | anand.padmanabha.iyer@gmail.com/all = 'tag:trash':anand.padmanabha.iyer@gmail.com/trash
14 | anand.iyer.p@gmail.com/inbox = 'tag:trash':anand.iyer.p@gmail.com/trash 'NOT tag:inbox':anand.iyer.p@gmail.com/all
15 | anand.iyer.p@gmail.com/all = 'tag:trash':anand.iyer.p@gmail.com/trash
16 | bmail/inbox = 'tag:trash':bmail/trash 'NOT tag:inbox':bmail/all
17 | bmail/all = 'tag:trash':bmail/trash
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-flycheck.el:
--------------------------------------------------------------------------------
1 | ;;; setup-flycheck.el --- Flycheck -*- lexical-binding: t; -*-
2 | ;;; Commentary:
3 | ;;; Code:
4 |
5 | (use-package flycheck
6 | :diminish (flycheck-mode . " ⓢ")
7 | :commands (flycheck-mode
8 | flycheck-list-errors
9 | flycheck-buffer)
10 | :init
11 | ;; Turn on `flycheck-mode' for programming modes.
12 | (add-hook 'prog-mode-hook #'flycheck-mode)
13 |
14 | ;; Check the buffer when `ESC' is pressed.
15 | (defun api|flycheck-buffer ()
16 | (when flycheck-mode
17 | (ignore-errors (flycheck-buffer))
18 | nil))
19 |
20 | (after! evil
21 | (add-hook '+evil-esc-hook #'api|flycheck-buffer t))
22 |
23 | :config
24 | (setq flycheck-indication-mode 'right-fringe
25 | flycheck-check-syntax-automatically '(save idle mode-enabled))
26 |
27 | (fringe-helper-define 'flycheck-fringe-bitmap-double-arrow 'center
28 | "...X...."
29 | "..XX...."
30 | ".XXX...."
31 | "XXXX...."
32 | ".XXX...."
33 | "..XX...."
34 | "...X...."))
35 |
36 | (provide 'setup-flycheck)
37 |
38 | ;;; setup-flycheck.el ends here
39 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-yasnippet.el:
--------------------------------------------------------------------------------
1 | ;;; setup-yasnippet.el --- yanippet related setup -*- lexical-binding: t; -*-
2 | ;;; Commentary:
3 | ;;; Code:
4 |
5 | (use-package yasnippet
6 | :diminish yas-minor-mode
7 | :commands (yas-minor-mode yas-minor-mode-on yas-expand yas-expand-snippet
8 | yas-lookup-snippet yas-insert-snippet yas-new-snippet
9 | yas-visit-snippet-file snippet-mode)
10 | :preface (defvar yas-minor-mode-map (make-sparse-keymap))
11 | :init
12 | (add-hook 'yas-minor-mode-hook #'yas-reload-all)
13 | (add-hook 'text-mode-hook #'yas-minor-mode-on)
14 | (add-hook 'prog-mode-hook #'yas-minor-mode-on)
15 | (add-hook 'latex-mode-hook #'yas-minor-mode-on)
16 | (add-hook 'snippet-mode-hook #'yas-minor-mode-on)
17 | (add-hook 'org-mode-hook #'yas-minor-mode-on)
18 |
19 | :config
20 | (setq yas-verbosity 0
21 | yas-also-auto-indent-first-line t
22 | yas-prompt-functions (delq 'yas-dropdown-prompt yas-prompt-functions)
23 | yas-triggers-in-field t)
24 |
25 | ;; fix an error caused by smartparens interfering with yasnippet bindings
26 | (advice-add #'yas-expand :before #'sp-remove-active-pair-overlay)
27 |
28 | ;; Exit snippets on ESC from normal mode
29 | (add-hook '+evil-esc-hook #'yas-exit-all-snippets))
30 |
31 | ;(use-package yasnippet-snippets
32 | ;:defer t
33 | ; :after yasnippet)
34 |
35 | (provide 'setup-yasnippet)
36 | ;;; setup-yasnippet ends here
37 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-hydra.el:
--------------------------------------------------------------------------------
1 | ;;; setup-hydra.el --- Hydra -*- lexical-binding: t; -*-
2 | ;;
3 | ;;; Commentary:
4 | ;;
5 | ;; Hydra related settings
6 | ;;
7 | ;;; Code:
8 |
9 | (defhydra api/themes-hydra (:hint nil :color pink :columns 3)
10 | "
11 | Themes
12 |
13 | ^Gruvbox^ ^Material^ ^Other^ ^Solarized^
14 | ----------------------------------------------------
15 | _g_: Dark _m_: Dark _z_: Zenburn _s_: Dark
16 | _G_: Light _M_: Light _s_: Seoul256 _S_: Light
17 | _n_: Nord
18 | "
19 | ("g" (load-theme 'gruvbox-dark-soft t))
20 | ("G" (load-theme 'gruvbox-light t))
21 | ("m" (load-theme 'material t))
22 | ("M" (load-theme 'material-light t))
23 | ("s" (load-theme 'solarized-dark t))
24 | ("S" (load-theme 'solarized-light t))
25 | ("z" (load-theme 'zenburn t))
26 | ("s" (load-theme 'seoul256 t))
27 | ("n" (load-theme 'nord t))
28 | ("RET" nil "done" :color blue))
29 |
30 | (use-package multiple-cursors
31 | :defer t)
32 |
33 | (defhydra api/multiple-cursors-hydra (:hint nil)
34 | "
35 | ^Up^ ^Down^ ^Miscellaneous^
36 | ----------------------------------------------
37 | [_p_] Next [_n_] Next [_l_] Edit lines
38 | [_P_] Skip [_N_] Skip [_a_] Mark all
39 | [_M-p_] Unmark [_M-n_] Unmark [_q_] Quit"
40 | ("l" mc/edit-lines :exit t)
41 | ("a" mc/mark-all-like-this :exit t)
42 | ("n" mc/mark-next-like-this)
43 | ("N" mc/skip-to-next-like-this)
44 | ("M-n" mc/unmark-next-like-this)
45 | ("p" mc/mark-previous-like-this)
46 | ("P" mc/skip-to-previous-like-this)
47 | ("M-p" mc/unmark-previous-like-this)
48 | ("q" nil))
49 |
50 | (provide 'setup-hydra)
51 | ;;; setup-hydra.el ends here
52 |
--------------------------------------------------------------------------------
/.msmtprc:
--------------------------------------------------------------------------------
1 | # Set default values for all following accounts.
2 | defaults
3 | auth on
4 | tls on
5 | logfile ~/.msmtp.log
6 |
7 | # Bmail (anand.iyer@berkeley.edu)
8 | account bmail
9 | host smtp.gmail.com
10 | port 587
11 | tls_certcheck off
12 | from anand.iyer@berkeley.edu
13 | user anand.iyer@berkeley.edu
14 | passwordeval "security find-generic-password -s emacs-email -a anand.iyer@berkeley.edu -w"
15 |
16 | # Bmail alias
17 | account bmail.cs : bmail
18 | from api@cs.berkeley.edu
19 | account bmail.eecs : bmail
20 | from api@eecs.berkeley.edu
21 |
22 | # Gmail (anand.padmanabha.iyer@gmail.com)
23 | account anand.padmanabha.iyer@gmail.com
24 | host smtp.gmail.com
25 | port 587
26 | tls_certcheck off
27 | from anand.padmanabha.iyer@gmail.com
28 | user anand.padmanabha.iyer@gmail.com
29 | passwordeval "security find-generic-password -s emacs-email -a anand.padmanabha.iyer@gmail.com -w"
30 |
31 | # Gmail (anand.iyer.p@gmail.com)
32 | account anand.iyer.p@gmail.com
33 | host smtp.gmail.com
34 | port 587
35 | tls_certcheck off
36 | from anand.iyer.p@gmail.com
37 | user anand.iyer.p@gmail.com
38 | passwordeval "security find-generic-password -s emacs-email -a anand.iyer.p@gmail.com -w"
39 |
40 | # Gmail (anand.ebiz@gmail.com)
41 | account anand.ebiz@gmail.com
42 | host smtp.gmail.com
43 | port 587
44 | tls_certcheck off
45 | from anand.ebiz@gmail.com
46 | user anand.ebiz@gmail.com
47 | passwordeval "security find-generic-password -s emacs-email -a anand.ebiz@gmail.com -w"
48 |
49 | # Set a default account
50 | account default : anand.iyer.p@gmail.com
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-jump.el:
--------------------------------------------------------------------------------
1 | ;;; setup-jump.el -*- lexical-binding: t; -*-
2 |
3 | (use-package dumb-jump
4 | :commands (dumb-jump-go
5 | dumb-jump-go-other-window
6 | dumb-jump-go-prefer-external
7 | dumb-jump-go-prefer-external-other-window
8 | dumb-jump-go-prompt
9 | dumb-jump-quick-look
10 | dumb-jump-back)
11 | :init
12 | (after! hydra
13 | (defhydra api@dumb-jump (:color blue :columns 3)
14 | "Dumb Jump"
15 | ("j" dumb-jump-go "Go")
16 | ("o" dumb-jump-go-other-window "Other window")
17 | ("e" dumb-jump-go-prefer-external "Go external")
18 | ("x" dumb-jump-go-prefer-external-other-window "Go external other window")
19 | ("i" dumb-jump-go-prompt "Prompt")
20 | ("l" dumb-jump-quick-look "Quick look")
21 | ("b" dumb-jump-back "Back")))
22 | :config
23 | (setq dumb-jump-selector 'helm))
24 |
25 | (use-package avy
26 | :commands (avy-goto-char-2 avy-goto-line)
27 | :config
28 | (setq avy-all-windows nil
29 | avy-background t))
30 |
31 | ;; (use-package ace-jump-helm-line
32 | ;; :defer t
33 | ;; :after helm
34 | ;; :init
35 | ;; (with-eval-after-load 'helm
36 | ;; (define-key helm-map (kbd "C-'") 'ace-jump-helm-line))
37 |
38 | ;; ;; or if using key-chord-mode
39 | ;; ;; (eval-after-load "helm"
40 | ;; ;; '(key-chord-define helm-map "jj" 'ace-jump-helm-line))
41 | ;; ;;(setq ace-jump-helm-line-style 'pre)
42 | ;; ;;(setq ace-jump-helm-line-background t)
43 | ;; (setq ace-jump-helm-line-default-action 'select)
44 | ;; (setq ace-jump-helm-line-select-key ?e) ;; this line is not needed
45 | ;; ;; Set the move-only and persistent keys
46 | ;; (setq ace-jump-helm-line-move-only-key ?o)
47 | ;; (setq ace-jump-helm-line-persistent-key ?p)
48 | ;; ;; enable hints preview
49 | ;; ;;(ace-jump-helm-line-autoshow-mode +1)
50 | ;; ;; use `linum-mode' to show
51 | ;; (setq ace-jump-helm-line-autoshow-mode-use-linum t))
52 |
53 | (provide 'setup-jump)
54 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-fonts.el:
--------------------------------------------------------------------------------
1 | ;; init-fonts.el --- Fonts -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | (defvar api-emacs-font-size 14)
9 | (defvar api-emacs-font (font-spec :family "PragmataPro" :size api-emacs-font-size))
10 | (defvar api-emacs-variable-pitch-font (font-spec :family "PragmataPro"))
11 | (defvar api-emacs-fixed-pitch-font (font-spec :family "PragmataPro"))
12 | (defvar api-emacs-unicode-font (font-spec :family "PragmataPro"))
13 | (defvar api-emacs-fallback-font (font-spec :family "PragmataPro"))
14 |
15 | (use-package fonts
16 | :ensure nil
17 | :hook (after-init . api|set-fonts)
18 | :preface
19 | (defun api|set-fonts ()
20 | (interactive)
21 | (set-face-attribute 'default t :font api-emacs-font)
22 | (set-frame-font api-emacs-font nil t)
23 | (set-fontset-font t 'unicode api-emacs-unicode-font)
24 | (set-face-attribute 'fixed-pitch nil
25 | :family api-emacs-fixed-pitch-font
26 | :height (* (+ api-emacs-font-size 2) 10))
27 |
28 | (set-fontset-font "fontset-default"
29 | '(#x2776 . #x2793) api-emacs-fallback-font nil 'prepend)
30 | (set-fontset-font "fontset-default"
31 | '(#x24b6 . #x24fe) api-emacs-fallback-font nil 'prepend)
32 | (set-fontset-font "fontset-default"
33 | '(#x2295 . #x22a1) api-emacs-fallback-font nil 'prepend)
34 | (set-fontset-font "fontset-default"
35 | '(#x2190 . #x2200) api-emacs-fallback-font nil 'prepend))
36 | :hook (after-init . api|set-fonts))
37 | (provide 'init-fonts)
38 |
39 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
40 | ;;; init-fonts.el ends here
41 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-spellcheck.el:
--------------------------------------------------------------------------------
1 | ;;; setup-spellcheck.el --- Spell check -*- lexical-binding: t; -*-
2 | ;;; Commentary:
3 | ;;; Code:
4 |
5 | ;;------------------------------------------------------------------------------
6 | ;; `ispell':
7 | ;;------------------------------------------------------------------------------
8 | (use-package ispell
9 | :ensure nil ; in-built
10 | :init
11 | (setq ispell-program-name (executable-find "aspell")
12 | ispell-extra-args '("--sug-mode=ultra"
13 | "--lang=en_US")))
14 |
15 | ;;------------------------------------------------------------------------------
16 | ;; `flyspell':
17 | ;;------------------------------------------------------------------------------
18 | (use-package flyspell
19 | :ensure nil ; in-built
20 | :defer t
21 | :commands (flyspell-mode
22 | turn-on-flyspell)
23 | :init
24 | (dolist (hook '(prog-mode-hook
25 | latex-mode-hook
26 | text-mode-hook))
27 | (add-hook hook #'turn-on-flyspell))
28 | :bind (:map flyspell-mouse-map
29 | ("RET" . flyspell-correct-word)
30 | ([mouse-1] . flyspell-correct-word))
31 | :config
32 | (setq flyspell-sort-corrections nil
33 | flyspell-issue-welcome-flag nil
34 | flyspell-issue-message-flag nil))
35 |
36 | ;;------------------------------------------------------------------------------
37 | ;; `flyspell-correct':
38 | ;;------------------------------------------------------------------------------
39 | (use-package flyspell-correct
40 | :disabled
41 | :after (flyspell avy)
42 | :commands (flyspell-correct-next
43 | flyspell-correct-previous
44 | flyspell-correct-wrapper
45 | flyspell-correct-at-point))
46 |
47 | (use-package flyspell-correct-popup
48 | :disabled
49 | :defer t
50 | :after flyspell-correct)
51 | ;:commands (flyspell-correct-word-generic
52 | ; flyspell-correct-previous-word-generic))
53 |
54 | ;; (use-package flyspell-correct
55 | ;; :requires (flyspell-correct-helm flyspell-correct-popup)
56 | ;; :after (flyspell helm)
57 | ;; :commands (flyspell-correct-word-generic
58 | ;; flyspell-correct-previous-word-generic)
59 | ;; :config
60 | ;; (require 'flyspell-correct-helm)
61 | ;; (require 'flyspell-correct-popup)
62 | ;; (setq flyspell-popup-correct-delay 0.8))
63 |
64 | (provide 'setup-spellcheck)
65 | ;;; setup-spellcheck.el ends here
66 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-company.el:
--------------------------------------------------------------------------------
1 | ;;; setup-company.el --- Company related setup -*- lexical-binding: t; -*-
2 | ;;; Commentary:
3 | ;;; Code:
4 |
5 | (defvar company-mode/enable-yas t "Enable yasnippet for all backends.")
6 |
7 | (use-package company
8 | :diminish company-mode
9 | :commands (company-mode global-company-mode company-complete
10 | company-complete-common company-manual-begin company-grab-line)
11 | :init
12 | (add-hook 'emacs-startup-hook #'global-company-mode)
13 | :config
14 | (setq company-idle-delay 0.2
15 | company-minimum-prefix-length 3
16 | company-tooltip-limit 10
17 | company-dabbrev-downcase nil
18 | company-dabbrev-ignore-case nil
19 | company-dabbrev-code-other-buffers t
20 | company-tooltip-align-annotations t
21 | company-selection-wrap-around t
22 | company-require-match 'never
23 | company-global-modes '(not eshell-mode comint-mode erc-mode message-mode help-mode gud-mode)
24 | company-frontends '(company-pseudo-tooltip-frontend company-echo-metadata-frontend)
25 | company-backends '(company-capf company-dabbrev company-ispell)
26 | company-transformers '(company-sort-by-occurrence))
27 |
28 | ;; fci-mode conflicts with company-mode, see:
29 | ;; https://github.com/company-mode/company-mode/issues/180
30 | ;; (defvar-local company-fci-mode-on-p nil)
31 |
32 | ;; (defun company-turn-off-fci (&rest ignore)
33 | ;; (when (boundp 'fci-mode)
34 | ;; (setq company-fci-mode-on-p fci-mode)
35 | ;; (when fci-mode (fci-mode -1))))
36 |
37 | ;; (defun company-maybe-turn-on-fci (&rest ignore)
38 | ;; (when company-fci-mode-on-p (fci-mode 1)))
39 |
40 | ;; (add-hook 'company-completion-started-hook 'company-turn-off-fci)
41 | ;; (add-hook 'company-completion-finished-hook 'company-maybe-turn-on-fci)
42 | ;; (add-hook 'company-completion-cancelled-hook 'company-maybe-turn-on-fci)
43 |
44 | ;; Add yasnippet support for all company backends
45 | ;; https://github.com/syl20bnr/spacemacs/pull/179
46 | (defun company-mode/backend-with-yas (backend)
47 | (if (or (not company-mode/enable-yas) (and (listp backend) (member 'company-yasnippet backend)))
48 | backend
49 | (append (if (consp backend) backend (list backend))
50 | '(:with company-yasnippet))))
51 |
52 | (setq company-backends (mapcar #'company-mode/backend-with-yas company-backends))
53 | (nconc company-backends '(company-yasnippet)))
54 |
55 | ;; (use-package helm-company
56 | ;; :after company
57 | ;; :config
58 | ;; (define-key company-active-map (kbd "C-/") 'helm-company))
59 |
60 | (provide 'setup-company)
61 | ;;; setup-company.el ends here
62 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-utils.el:
--------------------------------------------------------------------------------
1 | ;;; init-utils.el --- helpers -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | (defun api/byte-compile ()
9 | "Byte compile all user init files."
10 | (interactive)
11 | (let (compile-targets)
12 | (setq compile-targets
13 | (nconc
14 | (nreverse (directory-files-recursively user-emacs-modules-directory "\\.el$"))))
15 | (push (expand-file-name "init.el" user-emacs-directory) compile-targets)
16 |
17 | (let ((byte-compile-warnings nil))
18 | (dolist (target compile-targets)
19 | (byte-compile-file target)))
20 | ;;(load target t t)
21 | (message "Compilation complete. Restart Emacs to load.")))
22 |
23 | (defun remove-elc-on-save ()
24 | "If we're saving an elisp file, likely the .elc is no longer valid."
25 | (add-hook 'after-save-hook
26 | (lambda ()
27 | (if (file-exists-p (concat buffer-file-name "c"))
28 | (delete-file (concat buffer-file-name "c"))))
29 | nil
30 | t))
31 | (add-hook 'emacs-lisp-mode-hook 'remove-elc-on-save)
32 |
33 | (defun api/clean-byte-compiled-files ()
34 | "Delete all compiled elc files excluding packages."
35 | (interactive)
36 | (let ((targets (append (list (expand-file-name "init.elc" user-emacs-directory))
37 | (directory-files-recursively user-emacs-modules-directory "\\.elc$")))
38 | (default-directory user-emacs-directory))
39 | (unless (cl-loop for path in targets
40 | if (file-exists-p path)
41 | collect path
42 | and do (delete-file path)
43 | and do (message "✓ Deleted %s" (file-relative-name path)))
44 | (message "Everything is clean"))))
45 |
46 | ;;------------------------------------------------------------------------------
47 | ;; Allow loading packages after some other packages.
48 | ;;------------------------------------------------------------------------------
49 | (defmacro after! (feature &rest body)
50 | "After FEATURE is loaded, evaluate BODY. Supress warnings during compilation."
51 | (declare (indent defun) (debug t))
52 | `(,(if (or (not (bound-and-true-p byte-compile-current-file))
53 | (if (symbolp feature)
54 | (require feature nil :no-error)
55 | (load feature :no-message :no-error)))
56 | #'progn
57 | #'with-no-warnings)
58 | (with-eval-after-load ',feature ,@body)))
59 |
60 | (provide 'init-utils)
61 |
62 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
63 | ;;; init-utils.el ends here
64 |
--------------------------------------------------------------------------------
/.config/yabai/yabairc:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # the scripting-addition must be loaded manually if
4 | # you are running yabai on macOS Big Sur. Uncomment
5 | # the following line to have the injection performed
6 | # when the config is executed during startup.
7 | #
8 | # for this to work you must configure sudo such that
9 | # it will be able to run the command without password
10 | #
11 | # see this wiki page for information:
12 | # - https://github.com/koekeishiya/yabai/wiki/Installing-yabai-(latest-release)
13 | #
14 | # sudo yabai --load-sa
15 | # yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"
16 |
17 | # global settings
18 | yabai -m config mouse_follows_focus off
19 | yabai -m config focus_follows_mouse off
20 | yabai -m config window_placement second_child
21 | yabai -m config window_topmost off
22 | yabai -m config window_shadow on
23 | yabai -m config window_opacity off
24 | yabai -m config window_opacity_duration 0.0
25 | yabai -m config active_window_opacity 1.0
26 | yabai -m config normal_window_opacity 0.90
27 | yabai -m config window_border off
28 | yabai -m config window_border_width 6
29 | yabai -m config active_window_border_color 0xff775759
30 | yabai -m config normal_window_border_color 0xff555555
31 | yabai -m config insert_feedback_color 0xffd75f5f
32 | yabai -m config split_ratio 0.50
33 | yabai -m config auto_balance off
34 | yabai -m config mouse_modifier ctrl
35 | yabai -m config mouse_action1 move
36 | yabai -m config mouse_action2 resize
37 | yabai -m config mouse_drop_action swap
38 |
39 | # general space settings
40 | yabai -m config layout bsp
41 | yabai -m config top_padding 05
42 | yabai -m config bottom_padding 05
43 | yabai -m config left_padding 05
44 | yabai -m config right_padding 05
45 | yabai -m config window_gap 06
46 |
47 | # Rules
48 | yabai -m rule --add title='^System Preferences$' manage=off
49 | yabai -m rule --add title='Copy' manage=off
50 | yabai -m rule --add title='Print' manage=off
51 | yabai -m rule --add app='App Store' manage=off
52 | yabai -m rule --add app='Fantastical$' manage=off
53 | yabai -m rule --add app="thinkorswim$" manage=off
54 | yabai -m rule --add app='Parallels Desktop' manage=off
55 | yabai -m rule --add app='Microsoft Teams' manage=off
56 | yabai -m rule --add app='Microsoft Outlook' manage=off
57 | yabai -m rule --add title='• Calendar • api@microsoft.com$' manage=off
58 | yabai -m rule --add app='Emacs' manage=on space=3
59 |
60 | echo "yabai configuration loaded.."
61 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-mac.el:
--------------------------------------------------------------------------------
1 | ;;; init-mac.el --- Mac specific settings -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;; Taken from doom-emacs.
6 |
7 | ;;; Code:
8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 |
10 | (setq mac-command-modifier 'super
11 | ;;mac-right-control-modifier 'hyper
12 | mac-function-modifier 'hyper ; make Fn key do Hyper
13 | mac-option-modifier 'hyper ; make option do Hyper
14 |
15 | ;; clipboard
16 | x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)
17 | ;; Use a shared clipboard
18 | select-enable-clipboard t
19 | select-enable-primary t
20 |
21 | mac-redisplay-dont-reset-vscroll t
22 | mac-mouse-wheel-smooth-scroll nil
23 | mouse-wheel-scroll-amount '(5 ((shift) . 2)) ; one line at a time
24 | mouse-wheel-progressive-speed nil ; don't accelerate scrolling
25 |
26 | ;; NOTE Meaningless to railwaycat's emacs-mac build
27 | ns-use-native-fullscreen nil
28 | ;; Don't open files from the workspace in a new frame
29 | ns-pop-up-frames nil)
30 |
31 | ;; https://www.reddit.com/r/emacs/comments/8ph0hq/i_have_converted_from_the_mac_port_to_the_ns_port/
32 | ;; Will at least display native Unicode emojis if the multicolor font
33 | ;; patch is applied
34 | (set-fontset-font "fontset-default" 'unicode "Apple Color Emoji" nil 'prepend)
35 | (setq frame-title-format "%b"
36 | ns-use-mwheel-momentum t
37 | ns-use-mwheel-acceleration t
38 | ;;pixel-scroll-mode t
39 | mouse-wheel-flip-direction t
40 | mouse-wheel-tilt-scroll t
41 | ;; MacPorts emacs-app port bug
42 | ;;x-colors (ns-list-colors)
43 | )
44 |
45 | (after! evil
46 | ;; stop copying each visual state move to the clipboard:
47 | ;; https://bitbucket.org/lyro/evil/issue/336/osx-visual-state-copies-the-region-on
48 | ;; Most of this code grokked from:
49 | ;; http://stackoverflow.com/questions/15873346/elisp-rename-macro
50 | (advice-add #'evil-visual-update-x-selection :override #'ignore))
51 |
52 | ;;------------------------------------------------------------------------------
53 | ;; `exec-path-from-shell':
54 | ;;------------------------------------------------------------------------------
55 | (use-package exec-path-from-shell
56 | ;;:disabled
57 | :if (display-graphic-p)
58 | :init
59 | (when (require 'exec-path-from-shell nil t)
60 | (setq exec-path-from-shell-check-startup-files nil
61 | exec-path-from-shell-arguments (delete "-i" exec-path-from-shell-arguments))
62 | (exec-path-from-shell-initialize)))
63 |
64 | (provide 'init-mac)
65 |
66 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
67 | ;;; init-mac.el ends here
68 |
--------------------------------------------------------------------------------
/.tmux.conf:
--------------------------------------------------------------------------------
1 | #run-shell "powerline-daemon -q"
2 | #source-file "/usr/local/lib/python2.7/site-packages/powerline/bindings/tmux/powerline.conf"
3 |
4 | #Start windows and pane numbering with index 1 instead of 0
5 | set -g base-index 1
6 | setw -g pane-base-index 1
7 |
8 | # re-number windows when one is closed
9 | set -g renumber-windows on
10 |
11 | # highlight window when it has new activity
12 | setw -g monitor-activity on
13 | set -g visual-activity on
14 |
15 | # Show times longer than supposed
16 | set -g display-panes-time 2000
17 |
18 | # Split horiziontal and vertical splits, instead of % and "
19 | # Also open them in the same directory
20 | bind-key v split-window -h -c '#{pane_current_path}'
21 | bind-key s split-window -v -c '#{pane_current_path}'
22 |
23 | # Mouse mode on
24 | set -g mouse on
25 |
26 | # Vim style copy paste
27 | #setw -g mode-keys vi
28 | #bind-key -t vi-copy v begin-selection
29 | #bind-key -t vi-copy y copy-pipe "pbcopy"
30 | #unbind -t vi-copy Enter
31 | #bind-key -t vi-copy Enter copy-pipe "pbcopy"
32 | # Use vim keybindings in copy mode
33 | setw -g mode-keys vi
34 | # Select and copy with v and y, instead of default space and enter
35 | bind-key -T edit-mode-vi Up send-keys -X history-up
36 | bind-key -T edit-mode-vi Down send-keys -X history-down
37 | unbind-key -T copy-mode-vi Space ; bind-key -T copy-mode-vi v send-keys -X begin-selection
38 | unbind-key -T copy-mode-vi Enter ; bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "reattach-to-user-namespace pbcopy"
39 | unbind-key -T copy-mode-vi C-v ; bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle
40 | unbind-key -T copy-mode-vi [ ; bind-key -T copy-mode-vi [ send-keys -X begin-selection
41 | unbind-key -T copy-mode-vi ] ; bind-key -T copy-mode-vi ] send-keys -X copy-selection
42 |
43 | # Set title
44 | set -g set-titles on
45 | set -g set-titles-string "#T"
46 |
47 | set -g @resurrect-capture-pane-contents 'on'
48 | set -g @resurrect-strategy-vim 'session'
49 | set -g @resurrect-strategy-nvim 'session'
50 |
51 | set -g status-right '#{prefix_highlight} | %a %Y-%m-%d %H:%M'
52 | set -g @prefix_highlight_show_copy_mode 'on'
53 |
54 | set -g @continuum-save-interval '15'
55 | set -g @continuum-restore 'on'
56 |
57 | #------------------------------------------------------------------------------
58 | # Plugins
59 | #------------------------------------------------------------------------------
60 | set -g @plugin 'tmux-plugins/tpm'
61 | set -g @plugin 'tmux-plugins/tmux-resurrect'
62 | #set -g @plugin 'tmux-plugins/tmux-continuum'
63 | set -g @plugin 'tmux-plugins/tmux-sensible'
64 | set -g @plugin 'tmux-plugins/tmux-prefix-highlight'
65 | set -g @plugin 'tmux-plugins/tmux-copycat'
66 | set -g @plugin 'tmux-plugins/tmux-yank'
67 |
68 | run '~/.tmux/plugins/tpm/tpm'
69 |
--------------------------------------------------------------------------------
/.notmuch-config:
--------------------------------------------------------------------------------
1 | # .notmuch-config - Configuration file for the notmuch mail system
2 | #
3 | # For more information about notmuch, see https://notmuchmail.org
4 |
5 | # Database configuration
6 | #
7 | # The only value supported here is 'path' which should be the top-level
8 | # directory where your mail currently exists and to where mail will be
9 | # delivered in the future. Files should be individual email messages.
10 | # Notmuch will store its database within a sub-directory of the path
11 | # configured here named ".notmuch".
12 | #
13 |
14 | [database]
15 | path=/Users/api/Maildir
16 |
17 | # User configuration
18 | #
19 | # Here is where you can let notmuch know how you would like to be
20 | # addressed. Valid settings are
21 | #
22 | # name Your full name.
23 | # primary_email Your primary email address.
24 | # other_email A list (separated by ';') of other email addresses
25 | # at which you receive email.
26 | #
27 | # Notmuch will use the various email addresses configured here when
28 | # formatting replies. It will avoid including your own addresses in the
29 | # recipient list of replies, and will set the From address based on the
30 | # address to which the original email was addressed.
31 | #
32 |
33 | [user]
34 | name=Anand
35 | primary_email=anand.iyer.p@gmail.com
36 | other_email=anand.padmanabha.iyer@gmail.com;anand.ebiz@gmail.com;anand.iyer@berkeley.edu;api@cs.berkeley.edu;api@eecs.berkeley.edu
37 |
38 | # Configuration for "notmuch new"
39 | #
40 | # The following options are supported here:
41 | #
42 | # tags A list (separated by ';') of the tags that will be
43 | # added to all messages incorporated by "notmuch new".
44 | #
45 | # ignore A list (separated by ';') of file and directory names
46 | # that will not be searched for messages by "notmuch new".
47 | #
48 | # NOTE: *Every* file/directory that goes by one of those
49 | # names will be ignored, independent of its depth/location
50 | # in the mail store.
51 | #
52 |
53 | [new]
54 | tags=new
55 | ignore=*.json
56 |
57 | # Search configuration
58 | #
59 | # The following option is supported here:
60 | #
61 | # exclude_tags
62 | # A ;-separated list of tags that will be excluded from
63 | # search results by default. Using an excluded tag in a
64 | # query will override that exclusion.
65 | #
66 |
67 | [search]
68 | exclude_tags=deleted;spam;
69 |
70 | # Maildir compatibility configuration
71 | #
72 | # The following option is supported here:
73 | #
74 | # synchronize_flags Valid values are true and false.
75 | #
76 | # If true, then the following maildir flags (in message filenames)
77 | # will be synchronized with the corresponding notmuch tags:
78 | #
79 | # Flag Tag
80 | # ---- -------
81 | # D draft
82 | # F flagged
83 | # P passed
84 | # R replied
85 | # S unread (added when 'S' flag is not present)
86 | #
87 | # The "notmuch new" command will notice flag changes in filenames
88 | # and update tags, while the "notmuch tag" and "notmuch restore"
89 | # commands will notice tag changes and update flags in filenames
90 | #
91 |
92 | [maildir]
93 | synchronize_flags=true
94 |
--------------------------------------------------------------------------------
/.emacs.d/init.el:
--------------------------------------------------------------------------------
1 | ;;; init.el --- Emacs configuration of Anand Iyer -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | (defconst user-emacs-config-directory
9 | (expand-file-name (concat user-emacs-directory "config/"))
10 | "Directory for storing user's local files.")
11 |
12 | (defconst user-emacs-modules-directory
13 | (expand-file-name (concat user-emacs-directory "lisp/"))
14 | "Directory for storing modules.")
15 |
16 | (defconst user-emacs-data-directory
17 | (expand-file-name (concat user-emacs-directory "data/"))
18 | "Directory where cache files are stored.")
19 |
20 | (defconst user-emacs-temp-directory
21 | (expand-file-name (concat user-emacs-directory "tmp/"))
22 | "Directory where temp files are stored.")
23 |
24 | (defconst org-root-directory
25 | "~/Library/Mobile Documents/iCloud~com~appsonthemove~beorg/Documents/org-mode/"
26 | "Directory where org files are stored.")
27 |
28 | (setq-default load-prefer-newer t)
29 |
30 | (eval-and-compile
31 |
32 | ;; Temporarily change GC threshold and file handler alist.
33 | (when (version< emacs-version "27.0")
34 | (unless (or after-init-time noninteractive)
35 | (defvar api--file-name-handler-alist file-name-handler-alist)
36 | (setq gc-cons-threshold (* 512 1024 1024)
37 | gc-cons-percentage 1.0
38 | file-name-handler-alist nil)
39 | (defun api|reset-gc()
40 | (setq gc-cons-threshold (* 16 1024 1024)
41 | gc-cons-percentage 0.1
42 | file-name-handler-alist api--file-name-handler-alist))
43 | (add-hook 'emacs-startup-hook #'api|reset-gc)))
44 |
45 | (add-to-list 'load-path user-emacs-modules-directory)
46 |
47 | (require 'cl-lib)
48 |
49 | ;; useful functions and macros.
50 | (require 'init-utils)
51 | ;; calls (package-initialize)
52 | (require 'init-package)
53 | (require 'init-core)
54 | (require 'init-theme)
55 | (require 'init-fonts)
56 | (require 'init-ui)
57 | (require 'init-frames)
58 | (require 'init-windows)
59 | (require 'init-modeline)
60 | (require 'init-mac)
61 | (require 'init-editor)
62 | (require 'init-evil)
63 | (require 'init-keybindings)
64 |
65 | ;;(require 'setup-helm)
66 | (require 'setup-ivy)
67 |
68 | ;; Packages.
69 | (require 'setup-company)
70 | (require 'setup-flycheck)
71 | (require 'setup-yasnippet)
72 | (require 'setup-projectile)
73 | (require 'setup-spellcheck)
74 | (require 'setup-jump)
75 | (require 'setup-git)
76 | (require 'setup-org)
77 | (require 'setup-pdf)
78 | (require 'setup-tex)
79 | ;;(require 'setup-scala)
80 | (require 'setup-email)
81 | ;;(require 'setup-music)
82 |
83 | ;; Let emacsclients connect.
84 | (require 'server)
85 | (unless (server-running-p) (server-start))
86 |
87 | (when (file-exists-p custom-file)
88 | (load custom-file))
89 |
90 | (require 'init-locales))
91 |
92 | (provide 'init)
93 |
94 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
95 | ;;; init.el ends here
96 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-music.el:
--------------------------------------------------------------------------------
1 | ;;; setup-music.el --- Music control with Emacs -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | (setq mpc-host "localhost:6600")
9 |
10 | ;;------------------------------------------------------------------------------
11 | ;; `emms': Emacs Multimedia System
12 | ;;------------------------------------------------------------------------------
13 | (use-package emms
14 | :commands (emms
15 | emms-add-directory-tree
16 | emms-player-mpd-connect
17 | emms-cache-set-from-mpd-all
18 | emms-smart-browse
19 | emms-pause
20 | emms-next)
21 | :init
22 | (defun api/connect-to-music-daemon ()
23 | "Connect to MPD."
24 | (interactive)
25 | (emms-player-mpd-connect)
26 | (emms-cache-set-from-mpd-all)
27 | (message "EMMS connected to MPD!"))
28 | ;;(add-hook 'emacs-startup-hook #'api/connect-to-music-daemon)
29 | :config
30 | (require 'emms-setup)
31 | (require 'emms-player-mpd)
32 | (emms-all)
33 | (api/connect-to-music-daemon)
34 | (setq emms-source-file-default-directory "~/Music/beets/"
35 | emms-info-asynchronously t
36 | emms-show-format "♪ %s"
37 | emms-seek-seconds 5
38 | emms-player-list '(emms-player-mpd)
39 | emms-info-functions '(emms-info-mpd)
40 | emms-player-mpd-music-directory "~/Music/beets/"
41 | emms-player-mpd-server-name "localhost"
42 | emms-player-mpd-server-port "6600")
43 |
44 | (require 'emms-mode-line)
45 | (emms-mode-line 1)
46 | (require 'emms-playing-time)
47 | (emms-playing-time 1)
48 |
49 | (add-hook 'emms-browser-mode-hook 'evil-emacs-state)
50 | (add-hook 'emms-playlist-mode-hook 'evil-emacs-state))
51 |
52 | ;;------------------------------------------------------------------------------
53 | ;; `mingus': Frontend for GNU Emacs to the Music Player daemon.
54 | ;;------------------------------------------------------------------------------
55 | (use-package mingus
56 | :disabled ;; doesn't play well with mu4e.
57 | :commands (mingus
58 | mingus-browse)
59 | :init
60 | (setq mingus-mode-always-modeline t
61 | mingus-mode-line-show-status t
62 | mingus-mode-line-show-elapsed-time t
63 | mingus-mode-line-show-volume nil
64 | mingus-mode-line-separator
65 | (if window-system
66 | " ● "
67 | " + "))
68 | (add-hook 'mingus-browse-hook 'evil-emacs-state t)
69 | (add-hook 'mingus-playlist-hooks 'evil-emacs-state t))
70 |
71 | ;;------------------------------------------------------------------------------
72 | ;; `simple-mpc': Very simple frontend for MPD.
73 | ;;------------------------------------------------------------------------------
74 | (use-package simple-mpc
75 | :commands (simple-mpc)
76 | :config
77 | (evil-set-initial-state 'simple-mpc-mode 'emacs))
78 |
79 | (provide 'setup-music)
80 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
81 | ;;; setup-music.el ends here
82 |
--------------------------------------------------------------------------------
/.chunkwmrc:
--------------------------------------------------------------------------------
1 | ##!/bin/bash
2 |
3 | #
4 | # NOTE: specify the absolutepath of the file to use for logging.
5 | # 'stdout' and 'stderr' are valid values.
6 | #
7 |
8 | chunkc core::log_file stdout
9 |
10 | #
11 | # NOTE: specify the desired level of logging.
12 | #
13 | # - none, debug, warn, error
14 | #
15 |
16 | chunkc core::log_level warn
17 |
18 | #
19 | # NOTE: specify the absolutepath to the directory to use when
20 | # loading a plugin. '~' expansion is supported.
21 |
22 | chunkc core::plugin_dir /usr/local/opt/chunkwm/share/chunkwm/plugins
23 |
24 | #
25 | # NOTE: if enabled, chunkwm will monitor the specified plugin_dir
26 | # and automatically reload any '.so' file that is changed.
27 | #
28 |
29 | chunkc core::hotload 1
30 |
31 | #
32 | # NOTE: the following are config variables for the chunkwm-tiling plugin.
33 | #
34 |
35 | chunkc set global_desktop_mode bsp
36 |
37 | chunkc set global_desktop_offset_top 2
38 | chunkc set global_desktop_offset_bottom 2
39 | chunkc set global_desktop_offset_left 2
40 | chunkc set global_desktop_offset_right 2
41 | chunkc set global_desktop_offset_gap 2
42 |
43 | #
44 | # NOTE: shell commands require escaped quotes
45 | # to pass value containing a whitespace.
46 | #
47 |
48 | chunkc set desktop_padding_step_size 10.0
49 | chunkc set desktop_gap_step_size 5.0
50 |
51 | chunkc set bsp_spawn_left 0
52 | chunkc set bsp_optimal_ratio 1.618
53 | chunkc set bsp_split_mode optimal
54 | chunkc set bsp_split_ratio 0.5
55 |
56 | chunkc set monitor_focus_cycle 1
57 | chunkc set window_focus_cycle monitor
58 |
59 | chunkc set mouse_follows_focus intrinsic
60 | chunkc set window_float_next 0
61 | chunkc set window_region_locked 1
62 |
63 | chunkc set mouse_move_window \"ctrl cmd alt\"
64 | chunkc set mouse_resize_window \"ctrl cmd shift alt\"
65 | chunkc set mouse_motion_interval 35
66 |
67 | chunkc set preselect_border_color 0xffd75f5f
68 | chunkc set preselect_border_width 5
69 |
70 | #
71 | # NOTE: the following are config variables for the chunkwm-border plugin.
72 | #
73 |
74 | chunkc set focused_border_color 0xffc0b18b
75 | chunkc set focused_border_width 5
76 | chunkc set focused_border_radius 0
77 | chunkc set focused_border_skip_floating 0
78 |
79 |
80 | #
81 | # NOTE: the following are config variables for the chunkwm-ffm plugin.
82 | #
83 |
84 | chunkc set ffm_bypass_modifier \"ctrl cmd alt\"
85 | #chunkc set ffm_bypass_modifier fn
86 |
87 | #
88 | # NOTE: specify plugins to load when chunkwm starts.
89 | # if chunkc plugin_dir is not set, the absolutepath is necessary.
90 | #
91 |
92 | chunkc core::load tiling.so
93 | chunkc core::load ffm.so
94 | #chunkc core::load border.so
95 |
96 | #
97 | # Rules for the tiling plugin
98 | #
99 |
100 | chunkc tiling::rule --owner Finder --name Copy --state float
101 | chunkc tiling::rule --owner \"App Store\" --state float
102 | chunkc tiling::rule --owner Fantastical --state float
103 | #chunkc tiling::rule --owner Emacs --except "^$" --state tile
104 |
--------------------------------------------------------------------------------
/.dotfiles/README.md:
--------------------------------------------------------------------------------
1 | # Keep dotfiles where they belong and avoid symlinks entirely.
2 |
3 | This arrangement of dotfiles is taken from [here](https://news.ycombinator.com/item?id=11070797) and [here](https://developer.atlassian.com/blog/2016/02/best-way-to-store-dotfiles-git-bare-repo/). The idea is to keep all the dotfiles at their original locations, and avoid symlinks entirely (as opposed to the general approach of putting all config files in one directory and symlinking them with a script or GNU stow). Basically, we create a bare git repo and set the work-tree to be our `$HOME` directory. Then everytime we add a new config file to this repo, we do so specifying this work-tree (we make this easy by defining an alias command). This lets us keep the config files at their original locations, while also allowing them to be under version control. Here's how to do it:
4 |
5 | ## First time setup
6 | ```
7 | git init --bare $HOME/.dotfiles
8 | alias dotfiles='/usr/local/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
9 | dotfiles config --local status.showUntrackedFiles no
10 | dotfiles remote add origin git@github.com:anandpiyer/.dotfiles.git
11 | ```
12 | You'll need to change the remote URL to your git repo. You should also add the `dotfiles` alias command to your `.bashrc` or `.zshrc`. Now, you can use the `dotfiles` command to do git operation from anywhere in your $HOME directory:
13 |
14 | ### Operations
15 | ```
16 | cd $HOME
17 | dotfiles add .tmux.conf
18 | dotfiles commit -m "Add .tmux.conf"
19 | dotfiles push
20 | ```
21 | ## New machine setup
22 | To set up a new machine, clone the repo to a temporary directory. This is because you might have some default config files in your $HOME which will cause a normal clone to fail.
23 | ```
24 | git clone --separate-git-dir=$HOME/.dotfiles https://github.com/anandpiyer/.dotfiles.git tmpdotfiles
25 | rsync --recursive --verbose --exclude '.git' tmpdotfiles/ $HOME/
26 | rm -r tmpdotfiles
27 | ```
28 | ## Apps I use
29 |
30 | ### [FASD](https://github.com/clvv/fasd) + [FZF](https://github.com/junegunn/fzf)
31 | I use this combination to define a bunch of [zsh auto-functions](https://github.com/anandpiyer/.dotfiles/blob/master/.zshrc). For example, function `e` opens any file in `$EDITOR` (Emacs) using `fasd` (if `e` has no arguments) or `fzf` to filter the output of `fasd` (if `e` is used with an argument). Similarly, `o` opens finder and `j` jumps to directories using fuzzy matching.
32 |
33 | ### [Hammerspoon](http://www.hammerspoon.org/)
34 | Hammerspoon is used for both window management and app management. Specifically, I assign key combinations to my most frequently used apps for quick switching (e.g., hyper+e launches or focuses my Emacs). I also [use it](https://github.com/anandpiyer/.dotfiles/blob/b2ec2a12dfe6b8917e0304b728d680c06b06f5ba/.hammerspoon/init.lua#L20) to achieve Caffeine's functionality.
35 |
36 | ### [Karabiner-Elements](https://pqrs.org/osx/karabiner/)
37 | I use Karabiner-Elements for key remapping. Specifically, I remap my capslock
38 | key to both Esc (when pressed and released) and ctrl (when
39 | held). Since this frees my ctrl key, I remap ctrl to be my
40 | hyper key (shift+ctrl+option). This
41 | gives me two modifier keys: hyper and cmd+hyper.
42 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-pdf.el:
--------------------------------------------------------------------------------
1 | ;;; setup-pdf.el --- PDF -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 |
7 | ;;------------------------------------------------------------------------------
8 | ;; `pdf-tools':
9 | ;;------------------------------------------------------------------------------
10 | ;; use brew to install pdf-tools so that epdfinfo gets installed properly:
11 | ;; brew install pdf-tools
12 | ;; and set the path to epdfinfo from brew installation. To upgrade, do
13 | ;; 'brew upgrade pdf-tools' PRIOR to upgrading pdf-tools emacs package. If
14 | ;; things are messed up, uninstall brew pdf-tools, remove elpa pdf-tools and
15 | ;; start over.
16 | ;;------------------------------------------------------------------------------
17 | (use-package pdf-tools
18 | :if (display-graphic-p)
19 | :mode (("\\.pdf\\'" . pdf-view-mode))
20 | :bind
21 | (:map pdf-view-mode-map
22 | ("C-c h" . api@pdftools/body)
23 | ("C-s" . isearch-forward)) ;; swiper doesn't work properly.
24 | :init
25 | (load "pdf-tools-autoloads" nil t)
26 | :config
27 | (defhydra api@pdftools (:color blue :hint nil)
28 | "
29 | ╭───────────┐
30 | Move History Scale/Fit Annotations Search/Link Do │ PDF Tools │
31 | ╭──────────────────────────────────────────────────────────────────┴───────────╯
32 | ^^_g_^^ _B_ ^↧^ _+_ ^ ^ [_al_] list [_s_] search [_u_] revert buffer
33 | ^^^↑^^^ ^↑^ _H_ ^↑^ ↦ _W_ ↤ [_am_] markup [_o_] outline [_i_] info
34 | ^^_p_^^ ^ ^ ^↥^ _0_ ^ ^ [_at_] text [_F_] link [_d_] dark mode
35 | ^^^↑^^^ ^↓^ ╭─^─^─┐ ^↓^ ╭─^ ^─┐ [_ad_] delete [_f_] search link
36 | _h_ ←pag_e_→ _l_ _N_ │ _P_ │ _-_ _b_ [_aa_] dired
37 | ^^^↓^^^ ^ ^ ╰─^─^─╯ ^ ^ ╰─^ ^─╯ [_y_] yank
38 | ^^_n_^^ ^ ^ _r_eset slice box
39 | ^^^↓^^^
40 | ^^_G_^^
41 | --------------------------------------------------------------------------------
42 | "
43 | ("" nil "quit")
44 | ("al" pdf-annot-list-annotations)
45 | ("ad" pdf-annot-delete)
46 | ("aa" pdf-annot-attachment-dired)
47 | ("am" pdf-annot-add-markup-annotation)
48 | ("at" pdf-annot-add-text-annotation)
49 | ("y" pdf-view-kill-ring-save)
50 | ("+" pdf-view-enlarge :color red)
51 | ("-" pdf-view-shrink :color red)
52 | ("0" pdf-view-scale-reset)
53 | ("H" pdf-view-fit-height-to-window)
54 | ("W" pdf-view-fit-width-to-window)
55 | ("P" pdf-view-fit-page-to-window)
56 | ("n" pdf-view-next-page-command :color red)
57 | ("p" pdf-view-previous-page-command :color red)
58 | ("d" pdf-view-dark-minor-mode)
59 | ("b" pdf-view-set-slice-from-bounding-box)
60 | ("r" pdf-view-reset-slice)
61 | ("g" pdf-view-first-page)
62 | ("G" pdf-view-last-page)
63 | ("e" pdf-view-goto-page)
64 | ("o" pdf-outline)
65 | ("s" pdf-occur)
66 | ("i" pdf-misc-display-metadata)
67 | ("u" pdf-view-revert-buffer)
68 | ("F" pdf-links-action-perform)
69 | ("f" pdf-links-isearch-link)
70 | ("B" pdf-history-backward :color red)
71 | ("N" pdf-history-forward :color red)
72 | ("l" image-forward-hscroll :color red)
73 | ("h" image-backward-hscroll :color red))
74 | ;;:config
75 | (custom-set-variables '(pdf-tools-handle-upgrades nil))
76 | (setq pdf-view-resize-factor 1.1
77 | pdf-info-epdfinfo-program "/usr/local/bin/epdfinfo")
78 | (pdf-tools-install))
79 | (provide 'setup-pdf)
80 | ;;; setup-pdf.el ends here
81 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-package.el:
--------------------------------------------------------------------------------
1 | ;;; init-package.el --- Package related things -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;; Declare archives and bootstrap use-package.
6 |
7 | ;;; Code:
8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 |
10 | (setq package-archives '(("melpa" . "https://melpa.org/packages/")
11 | ;("melpa-stable" . "https://stable.melpa.org/packages/")
12 | ("gnu" . "https://elpa.gnu.org/packages/"))
13 | package-enable-at-startup nil
14 | package--init-file-ensured t)
15 |
16 | (eval-and-compile
17 | (setq use-package-verbose (not (bound-and-true-p byte-compile-current-file))))
18 |
19 | ;; Add the macro generated list of package.el loadpaths to load-path.
20 | (mapc #'(lambda (add) (add-to-list 'load-path add))
21 | (eval-when-compile
22 | ;; (require 'package)
23 | (package-initialize)
24 | ;; Install use-package if not installed yet.
25 | (unless (package-installed-p 'use-package)
26 | (package-refresh-contents)
27 | (package-install 'use-package))
28 | ;; (require 'use-package)
29 | (setq use-package-always-ensure t)
30 | (let ((package-user-dir-real (file-truename package-user-dir)))
31 | ;; The reverse is necessary, because outside we mapc
32 | ;; add-to-list element-by-element, which reverses.
33 | (nreverse (apply #'nconc
34 | ;; Only keep package.el provided loadpaths.
35 | (mapcar #'(lambda (path)
36 | (if (string-prefix-p package-user-dir-real path)
37 | (list path)
38 | nil))
39 | load-path))))))
40 |
41 | (setq use-package-always-defer t)
42 |
43 | ;; (if api-debug-enabled
44 | ;; (setq use-package-expand-minimally nil
45 | ;; use-package-compute-statistics t
46 | ;; use-package-minimum-reported-time 0.01
47 | ;; use-package-verbose (not (bound-and-true-p byte-compile-current-file)))
48 | ;; (setq use-package-verbose nil
49 | ;; use-package-expand-minimally t))
50 |
51 | (eval-when-compile (require 'use-package))
52 | ;;(require 'diminish)
53 | (require 'bind-key)
54 | ;;(use-package diminish)
55 | ;;(use-package bind-key)
56 | ;; so we can (require 'use-package) even in compiled emacs to e.g. read docs
57 | ;;(use-package use-package :commands use-package-autoload-keymap)
58 |
59 | ;;------------------------------------------------------------------------------
60 | ;; Allow loading packages after some other packages.
61 | ;;------------------------------------------------------------------------------
62 | ;; (defmacro after! (feature &rest body)
63 | ;; "After FEATURE is loaded, evaluate BODY. Supress warnings during compilation."
64 | ;; (declare (indent defun) (debug t))
65 | ;; `(,(if (or (not (bound-and-true-p byte-compile-current-file))
66 | ;; (if (symbolp feature)
67 | ;; (require feature nil :no-error)
68 | ;; (load feature :no-message :no-error)))
69 | ;; #'progn
70 | ;; #'with-no-warnings)
71 | ;; (with-eval-after-load ',feature ,@body)))
72 |
73 | ;;------------------------------------------------------------------------------
74 | ;; `paradox': Project for modernizing Emacs' Package Menu.
75 | ;;------------------------------------------------------------------------------
76 | (use-package paradox
77 | :hook ((emacs-startup . paradox-enable)))
78 |
79 | (provide 'init-package)
80 |
81 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
82 | ;;; init-package.el ends here
83 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-git.el:
--------------------------------------------------------------------------------
1 | ;;; setup-git.el --- git related packages -*- lexical-binding: t; -*-
2 | ;;; Commentary:
3 | ;;; Code:
4 |
5 | (use-package magit
6 | :after evil
7 | :commands (magit-status magit-blame)
8 | :config
9 | (setq magit-auto-revert-mode nil)
10 | ;; Switch to emacs state only while in `magit-blame-mode', then back when
11 | ;; its done (since it's a minor-mode).
12 | (add-hook 'magit-blame-mode-hook
13 | (evil-local-mode (if magit-blame-mode -1 +1))))
14 |
15 | ;; (use-package evil-magit
16 | ;; :after magit
17 | ;; :commands (evil-magit-init)
18 | ;; :init
19 | ;; ;; optional: this is the evil state that evil-magit will use
20 | ;; ;; (setq evil-magit-state 'normal)
21 | ;; ;; optional: disable additional bindings for yanking text
22 | ;; ;; (setq evil-magit-use-y-for-yank nil)
23 | ;; (require 'evil-magit))
24 |
25 | ;; Show git status in the fringe.
26 | (use-package git-gutter-fringe
27 | :disabled
28 | :ensure git-gutter
29 | :commands (git-gutter-mode)
30 | :hook ((prog-mode . api|git-gutter-maybe)
31 | (latex-mode . api|git-gutter-maybe)
32 | (text-mode . api|git-gutter-maybe)
33 | (conf-mode . api|git-gutter-maybe))
34 | :preface
35 | (defun api|git-gutter-maybe ()
36 | "Enable `git-gutter-mode' in non-remote buffers."
37 | (when (and (buffer-file-name)
38 | (not (file-remote-p (buffer-file-name))))
39 | (progn
40 | (require 'git-gutter-fringe)
41 | (git-gutter-mode +1))))
42 | ;; (dolist (hook '(prog-mode-hook
43 | ;; latex-mode-hook
44 | ;; text-mode-hook
45 | ;; conf-mode-hook))
46 | ;; (add-hook hook #'api|git-gutter-maybe))
47 |
48 | :config
49 | (defhydra api@git-gutter (:body-pre (git-gutter-mode 1)
50 | :hint nil)
51 | "
52 | ╭─────────────────┐
53 | Movement Hunk Actions Misc. │ gg: +%-4s(car (git-gutter:statistic))/ -%-3s(cdr (git-gutter:statistic)) │
54 | ╭──────────────────────────────────┴─────────────────╯
55 | ^_g_^ [_s_] stage [_R_] set start Rev
56 | ^_k_^ [_r_] revert
57 | ^↑ ^ [_m_] mark
58 | ^↓ ^ [_p_] popup ╭──────────────────────
59 | ^_j_^ │[_q_] quit
60 | ^_G_^ │[_Q_] Quit and disable"
61 | ("j" (progn (git-gutter:next-hunk 1)
62 | (recenter)))
63 | ("k" (progn (git-gutter:previous-hunk 1)
64 | (recenter)))
65 | ("g" (progn (goto-char (point-min))
66 | (git-gutter:next-hunk 1)))
67 | ("G" (progn (goto-char (point-min))
68 | (git-gutter:previous-hunk 1)))
69 | ("s" git-gutter:stage-hunk)
70 | ("r" git-gutter:revert-hunk)
71 | ("m" git-gutter:mark-hunk)
72 | ("p" git-gutter:popup-hunk)
73 | ("R" git-gutter:set-start-revision)
74 | ("q" nil :color blue)
75 | ("Q" (git-gutter-mode -1) :color blue))
76 |
77 | (setq-default fringes-outside-margins t)
78 |
79 | (fringe-helper-define 'git-gutter-fr:added '(center repeated)
80 | "XXX.....")
81 | (fringe-helper-define 'git-gutter-fr:modified '(center repeated)
82 | "XXX.....")
83 | (fringe-helper-define 'git-gutter-fr:deleted 'bottom
84 | "X......."
85 | "XX......"
86 | "XXX....."
87 | "XXXX....")
88 |
89 | ;; Update git-gutter on focus (in case I was using git externally)
90 | (add-hook 'focus-in-hook #'git-gutter:update-all-windows)
91 |
92 | (defun api|update-git-gutter ()
93 | "Refresh git-gutter on `ESC'. Return nil to prevent shadowing other
94 | `+evil-esc-hook' hooks."
95 | (when git-gutter-mode
96 | (git-gutter)
97 | nil))
98 | (add-hook '+evil-esc-hook #'api|update-git-gutter t))
99 |
100 | (provide 'setup-git)
101 | ;;; setup-git.el ends here
102 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-core.el:
--------------------------------------------------------------------------------
1 | ;;; core.el --- Core Emacs stuff -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | ;;------------------------------------------------------------------------------
9 | ;; `benchmark-init': Benchmark init files.
10 | ;;------------------------------------------------------------------------------
11 | (use-package benchmark-init
12 | :if (not (bound-and-true-p byte-compile-current-file))
13 | :init
14 | (require 'benchmark-init)
15 | ;; To disable collection of benchmark data after init is done.
16 | :hook (after-init . benchmark-init/deactivate))
17 |
18 | ;;------------------------------------------------------------------------------
19 | ;; `desktop': Allow saving sessions.
20 | ;;------------------------------------------------------------------------------
21 | (use-package desktop
22 | :disabled
23 | :ensure nil ;; in-built
24 | :init
25 | (progn
26 | (desktop-save-mode 1)
27 | (setq desktop-auto-save-timeout 60
28 | desktop-globals-to-save
29 | (append '((file-name-history . 100)
30 | (compile-history . 100)
31 | (command-history . 100)
32 | (extended-command-history . 100)
33 | (shell-command-history . 100)
34 | (query-replace-history . 100)
35 | (regexp-history . 100)
36 | (grep-history . 100)
37 | (minibuffer-history . 100))
38 | desktop-globals-to-save))))
39 |
40 | ;;------------------------------------------------------------------------------
41 | ;; `esup': Emacs Startup Profiler
42 | ;;------------------------------------------------------------------------------
43 | (use-package esup
44 | :commands (esup))
45 |
46 | ;;------------------------------------------------------------------------------
47 | ;; `fullscreen': Advice commands to execute fullscreen, restoring original
48 | ;; window setup when exiting.
49 | ;;------------------------------------------------------------------------------
50 | (use-package fullframe
51 | :init
52 | (defun api|init-fullframe ()
53 | (fullframe list-package quit-window))
54 | (add-hook 'emacs-startup-hook #'api|init-fullframe))
55 |
56 | ;;------------------------------------------------------------------------------
57 | ;; `helpful': better contextual help.
58 | ;;------------------------------------------------------------------------------
59 | (use-package helpful
60 | ;;:disabled
61 | :commands (helpful-callable
62 | helpful-key
63 | helpful-variable
64 | helpful-symbol)
65 | :bind
66 | (("C-h k" . helpful-key)
67 | ("C-h f" . helpful-callable)
68 | ("C-h v" . helpful-variable))
69 | :init
70 | (defalias #'describe-key #'helpful-key)
71 | (defalias #'describe-function #'helpful-callable)
72 | (defalias #'describe-variable #'helpful-variable)
73 | (defalias #'describe-symbol #'helpful-symbol))
74 |
75 | ;;------------------------------------------------------------------------------
76 | ;; `no-littering': do not litter emacs.d.
77 | ;;------------------------------------------------------------------------------
78 | (use-package no-littering
79 | :init
80 | (setq no-littering-etc-directory
81 | (expand-file-name "config/" user-emacs-directory))
82 | (setq no-littering-var-directory
83 | (expand-file-name "data/" user-emacs-directory))
84 | (require 'no-littering)
85 | (setq custom-file (no-littering-expand-etc-file-name "custom.el")))
86 |
87 | ;;------------------------------------------------------------------------------
88 | ;; `terminal-here': launch terminals at current file location.
89 | ;;------------------------------------------------------------------------------
90 | (use-package terminal-here
91 | :commands (terminal-here-launch terminal-here-project-launch))
92 |
93 | (provide 'init-core)
94 |
95 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
96 | ;;; init-core.el ends here
97 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-frames.el:
--------------------------------------------------------------------------------
1 | ;; init-frames.el --- Emacs frames -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | (setq-default
9 | ;; do not mess with frame size when altering fonts or settings.
10 | frame-inhibit-implied-resize t)
11 |
12 | ;;; Transparent titlebar
13 | ;; https://github.com/d12frosted/homebrew-emacs-plus/blob/master/Formula/emacs-plus.rb#L98
14 | ;; https://github.com/d12frosted/homebrew-emacs-plus/issues/55
15 | ;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Properties-in-Mode.html#Properties-in-Mode
16 | (when (memq window-system '(mac ns))
17 | ;;(add-to-list 'default-frame-alist '(ns-appearance . dark)) ; nil for dark text
18 | ;;(add-to-list 'default-frame-alist '(ns-transparent-titlebar . nil)))
19 | (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
20 | (add-to-list 'default-frame-alist '(ns-appearance . light)))
21 |
22 | ;;------------------------------------------------------------------------------
23 | ;; `frames-only-mode': Use frames only, no windows (use tiling managers).
24 | ;; http://compsoc.man.ac.uk/~shep/tearing-out-the-emacs-window-manager.html
25 | ;;------------------------------------------------------------------------------
26 | (use-package frames-only-mode
27 | :disabled
28 | :hook (emacs-startup . frames-only-mode))
29 | ;;:init
30 | ;;(add-hook 'emacs-startup-hook (lambda () (frames-only-mode t))))
31 | ;;:config (frames-only-mode t))
32 |
33 | ;;------------------------------------------------------------------------------
34 | ;; `nameframe': Use named frames.
35 | ;;------------------------------------------------------------------------------
36 | (use-package nameframe
37 | :commands (nameframe-frame-alist
38 | nameframe-get-frame
39 | nameframe-make-frame)
40 | :config (require 'nameframe))
41 |
42 | ;;------------------------------------------------------------------------------
43 | ;; `yequake': Drop-down emacs frames
44 | ;;------------------------------------------------------------------------------
45 | (use-package yequake
46 | :commands (yequake-toggle
47 | yequake-org-capture
48 | yequake-retoggle)
49 | :config
50 | (setq yequake-frames
51 | '(("Org" .
52 | ((name . "Org")
53 | (width . 0.9)
54 | (height . 0.8)
55 | (alpha . 0.95)
56 | (buffer-fns . ((lambda nil
57 | (or (get-buffer "*Org Agenda*")
58 | (save-excursion
59 | (org-agenda-list)
60 | (current-buffer))))
61 | split-window-horizontally
62 | "~/iCloud/beorg/org-mode/organizer.org"))
63 | (frame-parameters . ((undecorated . t)
64 | (skip-taskbar . t)
65 | (sticky . t)))))
66 | ("mu4e" .
67 | ((name . "mu4e")
68 | (width . 0.9)
69 | (height . 0.8)
70 | (alpha . 0.95)
71 | (buffer-fns . ((lambda nil
72 | (or (get-buffer "*mu4e-headers*")
73 | (get-buffer "*mu4e-main*")
74 | (save-excursion
75 | (mu4e)
76 | (current-buffer))))))
77 | (frame-parameters . ((undecorated . t)
78 | (skip-taskbar . t)
79 | (sticky . t)))))
80 | ("Capture" .
81 | ((name . "Capture")
82 | (width . 0.75)
83 | (height . 0.5)
84 | (alpha . 0.95)
85 | (buffer-fns . (yequake-org-capture))
86 | (frame-parameters . ((undecorated . t)
87 | (skip-taskbar . t)
88 | (sticky . t)))))
89 | )))
90 |
91 | (provide 'init-frames)
92 |
93 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
94 | ;;; init-frames.el ends here
95 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-projectile.el:
--------------------------------------------------------------------------------
1 | ;;; setup-projectile.el --- Projectile -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | ;;------------------------------------------------------------------------------
9 | ;; `counsel-projectile':
10 | ;;------------------------------------------------------------------------------
11 | (use-package counsel-projectile
12 | :after (counsel
13 | projectile)
14 | :commands (counsel-projectile
15 | counsel-projectile-find-file
16 | counsel-projectile-find-dir
17 | counsel-projectile-switch-to-buffer
18 | counsel-projectile-grep
19 | counsel-projectile-ag
20 | counsel-projectile-switch-project))
21 |
22 | ;;------------------------------------------------------------------------------
23 | ;; `projectile':
24 | ;;------------------------------------------------------------------------------
25 | (use-package projectile
26 | :hook (emacs-startup . projectile-mode)
27 | :init
28 | (setq projectile-sort-order 'recentf
29 | projectile-enable-caching (not noninteractive)
30 | projectile-indexing-method 'alien
31 | projectile-globally-ignored-files '(".DS_Store" "TAGS")
32 | projectile-globally-ignored-directories '("~/.emacs.d/elpa")
33 | projectile-globally-ignored-file-suffixes '(".elc" ".pyc" ".o"))
34 | :config
35 | ;; Don't consider my home dir as a project
36 | (add-to-list 'projectile-ignored-projects `,(concat (getenv "HOME") "/"))
37 |
38 | ;; Default rg arguments
39 | ;; https://github.com/BurntSushi/ripgrep
40 | (defconst api--rg-arguments
41 | `("--no-ignore-vcs" ;Ignore files/dirs ONLY from `.ignore'
42 | "--line-number" ;Line numbers
43 | "--smart-case"
44 | "--follow" ;Follow symlinks
45 | "--max-columns" "150" ;Emacs doesn't handle long line lengths very well
46 | "--ignore-file" ,(expand-file-name ".ignore" (getenv "HOME")))
47 | "Default rg arguments used in the functions in `counsel' and `projectile' packages.")
48 |
49 | (defun api*advice-projectile-use-rg ()
50 | "Always use `rg' for getting a list of all files in the project."
51 | (let* ((prj-user-ignore-name (expand-file-name
52 | (concat ".ignore." user-login-name)
53 | (projectile-project-root)))
54 | (prj-user-ignore (when (file-exists-p prj-user-ignore-name)
55 | (concat "--ignore-file " prj-user-ignore-name))))
56 | (mapconcat #'shell-quote-argument
57 | (if prj-user-ignore
58 | (append '("rg")
59 | api--rg-arguments
60 | `(,prj-user-ignore)
61 | '("--null" ;Output null separated results
62 | ;; Get names of all the to-be-searched files,
63 | ;; same as the "-g ''" argument in ag.
64 | "--files"))
65 | (append '("rg")
66 | api--rg-arguments
67 | '("--null"
68 | "--files")))
69 | " ")))
70 |
71 | (if (executable-find "rg")
72 | (advice-add 'projectile-get-ext-command :override #'api*advice-projectile-use-rg))
73 |
74 | (after! ivy
75 | (setq projectile-completion-system 'ivy))
76 |
77 | ;; (after! helm
78 | ;; (defvar helm-projectile-find-file-map (make-sparse-keymap))
79 | ;; (require 'helm-projectile)
80 | ;; (set-keymap-parent helm-projectile-find-file-map helm-map))
81 |
82 | (add-hook 'dired-before-readin-hook #'projectile-track-known-projects-find-file-hook))
83 |
84 | ;;------------------------------------------------------------------------------
85 | ;; `nameframe-projectile':
86 | ;;------------------------------------------------------------------------------
87 | (use-package nameframe-projectile
88 | :after (nameframe projectile)
89 | :hook (emacs-startup . nameframe-projectile-mode)
90 | :config
91 | (require 'nameframe-projectile))
92 |
93 | (provide 'setup-projectile)
94 |
95 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
96 | ;;; setup-projectile.el ends here
97 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-ivy.el:
--------------------------------------------------------------------------------
1 | ;;; setup-ivy.el --- Ivy setup -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;; Setup ivy and related packages.
6 |
7 | ;;; Code:
8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 |
10 | ;;------------------------------------------------------------------------------
11 | ;; Allow persisting ivy-views.
12 | ;;------------------------------------------------------------------------------
13 | (defconst ivy-views-file
14 | (expand-file-name (concat user-emacs-data-directory "ivy/ivy-views.el"))
15 | "File in which ivy-views will be saved.")
16 |
17 | ;;------------------------------------------------------------------------------
18 | ;; `ivy':
19 | ;;------------------------------------------------------------------------------
20 | (use-package ivy
21 | :ensure ivy-hydra
22 | :hook (emacs-startup . ivy-mode)
23 | :config
24 | (setq ivy-height 12
25 | ivy-do-completion-in-region nil
26 | ivy-wrap t
27 | ivy-fixed-height-minibuffer t
28 | ivy-use-virtual-buffers t
29 | smex-completion-method 'ivy
30 | ;; highlight til EOL
31 | ivy-format-function #'ivy-format-function-line
32 | ;; disable magic slash on non-match
33 | ivy-magic-slash-non-match-action nil
34 | ;; Do not show ^
35 | ivy-initial-inputs-alist nil)
36 |
37 | (defun api/save-ivy-views ()
38 | "Save ivy-views to file."
39 | (interactive)
40 | (with-temp-file ivy-views-file
41 | (prin1 ivy-views (current-buffer))
42 | (message "Saved ivy-views to file %s." ivy-views-file)))
43 |
44 | (defun api/load-ivy-views ()
45 | "Load ivy-views from file."
46 | (interactive)
47 | (if (file-exists-p ivy-views-file)
48 | (progn (setq ivy-views
49 | (with-temp-buffer (insert-file-contents ivy-views-file)
50 | (read (current-buffer))))
51 | (message "Loaded ivy-views from file %s." ivy-views-file))
52 | (message "File %s does not exist!" ivy-views-file)))
53 |
54 | (api/load-ivy-views))
55 |
56 | ;;------------------------------------------------------------------------------
57 | ;; `ivy-posframe':
58 | ;;------------------------------------------------------------------------------
59 | (use-package ivy-posframe
60 | ;;:disabled
61 | :hook (ivy-mode . ivy-posframe-mode)
62 | :config
63 | (defun api/ivy-posframe-get-size ()
64 | "Set the ivy-posframe size according to the current frame."
65 | (let ((height (or ivy-posframe-height (or ivy-height 10)))
66 | (width (min (or ivy-posframe-width 200) (round (* 0.99 (frame-width))))))
67 | (list :height height :width width :min-height height :min-width width)))
68 |
69 | (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-frame-top-center))
70 | ivy-fixed-height-minibuffer nil
71 | ivy-posframe-size-function 'api/ivy-posframe-get-size
72 | ;;ivy-posframe-width '(frame-width)
73 | ivy-posframe-border-width 10))
74 |
75 | ;;------------------------------------------------------------------------------
76 | ;; `ivy-rich': Show more info in ivy-switch-buffer.
77 | ;;------------------------------------------------------------------------------
78 | (use-package ivy-rich
79 | :commands (ivy-rich-switch-buffer-transformer)
80 | :hook (ivy-mode . ivy-rich-mode)
81 | :init
82 | (setq ivy-virtual-abbreviate 'full
83 | ivy-rich-switch-buffer-align-virtual-buffer t
84 | ivy-rich-path-style 'abbrev))
85 |
86 | ;;------------------------------------------------------------------------------
87 | ;; `swiper':
88 | ;;------------------------------------------------------------------------------
89 | (use-package swiper
90 | :commands (swiper
91 | swiper-all))
92 |
93 | ;;------------------------------------------------------------------------------
94 | ;; `counsel':
95 | ;;------------------------------------------------------------------------------
96 | (use-package counsel
97 | :commands (counsel-ag counsel-rg counsel-pt counsel-apropos counsel-bookmark
98 | counsel-describe-function counsel-describe-variable
99 | counsel-describe-face counsel-M-x counsel-file-jump
100 | counsel-find-file counsel-find-library counsel-info-lookup-symbol
101 | counsel-imenu counsel-recentf counsel-yank-pop
102 | counsel-descbinds counsel-org-capture counsel-grep-or-swiper)
103 | :config
104 | ;; Counsel resets the ivy-initial-inputs-alist to default, so
105 | ;; set it not to show ^.
106 | (setq ivy-initial-inputs-alist nil))
107 |
108 | ;;------------------------------------------------------------------------------
109 | ;; `smex': Used by counsel-M-x
110 | ;;------------------------------------------------------------------------------
111 | (use-package smex
112 | :commands (smex smex-major-mode-commands)
113 | :config
114 | (smex-initialize))
115 |
116 | (provide 'setup-ivy)
117 |
118 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
119 | ;;; setup-ivy.el ends here
120 |
--------------------------------------------------------------------------------
/.vimrc:
--------------------------------------------------------------------------------
1 | set nocompatible
2 |
3 | "------------------------------------------------------------------------------
4 | " Plugins
5 | " -----------------------------------------------------------------------------
6 |
7 | " Set up Plug if not present.
8 | if empty(glob('~/.vim/autoload/plug.vim'))
9 | silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs
10 | \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
11 | autocmd VimEnter * PlugInstall | source ~/.vimrc
12 | endif
13 |
14 | call plug#begin('~/.vim/plugged')
15 |
16 | Plug 'vim-airline/vim-airline'
17 | Plug 'vim-airline/vim-airline-themes'
18 | Plug 'altercation/vim-colors-solarized'
19 | Plug 'junegunn/seoul256.vim'
20 | Plug 'flazz/vim-colorschemes'
21 | Plug 'morhetz/gruvbox'
22 | Plug 'airblade/vim-gitgutter'
23 | Plug 'tpope/vim-vinegar'
24 | Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': '.install --all' }
25 | Plug '/usr/local/opt/fzf' | Plug 'junegunn/fzf.vim'
26 | Plug 'easymotion/vim-easymotion'
27 | Plug 'LaTeX-Box-Team/LaTeX-Box'
28 | Plug 'derekwyatt/vim-scala', { 'for': 'scala' }
29 | "if has('nvim')
30 | " Plug 'Shougo/deoplete.nvim', { 'do': ':UpdateRemotePlugins' }
31 | "else
32 | " Plug 'Shougo/deoplete.nvim'
33 | " Plug 'roxma/nvim-yarp'
34 | " Plug 'roxma/vim-hug-neovim-rpc'
35 | "endif
36 | Plug 'myusuf3/numbers.vim'
37 | Plug 'tpope/vim-obsession'
38 | Plug 'hecal3/vim-leader-guide'
39 | Plug 'mhinz/vim-startify'
40 | Plug 'scrooloose/nerdcommenter'
41 | Plug 'w0rp/ale'
42 |
43 | call plug#end()
44 |
45 | filetype plugin indent on
46 |
47 | "------------------------------------------------------------------------------
48 | " General
49 | " -----------------------------------------------------------------------------
50 |
51 | syntax enable " Enable syntax highlighting.
52 |
53 | if &encoding ==# 'latin1' && has('gui_running')
54 | set encoding=utf-8
55 | endif
56 | set autoindent " Indentation level for next line.
57 | set backspace=indent,eol,start " Be more flexible with backspace.
58 | set autoread " reload files when changed.
59 | set showmode " Don't show mode, for airline.
60 | set nowrap " Don't wrap lines.
61 | set incsearch " Incremental search.
62 | set ignorecase " Ignore case while searching.
63 | set number " Show line numbers.
64 | set nocursorline " Highlight current line.
65 | set ruler " Show where we are.
66 | set showmatch " Show matching brackets.
67 | set colorcolumn=80 " Guideline at 80th column.
68 | set shiftwidth=4 " 4 indents for tabs.
69 | set expandtab " Expand tabs to spaces.
70 | set tabstop=4 " 4 column indents.
71 | set softtabstop=4 " Insert mode tab and backspace use 4 spaces.
72 | set clipboard+=unnamed " Yank and paste with system clipboard.
73 | set laststatus=2 " Show status line.
74 | set wildmenu " Wildcard searches.
75 | set complete-=i " Ignore included files in complete.
76 | set smarttab " Use smarttabs.
77 | set nobackup " No need for backups.
78 | set nowb " No autobackup.
79 | set noswapfile " No swap.
80 |
81 | "------------------------------------------------------------------------------
82 | " Plugin related settings
83 | " -----------------------------------------------------------------------------
84 |
85 | " airline
86 | let g:airline#extensions#tabline#enabled=1
87 | let g:airline#extensions#tabline#fnamemod=':t'
88 | let g:airline_powerline_fonts=1
89 | let g:airline_theme='zenburn'
90 |
91 | " ALE
92 | let g:ale_sign_warning = '▲'
93 | let g:ale_sign_error = '✗'
94 | highlight link ALEWarningSign String
95 | highlight link ALEErrorSign Title
96 |
97 | " deoplete
98 | let g:deoplete#enable_at_startup=1
99 |
100 | " gruvbox
101 | let g:gruvbox_contrast_light='soft'
102 | let g:gruvbox_contrast_dark='soft'
103 |
104 | " seoul256
105 | let g:seoul256_background = 237
106 | let g:seoul256_light_background = 253
107 |
108 | "------------------------------------------------------------------------------
109 | " Key remaps
110 | "------------------------------------------------------------------------------
111 |
112 | let mapleader="\"
113 |
114 | nnoremap w :w
115 | inoremap w :w
116 | nnoremap bb :Buffers
117 | nnoremap bd :bd
118 | nnoremap :
119 | nnoremap e :Files
120 |
121 | ino jk
122 | cno jk
123 | vno v
124 |
125 | nnoremap :bnext
126 | nnoremap :bprevious
127 | nnoremap
128 | nnoremap
129 | nnoremap
130 | nnoremap
131 |
132 | " Reformat selected text (fill region)
133 | nnoremap fr gq
134 | " Reformat paragraph (fill paragraph)
135 | nnoremap fp gq}
136 |
137 | " Configure leader guide.
138 | let g:lmap = {}
139 | call leaderGuide#register_prefix_descriptions("", "g:lmap")
140 | nnoremap :LeaderGuide ''
141 | vnoremap :LeaderGuideVisual ''
142 |
143 | if has('gui_running')
144 | set lines=40
145 | set macligatures
146 | set guifont=PragmataPro:h14
147 | endif
148 |
149 | "set background=light
150 | "colorscheme gruvbox
151 | "colorscheme seoul256
152 | colorscheme zenburn
153 |
154 | let g:fzf_colors =
155 | \ { 'fg': ['fg', 'Normal'],
156 | \ 'bg': ['bg', 'Normal'],
157 | \ 'hl': ['fg', 'Comment'],
158 | \ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
159 | \ 'bg+': ['bg', 'CursorLine', 'CursorColumn'],
160 | \ 'hl+': ['fg', 'Statement'],
161 | \ 'info': ['fg', 'PreProc'],
162 | \ 'prompt': ['fg', 'Conditional'],
163 | \ 'pointer': ['fg', 'Exception'],
164 | \ 'marker': ['fg', 'Keyword'],
165 | \ 'spinner': ['fg', 'Label'],
166 | \ 'header': ['fg', 'Comment'] }
167 |
168 | if has('nvim')
169 | set termguicolors " Doesn't work with Terminal.app.
170 | let $NVIM_TUI_ENABLE_TRUE_COLOR=1
171 | endif
172 |
--------------------------------------------------------------------------------
/.mbsyncrc:
--------------------------------------------------------------------------------
1 | Create Slave
2 | Expunge Both
3 | SyncState *
4 |
5 | # IMAPAccount anand.iyer@berkeley.edu
6 | #
7 |
8 | IMAPAccount bmail
9 | Host imap.gmail.com
10 | User anand.iyer@berkeley.edu
11 | PassCmd "security find-generic-password -s emacs-email -a anand.iyer@berkeley.edu -w"
12 | SSLType IMAPS
13 | AuthMechs LOGIN
14 |
15 | IMAPStore bmail-remote
16 | Account bmail
17 |
18 | MaildirStore bmail-local
19 | Path ~/Maildir/bmail/
20 | Inbox ~/Maildir/bmail/Inbox
21 |
22 | Channel bmail-inbox
23 | Master :bmail-remote:"INBOX"
24 | Slave :bmail-local:"Inbox"
25 | #Patterns "INBOX"
26 |
27 | Channel bmail-all
28 | Master :bmail-remote:"[Gmail]/All Mail"
29 | Slave :bmail-local:all
30 |
31 | Channel bmail-drafts
32 | Master :bmail-remote:"[Gmail]/Drafts"
33 | Slave :bmail-local:drafts
34 |
35 | Channel bmail-sent
36 | Master :bmail-remote:"[Gmail]/Sent Mail"
37 | Slave :bmail-local:sent
38 |
39 | Channel bmail-trash
40 | Master :bmail-remote:"[Gmail]/Trash"
41 | Slave :bmail-local:trash
42 |
43 | Group bmail
44 | Channel bmail-all
45 | Channel bmail-inbox
46 | Channel bmail-drafts
47 | Channel bmail-sent
48 | Channel bmail-trash
49 |
50 | # IMAPAccount anand.padmanabha.iyer@gmail.com
51 | #
52 |
53 | IMAPAccount anand.padmanabha.iyer@gmail.com
54 | Host imap.gmail.com
55 | User anand.padmanabha.iyer@gmail.com
56 | PassCmd "security find-generic-password -s emacs-email -a anand.padmanabha.iyer@gmail.com -w"
57 | SSLType IMAPS
58 | AuthMechs LOGIN
59 |
60 | IMAPStore anand.padmanabha.iyer@gmail.com-remote
61 | Account anand.padmanabha.iyer@gmail.com
62 |
63 | MaildirStore anand.padmanabha.iyer@gmail.com-local
64 | Path ~/Maildir/anand.padmanabha.iyer@gmail.com/
65 | Inbox ~/Maildir/anand.padmanabha.iyer@gmail.com/inbox
66 |
67 | Channel anand.padmanabha.iyer@gmail.com-inbox
68 | Master :anand.padmanabha.iyer@gmail.com-remote:
69 | Slave :anand.padmanabha.iyer@gmail.com-local:
70 | Patterns "INBOX"
71 |
72 | Channel anand.padmanabha.iyer@gmail.com-all
73 | Master :anand.padmanabha.iyer@gmail.com-remote:"[Gmail]/All Mail"
74 | Slave :anand.padmanabha.iyer@gmail.com-local:all
75 |
76 | Channel anand.padmanabha.iyer@gmail.com-drafts
77 | Master :anand.padmanabha.iyer@gmail.com-remote:"[Gmail]/Drafts"
78 | Slave :anand.padmanabha.iyer@gmail.com-local:drafts
79 |
80 | Channel anand.padmanabha.iyer@gmail.com-sent
81 | Master :anand.padmanabha.iyer@gmail.com-remote:"[Gmail]/Sent Mail"
82 | Slave :anand.padmanabha.iyer@gmail.com-local:sent
83 |
84 | Channel anand.padmanabha.iyer@gmail.com-trash
85 | Master :anand.padmanabha.iyer@gmail.com-remote:"[Gmail]/Trash"
86 | Slave :anand.padmanabha.iyer@gmail.com-local:trash
87 |
88 | Group anand.padmanabha.iyer@gmail.com
89 | Channel anand.padmanabha.iyer@gmail.com-inbox
90 | Channel anand.padmanabha.iyer@gmail.com-all
91 | Channel anand.padmanabha.iyer@gmail.com-drafts
92 | Channel anand.padmanabha.iyer@gmail.com-sent
93 | Channel anand.padmanabha.iyer@gmail.com-trash
94 |
95 | # IMAPAccount anand.iyer.p@gmail.com
96 | #
97 |
98 | IMAPAccount anand.iyer.p@gmail.com
99 | Host imap.gmail.com
100 | User anand.iyer.p@gmail.com
101 | PassCmd "security find-generic-password -s emacs-email -a anand.iyer.p@gmail.com -w"
102 | SSLType IMAPS
103 | AuthMechs LOGIN
104 |
105 | IMAPStore anand.iyer.p@gmail.com-remote
106 | Account anand.iyer.p@gmail.com
107 |
108 | MaildirStore anand.iyer.p@gmail.com-local
109 | Path ~/Maildir/anand.iyer.p@gmail.com/
110 | Inbox ~/Maildir/anand.iyer.p@gmail.com/inbox
111 |
112 | Channel anand.iyer.p@gmail.com-inbox
113 | Master :anand.iyer.p@gmail.com-remote:
114 | Slave :anand.iyer.p@gmail.com-local:
115 | Patterns "INBOX"
116 |
117 | Channel anand.iyer.p@gmail.com-all
118 | Master :anand.iyer.p@gmail.com-remote:"[Gmail]/All Mail"
119 | Slave :anand.iyer.p@gmail.com-local:all
120 |
121 | Channel anand.iyer.p@gmail.com-drafts
122 | Master :anand.iyer.p@gmail.com-remote:"[Gmail]/Drafts"
123 | Slave :anand.iyer.p@gmail.com-local:drafts
124 |
125 | Channel anand.iyer.p@gmail.com-sent
126 | Master :anand.iyer.p@gmail.com-remote:"[Gmail]/Sent Mail"
127 | Slave :anand.iyer.p@gmail.com-local:sent
128 |
129 | Channel anand.iyer.p@gmail.com-trash
130 | Master :anand.iyer.p@gmail.com-remote:"[Gmail]/Trash"
131 | Slave :anand.iyer.p@gmail.com-local:trash
132 |
133 | Group anand.iyer.p@gmail.com
134 | Channel anand.iyer.p@gmail.com-inbox
135 | Channel anand.iyer.p@gmail.com-all
136 | Channel anand.iyer.p@gmail.com-drafts
137 | Channel anand.iyer.p@gmail.com-sent
138 | Channel anand.iyer.p@gmail.com-trash
139 |
140 | # IMAPAccount sand.rain.online@gmail.com
141 | #
142 |
143 | IMAPAccount sand.rain.online@gmail.com
144 | Host imap.gmail.com
145 | User sand.rain.online@gmail.com
146 | PassCmd "security find-generic-password -s emacs-email -a sand.rain.online@gmail.com -w"
147 | SSLType IMAPS
148 | AuthMechs LOGIN
149 |
150 | IMAPStore sand.rain.online@gmail.com-remote
151 | Account sand.rain.online@gmail.com
152 |
153 | MaildirStore sand.rain.online@gmail.com-local
154 | Path ~/Maildir/sand.rain.online@gmail.com/
155 | Inbox ~/Maildir/sand.rain.online@gmail.com/INBOX
156 |
157 | Channel sand.rain.online@gmail.com-inbox
158 | Master :sand.rain.online@gmail.com-remote:
159 | Slave :sand.rain.online@gmail.com-local:
160 | Patterns "INBOX"
161 |
162 | Channel sand.rain.online@gmail.com-all
163 | Master :sand.rain.online@gmail.com-remote:"[Gmail]/All Mail"
164 | Slave :sand.rain.online@gmail.com-local:all
165 |
166 | Channel sand.rain.online@gmail.com-drafts
167 | Master :sand.rain.online@gmail.com-remote:"[Gmail]/Drafts"
168 | Slave :sand.rain.online@gmail.com-local:drafts
169 |
170 | Channel sand.rain.online@gmail.com-sent
171 | Master :sand.rain.online@gmail.com-remote:"[Gmail]/Sent Mail"
172 | Slave :sand.rain.online@gmail.com-local:sent
173 |
174 | Channel sand.rain.online@gmail.com-trash
175 | Master :sand.rain.online@gmail.com-remote:"[Gmail]/Trash"
176 | Slave :sand.rain.online@gmail.com-local:trash
177 |
178 | Group sand.rain.online@gmail.com
179 | Channel sand.rain.online@gmail.com-inbox
180 | Channel sand.rain.online@gmail.com-all
181 | Channel sand.rain.online@gmail.com-drafts
182 | Channel sand.rain.online@gmail.com-sent
183 | Channel sand.rain.online@gmail.com-trash
184 |
185 | # Gmail mailboxes:
186 | # "All Mail"
187 | # "Drafts"
188 | # "Important"
189 | # "Sent Mail"
190 | # "Spam"
191 | # "Starred"
192 | # "Trash"
193 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #===============================================================================
2 | # MacOS
3 | #===============================================================================
4 | # General
5 | .DS_Store
6 | .AppleDouble
7 | .LSOverride
8 |
9 | # Icon must end with two \r
10 | Icon
11 |
12 | # Thumbnails
13 | ._*
14 |
15 | # Files that might appear in the root of a volume
16 | .DocumentRevisions-V100
17 | .fseventsd
18 | .Spotlight-V100
19 | .TemporaryItems
20 | .Trashes
21 | .VolumeIcon.icns
22 | .com.apple.timemachine.donotpresent
23 |
24 | # Directories potentially created on remote AFP share
25 | .AppleDB
26 | .AppleDesktop
27 | Network Trash Folder
28 | Temporary Items
29 | .apdisk
30 |
31 | #===============================================================================
32 | # JetBrains
33 | #===============================================================================
34 | # Idea
35 | .idea
36 |
37 | #===============================================================================
38 | # Latex
39 | #===============================================================================
40 | ## Core latex/pdflatex auxiliary files:
41 | *.aux
42 | *.lof
43 | *.log
44 | *.lot
45 | *.fls
46 | *.out
47 | *.toc
48 | *.fmt
49 | *.fot
50 | *.cb
51 | *.cb2
52 | .*.lb
53 |
54 | ## Intermediate documents:
55 | *.dvi
56 | *.xdv
57 | *-converted-to.*
58 |
59 | ## Bibliography auxiliary files (bibtex/biblatex/biber):
60 | *.bbl
61 | *.bcf
62 | *.blg
63 | *-blx.aux
64 | *-blx.bib
65 | *.run.xml
66 |
67 | ## Build tool auxiliary files:
68 | *.fdb_latexmk
69 | *.synctex
70 | *.synctex(busy)
71 | *.synctex.gz
72 | *.synctex.gz(busy)
73 | *.pdfsync
74 |
75 | # minted
76 | _minted*
77 | *.pyg
78 |
79 | # auto folder when using emacs and auctex
80 | ./auto/*
81 | *.el
82 |
83 | #===============================================================================
84 | # Sublime Text
85 | #===============================================================================
86 | # Cache files for Sublime Text
87 | *.tmlanguage.cache
88 | *.tmPreferences.cache
89 | *.stTheme.cache
90 |
91 | # Workspace files are user-specific
92 | *.sublime-workspace
93 |
94 | # SFTP configuration file
95 | sftp-config.json
96 |
97 | # Package control specific files
98 | Package Control.last-run
99 | Package Control.ca-list
100 | Package Control.ca-bundle
101 | Package Control.system-ca-bundle
102 | Package Control.cache/
103 | Package Control.ca-certs/
104 | Package Control.merged-ca-bundle
105 | Package Control.user-ca-bundle
106 | oscrypto-ca-bundle.crt
107 | bh_unicode_properties.cache
108 |
109 | # Sublime-github package stores a github token in this file
110 | # https://packagecontrol.io/packages/sublime-github
111 | GitHub.sublime-settings
112 |
113 | #===============================================================================
114 | # Emacs
115 | #===============================================================================
116 | # -*- mode: gitignore; -*-
117 | *~
118 | \#*\#
119 | /.emacs.desktop
120 | /.emacs.desktop.lock
121 | *.elc
122 | auto-save-list
123 | tramp
124 | .\#*
125 |
126 | # Org-mode
127 | .org-id-locations
128 | *_archive
129 |
130 | # flymake-mode
131 | *_flymake.*
132 |
133 | # eshell files
134 | /eshell/history
135 | /eshell/lastdir
136 |
137 | # elpa packages
138 | /elpa/
139 |
140 | # reftex files
141 | *.rel
142 |
143 | # AUCTeX auto folder
144 | /auto/
145 |
146 | # cask packages
147 | .cask/
148 | dist/
149 |
150 | # Flycheck
151 | flycheck_*.el
152 |
153 | # server auth directory
154 | /server/
155 |
156 | # projectiles files
157 | .projectile
158 |
159 | # directory configuration
160 | .dir-locals.el
161 |
162 | #===============================================================================
163 | # Python
164 | #===============================================================================
165 | # Byte-compiled / optimized / DLL files
166 | __pycache__/
167 | *.py[cod]
168 | *$py.class
169 |
170 | # C extensions
171 | *.so
172 |
173 | # Distribution / packaging
174 | .Python
175 | build/
176 | develop-eggs/
177 | dist/
178 | downloads/
179 | eggs/
180 | .eggs/
181 | lib/
182 | lib64/
183 | parts/
184 | sdist/
185 | var/
186 | wheels/
187 | share/python-wheels/
188 | *.egg-info/
189 | .installed.cfg
190 | *.egg
191 | MANIFEST
192 |
193 | # PyInstaller
194 | # Usually these files are written by a python script from a template
195 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
196 | *.manifest
197 | *.spec
198 |
199 | # Installer logs
200 | pip-log.txt
201 | pip-delete-this-directory.txt
202 |
203 | # Unit test / coverage reports
204 | htmlcov/
205 | .tox/
206 | .nox/
207 | .coverage
208 | .coverage.*
209 | .cache
210 | nosetests.xml
211 | coverage.xml
212 | *.cover
213 | *.py,cover
214 | .hypothesis/
215 | .pytest_cache/
216 | cover/
217 |
218 | # Translations
219 | *.mo
220 | *.pot
221 |
222 | # Django stuff:
223 | *.log
224 | local_settings.py
225 | db.sqlite3
226 | db.sqlite3-journal
227 |
228 | # Flask stuff:
229 | instance/
230 | .webassets-cache
231 |
232 | # Scrapy stuff:
233 | .scrapy
234 |
235 | # Sphinx documentation
236 | docs/_build/
237 |
238 | # PyBuilder
239 | .pybuilder/
240 | target/
241 |
242 | # Jupyter Notebook
243 | .ipynb_checkpoints
244 |
245 | # IPython
246 | profile_default/
247 | ipython_config.py
248 |
249 | # pyenv
250 | # For a library or package, you might want to ignore these files since the code is
251 | # intended to run in multiple environments; otherwise, check them in:
252 | # .python-version
253 |
254 | # pipenv
255 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
256 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
257 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
258 | # install all needed dependencies.
259 | #Pipfile.lock
260 |
261 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
262 | __pypackages__/
263 |
264 | # Celery stuff
265 | celerybeat-schedule
266 | celerybeat.pid
267 |
268 | # SageMath parsed files
269 | *.sage.py
270 |
271 | # Environments
272 | .env
273 | .venv
274 | env/
275 | venv/
276 | ENV/
277 | env.bak/
278 | venv.bak/
279 |
280 | # Spyder project settings
281 | .spyderproject
282 | .spyproject
283 |
284 | # Rope project settings
285 | .ropeproject
286 |
287 | # mkdocs documentation
288 | /site
289 |
290 | # mypy
291 | .mypy_cache/
292 | .dmypy.json
293 | dmypy.json
294 |
295 | # Pyre type checker
296 | .pyre/
297 |
298 | # pytype static type analyzer
299 | .pytype/
300 |
301 | # Cython debug symbols
302 | cython_debug/
303 |
304 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-tex.el:
--------------------------------------------------------------------------------
1 | ;;; setup-tex.el --- latex configuration -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 |
7 | ;;------------------------------------------------------------------------------
8 | ;; Defaults & Helpers
9 | ;;------------------------------------------------------------------------------
10 | (put 'TeX-command-extra-options 'safe-local-variable #'string)
11 |
12 | (defun api/current-bib ()
13 | "Set the bibliography to the current directory."
14 | (interactive)
15 | (let ((local-bib-file (concat (file-name-directory buffer-file-name) "references.bib")))
16 | (if (file-exists-p local-bib-file)
17 | (progn
18 | (setq bibtex-completion-bibliography local-bib-file)
19 | (message (concat "Local bib file is " local-bib-file)))
20 | (message "Local bib file references.bib not found!"))))
21 |
22 | ;;------------------------------------------------------------------------------
23 | ;; `auctex-latexmk': Latex Mk support for AUCTeX
24 | ;;------------------------------------------------------------------------------
25 | (use-package auctex-latexmk
26 | :commands (auctex-latexmk-setup)
27 | ;;:disabled
28 | :init
29 | (setq auctex-latexmk-inherit-TeX-PDF-mode t)
30 | (add-hook 'emacs-startup-hook #'auctex-latexmk-setup))
31 |
32 | ;;------------------------------------------------------------------------------
33 | ;; `bibtex':
34 | ;;------------------------------------------------------------------------------
35 | (use-package bibtex
36 | :ensure nil ; in-built
37 | :mode ("\\.bib" . bibtex-mode)
38 | :config
39 | (setq bibtex-dialect 'biblatex
40 | bibtex-align-at-equal-sign t
41 | bibtex-autokey-name-year-separator ""
42 | bibtex-autokey-year-title-separator ""
43 | bibtex-autokey-titleword-first-ignore '("the" "a" "if" "and" "an")
44 | bibtex-autokey-titleword-length 0
45 | bibtex-autokey-titlewords 0
46 | bibtex-autokey-year-length 4))
47 |
48 | ;;------------------------------------------------------------------------------
49 | ;; `company-auctex':
50 | ;;------------------------------------------------------------------------------
51 | (use-package company-auctex
52 | :after company
53 | :init
54 | (defun api|add-company-auctex-backend ()
55 | "Add company-auctex to company backends."
56 | (make-variable-buffer-local 'company-backends)
57 | (company-auctex-init))
58 | (add-hook 'latex-mode-hook #'api|add-company-auctex-backend))
59 |
60 | ;;------------------------------------------------------------------------------
61 | ;; `helm-bibtex':
62 | ;;------------------------------------------------------------------------------
63 | ;; (use-package helm-bibtex
64 | ;; :disabled
65 | ;; :requires helm
66 | ;; :commands helm-bibtex
67 | ;; :init
68 | ;; (setq bibtex-completion-bibliography `(,(concat org-root-directory "papers/references.bib"))
69 | ;; bibtex-completion-library-path (concat org-root-directory "papers/pdfs")
70 | ;; bibtex-completion-notes-path (concat org-root-directory "papers/notes.org")))
71 |
72 | ;;------------------------------------------------------------------------------
73 | ;; `ivy-bibtex':
74 | ;;------------------------------------------------------------------------------
75 | (use-package ivy-bibtex
76 | :after ivy
77 | :commands (ivy-bibtex
78 | ivy-bibtex-with-local-bibliography)
79 | :config
80 | (setq bibtex-completion-bibliography `(,(concat org-root-directory "papers/references.bib"))
81 | bibtex-completion-library-path (concat org-root-directory "papers/pdfs")
82 | bibtex-completion-notes-path (concat org-root-directory "papers/notes.org"))
83 | (setq ivy-bibtex-default-action 'ivy-bibtex-insert-key))
84 |
85 | ;;------------------------------------------------------------------------------
86 | ;; `reftex':
87 | ;;------------------------------------------------------------------------------
88 | (use-package reftex
89 | :ensure nil ; in-built
90 | :commands (turn-on-reftex)
91 | :init
92 | (setq reftex-plug-into-AUCTeX t)
93 | (add-hook 'LaTeX-mode-hook #'turn-on-reftex))
94 |
95 | ;;------------------------------------------------------------------------------
96 | ;; `tex':
97 | ;;------------------------------------------------------------------------------
98 | (use-package tex
99 | :ensure auctex
100 | :mode ("\\.tex\\'" . latex-mode)
101 | :init
102 | (setq TeX-auto-save t
103 | TeX-parse-self t
104 | TeX-save-query nil
105 | TeX-PDF-mode t
106 | ;;TeX-show-compilation t
107 | TeX-view-program-selection '((output-pdf "PDF Viewer"))
108 | ;;TeX-view-program-selection '((output-pdf "PDF Tools"))
109 | TeX-source-correlate-start-server t
110 | TeX-source-correlate-method 'synctex
111 | TeX-syntactic-comment t
112 | LaTeX-fill-break-at-separators nil
113 | LaTeX-section-hook
114 | '(LaTeX-section-heading
115 | LaTeX-section-title
116 | LaTeX-section-toc
117 | LaTeX-section-section
118 | LaTeX-section-label))
119 |
120 | (defadvice TeX-LaTeX-sentinel
121 | (around mg-TeX-LaTeX-sentinel-open-output activate)
122 | "Open output when there are errors."
123 | ;; Run `TeX-LaTeX-sentinel' as usual.
124 | ad-do-it
125 | ;; Check for the presence of errors.
126 | (when
127 | (with-current-buffer TeX-command-buffer
128 | (plist-get TeX-error-report-switches (intern (TeX-master-file))))
129 | ;; If there are errors, open the output buffer.
130 | (TeX-recenter-output-buffer nil)))
131 |
132 | (setq-default TeX-master nil)
133 | ;;(setq LaTeX-command-style '(("" "%(PDF)%(latex) -synctex=1 %(file-line-error) %(extraopts) %S%(PDFout)")))
134 | (add-hook 'LaTeX-mode-hook 'TeX-PDF-mode)
135 | (add-hook 'LaTeX-mode-hook 'LaTeX-math-mode)
136 | (add-hook 'LaTeX-mode-hook 'TeX-source-correlate-mode)
137 | (add-hook 'LaTeX-mode-hook 'LaTeX-preview-setup)
138 | (add-hook 'LaTeX-mode-hook #'turn-on-auto-fill)
139 | (add-hook 'LaTeX-mode-hook
140 | (lambda () (local-set-key (kbd "") #'TeX-view))
141 | )
142 | :config
143 | (setq TeX-view-program-list
144 | '(("PDF Viewer" "/Applications/Skim.app/Contents/SharedSupport/displayline -b -g %n %o %b")))
145 | (unless (assoc "PDF Tools" TeX-view-program-list-builtin)
146 | (push '("PDF Tools" TeX-pdf-tools-sync-view) TeX-view-program-list))
147 | ;;(add-hook 'LaTeX-mode-hook (lambda () (setq compile-command "latexmk -pdf")))
148 | (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer))
149 |
150 | ;;------------------------------------------------------------------------------
151 | ;; `writegood-mode': Improve English writing.
152 | ;;
153 | ;; http://matt.might.net/articles/shell-scripts-for-passive-voice-weasel-words-duplicates/
154 | ;;------------------------------------------------------------------------------
155 | (use-package writegood-mode
156 | :hook (LaTeX-mode . writegood-mode))
157 |
158 | (provide 'setup-tex)
159 | ;;; setup-tex.el ends here
160 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-evil.el:
--------------------------------------------------------------------------------
1 | ;;; init-evil.el --- Evil settings -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | ;;------------------------------------------------------------------------------
9 | ;; `evil': Extensible vi layer.
10 | ;;------------------------------------------------------------------------------
11 | (use-package evil
12 | :hook (after-init . evil-mode)
13 | :init
14 | (setq evil-want-C-u-scroll t
15 | evil-want-visual-char-semi-exclusive t
16 | evil-want-Y-yank-to-eol t
17 | evil-magic t
18 | evil-echo-state t
19 | evil-indent-convert-tabs t
20 | evil-ex-search-vim-style-regexp t
21 | evil-ex-substitute-global t
22 | evil-ex-visual-char-range t ; column range for ex commands
23 | evil-insert-skip-empty-lines t
24 | evil-mode-line-format 'nil
25 | ;; more vim-like behavior
26 | evil-symbol-word-search t
27 | ;; don't activate mark on shift-click
28 | shift-select-mode nil)
29 |
30 | :config
31 | (evil-select-search-module 'evil-search-module 'evil-search)
32 |
33 | ;; Set cursor colors later, once theme is loaded
34 | (defun +evil*init-cursors (&rest _)
35 | (setq evil-default-cursor (face-background 'cursor nil t)
36 | evil-normal-state-cursor 'box
37 | evil-emacs-state-cursor `(,(face-foreground 'warning) box)
38 | evil-insert-state-cursor 'bar
39 | evil-visual-state-cursor 'hollow))
40 | (advice-add #'load-theme :after #'+evil*init-cursors)
41 |
42 | ;; default modes
43 | (dolist (mode '(tabulated-list-mode view-mode comint-mode
44 | term-mode calendar-mode Man-mode grep-mode))
45 | (evil-set-initial-state mode 'emacs))
46 | (dolist (mode '(help-mode debugger-mode))
47 | (evil-set-initial-state mode 'normal)))
48 |
49 | ;;------------------------------------------------------------------------------
50 | ;; `evil-collection': Set of keybindings for evil.
51 | ;;------------------------------------------------------------------------------
52 | (use-package evil-collection
53 | :disabled ;; TODO: Too many bugs, wait for stabilization.
54 | ;; :requires (helm) ; if evil-collection is installed before helm, helm craps out.
55 | :after (evil)
56 | :preface
57 | (setq evil-want-integration nil ; must be set before evil is loaded
58 | evil-collection-company-use-tng nil)
59 | :config
60 | (evil-collection-init))
61 |
62 | ;;------------------------------------------------------------------------------
63 | ;; `evil-escape': Key sequence to escape from insert state and everything else.
64 | ;;------------------------------------------------------------------------------
65 | (use-package evil-escape
66 | :after evil
67 | :hook (after-init . evil-escape-mode)
68 | :config
69 | (setq evil-escape-excluded-states '(normal visual multiedit emacs motion)
70 | evil-escape-excluded-major-modes '(neotree-mode)
71 | evil-escape-key-sequence "fd"
72 | evil-escape-delay 0.25))
73 |
74 | ;;------------------------------------------------------------------------------
75 | ;; `evil-goggles': Displays a visual hint when editing with evil.
76 | ;;------------------------------------------------------------------------------
77 | (use-package evil-goggles
78 | :after evil
79 | :hook (after-init . evil-goggles-mode)
80 | :config
81 | (setq evil-goggles-duration 0.1
82 | evil-goggles-pulse nil
83 | evil-goggles-enable-delete nil))
84 |
85 | ;;------------------------------------------------------------------------------
86 | ;; `evil-matchit': Press “%” to jump between matched tags in Emacs.
87 | ;;------------------------------------------------------------------------------
88 | (use-package evil-matchit
89 | :after evil
90 | :hook (emacs-startup . global-evil-matchit-mode))
91 | ;;:init
92 | ;;(add-hook 'emacs-startup-hook #'global-evil-matchit-mode))
93 |
94 | ;;------------------------------------------------------------------------------
95 | ;; `evil-mc': Multiple cursors implementation for evil-mode.
96 | ;;------------------------------------------------------------------------------
97 | (use-package evil-mc
98 | :after hydra
99 | :commands (evil-mc-make-all-cursors
100 | evil-mc-undo-all-cursors
101 | evil-mc-pause-cursors
102 | evil-mc-resume-cursors
103 | evil-mc-make-and-goto-first-cursor
104 | evil-mc-make-and-goto-last-cursor
105 | evil-mc-make-cursor-here
106 | evil-mc-make-cursor-move-next-line
107 | evil-mc-make-cursor-move-prev-line
108 | evil-mc-make-and-goto-next-cursor
109 | evil-mc-skip-and-goto-next-cursor
110 | evil-mc-make-and-goto-prev-cursor
111 | evil-mc-skip-and-goto-prev-cursor
112 | evil-mc-make-and-goto-next-match
113 | evil-mc-skip-and-goto-next-match
114 | evil-mc-make-and-goto-prev-match
115 | evil-mc-skip-and-goto-prev-match)
116 | :init
117 | ;(defvar evil-mc-key-map (make-sparse-keymap))
118 | ;; remove emc prefix when there is not multiple cursors
119 | (setq evil-mc-undo-cursors-on-keyboard-quit t
120 | evil-mc-mode-line
121 | `(:eval (when (> (evil-mc-get-cursor-count) 1)
122 | (format ,(propertize " %s:%d" 'face 'cursor)
123 | evil-mc-mode-line-prefix
124 | (evil-mc-get-cursor-count)))))
125 | (defhydra api@multiple-cursors (:hint nil)
126 | "
127 | ^Up^ ^Down^ ^Miscellaneous^
128 | ----------------------------------------------
129 | [_p_] Next [_n_] Next [_a_] Match all
130 | [_P_] Skip [_N_] Skip [_q_] Quit
131 | "
132 | ("a" evil-mc-make-all-cursors)
133 | ("n" evil-mc-make-and-goto-next-match)
134 | ("N" evil-mc-skip-and-goto-next-match)
135 | ("p" evil-mc-make-and-goto-prev-match)
136 | ("P" evil-mc-skip-and-goto-prev-match)
137 | ("q" nil))
138 |
139 | :config
140 | (global-evil-mc-mode 1)
141 |
142 | (defun api|escape-multiple-cursors ()
143 | "Clear evil-mc cursors and restore state."
144 | (when (evil-mc-has-cursors-p)
145 | (evil-mc-undo-all-cursors)
146 | (evil-mc-resume-cursors)
147 | t))
148 | (advice-add #'evil-force-normal-state :after #'api|escape-multiple-cursors))
149 |
150 | ;;------------------------------------------------------------------------------
151 | ;; `evil-multiedit': Multiedit capability in evil.
152 | ;;------------------------------------------------------------------------------
153 | (use-package evil-multiedit
154 | :commands (evil-multiedit-match-all
155 | evil-multiedit-match-and-next
156 | evil-multiedit-match-and-prev
157 | evil-multiedit-match-symbol-and-next
158 | evil-multiedit-match-symbol-and-prev
159 | evil-multiedit-toggle-marker-here
160 | evil-multiedit-toggle-or-restrict-region
161 | evil-multiedit-next
162 | evil-multiedit-prev
163 | evil-multiedit-restore
164 | evil-multiedit-abort
165 | evil-multiedit-ex-match))
166 |
167 | ;;------------------------------------------------------------------------------
168 | ;; `evil-nerd-commenter': Block commenting.
169 | ;;------------------------------------------------------------------------------
170 | (use-package evil-nerd-commenter
171 | :commands (evilnc-comment-or-uncomment-lines))
172 |
173 | (provide 'init-evil)
174 |
175 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
176 | ;;; init-evil.el ends here
177 |
--------------------------------------------------------------------------------
/.zshrc:
--------------------------------------------------------------------------------
1 | #------------------------------------------------------------------------------
2 | # 1. Tmux
3 | #------------------------------------------------------------------------------
4 | if [ -z "$TMUX" ]
5 | then
6 | tmux attach -t TMUX || tmux new -s TMUX
7 | fi
8 |
9 | #------------------------------------------------------------------------------
10 | # 2. Exports
11 | #------------------------------------------------------------------------------
12 | #export PATH="/usr/local/bin:/usr/local/sbin:$PATH"
13 | #export PATH="$HOME/.cargo/bin:$PATH"
14 | export EDITOR="emacsclient -c -n"
15 | export LC_ALL=en_US.UTF-8
16 | export LANG=en_US.UTF-8
17 |
18 | #------------------------------------------------------------------------------
19 | # 3. Aliases
20 | #------------------------------------------------------------------------------
21 | alias ..='cd ..'
22 | alias ...='cd ../..'
23 | alias ....='cd ../../..'
24 | alias dotfiles='/usr/local/bin/git --git-dir=$HOME/.dotfiles/ --work-tree=$HOME'
25 | alias ll="exa -lGx"
26 | alias emacsc='emacsclient -c -n'
27 |
28 | #------------------------------------------------------------------------------
29 | # 4. Colors
30 | #------------------------------------------------------------------------------
31 | autoload -U colors && colors
32 | export CLICOLOR="yes"
33 |
34 | #------------------------------------------------------------------------------
35 | # 5. Completion
36 | #------------------------------------------------------------------------------
37 | autoload -U compinit && compinit
38 | zmodload -i zsh/complist
39 | setopt auto_menu
40 | setopt complete_in_word
41 |
42 | zstyle ':completion:*' list-colors ''
43 |
44 | #------------------------------------------------------------------------------
45 | # 6. History
46 | #------------------------------------------------------------------------------
47 | if [ -z $HISTFILE ]; then
48 | HISTFILE=$HOME/.zsh_history
49 | fi
50 | HISTSIZE=10000
51 | SAVEHIST=10000
52 |
53 | setopt append_history
54 | setopt inc_append_history
55 | setopt extended_history
56 | setopt hist_expire_dups_first
57 | setopt hist_ignore_dups
58 | setopt hist_ignore_space
59 | setopt hist_verify
60 | setopt share_history
61 |
62 | #------------------------------------------------------------------------------
63 | # 7. Prompt
64 | #------------------------------------------------------------------------------
65 | #autoload -U promptinit && promptinit
66 | #prompt pure
67 |
68 | ## http://zanshin.net/2013/02/02/zsh-configuration-from-the-ground-up/
69 | ## http://sheerun.net/2014/03/21/how-to-boost-your-vim-productivity/
70 | ## https://github.com/myfreeweb/dotfiles/blob/master/zsh/zshrc
71 |
72 | #------------------------------------------------------------------------------
73 | # 8. Functions
74 | #------------------------------------------------------------------------------
75 | ## Use ctrl-z to return to paused Vim instead of 'fg'.
76 | ## http://sheerun.net/2014/03/21/how-to-boost-your-vim-productivity/
77 | fancy-ctrl-z () {
78 | if [[ $#BUFFER -eq 0 ]]; then
79 | BUFFER="fg"
80 | zle accept-line
81 | else
82 | zle push-input
83 | zle clear-screen
84 | fi
85 | }
86 | zle -N fancy-ctrl-z
87 | bindkey '^Z' fancy-ctrl-z
88 |
89 | ##-------------------------------------------------------------------
90 | ## myIP address
91 | ## -------------------------------------------------------------------
92 | function myip() {
93 | ifconfig lo0 | grep 'inet ' | sed -e 's/:/ /' | awk '{print "lo0 : " $2}'
94 | ifconfig en0 | grep 'inet ' | sed -e 's/:/ /' | awk '{print "en0 (IPv4): " $2 " " $3 " " $4 " " $5 " " $6}'
95 | ifconfig en0 | grep 'inet6 ' | sed -e 's/ / /' | awk '{print "en0 (IPv6): " $2 " " $3 " " $4 " " $5 " " $6}'
96 | ifconfig en1 | grep 'inet ' | sed -e 's/:/ /' | awk '{print "en1 (IPv4): " $2 " " $3 " " $4 " " $5 " " $6}'
97 | ifconfig en1 | grep 'inet6 ' | sed -e 's/ / /' | awk '{print "en1 (IPv6): " $2 " " $3 " " $4 " " $5 " " $6}'
98 | }
99 |
100 | # -------------------------------------------------------------------
101 | # compressed file expander
102 | # (from https://github.com/myfreeweb/zshuery/blob/master/zshuery.sh)
103 | # -------------------------------------------------------------------
104 | ex() {
105 | if [[ -f $1 ]]; then
106 | case $1 in
107 | *.tar.bz2) tar xvjf $1;;
108 | *.tar.gz) tar xvzf $1;;
109 | *.tar.xz) tar xvJf $1;;
110 | *.tar.lzma) tar --lzma xvf $1;;
111 | *.bz2) bunzip $1;;
112 | *.rar) unrar $1;;
113 | *.gz) gunzip $1;;
114 | *.tar) tar xvf $1;;
115 | *.tbz2) tar xvjf $1;;
116 | *.tgz) tar xvzf $1;;
117 | *.zip) unzip $1;;
118 | *.Z) uncompress $1;;
119 | *.7z) 7z x $1;;
120 | *.dmg) hdiutul mount $1;; # mount OS X disk images
121 | *) echo "'$1' cannot be extracted via >ex<";;
122 | esac
123 | else
124 | echo "'$1' is not a valid file"
125 | fi
126 | }
127 |
128 | #------------------------------------------------------------------------------
129 | # 9. FASD & FZF
130 | # - https://github.com/clvv/fasd
131 | #------------------------------------------------------------------------------
132 | eval "$(fasd --init auto)"
133 | [ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
134 |
135 | export FZF_DEFAULT_COMMAND='rg --files --no-ignore --hidden --follow -g "!{.git,node_modules}/*" 2> /dev/null'
136 | export FZF_CTRL_T_OPTS="--select-1 --exit-0"
137 | export FZF_COMPLETION_TRIGGER=''
138 |
139 | #bindkey '^T' fzf-completion
140 | #bindkey '^I' $fzf_default_completion
141 |
142 | # Use fd (https://github.com/sharkdp/fd) instead of the default find
143 | # command for listing path candidates.
144 | # - The first argument to the function ($1) is the base path to start traversal
145 | # - See the source code (completion.{bash,zsh}) for the details.
146 | _fzf_compgen_path() {
147 | fd --hidden --follow --exclude ".git" . "$1"
148 | }
149 |
150 | # Use fd to generate the list for directory completion
151 | _fzf_compgen_dir() {
152 | fd --type d --hidden --follow --exclude ".git" . "$1"
153 | }
154 |
155 | # fasd & fzf - jump using `fasd` if argument is given, filter output of `fasd`
156 | # using `fzf` otherwise.
157 | unalias j 2>/dev/null
158 | j() {
159 | [ $# -gt 0 ] && fasd_cd -d "$*" && return
160 | local dir
161 | dir="$(fasd -Rdl "$1" | fzf -1 -0 --no-sort +m)" && cd "${dir}" || return 1
162 | }
163 |
164 | # fasd & fzf - use $EDITOR to edit file. Pick best matched file using `fasd`
165 | # if argument given, else use `fzf` to filter `fasd` output.
166 | unalias e 2>/dev/null
167 | e() {
168 | [ $# -gt 0 ] && fasd -f -e ${EDITOR} "$*" && return
169 | local file
170 | file="$(fasd -Rfl "$1" | fzf -1 -0 --no-sort +m)" && ${EDITOR} "${file}" || return 1
171 | }
172 |
173 | # fe [FUZZY PATTERN] - Open the selected file with the default editor
174 | # - Bypass fuzzy finder if there's only one match (--select-1)
175 | # - Exit if there's no match (--exit-0)
176 | fe() {
177 | local files
178 | IFS=$'\n' files=($(fzf-tmux --query="$1" --multi --select-1 --exit-0))
179 | [[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
180 | }
181 |
182 | # fasd & fzf - open finder. If argument given, use `fasd` to pick the best match
183 | # else use `fzf` to select from `fasd` results.
184 | unalias o 2>/dev/null
185 | o() {
186 | [ $# -gt 0 ] && fasd -a -e open "$*" && return
187 | local res
188 | res="$(fasd -Rla "$1" | fzf -1 -0 --no-sort +m)"
189 | if [[ -d "${res}" ]]; then
190 | open "${res}"
191 | else
192 | open "$(dirname "$res")"
193 | fi
194 | }
195 |
196 | #------------------------------------------------------------------------------
197 | # 10. zinit
198 | #------------------------------------------------------------------------------
199 | ### Added by zinit's installer
200 | source '/Users/api/.zinit/bin/zinit.zsh'
201 | autoload -Uz _zinit
202 | (( ${+_comps} )) && _comps[zinit]=_zinit
203 | ### End of zinit's installer chunk
204 |
205 | zinit load zdharma/history-search-multi-word
206 |
207 | zinit ice compile"*.lzui"
208 | zinit load zdharma/zui
209 | zinit light zdharma/zinit-crasis
210 |
211 | zinit light zsh-users/zsh-autosuggestions
212 | zinit light zsh-users/zsh-syntax-highlighting
213 |
214 | #zinit ice compile'(pure|async).zsh' pick'async.zsh' src'pure.zsh'
215 | #zinit light sindresorhus/pure
216 |
217 | # Local Variables:
218 | # eval: (outline-minor-mode 1)
219 | # outline-regexp: "^# [0-9]+"
220 | # End:
221 | ### End of Zinit's installer chunk
222 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-editor.el:
--------------------------------------------------------------------------------
1 | ;;; init-editor.el --- Editor related settings -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | (setq-default fill-column 80
9 | word-wrap t
10 | sentence-end-double-space nil
11 |
12 | ;; use spaces, not tabs
13 | indent-tabs-mode nil
14 | tab-always-indent t
15 | tab-width 4
16 |
17 | ;;
18 | auto-save-default nil
19 | create-lockfiles nil
20 | history-length 500
21 | make-backup-files nil
22 |
23 | ;; Scrolling
24 | hscroll-margin 1
25 | hscroll-step 1
26 | scroll-conservatively 101
27 | scroll-margin 0
28 | scroll-preserve-screen-position t
29 |
30 | size-indication-mode t
31 | ; line-number-mode t
32 | display-line-numbers-width 3
33 | column-number-mode t
34 | delete-selection-mode t)
35 |
36 | ;;------------------------------------------------------------------------------
37 | ;; Show matching parenthesis.
38 | ;;------------------------------------------------------------------------------
39 | (setq show-paren-delay 0.1
40 | show-paren-highlight-openparen t
41 | show-paren-when-point-inside-paren t)
42 | (add-hook 'after-init-hook #'show-paren-mode)
43 |
44 | ;;------------------------------------------------------------------------------
45 | ;; Line numbers.
46 | ;;------------------------------------------------------------------------------
47 | (defvar api-line-numbers-style 'relative
48 | "Style to use for `display-line-numbers' styles, which are:
49 | t Ordinary line numbers
50 | 'relative Relative line numbers")
51 |
52 | (defun api/enable-line-numbers ()
53 | "Show line number display."
54 | (interactive)
55 | (if (boundp 'display-line-numbers)
56 | (setq display-line-numbers api-line-numbers-style)))
57 |
58 | (defun api/disable-line-numbers ()
59 | "Disable line number display."
60 | (interactive)
61 | (if (boundp 'display-line-numbers)
62 | (setq display-line-numbers nil)))
63 |
64 | ;; enable line numbers by default in some modes.
65 | (dolist (hook '(prog-mode-hook
66 | text-mode-hook))
67 | (add-hook hook #'api/enable-line-numbers))
68 |
69 | ;;------------------------------------------------------------------------------
70 | ;; `auto-fill-mode':
71 | ;;------------------------------------------------------------------------------
72 | (use-package auto-fill-mode
73 | :ensure nil ;; in-built
74 | :commands (auto-fill-mode)
75 | :hook ((text-mode . auto-fill-mode)
76 | (latex-mode . auto-fill-mode)))
77 |
78 | ;;------------------------------------------------------------------------------
79 | ;; `column-enforce-mode': highlight text that extends beyond a certain column.
80 | ;; Main difference from whitespace mode is that this allows skipping comments.
81 | ;;------------------------------------------------------------------------------
82 | (use-package column-enforce-mode
83 | ;;:disabled ;; whitespace-mode is enough for now.
84 | :hook ((prog-mode . column-enforce-mode)
85 | (latex-mode . column-enforce-mode)
86 | (text-mode . column-enforce-mode))
87 | :config
88 | (setq column-enforce-comments nil
89 | column-enforce-column 80))
90 |
91 | ;;(dolist (hook '(prog-mode-hook
92 | ;; latex-mode-hook
93 | ;; text-mode-hook))
94 | ;; (add-hook hook 'column-enforce-mode)))
95 |
96 | ;;------------------------------------------------------------------------------
97 | ;; `expand-region': Expand region by semantic units.
98 | ;;------------------------------------------------------------------------------
99 | (use-package expand-region
100 | :commands (er/expand-region
101 | er/contract-region
102 | er/mark-symbol
103 | er/mark-word))
104 |
105 | ;;------------------------------------------------------------------------------
106 | ;; `highlight-indent-guides': highlight indentations.
107 | ;;------------------------------------------------------------------------------
108 | (use-package highlight-indent-guides
109 | :commands (highlight-indentation-mode
110 | highlight-indentation-current-column-mode)
111 | :init (setq highlight-indent-guides-method 'character))
112 |
113 | ;;------------------------------------------------------------------------------
114 | ;; `highlight-symbol': highlight symbol at point throughout the current buffer.
115 | ;;------------------------------------------------------------------------------
116 | (use-package highlight-symbol
117 | :commands highlight-symbol)
118 |
119 | ;;------------------------------------------------------------------------------
120 | ;; `hl-line': highlight current line.
121 | ;;------------------------------------------------------------------------------
122 | (use-package hl-line
123 | :ensure nil ; in-built
124 | :hook ((prog-mode text-mode conf-mode) . hl-line-mode))
125 |
126 | ;;------------------------------------------------------------------------------
127 | ;; `rainbow-delimiters': Manage delimiter explosion.
128 | ;;------------------------------------------------------------------------------
129 | (use-package rainbow-delimiters
130 | :hook ((latex-mode . rainbow-delimiters-mode)
131 | (prog-mode . rainbow-delimiters-mode)))
132 |
133 | ;;------------------------------------------------------------------------------
134 | ;; `recentf': Manage recent files.
135 | ;;------------------------------------------------------------------------------
136 | (use-package recentf
137 | :ensure nil ; in-built
138 | :hook (emacs-startup . recentf-mode)
139 | :config
140 | (setq recentf-max-menu-items 0
141 | recentf-max-saved-items 300
142 | recentf-filename-handlers '(file-truename)
143 | recentf-exclude
144 | (list "^/tmp/" "^/ssh:" "\\.?ido\\.last$" "\\.revive$" "/TAGS$"
145 | "^/var/folders/.+$" "COMMIT_EDITMSG\\"
146 | no-littering-var-directory
147 | no-littering-etc-directory)))
148 |
149 | ;;------------------------------------------------------------------------------
150 | ;; `smartparens': Smarter parenthesis matching.
151 | ;;------------------------------------------------------------------------------
152 | (use-package smartparens
153 | :commands (smartparens-global-mode)
154 | :config
155 | (smartparens-global-mode +1)
156 | (require 'smartparens-config)
157 | (setq sp-autowrap-region t
158 | sp-highlight-pair-overlay nil
159 | sp-cancel-autoskip-on-backward-movement nil
160 | sp-show-pair-delay 0
161 | sp-max-pair-length 3)
162 |
163 | ;; Make smart paranthesis play nice with evil.
164 | ;; (use-package evil-smartparens
165 | ;; :after smartparens
166 | ;; :config (add-hook 'smartparens-enabled-hook #'evil-smartparens-mode))
167 |
168 | ;; disable smartparens in evil-mode's replace state (they conflict)
169 | (after! evil
170 | (add-hook 'evil-replace-state-entry-hook #'turn-off-smartparens-mode)
171 | (add-hook 'evil-replace-state-exit-hook #'turn-on-smartparens-mode)))
172 |
173 | ;;------------------------------------------------------------------------------
174 | ;; `undo-tree': visualize undo operations.
175 | ;;------------------------------------------------------------------------------
176 | (use-package undo-tree
177 | :hook (emacs-startup . global-undo-tree-mode)
178 | :config
179 | (setq undo-tree-auto-save-history nil
180 | undo-tree-visualizer-timestamps t
181 | undo-tree-visualizer-diff t))
182 |
183 | ;;------------------------------------------------------------------------------
184 | ;; `whitespace': show and clean unnecessary whitespace.
185 | ;;------------------------------------------------------------------------------
186 | (use-package whitespace
187 | :ensure nil ;; in-built
188 | :commands (whitespace-cleanup whitespace-mode)
189 | :init
190 | (dolist (hook '(prog-mode-hook
191 | tex-mode-hook
192 | latex-mode-hook
193 | text-mode-hook))
194 | (add-hook hook #'whitespace-mode))
195 | (add-hook 'before-save-hook #'whitespace-cleanup)
196 | :config
197 | (setq whitespace-line-column 80
198 | whitespace-style '(face tabs empty trailing lines-tail)))
199 |
200 | (provide 'init-editor)
201 |
202 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
203 | ;;; init-editor.el ends here
204 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-theme.el:
--------------------------------------------------------------------------------
1 | ;; init-theme.el --- Theme related settings -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | (setq custom-safe-themes t)
9 |
10 | (defvar api-theme-hooks nil
11 | "((theme-id . function) ...).")
12 |
13 | (defvar before-load-theme-hook nil
14 | "Hooks to run before `load-theme'.")
15 |
16 | (defvar after-load-theme-hook nil
17 | "Hooks to run after `load-theme'.")
18 |
19 | (defun api/disable-all-themes ()
20 | "Disable any custom themes."
21 | (interactive)
22 | (mapc #'disable-theme custom-enabled-themes))
23 |
24 | (defun api|add-theme-hook (theme-id hook-func)
25 | "Associate `THEME-ID' with `HOOK-FUNC'."
26 | (add-to-list 'api-theme-hooks (cons theme-id hook-func)))
27 |
28 | (defun api*load-theme-advice (f theme-id &optional no-confirm no-enable &rest args)
29 | "Enhances `load-theme' in two ways:
30 | 1. Disables enabled themes for a clean slate.
31 | 2. Calls functions registered using `api|add-theme-hook'."
32 | (unless no-enable
33 | (api/disable-all-themes))
34 | (prog1
35 | (apply f theme-id no-confirm no-enable args)
36 | (unless no-enable
37 | (pcase (assq theme-id api-theme-hooks)
38 | (`(,_ . ,f) (funcall f))))))
39 |
40 | (advice-add 'load-theme
41 | :around
42 | #'api*load-theme-advice)
43 |
44 | (defadvice load-theme (after run-after-load-theme-hook activate)
45 | "Run `after-load-theme-hook'."
46 | (run-hooks 'after-load-theme-hook))
47 |
48 | (defadvice load-theme (before run-before-load-theme-hook activate)
49 | "Disable any custom themes, and run `before-load-theme-hook'."
50 | (mapc #'disable-theme custom-enabled-themes)
51 | (run-hooks 'before-load-theme-hook))
52 |
53 | ;;------------------------------------------------------------------------------
54 | ;; `apropospriate-theme':
55 | ;;------------------------------------------------------------------------------
56 | (use-package apropospriate-theme
57 | :init
58 | (load "apropospriate-theme-autoloads" nil t)
59 | (add-hook 'after-init-hook (lambda () (load-theme 'apropospriate-dark t))))
60 |
61 | ;;------------------------------------------------------------------------------
62 | ;; `circadian': Automatically change theme on sunrise and sunset.
63 | ;;------------------------------------------------------------------------------
64 | (use-package circadian
65 | :disabled
66 | :commands (circadian-setup)
67 | :init
68 | (add-hook 'emacs-startup-hook #'circadian-setup)
69 | :config
70 | (add-hook 'circadian-after-load-theme-hook (lambda ()
71 | (when (fboundp 'powerline-reset)
72 | (powerline-reset))))
73 | (setq calendar-latitude 37.87
74 | calendar-longitude -122.27
75 | calendar-location-name "Berkeley, CA")
76 | (setq circadian-themes '((:sunrise . solarized-light)
77 | ;;(:sunset . zenburn)
78 | (:sunset . sanityinc-tomorrow-eighties))))
79 |
80 | ;;------------------------------------------------------------------------------
81 | ;; `doom-themes':
82 | ;;------------------------------------------------------------------------------
83 | (use-package doom-themes
84 | :disabled
85 | :init
86 | (add-hook 'after-init-hook (lambda()
87 | (load-theme 'doom-one t)))
88 | :config
89 | (setq doom-themes-enable-bold t
90 | doom-themes-enable-italic t)
91 | (doom-themes-org-config))
92 |
93 | ;;------------------------------------------------------------------------------
94 | ;; `seoul256':
95 | ;;------------------------------------------------------------------------------
96 | (use-package seoul256-theme
97 | :disabled
98 | :ensure nil
99 | :init
100 | (add-to-list 'custom-theme-load-path "~/Code/seoul256-emacs")
101 | (setq seoul256-background 236
102 | seoul256-alternate-background 253
103 | seoul256-override-colors-alist
104 | '((65 . "#a6a6a6")))
105 |
106 | (load-theme 'seoul256 t)
107 | )
108 |
109 | ;;(add-hook 'emacs-startup-hook (lambda ()
110 | ;; (load-theme 'seoul256 t))))
111 |
112 | ;;------------------------------------------------------------------------------
113 | ;; `solarized-theme': https://github.com/bbatsov/solarized-emacs
114 | ;;------------------------------------------------------------------------------
115 | (use-package solarized-theme
116 | :disabled
117 | :init
118 | (setq solarized-use-less-bold t
119 | solarized-use-more-italic t
120 |
121 | ;; make the fringe stand out from the background
122 | ;; solarized-distinct-fringe-background t
123 |
124 | ;; Don't change the font for some headings and titles
125 | solarized-use-variable-pitch nil
126 |
127 | ;; make the modeline high contrast
128 | ;; solarized-high-contrast-mode-line t
129 | x-underline-at-descent-line t
130 |
131 | ;; Use less colors for indicators such as git:gutter, flycheck and similar
132 | ;; solarized-emphasize-indicators nil
133 |
134 | ;; Don't change size of org-mode headlines (but keep other size-changes)
135 | ;; solarized-scale-org-headlines nil
136 |
137 | ;; Avoid all font-size changes
138 | solarized-distinct-doc-face t
139 | solarized-height-minus-1 1.0
140 | solarized-height-plus-1 1.0
141 | solarized-height-plus-2 1.0
142 | solarized-height-plus-3 1.0
143 | solarized-height-plus-4 1.0))
144 |
145 | ;;------------------------------------------------------------------------------
146 | ;; `tomorrow-theme': https://github.com/purcell/color-theme-sanityinc-tomorrow/
147 | ;;------------------------------------------------------------------------------
148 | (use-package color-theme-sanityinc-tomorrow
149 | :disabled
150 | :init (load-theme 'sanityinc-tomorrow-eighties t))
151 |
152 | ;;------------------------------------------------------------------------------
153 | ;; zenburn-theme:
154 | ;;------------------------------------------------------------------------------
155 | (use-package zenburn-theme
156 | :disabled
157 | :init
158 |
159 | (defun api|customize-zenburn ()
160 | "Customize `zenburn'."
161 | (custom-theme-set-faces
162 | 'zenburn
163 |
164 | ;;'(region ((t (:background "#007475"))))
165 | '(font-lock-comment-delimiter-face ((t (:foreground "gray55"))))
166 | '(font-lock-comment-face ((t (:foreground "gray55"))))
167 | '(font-lock-doc-face ((t (:foreground "gray70"))))
168 | '(shm-current-face ((t (:background "gray27"))))
169 | '(linum ((t (:foreground "gray37"))))
170 | '(fringe ((t (:background "#3f3f3f"))))
171 |
172 | `(isearch ((t (:background "#385f38" :foreground "#f8f893"))))
173 | `(lazy-highlight ((t (:foreground "#ffffe0" :background "#284f28"))))
174 |
175 | ;; column-enforce-mode
176 | '(column-enforce-face ((t (:foreground "#DC8CC3"))))
177 |
178 | ;; eyebrowse
179 | `(eyebrowse-mode-line-active ((t (:foreground "#F0DFAF"))))
180 | `(eyebrowse-mode-line-inactive ((t (:foreground "gray37"))))
181 |
182 | `(ivy-current-match ((t (:background "#4F4F4F"))))
183 | ;;`(ivy-current-match ((t (:inherit lazy-highlight))))
184 | `(ivy-minibuffer-match-face-1 ((t (:inherit match))))
185 | `(ivy-minibuffer-match-face-2 ((t (:inherit match))))
186 | `(ivy-minibuffer-match-face-3 ((t (:inherit match))))
187 | `(ivy-minibuffer-match-face-4 ((t (:inherit match))))
188 |
189 | `(mu4e-conversation-header ((t (:inherit header-line))))
190 |
191 | ;; ace-window
192 | `(aw-leading-char-face ((t (:foreground "#F0DFAF"
193 | :weight bold
194 | :height 1.0))))
195 |
196 | `(winum-face ((t (:foreground "#F0DFAF" :height 1.3))))
197 |
198 | ;; solaire-mode
199 | `(solaire-default-face ((t (:background "#383838"))))
200 | `(solaire-hl-line-face ((t (:background "#2B2B2B"))))
201 |
202 | ;; strike through unmatched parenthesis
203 | '(rainbow-delimiters-unmatched-face ((t (:foreground "red"
204 | :inherit unspecified
205 | :strike-through t))))))
206 |
207 | (api|add-theme-hook 'zenburn #'api|customize-zenburn)
208 | ;;(add-hook 'after-load-theme-hook #'api|customize-zenburn)
209 | ;;(load-theme 'zenburn t)
210 | (add-hook 'after-init-hook (lambda () (load-theme 'zenburn t)))
211 | )
212 |
213 | (provide 'init-theme)
214 |
215 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
216 | ;;; init-theme.el ends here
217 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-ui.el:
--------------------------------------------------------------------------------
1 | ;;; init-ui.el --- UI settings -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;;; Code:
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7 |
8 | (setq-default inhibit-startup-message t
9 | inhibit-startup-echo-area-message user-login-name
10 | inhibit-default-init t
11 | initial-major-mode 'fundamental-mode
12 | initial-scratch-message nil
13 |
14 | ;; don't use visual bells or dialog boxes.
15 | use-dialog-box nil
16 | ring-bell-function #'ignore
17 | visible-bell nil
18 |
19 | ;; update ui less often.
20 | idle-update-delay 2
21 |
22 | ;; don't show advice warnings.
23 | ad-redefinition-action 'accept
24 |
25 | ;; make 'apropos' useful.
26 | apropos-do-all t
27 |
28 | ;; confirm before quitting Emacs (avoids accidental quits).
29 | confirm-kill-emacs 'y-or-n-p
30 |
31 | ;; confirm before visiting non-existing file/buffer.
32 | confirm-nonexistent-file-or-buffer t
33 |
34 | ;; don't allow minibuffer commands while in minbuffer.
35 | enable-recursive-minibuffers nil
36 |
37 | ;; disable bidirectional text for tiny performance boost
38 | bidi-display-reordering nil
39 |
40 | ;; remove continuation arrow on right fringe
41 | fringe-indicator-alist (delq
42 | (assq 'continuation fringe-indicator-alist)
43 | fringe-indicator-alist)
44 |
45 | ;; keep the point out of the minibuffer
46 | minibuffer-prompt-properties '(read-only t point-entered minibuffer-avoid-prompt face minibuffer-prompt)
47 |
48 | ;; don't show buffer boundaries visually.
49 | indicate-buffer-boundaries nil
50 |
51 | ;; don't show empty lines.
52 | indicate-empty-lines nil
53 |
54 | ;; no need to make cursor overly visible.
55 | visible-cursor nil
56 |
57 | ;; don't stretch block cursor.
58 | x-stretch-cursor nil
59 |
60 | ;; don't ask for save confirmation before compilation, just do it.
61 | compilation-ask-about-save nil
62 |
63 | ;; scroll compilation output.
64 | compilation-scroll-output t
65 |
66 | ;; kill existing compilation before starting new, don't ask.
67 | compilation-always-kills t)
68 |
69 | ;;------------------------------------------------------------------------------
70 | ;; Avoid showing ugly stuff.
71 | ;;------------------------------------------------------------------------------
72 | ;;(if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
73 | (if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
74 | (if (fboundp 'tooltip-mode) (tooltip-mode -1))
75 | (if (display-graphic-p) (menu-bar-mode 1) (menu-bar-mode -1))
76 | ;;(unless (display-graphic-p) (menu-bar-mode -1))
77 |
78 | ;; standardize default fringe width
79 | (if (fboundp 'fringe-mode) (fringe-mode 4))
80 |
81 | ;; Make mouse less jumpy
82 | (setq mouse-wheel-scroll-amount '(1 ((shift) . 1)))
83 |
84 | ;; Enable y/n answers
85 | (defalias 'yes-or-no-p 'y-or-n-p)
86 |
87 | ;; be quiet at startup; don't load or display anything unnecessary
88 | (advice-add #'display-startup-echo-area-message :override #'ignore)
89 |
90 | ;;------------------------------------------------------------------------------
91 | ;; `all-the-icons': icons for many ui related packages.
92 | ;;------------------------------------------------------------------------------
93 | (use-package all-the-icons
94 | :commands (all-the-icons-octicon all-the-icons-faicon all-the-icons-fileicon
95 | all-the-icons-wicon all-the-icons-material all-the-icons-alltheicon
96 | all-the-icons-install-fonts all-the-icons-icon-for-buffer))
97 |
98 | ;;------------------------------------------------------------------------------
99 | ;; `beacon': show where the cursor is when the window moves.
100 | ;;------------------------------------------------------------------------------
101 | (use-package beacon
102 | :hook (emacs-startup . beacon-mode))
103 |
104 | ;;------------------------------------------------------------------------------
105 | ;; `dashboard': show a dashboard at start.
106 | ;;------------------------------------------------------------------------------
107 | (use-package dashboard
108 | :disabled
109 | :commands (dashboard-setup-startup-hook
110 | dashboard-refresh-buffer)
111 | ;; :preface
112 | ;; (defun api/dashboard-banner ()
113 | ;; "Set a dashboard banner including information on package initialization
114 | ;; time and garbage collections."""
115 | ;; (setq dashboard-banner-logo-title
116 | ;; (format "Emacs ready in %.2f seconds with %d garbage collections."
117 | ;; (float-time (time-subtract after-init-time before-init-time)) gcs-done)))
118 | :init
119 | (setq dashboard-init-info
120 | (format "Ready in %.2f seconds with %d garbage collections."
121 | (float-time (time-subtract after-init-time before-init-time)) gcs-done))
122 | :config
123 | ;; (setq dashboard-banner-logo-title
124 | ;; (format "Emacs ready in %.2f seconds with %d garbage collections."
125 | ;; (float-time (time-subtract after-init-time before-init-time)) gcs-done))
126 | ;; (setq dashboard-init-info
127 | ;; (format "Ready in %.2f seconds with %d garbage collections."
128 | ;; (float-time (time-subtract after-init-time before-init-time)) gcs-done))
129 | (setq dashboard-items '((recents . 5)
130 | (bookmarks . 5)
131 | (projects . 5)))
132 | :hook (after-init . dashboard-setup-startup-hook))
133 |
134 | ;;------------------------------------------------------------------------------
135 | ;; `dimmer': Interactively highlight which buffer is active by dimming others.
136 | ;;------------------------------------------------------------------------------
137 | ;; (use-package dimmer
138 | ;; :disabled
139 | ;; :init
140 | ;; (setq-default dimmer-fraction 0.2)
141 | ;; (add-hook 'after-init-hook 'dimmer-mode))
142 |
143 | ;;------------------------------------------------------------------------------
144 | ;; `fringe-helper': helper functions for fringe bitmaps.
145 | ;;------------------------------------------------------------------------------
146 | (use-package fringe-helper
147 | :commands (fringe-helper-define
148 | fringe-helper-convert)
149 | :init
150 | (unless (fboundp 'define-fringe-bitmap)
151 | ;; doesn't exist in terminal Emacs; define it to prevent errors
152 | (defun define-fringe-bitmap (&rest _))))
153 |
154 | ;;------------------------------------------------------------------------------
155 | ;; `solaire-mode': distinguish file-visiting buffers from other types of buffers.
156 | ;;------------------------------------------------------------------------------
157 | (use-package solaire-mode
158 | :disabled ;; not very useful.
159 | :init
160 | ;; brighten buffers (that represent real files)
161 | (add-hook 'after-change-major-mode-hook #'turn-on-solaire-mode)
162 | ;; To enable solaire-mode unconditionally for certain modes:
163 | (add-hook 'ediff-prepare-buffer-hook #'solaire-mode)
164 |
165 | ;; ...if you use auto-revert-mode, this prevents solaire-mode from turning
166 | ;; itself off every time Emacs reverts the file
167 | (add-hook 'after-revert-hook #'turn-on-solaire-mode)
168 |
169 | ;; highlight the minibuffer when it is activated:
170 | (add-hook 'minibuffer-setup-hook #'solaire-mode-in-minibuffer)
171 |
172 | ;; if the bright and dark background colors are the wrong way around, use this
173 | ;; to switch the backgrounds of the `default` and `solaire-default-face` faces.
174 | ;; This should be used *after* you load the active theme!
175 | ;;
176 | ;; NOTE: This is necessary for themes in the doom-themes package!
177 | (solaire-mode-swap-bg))
178 |
179 | ;;------------------------------------------------------------------------------
180 | ;; `which-key': interactively show available commands.
181 | ;;------------------------------------------------------------------------------
182 | (use-package which-key
183 | :hook (emacs-startup . which-key-mode)
184 | :config
185 | (setq which-key-sort-order #'which-key-prefix-then-key-order
186 | which-key-min-display-lines 5
187 | which-key-sort-uppercase-first nil
188 | which-key-add-column-padding 1
189 | which-key-max-display-columns nil)
190 | (set-face-attribute 'which-key-local-map-description-face nil :weight 'bold)
191 | (which-key-setup-side-window-bottom))
192 |
193 | (provide 'init-ui)
194 |
195 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
196 | ;;; init-ui.el ends here
197 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-keybindings.el:
--------------------------------------------------------------------------------
1 | ;;; init-keybindings.el --- Key bindings -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;; Initialize key bindings
6 |
7 | ;;; Code:
8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 |
10 | (defvar my-leader-key "SPC"
11 | "Anand's leader prefix key.")
12 |
13 | ;;; Super (cmd) key bindings
14 | (after! winum
15 | (global-set-key (kbd "s-0") 'winum-select-window-0-or-10)
16 | (global-set-key (kbd "s-1") 'winum-select-window-1)
17 | (global-set-key (kbd "s-2") 'winum-select-window-2)
18 | (global-set-key (kbd "s-3") 'winum-select-window-3)
19 | (global-set-key (kbd "s-4") 'winum-select-window-4))
20 |
21 | ;;; Hyper (alt) key bindings
22 | (global-set-key (kbd "H-h") help-map)
23 | (global-set-key (kbd "H-m") 'emms-smart-browse)
24 | (global-set-key (kbd "H-p") 'emms-pause)
25 |
26 | ;;------------------------------------------------------------------------------
27 | ;; `hydra':
28 | ;;------------------------------------------------------------------------------
29 | (use-package hydra
30 | :after evil
31 | :init
32 | (setq lv-use-seperator t)
33 |
34 | (defhydra api@text-zoom (:hint t :color red)
35 | "
36 | Text zoom: _j_:zoom in, _k_:zoom out, _0_:reset
37 | "
38 | ("j" text-scale-increase "in")
39 | ("k" text-scale-decrease "out")
40 | ("0" (text-scale-set 0) "reset"))
41 |
42 | (defhydra api@window-nav (:hint nil)
43 | "
44 | Move : _h_: far left _j_: very bottom _k_:very top _l_:far right _s_: swap with other
45 | Resize : _+_: increase height _-_: decrease height _<_:decrease width _>_:increase width _=_: balance
46 | "
47 | ("h" evil-window-move-far-left)
48 | ("j" evil-window-move-very-bottom)
49 | ("k" evil-window-move-very-top)
50 | ("l" evil-window-move-far-right)
51 | ("s" ace-swap-window)
52 |
53 | ("+" evil-window-increase-height)
54 | ("-" evil-window-decrease-height)
55 | ("<" evil-window-decrease-width)
56 | (">" evil-window-increase-width)
57 | ("=" balance-windows)
58 |
59 | ("q" nil)))
60 |
61 | ;;------------------------------------------------------------------------------
62 | ;; `general': Convenient key definitions.
63 | ;;------------------------------------------------------------------------------
64 | (use-package general
65 | :commands (general-evil-setup)
66 | :after evil
67 | :init
68 | (general-evil-setup t)
69 |
70 | (setq general-override-states '(insert
71 | emacs
72 | hybrid
73 | normal
74 | visual
75 | motion
76 | operator
77 | replace))
78 | (general-override-mode)
79 |
80 | (general-define-key :states '(insert visual operator replace)
81 | :keymaps 'global
82 | "C-g" 'evil-escape)
83 |
84 | (general-define-key :states '(normal visual emacs)
85 | :keymaps 'global
86 | :prefix my-leader-key
87 |
88 | "SPC" 'counsel-M-x
89 |
90 | "b" '(:ignore t :which-key "buffer")
91 | "bb" 'ivy-switch-buffer
92 | "bd" 'kill-this-buffer
93 | "bk" 'kill-this-buffer
94 | "bn" 'evil-buffer-new
95 | "bh" 'previous-buffer
96 | "bl" 'next-buffer
97 |
98 | "f" '(:ignore t :which-key "file")
99 | "ff" 'counsel-find-file
100 | "fs" 'save-buffer
101 |
102 | "g" '(:ignore t :which-key "git")
103 | "gs" 'magit-status
104 | "gd" 'magit-diff
105 | "gc" 'magit-commit
106 | "gp" 'magit-push
107 |
108 | "h" '(:ignore t :which-key "hydras")
109 | "hj" '(api@dumb-jump/body :which-key "Dumb Jump")
110 | "ht" '(api@text-zoom/body :which-key "Text zoom")
111 | "hw" '(api@window-nav/body :which-key "Window navigation")
112 | "hc" '(api@multiple-cursors/body :which-key "Multiple cursors")
113 | "hg" '(api@git-gutter/body :which-key "Git gutter")
114 |
115 | "l" '(:ignore t :which-key "window layout")
116 | "lc" '(eyebrowse-create-window-config :which-key "create new layout")
117 | "lp" '(eyebrowse-prev-window-config :which-key "previous layout")
118 | "ln" '(eyebrowse-next-window-config :which-key "next layout")
119 | "ls" '(eyebrowse-switch-to-window-config :which-key "switch layout")
120 | "ld" '(eyebrowse-close-window-config :which-key "delete this layout")
121 | "lr" '(eyebrowse-rename-window-config :which-key "rename layout")
122 | "ll" '(eyebrowse-last-window-config :which-key "last layout")
123 | "l0" '(eyebrowse-switch-to-window-config-0 :which-key "layout 0")
124 | "l1" '(eyebrowse-switch-to-window-config-1 :which-key "layout 1")
125 | "l2" '(eyebrowse-switch-to-window-config-2 :which-key "layout 2")
126 | "l3" '(eyebrowse-switch-to-window-config-3 :which-key "layout 3")
127 | "l4" '(eyebrowse-switch-to-window-config-4 :which-key "layout 4")
128 | "l5" '(eyebrowse-switch-to-window-config-5 :which-key "layout 5")
129 | "l6" '(eyebrowse-switch-to-window-config-6 :which-key "layout 6")
130 | "l7" '(eyebrowse-switch-to-window-config-7 :which-key "layout 7")
131 | "l8" '(eyebrowse-switch-to-window-config-8 :which-key "layout 8")
132 | "l9" '(eyebrowse-switch-to-window-config-9 :which-key "layout 9")
133 |
134 | "n" '((lambda ()
135 | (interactive)
136 | (notmuch-tree "folder:/inbox/ OR tag:inbox"))
137 | :which-key "notmuch")
138 |
139 | "m" 'mu4e
140 |
141 | "o" '(:ignore t :which-key "org-mode")
142 | "oa" 'api/show-org-agenda-frame
143 | "oc" 'api/open-org-capture-frame
144 | "od" 'org-deadline
145 | "or" 'org-refile
146 | "os" 'org-schedule
147 |
148 | "p" '(:ignore t :which-key "project")
149 | "pb" 'counsel-projectile-switch-to-buffer
150 | "pp" 'counsel-projectile
151 | "pf" 'counsel-projectile-find-file
152 | "ps" 'projectile-switch-project
153 | "pr" 'counsel-projectile-recentf
154 | "pv" 'counsel-projectile-vc
155 | "px" 'projectile-invalidate-cache
156 |
157 | "q" 'evil-quit
158 |
159 | "/" '(:ignore t :which-key "search")
160 | "//" 'swiper
161 | "/B" 'swiper-all
162 | "/f" 'helm-do-grep-ag
163 |
164 | "s" '(:ignore t :which-key "sessions")
165 | "sa" '(ivy-push-view :which-key "save session")
166 | "sd" '(ivy-pop-view :which-key "delete session")
167 | "sl" '(api/load-ivy-views :which-key "load saved sessions")
168 | "ss" '(ivy-switch-view :which-key "switch session")
169 | "sw" '(api/save-ivy-views :which-key "write sessions to file")
170 |
171 | "t" '(:ignore t :which-key "toggle")
172 | "tc" '(evilnc-comment-or-uncomment-lines :which-key "comments")
173 | "ti" 'highlight-indent-guides-mode
174 | "tt" 'flyspell-mode
175 | "ts" 'flycheck-mode
176 | "th" 'highlight-symbol
177 | "tg" '((lambda ()
178 | (interactive)
179 | (if (bound-and-true-p golden-ratio-mode)
180 | (progn
181 | (golden-ratio-mode -1)
182 | (balance-windows))
183 | (progn
184 | (golden-ratio-mode +1)
185 | (golden-ratio))))
186 | :which-key "golden ratio mode")
187 | "tw" 'writegood-mode
188 |
189 | "v" #'er/expand-region
190 | "V" #'er/contract-region
191 |
192 | "w" '(evil-window-map :which-key "window")
193 | ;;"w" '(:ignore t :which-key "window")
194 |
195 | "y" '(:ignore t :which-key "snippets")
196 | "yn" 'yas-new-snippet
197 | "yi" 'yas-insert-snippet
198 | "yv" 'yas-visit-snippet-file
199 |
200 | "TAB" 'ace-window))
201 |
202 | (provide 'init-keybindings)
203 |
204 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
205 | ;;; init-keybindings.el ends here
206 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/init-windows.el:
--------------------------------------------------------------------------------
1 | ;;; init-windows.el --- Emacs windows -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;; These are settings related to Emacs windows (not Windows as in OS)
6 |
7 | ;;; Code:
8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 |
10 | (setq-default highlight-nonselected-windows nil
11 |
12 | ;; hide cursors in other windows
13 | cursor-in-non-selected-windows nil
14 |
15 | ;; let minibuffer windows resize automatically.
16 | resize-mini-windows 'grow-only
17 |
18 | ;; maximum size for mini-windows.
19 | max-mini-window-height 0.4
20 |
21 | ;; lean towards horizontal splits.
22 | ;;split-width-threshold 999)
23 | )
24 | ;;------------------------------------------------------------------------------
25 | ;; set inter-window bordto be minimal,
26 | ;;------------------------------------------------------------------------------
27 | (setq-default window-divider-default-places t
28 | window-divider-default-bottom-width 0
29 | window-divider-default-right-width 1)
30 | (add-hook 'after-init-hook #'window-divider-mode)
31 |
32 | ;;------------------------------------------------------------------------------
33 | ;; Winner mode for quick window configurations.
34 | ;;------------------------------------------------------------------------------
35 | (use-package winner-mode
36 | :ensure nil ; in-built
37 | :if (fboundp 'winner-mode)
38 | :hook (after-init . winner-mode))
39 |
40 | ;;------------------------------------------------------------------------------
41 | ;; Allow switching between active windows using Shift + arrow keys.
42 | ;;------------------------------------------------------------------------------
43 | ;(when (fboundp 'windmove-default-keybindings) (windmove-default-keybindings))
44 | (use-package windmove
45 | :ensure nil ; in-built
46 | :when (fboundp 'windmove-default-keybindings)
47 | :hook (emacs-startup . windmove-default-keybindings))
48 |
49 | ;;------------------------------------------------------------------------------
50 | ;; `ace-window': Visually select windows.
51 | ;;------------------------------------------------------------------------------
52 | (use-package ace-window
53 | :commands (ace-window)
54 | :config
55 | (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)
56 | aw-scope 'global
57 | aw-background t))
58 |
59 | ;;------------------------------------------------------------------------------
60 | ;; `eyebrowse': Save and retrieve window layouts.
61 | ;;------------------------------------------------------------------------------
62 | (use-package eyebrowse
63 | ;;:disabled
64 | :commands (eyebrowse-mode)
65 | :config
66 | (add-to-list 'window-persistent-parameters '(window-side . writable))
67 | (add-to-list 'window-persistent-parameters '(window-slot . writable))
68 | (setq eyebrowse-mode-line-separator " "
69 | eyebrowse-mode-line-left-delimiter " "
70 | eyebrowse-mode-line-right-delimiter " "
71 | eyebrowse-wrap-around t
72 | eyebrowse-new-workspace t)
73 | (eyebrowse-mode))
74 |
75 | ;;------------------------------------------------------------------------------
76 | ;; `golden-ratio': Automatically resize windows.
77 | ;;------------------------------------------------------------------------------
78 | (use-package golden-ratio
79 | :config
80 | (progn
81 | ;; golden-ratio-exclude-modes
82 | (dolist (m '("bs-mode"
83 | "calc-mode"
84 | "ediff-mode"
85 | "dired-mode"
86 | "gud-mode"
87 | "gdb-locals-mode"
88 | "gdb-registers-mode"
89 | "gdb-breakpoints-mode"
90 | "gdb-threads-mode"
91 | "gdb-frames-mode"
92 | "gdb-inferior-io-mode"
93 | "gdb-disassembly-mode"
94 | "gdb-memory-mode"
95 | "speedbar-mode"
96 | ))
97 | (add-to-list 'golden-ratio-exclude-modes m))
98 |
99 | (add-to-list 'golden-ratio-exclude-buffer-regexp "^\\*[hH]elm.*")
100 |
101 | ;; golden-ratio-extra-commands
102 | (dolist (f '(ace-window
103 | ace-delete-window
104 | ace-select-window
105 | ace-swap-window
106 | ace-maximize-window
107 | avy-pop-mark
108 | buf-move-left
109 | buf-move-right
110 | buf-move-up
111 | buf-move-down
112 | evil-avy-goto-word-or-subword-1
113 | evil-avy-goto-line
114 | evil-window-delete
115 | evil-window-split
116 | evil-window-vsplit
117 | evil-window-left
118 | evil-window-right
119 | evil-window-up
120 | evil-window-down
121 | evil-window-bottom-right
122 | evil-window-top-left
123 | evil-window-mru
124 | evil-window-next
125 | evil-window-prev
126 | evil-window-new
127 | evil-window-vnew
128 | evil-window-rotate-upwards
129 | evil-window-rotate-downwards
130 | evil-window-move-very-top
131 | evil-window-move-far-left
132 | evil-window-move-far-right
133 | evil-window-move-very-bottom
134 | quit-window
135 | winum-select-window-0-or-10
136 | winum-select-window-1
137 | winum-select-window-2
138 | winum-select-window-3
139 | winum-select-window-4
140 | winum-select-window-5
141 | winum-select-window-6
142 | winum-select-window-7
143 | winum-select-window-8
144 | winum-select-window-9
145 | windmove-left
146 | windmove-right
147 | windmove-up
148 | windmove-down))
149 | (add-to-list 'golden-ratio-extra-commands f))
150 |
151 | ;; golden-ratio-exclude-buffer-names
152 | (dolist (n '(" *NeoTree*"
153 | "*LV*"
154 | " *which-key*"))
155 | (add-to-list 'golden-ratio-exclude-buffer-names n))))
156 |
157 | ;;------------------------------------------------------------------------------
158 | ;; `shackle': Tame pop-up windows.
159 | ;;------------------------------------------------------------------------------
160 | (use-package shackle
161 | :hook (emacs-startup . shackle-mode)
162 | :config
163 | (setq shackle-default-alignment 'below
164 | shackle-default-size 8
165 | helm-display-function 'pop-to-buffer
166 | shackle-rules
167 | '(("^\\*eww" :regexp t :size 0.5 :select t :autokill t :noesc t)
168 | ("^\\*ftp " :noselect t :autokill t :noesc t)
169 | ("^\\*pdf" :noselect t :align right)
170 | ;;(pdf-view-mode :noselect t :align right)
171 | ("\\`\\*helm.*?\\*\\'" :regexp t :align t :size 0.3)
172 | ;; built-in (emacs)
173 | ("*compilation*" :size 0.25 :noselect t :autokill t :autoclose t)
174 | ("*ert*" :same t :modeline t)
175 | ("*info*" :size 0.5 :select t :autokill t)
176 | ("*undo-tree*" :size 0.25 :align right)
177 | ("*Backtrace*" :size 20 :noselect t)
178 | ("*Warnings*" :size 12 :noselect t :autofit t)
179 | ("*Messages*" :size 12 :noselect t)
180 | ("*Help*" :size 0.3 :autokill t)
181 | ("^\\*.*Shell Command.*\\*$" :regexp t :size 20 :noselect t :autokill t)
182 | (apropos-mode :size 0.3 :autokill t :autoclose t)
183 | (Buffer-menu-mode :size 20 :autokill t)
184 | (comint-mode :noesc t)
185 | (grep-mode :size 25 :noselect t :autokill t)
186 | (profiler-report-mode :size 0.3 :regexp t :autokill t :modeline minimal)
187 | (tabulated-list-mode :noesc t)
188 | ("^ ?\\*" :regexp t :size 15 :noselect t :autokill t :autoclose t)))
189 | ;;(shackle-mode))
190 | )
191 |
192 | ;;------------------------------------------------------------------------------
193 | ;; `winum': Allow window selection by number.
194 | ;;------------------------------------------------------------------------------
195 | (use-package winum
196 | :hook (emacs-startup . winum-mode)
197 | ;;(add-hook 'emacs-startup-hook 'winum-mode)
198 | :config
199 | (setq winum-scope 'global
200 | winum-auto-setup-mode-line nil))
201 |
202 | ;;------------------------------------------------------------------------------
203 | ;; `zoom': Automatically zoom active window.
204 | ;;------------------------------------------------------------------------------
205 | (use-package zoom
206 | :disabled ;; doesn't play well with which-key
207 | :config
208 | ;(setq which-key-popup-type 'minibuffer)
209 | (setq zoom-ignored-major-modes '(calc-mode
210 | dired-mode
211 | ediff-mode
212 | markdown-mode
213 | speedbar-mode
214 | which-key-mode)
215 | zoom-ignored-buffer-name-regexps '("^*calc"
216 | "^\\*[hH]elm.*")
217 | zoom-ignored-buffer-names '(" *NeoTree*"
218 | " *which-key*")))
219 |
220 | (provide 'init-windows)
221 |
222 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
223 | ;;; init-windows.el ends here
224 |
--------------------------------------------------------------------------------
/.emacs.d/lisp/setup-org.el:
--------------------------------------------------------------------------------
1 | ;;; setup-org.el --- Org setup -*- lexical-binding: t; -*-
2 |
3 | ;;; Commentary:
4 |
5 | ;; Some settings related to org mode. Majorly based on:
6 | ;; https://m.reddit.com/r/emacs/comments/4gudyw/help_me_with_my_orgmode_workflow_for_notetaking/
7 | ;; https://github.com/sriramkswamy/dotemacs/
8 |
9 | ;;; Code:
10 |
11 | ;;------------------------------------------------------------------------------
12 | ;; Defaults & helpers:
13 | ;;------------------------------------------------------------------------------
14 | ;; http://stackoverflow.com/questions/21073859/is-there-a-way-with-org-capture-templates-to-not-insert-a-line-if-initial-conten
15 | (defun v-i-or-nothing ()
16 | "Use initial content only if available."
17 | (let ((v-i (plist-get org-store-link-plist :initial)))
18 | (if (equal v-i "")
19 | ""
20 | (concat v-i "\n"))))
21 |
22 | ;;------------------------------------------------------------------------------
23 | ;; `evil-org':
24 | ;;------------------------------------------------------------------------------
25 | (use-package evil-org
26 | :commands (evil-org-mode evil-org-recompute-clocks)
27 | :hook (org-mode . evil-org-mode)
28 | :config
29 | (setf evil-org-key-theme '(navigation insert textobjects additional))
30 | (require 'evil-org-agenda)
31 | (evil-org-agenda-set-keys))
32 |
33 | ;;------------------------------------------------------------------------------
34 | ;; `org':
35 | ;;------------------------------------------------------------------------------
36 | (use-package org-plus-contrib
37 | :mode (("\\.org\\'" . org-mode))
38 | ;;:bind ("C-c c" . org-capture)
39 | :init
40 | (setq org-directory org-root-directory
41 | org-default-notes-file (concat org-directory "organizer.org")
42 | org-startup-with-inline-images t
43 | org-src-fontify-natively t
44 | org-imenu-depth 8
45 | org-log-done t
46 | org-log-into-drawer t
47 | org-refile-targets '((org-agenda-files . (:maxlevel . 6))))
48 |
49 | (setq org-agenda-files
50 | (list (concat org-directory "organizer.org")
51 | (concat org-directory "beorg.org")
52 | (concat org-directory "papers/notes.org"))
53 | org-deadline-warning-days 7
54 | org-agenda-start-on-weekday nil
55 | org-agenda-show-all-dates t
56 | org-agenda-skip-deadline-if-done t
57 | org-agenda-skip-scheduled-if-done t
58 | org-agenda-span 7
59 | org-agenda-skip-scheduled-if-deadline-is-shown t
60 | org-reverse-note-order t)
61 |
62 | (setq org-capture-templates
63 | (quote (("t" "Todo" entry
64 | (file+headline org-default-notes-file "Inbox")
65 | "* TODO %^{Todo}\n:PROPERTIES:\n:CREATED: %T\n:END:\n%(v-i-or-nothing)"
66 | :empty-lines 1
67 | :prepend t
68 | :immediate-finish t
69 | :kill-buffer t)
70 | ("e" "Email-process-soon" entry (file+headline org-default-notes-file "Tasks")
71 | "* TODO [Email] %a %?\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))"
72 | :empty-lines 1)
73 | ("n" "Note" entry (file+headline org-default-notes-file "Notes")
74 | "* %U %?"
75 | :prepend t
76 | :empty-lines 1
77 | :kill-buffer t)
78 | ("p" "Paper" entry
79 | (file+headline org-default-notes-file "Papers")
80 | "* %^{Title} %(org-set-tags)\n:PROPERTIES:\n:CREATED: %U\n:Linked: %a\n:END:\n%i\nBrief description:\n%?"
81 | :prepend t
82 | :empty-lines 1
83 | :created t))))
84 |
85 | ;;;###autoload
86 | (defun api/show-org-agenda-frame ()
87 | "Show org-agenda in new frame or select the frame if already open."
88 | (interactive)
89 | (let* ((name "Org Agenda")
90 | (curr-frame (selected-frame))
91 | (frame-alist (nameframe-frame-alist))
92 | (frame (nameframe-get-frame name frame-alist)))
93 | (cond
94 | ;; org-agenda frame already exists
95 | ((and frame (not (equal frame curr-frame)))
96 | (select-frame-set-input-focus frame))
97 | ((not frame)
98 | (progn (nameframe-make-frame name)
99 | (funcall #'org-agenda-list)
100 | (delete-other-windows))))))
101 |
102 | ;; -- Make org-capture popup in its own frame.
103 | ;;;###autoload
104 | (defun api/open-org-capture-frame ()
105 | "Create a new frame and run `org-capture'."
106 | (interactive)
107 | (select-frame (make-frame '((api|org-capture . t))))
108 | (delete-other-windows)
109 | (cl-letf (((symbol-function 'switch-to-buffer-other-window) #'switch-to-buffer))
110 | (condition-case err
111 | (org-capture)
112 | ;; `org-capture' signals (error "Abort") when "q" is typed, so
113 | ;; delete the newly-created frame in this scenario.
114 | (error
115 | (message "org-capture: %s" (error-message-string err))
116 | (delete-frame)))))
117 |
118 | (defadvice org-capture-finalize (after delete-capture-frame activate)
119 | "Delete the frame after `capture-finalize'."
120 | (when (frame-parameter nil 'api|org-capture)
121 | (delete-frame)))
122 |
123 | (defadvice org-capture-destroy (after delete-capture-frame activate)
124 | "Delete the frame after `capture-destroy'."
125 | (when (frame-parameter nil 'api|org-capture)
126 | (delete-frame)))
127 |
128 | ;;Add creation date as a property in all captures.
129 | (require 'org-expiry)
130 | (add-hook 'org-capture-before-finalize-hook
131 | #'(lambda()
132 | (save-excursion
133 | (org-back-to-heading)
134 | (org-expiry-insert-created))))
135 |
136 | ;; Once inside the capture, change to insert state.
137 | (add-hook 'org-capture-mode-hook #'evil-insert-state)
138 |
139 | ;; No need to show line numbers in org mode.
140 | (add-hook 'org-mode-hook #'api/disable-line-numbers)
141 |
142 | (setq org-publish-project-alist
143 | '(
144 |
145 | ("org-api"
146 | ;; Path to your org files.
147 | :base-directory "~/Code/anand-iyer.com/_org/"
148 | :base-extension "org"
149 |
150 | ;; Path to your Jekyll project.
151 | :publishing-directory "~/Code/anand-iyer.com/"
152 | :recursive t
153 | :publishing-function org-html-publish-to-html
154 | :headline-levels 4
155 | :html-extension "html"
156 | :body-only t ;; Only export section between
157 |
158 | :section-numbers nil
159 | :with-toc nil
160 | :auto-index nil
161 | :auto-preamble nil
162 | :auto-postamble nil
163 | ))))
164 |
165 | ;;------------------------------------------------------------------------------
166 | ;; `org-babel':
167 | ;;------------------------------------------------------------------------------
168 | (use-package org-babel
169 | :ensure nil ; org
170 | :after org
171 | :init
172 | (org-babel-do-load-languages
173 | 'org-babel-load-languages
174 | '((awk . t)
175 | (C . t)
176 | (emacs-lisp . t)
177 | (gnuplot . t)
178 | (latex . t)
179 | (js . t)
180 | (perl . t)
181 | (python . t)
182 | (R . t)
183 | (sql . t))))
184 |
185 | ;;------------------------------------------------------------------------------
186 | ;; `org-bullets':
187 | ;;------------------------------------------------------------------------------
188 | (use-package org-bullets
189 | :hook (org-mode . org-bullets-mode))
190 |
191 | ;;------------------------------------------------------------------------------
192 | ;; `org-mime':
193 | ;;------------------------------------------------------------------------------
194 | (use-package org-mime
195 | :disabled
196 | :after (org mu4e)
197 | :config
198 | (setq
199 | org-mime-library 'mml
200 | org-mime-export-options '(:section-numbers nil :with-author nil :with-toc nil)))
201 |
202 | ;;------------------------------------------------------------------------------
203 | ;; `org-ref':
204 | ;;------------------------------------------------------------------------------
205 | (use-package org-ref
206 | :config
207 | (setq org-ref-completion-library 'org-ref-ivy-cite
208 | org-ref-notes-directory (concat org-directory "papers/notes")
209 | org-ref-bibliography-notes (concat org-directory "papers/notes.org")
210 | org-ref-default-bibliography `(,(concat org-directory "papers/references.bib"))
211 | org-ref-pdf-directory (concat org-directory "papers/pdfs/"))
212 | :init
213 | (add-hook 'org-mode-hook (lambda ()
214 | (require 'org-ref)
215 | (require 'org-ref-latex)
216 | (require 'org-ref-pdf)
217 | (require 'org-ref-url-utils))))
218 |
219 | ;; interleave PDFs with notes. This needs to be after pdf-tools. Also, interleave
220 | ;; needs to be removed and reinstalled everytime pdf-tools is updated.
221 | ;; See: https://github.com/rudolfochrist/interleave/issues/31#issuecomment-252351991
222 | ;; (use-package interleave
223 | ;; :init
224 | ;; (setq interleave-org-notes-dir-list `(,(concat org-directory "papers")))
225 | ;; (with-eval-after-load 'doc-view
226 | ;; (bind-key "i" #'interleave--open-notes-file-for-pdf doc-view-mode-map))
227 | ;; (with-eval-after-load 'pdf-view
228 | ;; (bind-key "i" #'interleave--open-notes-file-for-pdf pdf-view-mode-map)))
229 |
230 | ;;------------------------------------------------------------------------------
231 | ;; `org-noter':
232 | ;;------------------------------------------------------------------------------
233 | (use-package org-noter
234 | :init
235 | (setq org-noter-notes-search-path `(,(concat org-directory "papers")))
236 | :config
237 | (setq org-noter-auto-save-last-location t
238 | org-noter-separate-notes-from-heading t))
239 |
240 | ;;------------------------------------------------------------------------------
241 | ;; `org-ref': notational velocity and nvALT replacement.
242 | ;;------------------------------------------------------------------------------
243 | (use-package deft
244 | :commands (deft)
245 | :init
246 | (defun api/deft ()
247 | "Helper for deft"
248 | (interactive)
249 | (deft)
250 | (evil-insert-state nil))
251 | (setq deft-directory "~/Notes"
252 | deft-extensions '("org" "md" "txt" "markdown")
253 | deft-text-mode 'org-mode
254 | deft-use-filename-as-title t
255 | deft-use-filter-string-for-filename t))
256 |
257 | (use-package markdown-mode
258 | :commands (markdown-mode gfm-mode)
259 | :mode (("README\\.md\\'" . gfm-mode)
260 | ("\\.md\\'" . markdown-mode)
261 | ("\\.markdown\\'" . markdown-mode))
262 | :init (setq markdown-command "multimarkdown"))
263 |
264 | (provide 'setup-org)
265 | ;;; setup-org.el ends here
266 |
--------------------------------------------------------------------------------
/.hammerspoon/init.lua:
--------------------------------------------------------------------------------
1 | require("utils")
2 |
3 | local hotkey = require "hs.hotkey"
4 | local alert = require "hs.alert"
5 | hs.window.animationDuration = 0
6 |
7 | hyper = {"cmd", "alt", "ctrl"}
8 | hyper_shift = {"cmd", "alt", "ctrl", "shift"}
9 | shift_hyper = {"shift", "cmd", "alt", "ctrl"}
10 |
11 | -- -----------------------------------------------------------------------------
12 | -- Setup SpoonInstall so that we can install other spoons.
13 | -- -----------------------------------------------------------------------------
14 | hs.loadSpoon("SpoonInstall")
15 | spoonInstall = spoon.SpoonInstall
16 | spoonInstall.use_syncinstall = true
17 | spoonInstall:updateAllRepos()
18 |
19 | -- -----------------------------------------------------------------------------
20 | -- System Management
21 | -- -----------------------------------------------------------------------------
22 | -- local caffeinate = require "hs.caffeinate"
23 |
24 | -- Lockscreen
25 | -- hotkey.bind(hyper, "q", "Lock", function()
26 | -- caffeinate.lockScreen()
27 | -- end)
28 |
29 | -- caffeine functionality. icon images from keepingyouawake.
30 | -- local caffeine = hs.menubar.new()
31 | -- local activeMessage = "Sleeping prohitited"
32 | -- local inactiveMessage = "Sleeping allowed"
33 | -- function setCaffeineDisplay(state)
34 | -- if state then
35 | -- caffeine:setIcon("caffeine-active.png")
36 | -- caffeine:setTooltip(activeMessage)
37 | -- alert.show(activeMessage)
38 | -- else
39 | -- caffeine:setIcon("caffeine-inactive.png")
40 | -- caffeine:setTooltip(inactiveMessage)
41 | -- alert.show(inactiveMessage)
42 | -- end
43 | -- end
44 |
45 | -- function caffeineClicked()
46 | -- setCaffeineDisplay(caffeinate.toggle("displayIdle"))
47 | -- end
48 |
49 | -- if caffeine then
50 | -- caffeine:setClickCallback(caffeineClicked)
51 | -- setCaffeineDisplay(caffeinate.get("displayIdle"))
52 | -- end
53 |
54 | -- hotkey.bind({"cmd","shift"},"c", function()
55 | -- setCaffeineDisplay(caffeinate.toggle("displayIdle"))
56 | -- end)
57 |
58 | -- Make org-capture available system-wide.
59 | hotkey.bind(hyper, 'c', function()
60 | hs.execute("emacsclient -n -F '(quote (name . api|org-capture))' -e '(api/open-org-capture-frame)'", true)
61 | end)
62 |
63 | -- chunkwm doesn't correctly recognize hotplugging monitors. Current solution
64 | -- is to restart: https://github.com/koekeishiya/chunkwm/issues/313
65 | hotkey.bind(hyper, 'w', function()
66 | hs.notify.show("Yabai", "Restarting yabai", "")
67 | hs.execute("brew services restart yabai", true)
68 | hs.notify.show("Yabai", "Yabai restarted", "")
69 | end)
70 |
71 | -- -----------------------------------------------------------------------------
72 | -- Window Management with ChunkWM - emulate i3 but use hyper as modifier.
73 | -- -----------------------------------------------------------------------------
74 | mod1 = hyper -- {"alt"}
75 | mod2 = shift_hyper -- {"alt", "shift"}
76 |
77 | bindings = {
78 | -- Focus window
79 | { mod = mod1, key = 'h', command = "chunkc tiling::window --focus west" },
80 | { mod = mod1, key = 'j', command = "chunkc tiling::window --focus south" },
81 | { mod = mod1, key = 'k', command = "chunkc tiling::window --focus north" },
82 | { mod = mod1, key = 'l', command = "chunkc tiling::window --focus east" },
83 | { mod = mod1, key = 'p', command = "chunkc tiling::window --focus prev" },
84 | { mod = mod1, key = 'n', command = "chunkc tiling::window --focus next" },
85 | -- Fullscreen
86 | { mod = mod1, key = 'f', command = "chunkc tiling::window --toggle fullscreen" },
87 | -- Moving windows (swapping, actually)
88 | { mod = mod2, key = 'h', command = "chunkc tiling::window --swap west" },
89 | { mod = mod2, key = 'j', command = "chunkc tiling::window --swap south" },
90 | { mod = mod2, key = 'k', command = "chunkc tiling::window --swap north" },
91 | { mod = mod2, key = 'l', command = "chunkc tiling::window --swap east" },
92 | -- Reset and force windows to their original size
93 | { mod = mod1, key = '=', command = "chunkc tiling::desktop --equalize"},
94 | -- Close window
95 | { mod = mod2, key = 'q', command = "chunkc tiling::window --close" },
96 | }
97 |
98 | for _, binding in ipairs(bindings) do
99 | hotkey.bind(binding.mod, binding.key, function()
100 | hs.execute(binding.command, true)
101 | end)
102 | end
103 |
104 | --
105 | -- Resize mode
106 | --
107 | resize_mode = hs.hotkey.modal.new(hyper, "r")
108 |
109 | alert_uuid = nil
110 |
111 | function resize_mode:entered()
112 | alert_uuid = hs.alert.show("Window Resize Mode", true)
113 | end
114 |
115 | function resize_mode:exited()
116 | hs.alert.closeSpecific(alert_uuid)
117 | end
118 |
119 | resize_mode:bind({}, 'escape', function() resize_mode:exit() end)
120 | resize_mode:bind({}, 'return', function() resize_mode:exit() end)
121 | resize_mode:bind(hyper, 'r', function() resize_mode:exit() end)
122 | -- left will shrink the window’s width.
123 | resize_mode:bind({}, 'left', function()
124 | hs.execute("chunkc tiling::window --use-temporary-ratio -0.1 --adjust-window-edge east", true)
125 | end)
126 | -- right will grow the window’s width.
127 | resize_mode:bind({}, 'right', function()
128 | hs.execute("chunkc tiling::window --use-temporary-ratio 0.1 --adjust-window-edge east", true)
129 | end)
130 | -- up will shrink the window’s height.
131 | resize_mode:bind({}, 'up', function()
132 | hs.execute("chunkc tiling::window --use-temporary-ratio -0.1 --adjust-window-edge south", true)
133 | end)
134 | -- down will grow the window’s height.
135 | resize_mode:bind({}, 'down', function()
136 | hs.execute("chunkc tiling::window --use-temporary-ratio 0.1 --adjust-window-edge south", true)
137 | end)
138 |
139 | -- -----------------------------------------------------------------------------
140 | -- Window Management - not useful since I'm using a tiling WM.
141 | -- -----------------------------------------------------------------------------
142 | -- spoonInstall:installSpoonFromRepo("MiroWindowsManager")
143 | -- hs.loadSpoon("MiroWindowsManager")
144 | -- spoon.MiroWindowsManager:bindHotkeys({
145 | -- up = {hyper, "up"},
146 | -- right = {hyper, "right"},
147 | -- down = {hyper, "down"},
148 | -- left = {hyper, "left"},
149 | -- fullscreen = {hyper, "f"}
150 | -- })
151 |
152 | -- -----------------------------------------------------------------------------
153 | -- Window switching.
154 | -- -----------------------------------------------------------------------------
155 | --
156 | -- cmd-tab replacement using alt-tab. Not useful in most cases.
157 | --
158 | -- switcher = hs.window.switcher.new(hs.window.filter.new():setDefaultFilter{})
159 | -- switcher.ui.highlightColor = {0.4,0.4,0.5,0.8}
160 | -- switcher.ui.thumbnailSize = 128
161 | -- switcher.ui.selectedThumbnailSize = 284
162 | -- switcher.ui.backgroundColor = {0.3, 0.3, 0.3, 0.5}
163 | -- switcher.ui.fontName = 'System'
164 | -- switcher.ui.showSelectedTitle = false
165 |
166 | -- hs.hotkey.bind(hyper, "tab", function()switcher:next()end)
167 | -- hs.hotkey.bind(hyper_shift, "tab", function()switcher:previous()end)
168 |
169 | --
170 | -- ace-window style focused-window switcher in a given desktop with hyper-tab.
171 | --
172 | -- hs.hints.hintChars = {'a','s','d','f','g','h','j','k','l'}
173 | -- hotkey.bind(hyper, 'tab', function()
174 | -- hs.hints.windowHints()
175 | -- end)
176 |
177 | -- -----------------------------------------------------------------------------
178 | -- Application Management
179 | -- -----------------------------------------------------------------------------
180 | local application = require "hs.application"
181 |
182 | -- Quick launcher for most used apps bound to hyper + number.
183 |
184 | keysQuickApps = {
185 | {key = '1', name = 'Firefox'},
186 | {key = '2', name = 'nvALT'},
187 | {key = '3', name = 'Emacs'},
188 | {key = '4', name = 'Alacritty'},
189 | {key = '5', name = 'iTerm'},
190 | {key = '6', name = 'Finder'},
191 | }
192 |
193 | for _, app in ipairs(keysQuickApps) do
194 | hotkey.bind(hyper, app.key, app.name, function()
195 | hs.application.launchOrFocus(app.name)
196 | end)
197 | end
198 |
199 | --
200 | -- Modal bindings for other frequently used apps bound to [hyper + a] + key.
201 | --
202 | myModal = hotkey.modal.new({}, "F16")
203 |
204 | keysApps = {
205 | {key = 'a', name = 'Airmail 3'},
206 | {key = 'b', name = 'Firefox'},
207 | {key = 'e', name = 'Emacs'},
208 | {key = 'f', name = 'Finder'},
209 | {key = 'i', name = 'iTerm'},
210 | {key = 'p', name = 'Skim'},
211 | {key = 's', name = 'Safari'},
212 | {key = 't', name = 'Terminal'},
213 | }
214 |
215 | for _, app in ipairs(keysApps) do
216 | if app.id then
217 | local located_name = hs.application.nameForBundleID(app.id)
218 | if located_name then
219 | myModal:bind('', app.key, located_name, function()
220 | hs.application.launchOrFocusByBundleID(app.id)
221 | myModal:exit()
222 | end)
223 | end
224 | elseif app.name then
225 | myModal:bind('', app.key, app.name, function()
226 | hs.application.launchOrFocus(app.name)
227 | myModal:exit()
228 | end)
229 | end
230 | end
231 |
232 | pressedModal = function() myModal:enter() end
233 | releasedModal = function() end
234 | hotkey.bind(hyper, 'a', nil, pressedModal, releasedModal)
235 |
236 | -- -----------------------------------------------------------------------------
237 | -- Monitor battery power source and rebind keys if necessary.
238 | -- -----------------------------------------------------------------------------
239 | -- local battery = require "hs.battery"
240 | -- local currentPowerSource = ""
241 | -- local browser = ""
242 | -- --local appsOnACPowerOnly = {"Backup and Sync from Google", "Dropbox"}
243 |
244 | -- function watchBatteryPowerSource()
245 | -- local powerSource = battery.powerSource()
246 | -- if currentPowerSource ~= powerSource then
247 | -- currentPowerSource = powerSource
248 | -- local isOnBattery = powerSource == 'Battery Power'
249 |
250 | -- -- for _, appName in ipairs(appsOnACPowerOnly) do
251 | -- -- local app = {hs.application.find(appName)}
252 | -- -- if isOnBattery then
253 | -- -- if next(app) ~= nil then
254 | -- -- for _, id in ipairs(app) do
255 | -- -- id:kill(9)
256 | -- -- end
257 | -- -- end
258 | -- -- else
259 | -- -- if next(app) == nil then
260 | -- -- hs.application.launchOrFocus(appName)
261 | -- -- end
262 | -- -- end
263 | -- -- end
264 |
265 | -- browser = "Firefox"
266 | -- if isOnBattery then
267 | -- browser = "Safari"
268 | -- end
269 |
270 | -- hotkey.bind(hyper, '1', nil, function()
271 | -- hs.application.launchOrFocus(browser)
272 | -- end)
273 |
274 | -- end
275 | -- end
276 |
277 | -- battery.watcher.new(watchBatteryPowerSource):start()
278 | -- watchBatteryPowerSource()
279 |
280 | -- -----------------------------------------------------------------------------
281 | -- Watch for monitor configuration changes, and restart chunkwm everytime
282 | -- the monitor changes.
283 | -- -----------------------------------------------------------------------------
284 | local laptop_screen = "Color LCD"
285 | local home_screen = "FHD2303L"
286 | local work_screen = ""
287 |
288 | local timer = null
289 | local DELAY = 5
290 |
291 | common_window_layout = {
292 | {'Safari', nil, laptop_screen, hs.layout.maximized, nil, nil},
293 | {'Firefox', nil, laptop_screen, hs.layout.maximized, nil, nil},
294 | {'Mail', nil, laptop_screen, hs.layout.maximized, nil, nil},
295 | }
296 |
297 | function enforce_layout ()
298 | local all_screens = hs.screen.allScreens()
299 | local screen_count = table_length(all_screens)
300 |
301 | if (screen_count == 2) then
302 | local second_screen = all_screens[2]
303 | local window_layout = {
304 | {"Emacs", nil, second_screen, hs.layout.maximized, nil, nil},
305 | {"iTerm", nil, second_screen, hs.layout.maximized, nil, nil},
306 | {"Alacritty", nil, second_screen, hs.layout.maximized, nil, nil},
307 | }
308 |
309 | local final_layout = {}
310 | table_merge(final_layout, common_window_layout)
311 | table_merge(final_layout, window_layout)
312 | hs.layout.apply(final_layout)
313 | end
314 | end
315 |
316 | function screen_watcher_handler ()
317 | if (timer) then timer:stop() end
318 | timer = hs.timer.doAfter(DELAY, function()
319 | enforce_layout()
320 | end)
321 | end
322 |
323 | -- local screen_watcher = hs.screen.watcher.new(screen_watcher_handler)
324 | -- screen_watcher:start()
325 |
326 | -- -----------------------------------------------------------------------------
327 | -- Show the mouse when its hiding somewhere.
328 | -- -----------------------------------------------------------------------------
329 | spoonInstall:installSpoonFromRepo("MouseCircle")
330 | hs.loadSpoon("MouseCircle")
331 | spoon.MouseCircle:bindHotkeys({
332 | show = { hyper, "m" }
333 | })
334 |
335 | -- -----------------------------------------------------------------------------
336 | -- Reload config automatically upon change.
337 | -- -----------------------------------------------------------------------------
338 | spoonInstall:installSpoonFromRepo("ReloadConfiguration")
339 | hs.loadSpoon("ReloadConfiguration")
340 | --spoon.ReloadConfiguration:start()
341 | -- function reloadConfig(files)
342 | -- doReload = false
343 | -- for _,file in pairs(files) do
344 | -- if file:sub(-4) == ".lua" then
345 | -- doReload = true
346 | -- end
347 | -- end
348 | -- if doReload then
349 | -- hs.reload()
350 | -- end
351 | -- end
352 | -- local myWatcher = hs.pathwatcher.new("/Users/api/.hammerspoon/",
353 | -- reloadConfig):start()
354 | alert.show("Hammerspoon config loaded")
355 |
--------------------------------------------------------------------------------
/.hammerspoon/Spoons/SpoonInstall.spoon/init.lua:
--------------------------------------------------------------------------------
1 | --- === SpoonInstall ===
2 | ---
3 | --- Install and manage Spoons and Spoon repositories
4 | ---
5 | --- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/SpoonInstall.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/SpoonInstall.spoon.zip)
6 |
7 | local obj={}
8 | obj.__index = obj
9 |
10 | -- Metadata
11 | obj.name = "SpoonInstall"
12 | obj.version = "0.1"
13 | obj.author = "Diego Zamboni "
14 | obj.homepage = "https://github.com/Hammerspoon/Spoons"
15 | obj.license = "MIT - https://opensource.org/licenses/MIT"
16 |
17 | --- SpoonInstall.logger
18 | --- Variable
19 | --- Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.
20 | obj.logger = hs.logger.new('SpoonInstall')
21 |
22 | --- SpoonInstall.repos
23 | --- Variable
24 | --- Table containing the list of available Spoon repositories. The key
25 | --- of each entry is an identifier for the repository, and its value
26 | --- is a table with the following entries:
27 | --- * desc - Human-readable description for the repository
28 | --- * url - Base URL for the repository. For now the repository is assumed to be hosted in GitHub, and the URL should be the main base URL of the repository. Repository metadata needs to be stored under `docs/docs.json`, and the Spoon zip files need to be stored under `Spoons/`.
29 | ---
30 | --- Default value:
31 | --- ```
32 | --- {
33 | --- default = {
34 | --- url = "https://github.com/Hammerspoon/Spoons",
35 | --- desc = "Main Hammerspoon Spoon repository",
36 | --- }
37 | --- }
38 | --- ```
39 | obj.repos = {
40 | default = {
41 | url = "https://github.com/Hammerspoon/Spoons",
42 | desc = "Main Hammerspoon Spoon repository",
43 | }
44 | }
45 |
46 | --- SpoonInstall.use_syncinstall
47 | --- Variable
48 | --- If `true`, `andUse()` will update repos and install packages synchronously. Defaults to `false`.
49 | ---
50 | --- Keep in mind that if you set this to `true`, Hammerspoon will
51 | --- block until all missing Spoons are installed, but the notifications
52 | --- will happen at a more "human readable" rate.
53 | obj.use_syncinstall = false
54 |
55 | -- Execute a command and return its output with trailing EOLs trimmed. If the command fails, an error message is logged.
56 | local function _x(cmd, errfmt, ...)
57 | local output, status = hs.execute(cmd)
58 | if status then
59 | local trimstr = string.gsub(output, "\n*$", "")
60 | return trimstr
61 | else
62 | obj.logger.ef(errfmt, ...)
63 | return nil
64 | end
65 | end
66 |
67 | -- --------------------------------------------------------------------
68 | -- Spoon repository management
69 |
70 | -- Internal callback to process and store the data from docs.json about a repository
71 | -- callback is called with repo as arguments, only if the call is successful
72 | function obj:_storeRepoJSON(repo, callback, status, body, hdrs)
73 | local success=nil
74 | if (status < 100) or (status >= 400) then
75 | self.logger.ef("Error fetching JSON data for repository '%s'. Error code %d: %s", repo, status, body or "")
76 | else
77 | local json = hs.json.decode(body)
78 | if json then
79 | self.repos[repo].data = {}
80 | for i,v in ipairs(json) do
81 | v.download_url = self.repos[repo].download_base_url .. v.name .. ".spoon.zip"
82 | self.repos[repo].data[v.name] = v
83 | end
84 | self.logger.df("Updated JSON data for repository '%s'", repo)
85 | success=true
86 | else
87 | self.logger.ef("Invalid JSON received for repository '%s': %s", repo, body)
88 | end
89 | end
90 | if callback then
91 | callback(repo, success)
92 | end
93 | return success
94 | end
95 |
96 | -- Internal function to return the URL of the docs.json file based on the URL of a GitHub repo
97 | function obj:_build_repo_json_url(repo)
98 | if self.repos[repo] and self.repos[repo].url then
99 | self.repos[repo].json_url = string.gsub(self.repos[repo].url, "/$", "") .. "/raw/master/docs/docs.json"
100 | self.repos[repo].download_base_url = string.gsub(self.repos[repo].url, "/$", "") .. "/raw/master/Spoons/"
101 | return true
102 | else
103 | self.logger.ef("Invalid or unknown repository '%s'", repo)
104 | return nil
105 | end
106 | end
107 |
108 | --- SpoonInstall:asyncUpdateRepo(repo, callback)
109 | --- Method
110 | --- Asynchronously fetch the information about the contents of a Spoon repository
111 | ---
112 | --- Parameters:
113 | --- * repo - name of the repository to update. Defaults to `"default"`.
114 | --- * callback - if given, a function to be called after the update finishes (also if it fails). The function will receive the following arguments:
115 | --- * repo - name of the repository
116 | --- * success - boolean indicating whether the update succeeded
117 | ---
118 | --- Returns:
119 | --- * `true` if the update was correctly initiated (i.e. the repo name is valid), `nil` otherwise
120 | ---
121 | --- Notes:
122 | --- * For now, the repository data is not persisted, so you need to update it after every restart if you want to use any of the install functions.
123 | function obj:asyncUpdateRepo(repo, callback)
124 | if not repo then repo = 'default' end
125 | if self:_build_repo_json_url(repo) then
126 | hs.http.asyncGet(self.repos[repo].json_url, nil, hs.fnutils.partial(self._storeRepoJSON, self, repo, callback))
127 | return true
128 | else
129 | return nil
130 | end
131 | end
132 |
133 | --- SpoonInstall:updateRepo(repo)
134 | --- Method
135 | --- Synchronously fetch the information about the contents of a Spoon repository
136 | ---
137 | --- Parameters:
138 | --- * repo - name of the repository to update. Defaults to `"default"`.
139 | ---
140 | --- Returns:
141 | --- * `true` if the update was successful, `nil` otherwise
142 | ---
143 | --- Notes:
144 | --- * This is a synchronous call, which means Hammerspoon will be blocked until it finishes. For use in your configuration files, it's advisable to use `SpoonInstall.asyncUpdateRepo()` instead.
145 | --- * For now, the repository data is not persisted, so you need to update it after every restart if you want to use any of the install functions.
146 | function obj:updateRepo(repo)
147 | if not repo then repo = 'default' end
148 | if self:_build_repo_json_url(repo) then
149 | local a,b,c = hs.http.get(self.repos[repo].json_url)
150 | return self:_storeRepoJSON(repo, nil, a, b, c)
151 | else
152 | return nil
153 | end
154 | end
155 |
156 | --- SpoonInstall:updateAllRepos()
157 | --- Method
158 | --- Synchronously fetch the information about the contents of all Spoon repositories registered in `SpoonInstall.repos`
159 | ---
160 | --- Parameters:
161 | --- * None
162 | ---
163 | --- Returns:
164 | --- * None
165 | ---
166 | --- Notes:
167 | --- * This is a synchronous call, which means Hammerspoon will be blocked until it finishes.
168 | --- * For now, the repository data is not persisted, so you need to update it after every restart if you want to use any of the install functions.
169 | function obj:updateAllRepos()
170 | for k,v in pairs(self.repos) do
171 | self:updateRepo(k)
172 | end
173 | end
174 |
175 | --- SpoonInstall:repolist()
176 | --- Method
177 | --- Return a sorted list of registered Spoon repositories
178 | ---
179 | --- Parameters:
180 | --- * None
181 | ---
182 | --- Returns:
183 | --- * Table containing a list of strings with the repository identifiers
184 | function obj:repolist()
185 | local keys={}
186 | -- Create sorted list of keys
187 | for k,v in pairs(self.repos) do table.insert(keys, k) end
188 | table.sort(keys)
189 | return keys
190 | end
191 |
192 | --- SpoonInstall:search(pat)
193 | --- Method
194 | --- Search repositories for a pattern
195 | ---
196 | --- Parameters:
197 | --- * pat - Lua pattern that will be matched against the name and description of each spoon in the registered repositories. All text is converted to lowercase before searching it, so you can use all-lowercase in your pattern.
198 | ---
199 | --- Returns:
200 | --- * Table containing a list of matching entries. Each entry is a table with the following keys:
201 | --- * name - Spoon name
202 | --- * desc - description of the spoon
203 | --- * repo - identifier in the repository where the match was found
204 | function obj:search(pat)
205 | local res={}
206 | for repo,v in pairs(self.repos) do
207 | if v.data then
208 | for spoon,rec in pairs(v.data) do
209 | if string.find(string.lower(rec.name .. "\n" .. rec.desc), pat) then
210 | table.insert(res, { name = rec.name, desc = rec.desc, repo = repo })
211 | end
212 | end
213 | else
214 | self.logger.ef("Repository data for '%s' not available - call spoon.SpoonInstall:updateRepo('%s'), then try again.", repo, repo)
215 | end
216 | end
217 | return res
218 | end
219 |
220 | -- --------------------------------------------------------------------
221 | -- Spoon installation
222 |
223 | -- Internal callback function to finalize the installation of a spoon after the zip file has been downloaded.
224 | -- callback, if given, is called with (urlparts, success) as arguments
225 | function obj:_installSpoonFromZipURLgetCallback(urlparts, callback, status, body, headers)
226 | local success=nil
227 | if (status < 100) or (status >= 400) then
228 | self.logger.ef("Error downloading %s. Error code %d: %s", urlparts.absoluteString, status, body or "")
229 | else
230 | -- Write the zip file to disk in a temporary directory
231 | local tmpdir=_x("/usr/bin/mktemp -d", "Error creating temporary directory to download new spoon.")
232 | if tmpdir then
233 | local outfile = string.format("%s/%s", tmpdir, urlparts.lastPathComponent)
234 | local f=assert(io.open(outfile, "w"))
235 | f:write(body)
236 | f:close()
237 |
238 | -- Check its contents - only one *.spoon directory should be in there
239 | output = _x(string.format("/usr/bin/unzip -l %s '*.spoon/' | /usr/bin/awk '$NF ~ /\\.spoon\\/$/ { print $NF }' | /usr/bin/wc -l", outfile),
240 | "Error examining downloaded zip file %s, leaving it in place for your examination.", outfile)
241 | if output then
242 | if (tonumber(output) or 0) == 1 then
243 | -- Uncompress the zip file
244 | local outdir = string.format("%s/Spoons", hs.configdir)
245 | if _x(string.format("/usr/bin/unzip -o %s -d %s 2>&1", outfile, outdir),
246 | "Error uncompressing file %s, leaving it in place for your examination.", outfile) then
247 | -- And finally, install it using Hammerspoon itself
248 | self.logger.f("Downloaded and installed %s", urlparts.absoluteString)
249 | _x(string.format("/bin/rm -rf '%s'", tmpdir), "Error removing directory %s", tmpdir)
250 | success=true
251 | end
252 | else
253 | self.logger.ef("The downloaded zip file %s is invalid - it should contain exactly one spoon. Leaving it in place for your examination.", outfile)
254 | end
255 | end
256 | end
257 | end
258 | if callback then
259 | callback(urlparts, success)
260 | end
261 | return success
262 | end
263 |
264 | --- SpoonInstall:asyncInstallSpoonFromZipURL(url, callback)
265 | --- Method
266 | --- Asynchronously download a Spoon zip file and install it.
267 | ---
268 | --- Parameters:
269 | --- * url - URL of the zip file to install.
270 | --- * callback - if given, a function to call after the installation finishes (also if it fails). The function receives the following arguments:
271 | --- * urlparts - Result of calling `hs.http.urlParts` on the URL of the Spoon zip file
272 | --- * success - boolean indicating whether the installation was successful
273 | ---
274 | --- Returns:
275 | --- * `true` if the installation was correctly initiated (i.e. the URL is valid), `false` otherwise
276 | function obj:asyncInstallSpoonFromZipURL(url, callback)
277 | local urlparts = hs.http.urlParts(url)
278 | local dlfile = urlparts.lastPathComponent
279 | if dlfile and dlfile ~= "" and urlparts.pathExtension == "zip" then
280 | hs.http.asyncGet(url, nil, hs.fnutils.partial(self._installSpoonFromZipURLgetCallback, self, urlparts, callback))
281 | return true
282 | else
283 | self.logger.ef("Invalid URL %s, must point to a zip file", url)
284 | return nil
285 | end
286 | end
287 |
288 | --- SpoonInstall:installSpoonFromZipURL(url)
289 | --- Method
290 | --- Synchronously download a Spoon zip file and install it.
291 | ---
292 | --- Parameters:
293 | --- * url - URL of the zip file to install.
294 | ---
295 | --- Returns:
296 | --- * `true` if the installation was successful, `nil` otherwise
297 | function obj:installSpoonFromZipURL(url)
298 | local urlparts = hs.http.urlParts(url)
299 | local dlfile = urlparts.lastPathComponent
300 | if dlfile and dlfile ~= "" and urlparts.pathExtension == "zip" then
301 | a,b,c=hs.http.get(url)
302 | return self:_installSpoonFromZipURLgetCallback(urlparts, nil, a, b, c)
303 | else
304 | self.logger.ef("Invalid URL %s, must point to a zip file", url)
305 | return nil
306 | end
307 | end
308 |
309 | -- Internal function to check if a Spoon/Repo combination is valid
310 | function obj:_is_valid_spoon(name, repo)
311 | if self.repos[repo] then
312 | if self.repos[repo].data then
313 | if self.repos[repo].data[name] then
314 | return true
315 | else
316 | self.logger.ef("Spoon '%s' does not exist in repository '%s'. Please check and try again.", name, repo)
317 | end
318 | else
319 | self.logger.ef("Repository data for '%s' not available - call spoon.SpoonInstall:updateRepo('%s'), then try again.", repo, repo)
320 | end
321 | else
322 | self.logger.ef("Invalid or unknown repository '%s'", repo)
323 | end
324 | return nil
325 | end
326 |
327 | --- SpoonInstall:asyncInstallSpoonFromRepo(name, repo, callback)
328 | --- Method
329 | --- Asynchronously install a Spoon from a registered repository
330 | ---
331 | --- Parameters:
332 | --- * name - Name of the Spoon to install.
333 | --- * repo - Name of the repository to use. Defaults to `"default"`
334 | --- * callback - if given, a function to call after the installation finishes (also if it fails). The function receives the following arguments:
335 | --- * urlparts - Result of calling `hs.http.urlParts` on the URL of the Spoon zip file
336 | --- * success - boolean indicating whether the installation was successful
337 | ---
338 | --- Returns:
339 | --- * `true` if the installation was correctly initiated (i.e. the repo and spoon name were correct), `false` otherwise.
340 | function obj:asyncInstallSpoonFromRepo(name, repo, callback)
341 | if not repo then repo = 'default' end
342 | if self:_is_valid_spoon(name, repo) then
343 | self:asyncInstallSpoonFromZipURL(self.repos[repo].data[name].download_url, callback)
344 | end
345 | return nil
346 | end
347 |
348 | --- SpoonInstall:installSpoonFromRepo(name, repo)
349 | --- Method
350 | --- Synchronously install a Spoon from a registered repository
351 | ---
352 | --- Parameters:
353 | --- * name = Name of the Spoon to install.
354 | --- * repo - Name of the repository to use. Defaults to `"default"`
355 | ---
356 | --- Returns:
357 | --- * `true` if the installation was successful, `nil` otherwise.
358 | function obj:installSpoonFromRepo(name, repo, callback)
359 | if not repo then repo = 'default' end
360 | if self:_is_valid_spoon(name, repo) then
361 | return self:installSpoonFromZipURL(self.repos[repo].data[name].download_url)
362 | end
363 | return nil
364 | end
365 |
366 | --- SpoonInstall:andUse(name, arg)
367 | --- Method
368 | --- Declaratively install, load and configure a Spoon
369 | ---
370 | --- Parameters:
371 | --- * name - the name of the Spoon to install (without the `.spoon` extension). If the Spoon is already installed, it will be loaded using `hs.loadSpoon()`. If it is not installed, it will be installed using `SpoonInstall:asyncInstallSpoonFromRepo()` and then loaded.
372 | --- * arg - if provided, can be used to specify the configuration of the Spoon. The following keys are recognized (all are optional):
373 | --- * repo - repository from where the Spoon should be installed if not present in the system, as defined in `SpoonInstall.repos`. Defaults to `"default"`.
374 | --- * config - a table containing variables to be stored in the Spoon object to configure it. For example, `config = { answer = 42 }` will result in `spoon..answer` being set to 42.
375 | --- * hotkeys - a table containing hotkey bindings. If provided, will be passed as-is to the Spoon's `bindHotkeys()` method. The special string `"default"` can be given to use the Spoons `defaultHotkeys` variable, if it exists.
376 | --- * fn - a function which will be called with the freshly-loaded Spoon object as its first argument.
377 | --- * loglevel - if the Spoon has a variable called `logger`, its `setLogLevel()` method will be called with this value.
378 | --- * start - if `true`, call the Spoon's `start()` method after configuring everything else.
379 | --- * disable - if `true`, do nothing. Easier than commenting it out when you want to temporarily disable a spoon.
380 | ---
381 | --- Returns:
382 | --- * None
383 | function obj:andUse(name, arg)
384 | if not arg then arg = {} end
385 | if arg.disable then return true end
386 | if hs.spoons.use(name, arg, true) then
387 | return true
388 | else
389 | local repo = arg.repo or "default"
390 | if self.repos[repo] then
391 | if self.repos[repo].data then
392 | local load_and_config = function(_, success)
393 | if success then
394 | hs.notify.show("Spoon installed by SpoonInstall", name .. ".spoon is now available", "")
395 | hs.spoons.use(name, arg)
396 | else
397 | obj.logger.ef("Error installing Spoon '%s' from repo '%s'", name, repo)
398 | end
399 | end
400 | if self.use_syncinstall then
401 | return load_and_config(nil, self:installSpoonFromRepo(name, repo))
402 | else
403 | self:asyncInstallSpoonFromRepo(name, repo, load_and_config)
404 | end
405 | else
406 | local update_repo_and_continue = function(_, success)
407 | if success then
408 | obj:andUse(name, arg)
409 | else
410 | obj.logger.ef("Error updating repository '%s'", repo)
411 | end
412 | end
413 | if self.use_syncinstall then
414 | return update_repo_and_continue(nil, self:updateRepo(repo))
415 | else
416 | self:asyncUpdateRepo(repo, update_repo_and_continue)
417 | end
418 | end
419 | else
420 | obj.logger.ef("Unknown repository '%s' for Spoon", repo, name)
421 | end
422 | end
423 | end
424 |
425 | return obj
426 |
--------------------------------------------------------------------------------