-(setq compilation-exit-message-function
- (lambda (status code msg)
- "Close the compilation window if successful."
- ;; if M-x compile exits with 0
- (when (and (eq status 'exit) (zerop code))
- (bury-buffer)
- (delete-window (get-buffer-window (get-buffer "*compilation*"))))
- ;; return the result of compilation-exit-message-function
- (cons msg code)))
-
-(setq search-default-mode #'char-fold-to-regexp)
-
-;; uncomment to extend this behaviour to query-replace
-;; (setq replace-char-fold t)
-
-(bind-keys
- ("C-c a i" . ielm)
-
- ("C-c e b" . eval-buffer)
- ("C-c e r" . eval-region)
-
- ("C-c F m" . make-frame-command)
- ("C-c F d" . delete-frame)
- ("C-c F D" . delete-other-frames)
-
- ("C-c o" . other-window)
-
- ("C-c Q" . save-buffers-kill-terminal)
-
- ("C-S-h C" . describe-char)
- ("C-S-h F" . describe-face)
-
- ("C-x K" . kill-this-buffer)
-
- ("s-p" . beginning-of-buffer)
- ("s-n" . end-of-buffer))
-
-(use-package auto-compile
- :demand t
- :config
- (auto-compile-on-load-mode)
- (auto-compile-on-save-mode)
- (setq auto-compile-display-buffer nil
- auto-compile-mode-line-counter t
- auto-compile-source-recreate-deletes-dest t
- auto-compile-toggle-deletes-nonlib-dest t
- auto-compile-update-autoloads t)
- (add-hook 'auto-compile-inhibit-compile-hook
- 'auto-compile-inhibit-compile-detached-git-head))
-
-(use-package org
- :defer 1
- :config
- (setq org-src-tab-acts-natively t
- org-src-preserve-indentation nil
- org-edit-src-content-indentation 0
- org-email-link-description-format "Email %c: %s" ; %.30s
- org-highlight-latex-and-related '(entities)
- org-log-done 'time)
- (add-to-list 'org-structure-template-alist '("L" . "src emacs-lisp") t)
- (font-lock-add-keywords
- 'org-mode
- '(("[ \t]*\\(#\\+\\(BEGIN\\|END\\|begin\\|end\\)_\\(\\S-+\\)\\)[ \t]*\\([^\n:]*\\)"
- (1 '(:foreground "#5a5b5a" :background "#292b2b") t) ; directive
- (3 '(:foreground "#81a2be" :background "#292b2b") t) ; kind
- (4 '(:foreground "#c5c8c6") t))) ; title
- t)
- :bind (:map org-mode-map ("M-L" . org-insert-last-stored-link))
- :hook ((org-mode . org-indent-mode)
- (org-mode . auto-fill-mode)
- (org-mode . flyspell-mode))
- :custom
- (org-latex-packages-alist '(("" "listings") ("" "color")))
- :custom-face
- '(org-block-begin-line ((t (:foreground "#5a5b5a" :background "#1d1f21"))))
- '(org-block ((t (:background "#1d1f21"))))
- '(org-latex-and-related ((t (:foreground "#b294bb")))))
-
-(use-package ox-latex
- :after ox
- :config
- (setq org-latex-listings 'listings
- ;; org-latex-prefer-user-labels t
- )
- (add-to-list 'org-latex-packages-alist '("" "listings"))
- (add-to-list 'org-latex-packages-alist '("" "color"))
- (add-to-list 'org-latex-classes
- '("IEEEtran" "\\documentclass[11pt]{IEEEtran}"
- ("\\section{%s}" . "\\section*{%s}")
- ("\\subsection{%s}" . "\\subsection*{%s}")
- ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
- ("\\paragraph{%s}" . "\\paragraph*{%s}")
- ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
- t))
-
-(use-package ox-beamer
- :after ox)
-
-(use-package orgalist
- :after message
- :hook (message-mode . orgalist-mode))
-
-(after! org
- (defvar amin-show-async-tangle-results nil
- "Keep *emacs* async buffers around for later inspection.")
-
- (defvar amin-show-async-tangle-time nil
- "Show the time spent tangling the file.")
-
- (defvar amin-async-tangle-post-compile "make ti"
- "If non-nil, pass to `compile' after successful tangle.")
-
- (defun amin/async-babel-tangle ()
- "Tangle org file asynchronously."
- (interactive)
- (let* ((file-tangle-start-time (current-time))
- (file (buffer-file-name))
- (file-nodir (file-name-nondirectory file))
- (async-quiet-switch "-q"))
- (async-start
- `(lambda ()
- (require 'org)
- (org-babel-tangle-file ,file))
- (unless amin-show-async-tangle-results
- `(lambda (result)
- (if result
- (progn
- (message "Tangled %s%s"
- ,file-nodir
- (if amin-show-async-tangle-time
- (format " (%.3fs)"
- (float-time (time-subtract (current-time)
- ',file-tangle-start-time)))
- ""))
- (when amin-async-tangle-post-compile
- (compile amin-async-tangle-post-compile)))
- (message "Tangling %s failed" ,file-nodir))))))))
-
-(add-to-list
- 'safe-local-variable-values
- '(eval add-hook 'after-save-hook #'amin/async-babel-tangle 'append 'local))
-
-(use-package magit
- :defer 1
- :bind (("C-x g" . magit-status)
- ("s-g s" . magit-status)
- ("s-g l" . magit-log-buffer-file))
- :config
- (magit-add-section-hook 'magit-status-sections-hook
- 'magit-insert-modules
- 'magit-insert-stashes
- 'append)
- (setq
- magit-repository-directories '(("~/.emacs.d/" . 0)
- ("~/src/git/" . 1)))
- (nconc magit-section-initial-visibility-alist
- '(([unpulled status] . show)
- ([unpushed status] . show)))
- :custom-face (magit-diff-file-heading ((t (:weight normal)))))
-
-(use-package ivy
- :defer 1
- :bind
- (:map ivy-minibuffer-map
- ([escape] . keyboard-escape-quit)
- ([S-up] . ivy-previous-history-element)
- ([S-down] . ivy-next-history-element)
- ("DEL" . ivy-backward-delete-char))
- :config
- (setq ivy-wrap t)
- (ivy-mode 1)
- ;; :custom-face
- ;; (ivy-minibuffer-match-face-2 ((t (:background "#e99ce8" :weight semi-bold))))
- ;; (ivy-minibuffer-match-face-3 ((t (:background "#bbbbff" :weight semi-bold))))
- ;; (ivy-minibuffer-match-face-4 ((t (:background "#ffbbff" :weight semi-bold))))
-)
-
-(use-package swiper
- :bind (("C-s" . swiper)
- ("C-r" . swiper)))
-
-(use-package counsel
- :defer 1
- :bind (([remap execute-extended-command] . counsel-M-x)
- ([remap find-file] . counsel-find-file)
- ("s-r" . counsel-recentf)
- ("C-c x" . counsel-M-x)
- ("C-c f ." . counsel-find-file)
- :map minibuffer-local-map
- ("C-r" . counsel-minibuffer-history))
- :config
- (counsel-mode 1)
- (defalias 'locate #'counsel-locate))
-
-(use-package eshell
- :defer 1
- :commands eshell
- :config
- (eval-when-compile (defvar eshell-prompt-regexp))
- (defun amin/eshell-quit-or-delete-char (arg)
- (interactive "p")
- (if (and (eolp) (looking-back eshell-prompt-regexp nil))
- (eshell-life-is-too-much)
- (delete-char arg)))
-
- (defun amin/eshell-clear ()
- (interactive)
- (let ((inhibit-read-only t))
- (erase-buffer))
- (eshell-send-input))
-
- (defun amin|eshell-setup ()
- (make-local-variable 'company-idle-delay)
- (setq company-idle-delay nil)
- (bind-keys :map eshell-mode-map
- ("C-d" . amin/eshell-quit-or-delete-char)
- ("C-S-l" . amin/eshell-clear)
- ("M-r" . counsel-esh-history)
- ([tab] . company-complete)))
-
- :hook (eshell-mode . amin|eshell-setup)
- :custom
- (eshell-hist-ignoredups t)
- (eshell-input-filter 'eshell-input-filter-initial-space))
-
-(use-package ibuffer
- :defer t
- :bind
- (("C-x C-b" . ibuffer-other-window)
- :map ibuffer-mode-map
- ("P" . ibuffer-backward-filter-group)
- ("N" . ibuffer-forward-filter-group)
- ("M-p" . ibuffer-do-print)
- ("M-n" . ibuffer-do-shell-command-pipe-replace))
- :config
- ;; Use human readable Size column instead of original one
- (define-ibuffer-column size-h
- (:name "Size" :inline t)
- (cond
- ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0)))
- ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0)))
- ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0)))
- (t (format "%8d" (buffer-size)))))
- :custom
- (ibuffer-saved-filter-groups
- '(("default"
- ("dired" (mode . dired-mode))
- ("org" (mode . org-mode))
- ("web"
- (or
- (mode . web-mode)
- (mode . css-mode)
- (mode . scss-mode)
- (mode . js2-mode)))
- ("shell"
- (or
- (mode . eshell-mode)
- (mode . shell-mode)))
- ("notmuch" (name . "\*notmuch\*"))
- ("programming"
- (or
- (mode . python-mode)
- (mode . c++-mode)
- (mode . emacs-lisp-mode)))
- ("emacs"
- (or
- (name . "^\\*scratch\\*$")
- (name . "^\\*Messages\\*$")))
- ("slack"
- (or
- (name . "^\\*Slack*"))))))
- (ibuffer-formats
- '((mark modified read-only locked " "
- (name 18 18 :left :elide)
- " "
- (size-h 9 -1 :right)
- " "
- (mode 16 16 :left :elide)
- " " filename-and-process)
- (mark " "
- (name 16 -1)
- " " filename)))
- :hook (ibuffer . (lambda () (ibuffer-switch-to-saved-filter-groups "default"))))
-
-(use-package outline
- :defer t
- :hook (prog-mode . outline-minor-mode)
- :bind
- (:map
- outline-minor-mode-map
- ("<s-tab>" . outline-toggle-children)
- ("M-p" . outline-previous-visible-heading)
- ("M-n" . outline-next-visible-heading)
- :prefix-map amin--outline-prefix-map
- :prefix "s-o"
- ("TAB" . outline-toggle-children)
- ("a" . outline-hide-body)
- ("H" . outline-hide-body)
- ("S" . outline-show-all)
- ("h" . outline-hide-subtree)
- ("s" . outline-show-subtree)))
+(with-eval-after-load 'compile
+ ;; don't display *compilation* buffer on success. based on
+ ;; https://stackoverflow.com/a/17788551, with changes to use `cl-letf'
+ ;; instead of the now obsolete `flet'.
+ (defun b/compilation-finish-function (buffer outstr)
+ (unless (string-match "finished" outstr)
+ (switch-to-buffer-other-window buffer))
+ t)
+
+ (setq compilation-finish-functions #'b/compilation-finish-function)
+
+ (require 'cl-macs)
+
+ (defadvice compilation-start
+ (around inhibit-display
+ (command &optional mode name-function highlight-regexp))
+ (if (not (string-match "^\\(find\\|grep\\)" command))
+ (cl-letf (((symbol-function 'display-buffer) #'ignore))
+ (save-window-excursion ad-do-it))
+ ad-do-it))
+ (ad-activate 'compilation-start))
+
+;; isearch
+(csetq
+ ;; allow scrolling in Isearch
+ isearch-allow-scroll t
+ ;; search for non-ASCII characters: i’d like non-ASCII characters such
+ ;; as ‘’“”«»‹›áⓐ𝒶 to be selected when i search for their ASCII
+ ;; counterpart. shoutout to
+ ;; http://endlessparentheses.com/new-in-emacs-25-1-easily-search-non-ascii-characters.html
+ search-default-mode #'char-fold-to-regexp)
+
+;; replace
+;; uncomment to extend the above behaviour to query-replace
+;; (csetq replace-char-fold t)
+
+;; vc
+(global-set-key (kbd "C-x v C-=") #'vc-ediff)
+
+(with-eval-after-load 'vc-git
+ (csetq vc-git-print-log-follow t
+ vc-git-show-stash 0))
+
+(csetq ediff-window-setup-function 'ediff-setup-windows-plain
+ ediff-split-window-function 'split-window-horizontally)
+(with-eval-after-load 'ediff
+ (add-hook 'ediff-after-quit-hook-internal #'winner-undo))
+
+;; face-remap
+(csetq
+ ;; gentler font resizing
+ text-scale-mode-step 1.05)
+
+(run-with-idle-timer 0.4 nil #'require 'mwheel)
+(csetq mouse-wheel-scroll-amount '(1 ((shift) . 1)) ; one line at a time
+ mouse-wheel-progressive-speed nil ; don't accelerate scrolling
+ mouse-wheel-follow-mouse t) ; scroll window under mouse
+
+(run-with-idle-timer 0.4 nil #'require 'pixel-scroll)
+(with-eval-after-load 'pixel-scroll
+ (pixel-scroll-mode 1))
+
+;; epg-config
+(csetq
+ epg-gpg-program (executable-find "gpg")
+ ;; ask for GPG passphrase in minibuffer
+ ;; this will fail if gpg>=2.1 is not available
+ epg-pinentry-mode 'loopback)
+
+;; (require 'pinentry)
+;; workaround for systemd-based distros:
+;; (setq pinentry--socket-dir server-socket-dir)
+;; (pinentry-start)
+
+;; auth-source
+(csetq
+ auth-sources '("~/.authinfo.gpg")
+ authinfo-hidden (regexp-opt '("password" "client-secret" "token")))