This is part of the Emacs Starter Kit.
This macro is stolen from lunaryorn setup (see .emacs config) eval parameter after package or component has been loaded.
(unless (fboundp 'with-eval-after-load)
(defmacro with-eval-after-load (file &rest body)
"Execute BODY after FILE is loaded. Forward compatibility wrapper."
`(eval-after-load ,file
`(funcall (function ,(lambda () ,@body))))))
(defmacro starter-kit-after (feature &rest forms)
"After FEATURE is loaded, evaluate FORMS. FORMS is byte compiled.
FEATURE may be a named feature or a file name, see `eval-after-load' for details."
(declare (indent 1) (debug t))
;; Byte compile the body. If the feature is not available, ignore warnings.
;; Taken from
;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2012-11/msg01262.html
`(,(if (or (not (boundp 'byte-compile-current-file))
(not byte-compile-current-file)
(if (symbolp feature)
(require feature nil :no-error)
(load feature :no-message :no-error)))
'progn
(message "starter-kit-after: cannot find %s" feature)
'with-no-warnings)
(with-eval-after-load ',feature ,@forms)))
(add-hook 'emacs-lisp-mode-hook 'run-starter-kit-coding-hook)
(add-hook 'sh-mode-hook 'run-starter-kit-coding-hook)
(add-hook 'latex-mode-hook 'run-starter-kit-coding-hook)
(add-hook 'python-mode-hook 'run-starter-kit-coding-hook)
(cua-mode t)
(global-undo-tree-mode)
(setq undo-tree-enable-undo-in-region t)
Increase undo limit to keep most of the history
(setq undo-limit 800000
undo-strong-limit 12000000
undo-outer-limit 120000000)
Do not store undo-tree
file
(setq undo-tree-auto-save-history nil)
(starter-kit-after recentf
(setq recentf-max-saved-items 100))
(recentf-mode t)
(auto-compression-mode t)
(show-paren-mode t)
(setq show-paren-delay 0
show-paren-style 'mixed)
(require 'highlight-parentheses)
(defun turn-on-highlight-parentheses-mode ()
(highlight-parentheses-mode t))
(define-global-minor-mode global-highlight-parentheses-mode
highlight-parentheses-mode
turn-on-highlight-parentheses-mode)
(setq hl-paren-colors
'("orange1" "yellow1" "greenyellow" "green1"
"springgreen1" "cyan1" "slateblue1" "magenta1" "purple"))
(global-highlight-parentheses-mode)
(starter-kit-after whitespace
(setq whitespace-style '(face trailing lines-tail tabs)
whitespace-line-column 80))
Better backspace handling
(defun sk-isearch-delete ()
"Delete the failed portion of the search string, or the last char if successful."
(interactive)
(with-isearch-suspended
(setq isearch-new-string
(substring
isearch-string 0 (or (isearch-fail-pos) (1- (length isearch-string))))
isearch-new-message
(mapconcat 'isearch-text-char-description isearch-new-string ""))))
(define-key isearch-mode-map (kbd "<backspace>")
#'sk-isearch-delete)
Enable flex support
(require 'flex-isearch)
(global-flex-isearch-mode 1)
(setq flex-isearch-auto 'on-failed)
(starter-kit-after fill-column-indicator
(setq fci-rule-width 3))
(setq-default fill-column 100)
(global-hl-line-mode t)
(global-auto-revert-mode t)
;; revert without asking
(setq revert-without-query '(".*"))
(starter-kit-after smartparens
(setq sp-ignore-modes-list '(calc-mode dired-mode ibuffer-mode
minibuffer-incative-mode sr-mode)))
Set function name in the header part of emacs (from http://emacsredux.com/blog/2014/04/05/which-function-mode/).
(require 'which-func)
(add-to-list 'which-func-modes 'org-mode)
(add-to-list 'which-func-modes 'c++-mode)
(setq which-func-unknown "n/a")
(setq-default header-line-format
'((which-func-mode ("" which-func-format " "))))
(setq mode-line-misc-info
;; We remove Which Function Mode from the mode line, because it's mostly
;; invisible here anyway.
(assq-delete-all 'which-func-mode mode-line-misc-info))
(winner-mode 1)
Use a less intrusive color for idle-highlight-mode
(defface idle-highlight
'((t (:inherit match)))
"Face used to highlight other occurrences of the word at point."
:group 'idle-highlight)
;; (require 'delight)
;; (starter-kit-after idle-highlight (delight 'idle-highlight-mode ""))
(projectile-global-mode)
Stolen from https://gist.github.com/rejeep/5933343.
(defun rejeep-projectile-completion-fn (prompt choises)
"Projectile completion function that only shows file name.
If two files have same name, new completion appears to select between
them. These include the path relative to the project root."
(interactive)
(let* ((stripped-choises
(-uniq (--map (file-name-nondirectory it) choises)))
(choise
(ido-completing-read prompt stripped-choises))
(matching-files
(-filter
(lambda (file)
(equal (file-name-nondirectory file) choise))
choises)))
(if (> (length matching-files) 1)
(ido-completing-read prompt matching-files)
(car matching-files))))
(setq projectile-completion-system 'rejeep-projectile-completion-fn)
(setq projectile-mode-line
'(:propertize
(:eval (format " ❬⊶ %s❭"
(truncate-string-to-width (projectile-project-name) 10 nil nil "…")))
))
(setq projectile-known-projects-file (expand-file-name "projectile-bookmarks.eld"
temporary-file-directory))
(setq projectile-sort-order 'recentf)
(require 'magit)
(setq magit-stage-all-confirm nil)
(setq magit-omit-untracked-dir-contents t)
(setq magit-push-always-verify nil)
From Magnars blog
(defadvice magit-status (around magit-fullscreen activate)
(window-configuration-to-register :magit-fullscreen)
ad-do-it
(delete-other-windows))
(defun magit-quit-session ()
"Restores the previous window configuration and kills the magit buffer"
(interactive)
(kill-buffer)
(jump-to-register :magit-fullscreen))
(global-set-key (kbd "M-s") 'magit-status)
(define-key magit-status-mode-map (kbd "q") 'magit-quit-session)
(define-key magit-status-mode-map (kbd "p") 'magit-push-current)
(require 'magit-svn)
(define-key magit-svn-mode-map (kbd "p") 'magit-svn-dcommit)
(setq magit-diff-refine-hunk 'all)
Stolen from http://danlamanna.com/2013/03/11/svn-externals-with-git-svn-and-magit/
(add-hook 'magit-mode-hook (lambda()
(require 'magit-svn)
(magit-svn-mode)))
(add-hook 'magit-mode-hook (lambda()
(require 'ivy)
(ivy-mode 1)))
(require 'git-gutter)
(setq git-gutter-disabled-modes '(asm-mode image-mode org-mode))
(global-git-gutter-mode t)
;; If you would like to use git-gutter.el and linum-mode
(git-gutter:linum-setup)
(global-set-key (kbd "C-x C-g") 'git-gutter:toggle)
;; Jump to next/previous hunk
(global-set-key (kbd "C-x p") 'git-gutter:previous-hunk)
(global-set-key (kbd "C-x n") 'git-gutter:next-hunk)
;; Stage current hunk
(global-set-key (kbd "C-x v s") 'git-gutter:stage-hunk)
;; Revert current hunk
(global-set-key (kbd "C-x v r") 'git-gutter:revert-hunk)
Set git-gutter
signs
;; (setq git-gutter:modified-sign "◽")
;; (setq git-gutter:added-sign "◾")
;; (setq git-gutter:deleted-sign "▴")
(require 'popwin)
(popwin-mode 1)
(require 'direx)
(push '(direx:direx-mode :position left :width 40 :dedicated t :stick t)
popwin:special-display-config)
(global-set-key (kbd "C-ù") 'direx-project:jump-to-project-root-other-window)
(setq direx:leaf-icon " "
direx:open-icon "▾ "
direx:closed-icon "▸ ")
(defface direx-k-modified
'((t (:inherit warning :weight bold)))
"Face of added file in git repository"
:group 'dired-k)
(defface direx-k-untracked
'((t (:inherit error)))
"Face of untracked file in git repository"
:group 'dired-k)
(require 'direx-k)
(define-key direx:direx-mode-map (kbd "G") 'direx-k)
Tweak face by removing the foreground colors
(starter-kit-after diff-hl
(set-face-foreground 'diff-hl-insert nil)
(set-face-foreground 'diff-hl-change nil)
(set-face-foreground 'diff-hl-delete nil)
)
;;(global-diff-hl-mode)
Projectile is a project interaction library for Emacs.
(projectile-global-mode)
Stolen from https://gist.github.com/rejeep/5933343.
(defun rejeep-projectile-completion-fn (prompt choises)
"Projectile completion function that only shows file name.
If two files have same name, new completion appears to select between
them. These include the path relative to the project root."
(interactive)
(let* ((stripped-choises
(-uniq (--map (file-name-nondirectory it) choises)))
(choise
(ido-completing-read prompt stripped-choises))
(matching-files
(-filter
(lambda (file)
(equal (file-name-nondirectory file) choise))
choises)))
(if (> (length matching-files) 1)
(ido-completing-read prompt matching-files)
(car matching-files))))
(setq projectile-completion-system 'rejeep-projectile-completion-fn)
(setq projectile-mode-line
'(:propertize
(:eval (format " ❬⊶ %s❭"
(truncate-string-to-width (projectile-project-name) 10 nil nil "…")))
))
(setq projectile-known-projects-file (expand-file-name "projectile-bookmarks.eld"
temporary-file-directory))
(setq projectile-sort-order 'recentf)
(require 'golden-ratio)
(golden-ratio-mode 1)
(setq golden-ratio-exclude-modes '("dired-mode"))
(setq golden-ratio-exclude-buffer-names '(" *compilation*" " *scratch*" " Direx"))
(defhydra hydra-org-template (:color red :hint nil)
"
_s_rc s_h_ell
qu_o_te _e_macs-lisp
e_q_uation _p_ython
questio_n_ _j_upyter
"
("s" (insert "#+BEGIN_SRC\n#+END_SRC"))
("e" (insert "#+BEGIN_SRC emacs-lisp\n#+END_SRC"))
("h" (insert "#+BEGIN_SRC shell\n#+END_SRC"))
("o" (insert "#+BEGIN_QUOTE\n#+END_QUOTE"))
("n" (insert "#+BEGIN_QUESTION\n#+END_QUESTION"))
("j" (insert "#+BEGIN_SRC jupyter-python\n#+END_SRC"))
("p" (insert "#+BEGIN_SRC python\n#+END_SRC"))
("q" (insert "#+BEGIN_SRC latex\n\\begin{align*}\n\\end{align*}\n#+END_SRC"))
("<" self-insert-command "ins")
("o" nil "quit"))
(define-key org-mode-map "<"
(lambda () (interactive)
(if (looking-back "^")
(hydra-org-template/body)
(self-insert-command 1))))
(key-chord-define-global
",,"
(defhydra hydra-main (:color red :hint nil)
"
Split: _v_ert _h_orz
Delete: _o_nly _w_indow
File: _f_ile g_i_t-gutter
Mail: _g_mail _l_al
"
("<left>" windmove-left)
("<down>" windmove-down)
("<up>" windmove-up)
("<right>" windmove-right)
("|" (lambda ()
(interactive)
(split-window-right)
(windmove-right)))
("_" (lambda ()
(interactive)
(split-window-below)
(windmove-down)))
("v" split-window-right)
("h" split-window-below)
("o" delete-other-windows :exit t)
("w" delete-window)
("f" ido-find-file)
("i" hydra-git-gutter/body :exit t)
("g" sk-mu4e-gmail :exit t)
("l" sk-mu4e-lal :exit t)
("q" nil "quit")))
Defining hydra
(setq dumb-jump-selector 'ivy)
(key-chord-define-global
"$$"
(defhydra hydra-code (:body-pre (git-gutter-mode 1)
:hint nil)
"
[_q_] quit git-gutter
[_↑_] prev hunk [_s_] stage hunk [_p_] popup hunk
[_↓_] next hunk [_r_] revert hunk
"
("<down>" git-gutter:next-hunk)
("<up>" git-gutter:previous-hunk)
("h" (progn (goto-char (point-min))
(git-gutter:next-hunk 1)))
("l" (progn (goto-char (point-min))
(git-gutter:previous-hunk 1)))
("s" git-gutter:stage-hunk)
("r" git-gutter:revert-hunk)
("p" git-gutter:popup-hunk)
;; ("g" dumb-jump-go :color green)
;; ("b" dumb-jump-back :color green)
;; ("l" dumb-jump-quick-look)
("q" nil :color blue)
)
)
(require 'key-chord)
(key-chord-define-global "qq" 'delete-window)
(key-chord-define-global "ùù" 'delete-other-windows)
(key-chord-mode +1)
(global-set-key (kbd "C-s") 'swiper)
(setq ivy-display-style 'fancy)
;; (setq swiper-completion-method 'ivy)
;; (setq recenter-positions '(top middle bottom))
;;advise swiper to recenter on exit
(defun sk-swiper-recenter (&rest args)
"recenter display after swiper"
(recenter)
)
(advice-add 'swiper :after #'sk-swiper-recenter)
(require 'ivy)
(ivy-mode 1)
(define-key ivy-minibuffer-map (kbd "<up>") 'ivy-previous-line)
(define-key ivy-minibuffer-map (kbd "<down>") 'ivy-next-line)
(define-key ivy-minibuffer-map (kbd "C-w") 'ivy-yank-word)
(require 'hideshowvis)
(define-fringe-bitmap 'hideshowvis-hideable-marker [0 0 254 124 56 16 0 0])
(define-fringe-bitmap 'hs-marker [0 32 48 56 60 56 48 32])
(add-to-list 'auto-mode-alist '("\\.tikz\\'" . latex-mode))
(add-hook 'latex-mode-hook 'turn-on-orgtbl)
;;(add-hook 'latex-mode-hook 'turn-on-auto-fill)
(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
(setq mweb-default-major-mode 'html-mode)
(setq mweb-tags '((php-mode "<\\?php\\|<\\? \\|<\\?=" "\\?>")
(js-mode "<script +\\(type=\"text/javascript\"\\|language=\"javascript\"\\)[^>]*>" "</script>")
(css-mode "<style +type=\"text/css\"[^>]*>" "</style>")))
(setq mweb-filename-extensions '("php" "htm" "html" "ctp" "phtml" "php4" "php5"))
(multi-web-global-mode 1)
(require 'cmake-mode)
(setq auto-mode-alist
(append '(("CMakeLists\\.txt\\'" . cmake-mode)
("\\.cmake\\'" . cmake-mode))
auto-mode-alist))
(setq css-indent-offset 2)
(defvar hexcolour-keywords
'(("#[abcdef[:digit:]]\\{6\\}"
(0 (put-text-property
(match-beginning 0)
(match-end 0)
'face (list :background
(match-string-no-properties 0)))))))
(defun hexcolour-add-to-font-lock ()
(font-lock-add-keywords nil hexcolour-keywords))
(add-hook 'css-mode-hook 'hexcolour-add-to-font-lock)
Define some usual trac-wiki
projects.
(require 'trac-wiki)
(trac-wiki-define-project "trac-LAL"
"https://trac.lal.in2p3.fr/NEMO2/" t)
(trac-wiki-define-project "trac-LPC"
"https://nemo.lpc-caen.in2p3.fr/" t)
(autoload 'trac-wiki "trac-wiki"
"Trac wiki editing entry-point." t)
yasnippet is yet another snippet expansion system for Emacs. It is inspired by TextMate’s templating syntax (watch the video on YouTube or see the intro and tutorial)
(require 'yasnippet)
;; (yas-global-mode 1)
(yas-reload-all)
(setq yas-snippet-dirs '(concat starter-kit-dir "/snippets"))
(add-hook 'starter-kit-coding-hook '(lambda ()
(yas-minor-mode)))
(require 'auto-complete-config)
;; (global-auto-complete-mode t)
(ac-config-default)
(setq ac-auto-start 3
ac-ignore-case nil
ac-use-fuzzy t
ac-use-comphist t)
(ac-set-trigger-key "TAB")
(ac-set-trigger-key "<tab>")
(define-key ac-completing-map (kbd "ESC") 'ac-stop)
(add-hook 'after-init-hook 'global-company-mode)
(require 'company-tabnine)
(add-to-list 'company-backends #'company-tabnine)
;; Trigger completion immediately.
(setq company-idle-delay 0)
;; Number the candidates (use M-1, M-2 etc to select completions).
(setq company-show-numbers t)
(require 'expand-region)
(global-set-key (kbd "C-w") 'er/expand-region)
(require 'multiple-cursors)
(global-set-key (kbd "C->") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-<") 'mc/mark-next-like-this)
(require 'browse-kill-ring)
(global-set-key "\M-y" 'browse-kill-ring)
(require 'lorem-ipsum)
(add-hook 'after-save-hook
'executable-make-buffer-file-executable-if-script-p)
(setq firestarter-lighter "↯")
(setq tramp-ssh-controlmaster-options "")
(setenv "WORKON_HOME" (concat (getenv "HOME") "/.local/share/virtualenvs"))
(require 'isortify)
(add-hook 'python-mode-hook 'blacken-mode)
(add-hook 'python-mode-hook 'isortify-mode)
(setq blacken-line-length 100)
(setq isortify-line-length 100)
(defun sk-disable-python-minor-modes ()
(interactive)
(blacken-mode -1)
(isortify-mode -1)
)
(defgroup tomlfmt nil
"Reformat TOML code with \"taplo\"."
:group 'toml)
(defcustom tomlfmt-executable "taplo"
"Name of the executable to run."
:type 'string)
(defcustom tomlfmt-only-if-project-is-tomlfmted nil
"Only tomlfmt if project has a pyproject.toml with a [tool.tomlfmt] section."
:type 'boolean
:safe 'booleanp)
(defun tomlfmt-call-bin (input-buffer output-buffer error-buffer)
"Call process taplo.
Send INPUT-BUFFER content to the process stdin. Saving the
output to OUTPUT-BUFFER. Saving process stderr to ERROR-BUFFER.
Return black process the exit code."
(with-current-buffer input-buffer
(let ((process (make-process :name "tomlfmt"
:command `(,tomlfmt-executable ,@(tomlfmt-call-args))
:buffer output-buffer
:stderr error-buffer
:noquery t
:sentinel (lambda (process event)))))
(set-process-query-on-exit-flag (get-buffer-process error-buffer) nil)
(set-process-sentinel (get-buffer-process error-buffer) (lambda (process event)))
(save-restriction
(widen)
(process-send-region process (point-min) (point-max)))
(process-send-eof process)
(accept-process-output process nil nil t)
(while (process-live-p process)
(accept-process-output process nil nil t))
(process-exit-status process))))
(defun tomlfmt-call-args ()
"Build taplo process call arguments."
(append
(when (and (buffer-file-name (current-buffer))
(string-match "\\.toml\\'" (buffer-file-name (current-buffer))))
(list "format"))
'("-")))
(defun tomlfmt-project-is-tomlfmted (&optional display)
"Whether the project has a pyproject.toml with [tool.tomlfmt] in it."
(when-let (parent (locate-dominating-file default-directory "pyproject.toml"))
(with-temp-buffer
(insert-file-contents (concat parent "pyproject.toml"))
(re-search-forward "^\\[tool.tomlfmt\\]$" nil t 1))))
;;;###autoload
(defun tomlfmt-buffer (&optional display)
"Try to tomlfmt the current buffer.
Show taplo output, if taplo exit abnormally and DISPLAY is t."
(interactive (list t))
(let* ((original-buffer (current-buffer))
(original-window-states (mapcar
(lambda (w)
(list w (window-point w) (window-start w)))
(get-buffer-window-list)))
(tmpbuf (get-buffer-create "*tomlfmt*"))
(errbuf (get-buffer-create "*tomlfmt-error*")))
;; This buffer can be left after previous black invocation. It
;; can contain error message of the previous run.
(dolist (buf (list tmpbuf errbuf))
(with-current-buffer buf
(erase-buffer)))
(condition-case err
(if (not (zerop (tomlfmt-call-bin original-buffer tmpbuf errbuf)))
(error "taplo failed, see %s buffer for details" (buffer-name errbuf))
(unless (eq (compare-buffer-substrings tmpbuf nil nil original-buffer nil nil) 0)
(with-current-buffer tmpbuf
(copy-to-buffer original-buffer (point-min) (point-max)))
(dolist (win-stt original-window-states)
(set-window-point (car win-stt) (nth 1 win-stt))
(set-window-start (car win-stt) (nth 2 win-stt))))
(mapc 'kill-buffer (list tmpbuf errbuf)))
(error (message "%s" (error-message-string err))
(when display
(with-current-buffer errbuf
(setq-local scroll-conservatively 0))
(pop-to-buffer errbuf))))))
;;;###autoload
(define-minor-mode tomlfmt-mode
"Automatically run black before saving."
:lighter " "
(if tomlfmt-mode
(add-hook 'before-save-hook 'tomlfmt-buffer nil t)
(remove-hook 'before-save-hook 'tomlfmt-buffer t)))
(add-hook 'conf-toml-mode-hook 'tomlfmt-mode)
(require 'delight)
(delight 'python-mode "")
(delight 'org-mode "")
(delight 'dockerfile-mode "")
(delight 'js-mode "")
(delight 'css-mode "")
(delight 'yapf-mode nil "yapfify")
(delight 'isortify-mode nil "isortify")
(delight 'eldoc-mode nil "eldoc")
(delight 'golden-ratio-mode nil "golden-ratio")
(delight 'undo-tree-mode nil "undo-tree")
(delight 'highlight-parentheses-mode nil "highlight-parentheses")
(delight 'auto-complete-mode nil "auto-complete")
(delight 'wrap-region-mode nil "wrap-region")
(delight 'auto-fill-function nil "simple")
(delight 'smartparens-mode nil "smartparens")
(delight 'yas-minor-mode nil "yasnippet")
(delight 'ivy-mode nil "ivy")
(delight 'hs-minor-mode nil "hideshow")
(delight 'sh-mode "")
(delight 'c++-mode "")
(delight 'rainbow-mode " ")
(delight 'ivy-mode " ")
(delight 'mu4e-view-mode "")
(delight 'mu4e-main-mode "")
(delight 'magit-status-mode "")
(delight 'abbrev-mode nil "abbrev")
(delight 'inertias-global-minor-mode nil "inertial-scroll")
(delight 'blacken-mode " " "blacken")
(setq paradox-github-token
(cadr(auth-source-user-and-password "api.github.com" "xgarrido^paradox")))
(require 'yaml-mode)
(add-hook 'yaml-mode-hook #'superword-mode)
(define-key yaml-mode-map
(kbd "RET") #'newline-and-indent)
;; From https://gist.github.com/antonj/874106
(defun aj-toggle-fold ()
"Toggle fold all lines larger than indentation on current line"
(interactive)
(let ((col 1))
(save-excursion
(back-to-indentation)
(setq col (+ 1 (current-column)))
(set-selective-display
(if selective-display nil (or col 1))))))
;; From https://github.com/yoshiki/yaml-mode/issues/25
(defun yaml-outline-minor-mode ()
(outline-minor-mode)
(setq outline-regexp
(rx
(seq
bol
(group (zero-or-more " ")
(or (group
(seq (or (seq "\"" (*? (not (in "\"" "\n"))) "\"")
(seq "'" (*? (not (in "'" "\n"))) "'")
(*? (not (in ":" "\n"))))
":"
(?? (seq
(*? " ")
(or (seq "&" (one-or-more nonl))
(seq ">-")
(seq "|"))
eol))))
(group (seq
"- "
(+ (not (in ":" "\n")))
":"
(+ nonl)
eol))))))))
(add-hook 'yaml-mode-hook #'yaml-outline-minor-mode)
;; This weird key-binding to co-exist with outline-minor mode
(define-key yaml-mode-map
(kbd "C-c C-c") #'aj-toggle-fold)
From https://www.masteringemacs.org/article/keeping-secrets-in-emacs-gnupg-auth-sources
(fset 'epg-wait-for-status 'ignore)
(when (require 'openwith nil 'noerror)
(add-to-list 'mm-inhibit-file-name-handlers 'openwith-file-handler)
(setq openwith-associations '(("\\.pdf\\'" "evince" (file))))
(openwith-mode 1))