└── readme.org /readme.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Emacs configuration files 2 | #+AUTHOR: Tom Gustafsson 3 | 4 | * Introduction 5 | 6 | This is my reproducible Emacs configuration on top of Nix and straight.el. Nix 7 | takes care of any system-level dependencies and downloading an initial version 8 | of straight.el which then installs and manages itself and other Emacs Lisp 9 | packages. 10 | 11 | * Installation 12 | 13 | You can try the config, e.g., inside Docker by running the following steps: 14 | #+begin_src sh 15 | docker run -it nixos/nix /bin/sh 16 | nix-shell -p emacs-nox wget 17 | wget https://raw.githubusercontent.com/kinnala/nixemacs/master/readme.org 18 | emacs --file readme.org --eval '(progn (org-babel-tangle) (kill-emacs))' 19 | exit 20 | nix-env -i tom 21 | emacs 22 | #+end_src 23 | 24 | * Derivation for straight.el 25 | 26 | The initial version of straight.el is patched slightly so that it doesn't 27 | perform any HTTP requests while bootstrapping. All requests to straight.el 28 | GitHub repo are replaced by file reads to the Nix store. 29 | 30 | #+begin_src nix :mkdirp yes :tangle ~/.config/nixpkgs/straight/default.nix 31 | { stdenv, fetchFromGitHub }: 32 | 33 | stdenv.mkDerivation rec { 34 | name = "straight.el"; 35 | src = fetchFromGitHub { 36 | owner = "raxod502"; 37 | repo = "straight.el"; 38 | rev = "59c92dd45085b8f8fc44ea0039c205f4a3c43b62"; 39 | sha256 = "00ibxmgqfb5bqd4b9jqj8vdiszkph6vv64m1y3kf9xav15v8sfyx"; 40 | }; 41 | buildPhase = '' 42 | sed -i -e 's|(with-current-buffer|(with-temp-buffer|g' install.el 43 | sed -i -e 's|(url-retrieve-synchronously|(insert-file-contents "'"$out"'/share/straight/straight.el")|g' install.el 44 | sed -i -e 's| (format||g' install.el 45 | sed -i -e 's|(concat "https:\/\/raw.githubusercontent.com\/"||g' install.el 46 | sed -i -e 's|"raxod502\/straight.el\/install\/%s\/straight.el")||g' install.el 47 | sed -i -e 's|(substring (symbol-name version) 1))||g' install.el 48 | sed -i -e "s|'silent 'inhibit-cookies)||g" install.el 49 | sed -i -e "s|(unless (equal url-http-response-status 200)||g" install.el 50 | sed -i -e 's|(error "Unknown recipe version: %S" version))||g' install.el 51 | sed -i -e "s|(delete-region (point-min) url-http-end-of-headers)||g" install.el 52 | echo '(defvar bootstrap-version) 53 | (let ((bootstrap-file 54 | (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)) 55 | (bootstrap-version 5)) 56 | (unless (file-exists-p bootstrap-file) 57 | (with-temp-buffer 58 | (insert-file-contents "'"$out"'/share/straight/install.el") 59 | (goto-char (point-max)) 60 | (eval-print-last-sexp))) 61 | (load bootstrap-file nil '"'"'nomessage))' > init.el 62 | echo -e '#!/bin/bash\necho -n "'"$out"'/share/straight/init.el"' > straight-init-path 63 | ''; 64 | installPhase = '' 65 | mkdir -p $out/share/straight 66 | cp install.el straight.el init.el $out/share/straight/ 67 | mkdir -p $out/bin 68 | cp straight-init-path $out/bin/ 69 | chmod +x $out/bin/straight-init-path 70 | ''; 71 | } 72 | #+end_src 73 | 74 | * Overlay for dependencies 75 | 76 | This uses the above derivation and calls =buildEnv= for creating a set of 77 | packages. 78 | 79 | #+begin_src nix :mkdirp yes :tangle ~/.config/nixpkgs/overlays/emacs.nix 80 | self: super: 81 | { 82 | straight.el = super.callPackage (import ../straight/default.nix) {}; 83 | tom = super.buildEnv { 84 | name = "tom"; 85 | paths = [ 86 | self.emacs 87 | self.straight.el 88 | self.ripgrep 89 | self.gnumake 90 | self.pass 91 | ]; 92 | }; 93 | } 94 | #+end_src 95 | 96 | * Pinning Emacs packages 97 | 98 | This is a version lockfile for straight.el. 99 | 100 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/straight/versions/default.el 101 | (("Emacs-wgrep" . "f9687c28bbc2e84f87a479b6ce04407bb97cfb23") 102 | ("Highlight-Indentation-for-Emacs" . "d88db4248882da2d4316e76ed673b4ac1fa99ce3") 103 | ("csv-mode" . "53beddc207864b0c3f81da85b59245dff8eea5ce") 104 | ("dash.el" . "76606f90774c5349f7adac20c33e6d37a1939a1f") 105 | ("dired-k" . "1ddd8e0ea06f0e25cd5dedb2370cfa0cacfa8c9d") 106 | ("diredfl" . "62b559e1d6b69834a56a57eb1832ac6ad4d2e5d0") 107 | ("dumb-jump" . "1dd583011f4025b1b8c75fd785691851b6c5dfa3") 108 | ("el-get" . "a620c91fe7d6d482c0e7538df75e10af0af1bb16") 109 | ("emacs-which-key" . "1ab1d0cc88843c9a614ed3226c5a1070e32e4823") 110 | ("emacsmirror-mirror" . "2e1ceba3c8036637832e99414d9012359911f5e4") 111 | ("expand-region.el" . "7e5bbe2763c12bae3e77fe0c49bcad05ff91dbfe") 112 | ("f.el" . "feb6c2cb9f8e19ebdfdfde0d89edbdd5d7f51a96") 113 | ("gnu-elpa-mirror" . "808923d95777d378ca340b8020dd571e6a62460a") 114 | ("hydra" . "9e9e00cb240ea1903ffd36a54956b3902c379d29") 115 | ("json-mode" . "eedb4560034f795a7950fa07016bd4347c368873") 116 | ("json-reformat" . "8eb6668ed447988aea06467ba8f42e1f2178246f") 117 | ("json-snatcher" . "b28d1c0670636da6db508d03872d96ffddbc10f2") 118 | ("magit" . "a7953b2645503904b2a31e18e019f07af9e71a7a") 119 | ("markdown-mode" . "4477f381de0068a04b55e198c32614793f67b38a") 120 | ("melpa" . "40c73fda1fc5fd5cf01680838a9556fb3fa528cf") 121 | ("moe-theme.el" . "edf3fe47fb986e283e3b04cba443dcb39fe8720e") 122 | ("multiple-cursors.el" . "fd8441bfc8738d463601823e5a3d9c2d7123bfbf") 123 | ("nix-mode" . "8fe2ccf0b01f694a77d2528e06c10f06057784f6") 124 | ("org" . "604bfd9d755770e12c368c15148780ec723211df") 125 | ("phi-search" . "c34f5800968922d1f9e7b10092b8705d6640ad18") 126 | ("popup-el" . "976bd8e06100df5a266377d0e5f63b104ba93119") 127 | ("rust-mode" . "0df2f22479b98f76d97de90e1c390ff1b0902a46") 128 | ("s.el" . "08661efb075d1c6b4fa812184c1e5e90c08795a9") 129 | ("straight.el" . "af5437f2afd00936c883124d6d3098721c2d306c") 130 | ("swiper" . "f8d80a4055514f92d94f128f5fcb1cda79e5cd22") 131 | ("transient" . "2e4426fe8161893382f09b3f4635e152ee02488e") 132 | ("use-package" . "a7422fb8ab1baee19adb2717b5b47b9c3812a84c") 133 | ("virtualenvwrapper.el" . "c7e84505db4142fd1beebf38ffe37c3f42444ca3") 134 | ("with-editor" . "4ab8c6148bb2698ff793d4a8acdbd8d0d642e133") 135 | ("xclip" . "4772beb5579e13910c89c482a2e41271253c646b") 136 | ("yaml-mode" . "535273d5a1eb76999d20afbcf4d9f056d8ffd2da")) 137 | :beta 138 | #+end_src 139 | 140 | Note: to update, run =straight-pull-all= and =straight-freeze-versions= 141 | and replace above with the contents of =~/.emacs.d/straight/versions/default.el=. 142 | 143 | * Emacs init file 144 | 145 | The rest of the snippets are combined into Emacs init file. The first snippet 146 | configures straight.el and runs a customized straight.el initialization script 147 | from the Nix store (=straight-init-path= returns path to the initialization 148 | script): 149 | 150 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/init.el 151 | (setq straight-use-package-by-default t) 152 | (setq straight-vc-git-default-clone-depth 20) 153 | (load-file (shell-command-to-string "straight-init-path")) 154 | (straight-use-package 'use-package) 155 | #+end_src 156 | 157 | ** org-mode 158 | 159 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/init.el 160 | (use-package org 161 | :commands org-babel-do-load-languages 162 | :config 163 | (unbind-key "C-," org-mode-map) 164 | (unbind-key "C-." org-mode-map) 165 | :init 166 | (add-hook 'org-mode-hook (lambda () 167 | (fset 'tex-font-lock-suscript 'ignore) 168 | (org-babel-do-load-languages 169 | 'org-babel-load-languages 170 | '((python . t) 171 | (shell . t))))) 172 | (setq org-default-notes-file "~/Dropbox/Notes/agenda/inbox.org") 173 | (setq org-agenda-files '("~/Dropbox/Notes/agenda/")) 174 | (setq org-refile-targets '((nil :maxlevel . 9) 175 | (org-agenda-files :maxlevel . 9))) 176 | (setq org-log-done 'time) 177 | (setq org-tags-column 0) 178 | (setq org-agenda-tags-column 0) 179 | (setq org-agenda-window-setup 'only-window) 180 | (setq org-export-babel-evaluate nil) 181 | (setq org-startup-folded nil) 182 | (setq org-agenda-format-date 183 | (lambda (date) (concat "\n" 184 | (make-string (window-width) 9472) 185 | "\n" 186 | (org-agenda-format-date-aligned date)))) 187 | (setq org-agenda-skip-deadline-if-done t) 188 | (setq org-deadline-warning-days 5) 189 | (setq org-agenda-prefix-format '((agenda . " %i %-5e %-12:c%?-12t% s") 190 | (todo . " %i %-12:c %b") 191 | (tags . " %i %-12:c") 192 | (search . " %i %-12:c"))) 193 | (setq org-adapt-indentation nil) 194 | (setq org-refile-use-outline-path 'file) 195 | (setq org-structure-template-alist '(("l" . "latex latex") 196 | ("s" . "src"))) 197 | (setq org-outline-path-complete-in-steps nil) 198 | (setq org-src-preserve-indentation t) 199 | (setq org-confirm-babel-evaluate nil) 200 | (setq org-html-validation-link nil) 201 | (setq org-babel-default-header-args:sh '((:prologue . "exec 2>&1") 202 | (:epilogue . ":"))) 203 | (setq org-capture-templates '(("t" "Todo" entry 204 | (file "~/Dropbox/Notes/agenda/inbox.org") 205 | "* TODO %?\n SCHEDULED: %t\n%i\n%a") 206 | ("k" "Event" entry 207 | (file "~/Dropbox/Notes/agenda/inbox.org") 208 | "* %?\n%t"))) 209 | :bind (("C-c c" . org-capture) 210 | ("C-c a" . org-agenda))) 211 | #+end_src 212 | 213 | 214 | ** ivy and wgrep 215 | 216 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/init.el 217 | (use-package ivy 218 | :commands 219 | ivy-mode 220 | :init 221 | (ivy-mode 1) 222 | (setq ivy-height 10 223 | ivy-fixed-height-minibuffer t) 224 | :bind (("C-x b" . ivy-switch-buffer) 225 | ("C-c r" . ivy-resume) 226 | ("C-x C-b" . ibuffer))) 227 | 228 | (use-package counsel 229 | :init 230 | (setq counsel-find-file-ignore-regexp "\\archive\\'") 231 | :bind (("M-x" . counsel-M-x) 232 | ("C-x C-f" . counsel-find-file) 233 | ("C-c g" . counsel-rg) 234 | ("C-c G" . counsel-git) 235 | ("C-c j" . counsel-file-jump) 236 | ("C-x b" . counsel-switch-buffer) 237 | ("C-c h" . counsel-minibuffer-history) 238 | ("M-y" . counsel-yank-pop))) 239 | 240 | (use-package swiper 241 | :bind ("C-c s" . swiper)) 242 | 243 | (use-package wgrep) 244 | #+end_src 245 | 246 | ** magit 247 | 248 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/init.el 249 | (use-package magit 250 | :init 251 | (setq magit-repository-directories '(("~/src" . 1))) 252 | :bind (("C-x g" . magit-status) 253 | ("C-c M-g" . magit-file-dispatch))) 254 | #+end_src 255 | 256 | ** multiline editing 257 | 258 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/init.el 259 | (use-package expand-region 260 | :after (org) 261 | :bind ("C-." . er/expand-region) 262 | :init 263 | (require 'expand-region) 264 | (require 'cl) 265 | (defun mark-around* (search-forward-char) 266 | (let* ((expand-region-fast-keys-enabled nil) 267 | (char (or search-forward-char 268 | (char-to-string 269 | (read-char "Mark inner, starting with:")))) 270 | (q-char (regexp-quote char)) 271 | (starting-point (point))) 272 | (when search-forward-char 273 | (search-forward char (point-at-eol))) 274 | (cl-flet ((message (&rest args) nil)) 275 | (er--expand-region-1) 276 | (er--expand-region-1) 277 | (while (and (not (= (point) (point-min))) 278 | (not (looking-at q-char))) 279 | (er--expand-region-1)) 280 | (er/expand-region -1)))) 281 | (defun mark-around () 282 | (interactive) 283 | (mark-around* nil)) 284 | (define-key global-map (kbd "M-i") 'mark-around)) 285 | 286 | (use-package multiple-cursors 287 | :init 288 | (define-key global-map (kbd "C-'") 'mc-hide-unmatched-lines-mode) 289 | (define-key global-map (kbd "C-,") 'mc/mark-next-like-this) 290 | (define-key global-map (kbd "C-;") 'mc/mark-all-dwim) 291 | (setq hum/lines-to-expand 1)) 292 | 293 | (use-package phi-search 294 | :after multiple-cursors 295 | :init (require 'phi-replace) 296 | :bind ("C-:" . phi-replace) 297 | :bind (:map mc/keymap 298 | ("C-s" . phi-search) 299 | ("C-r" . phi-search-backward))) 300 | #+end_src 301 | 302 | ** dired 303 | 304 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/init.el 305 | (use-package term 306 | :straight nil) 307 | 308 | (use-package dired-x 309 | :straight nil) 310 | 311 | (use-package dired 312 | :straight nil 313 | :after (term dired-x) 314 | :init 315 | (setq dired-dwim-target t) 316 | (setq dired-omit-files "^\\...+$") 317 | (defun run-gnome-terminal-here () 318 | (interactive) 319 | (shell-command "kgx")) 320 | (setq dired-guess-shell-alist-user 321 | '(("\\.pdf\\'" "evince") 322 | ("\\.eps\\'" "evince") 323 | ("\\.jpe?g\\'" "eog") 324 | ("\\.png\\'" "eog") 325 | ("\\.gif\\'" "eog") 326 | ("\\.xpm\\'" "eog"))) 327 | :bind (("C-x C-j" . dired-jump)) 328 | :bind (:map dired-mode-map 329 | ("'" . run-gnome-terminal-here) 330 | ("j" . swiper) 331 | ("s" . swiper))) 332 | 333 | (use-package dired-k 334 | :after (dired) 335 | :bind (:map dired-mode-map 336 | ("g" . dired-k))) 337 | 338 | (use-package diredfl 339 | :commands diredfl-global-mode 340 | :init 341 | (diredfl-global-mode) 342 | (put 'diredp-tagged-autofile-name 'face-alias 'diredfl-tagged-autofile-name) 343 | (put 'diredp-autofile-name 'face-alias 'diredfl-autofile-name) 344 | (put 'diredp-ignored-file-name 'face-alias 'diredfl-ignored-file-name) 345 | (put 'diredp-symlink 'face-alias 'diredfl-symlink) 346 | (put 'diredp-compressed-file-name 'face-alias 'diredfl-compressed-file-name) 347 | (put 'diredp-file-suffix 'face-alias 'diredfl-file-suffix) 348 | (put 'diredp-compressed-extensions 'face-alias 'diredfl-compressed-extensions) 349 | (put 'diredp-deletion 'face-alias 'diredfl-deletion) 350 | (put 'diredp-deletion-file-name 'face-alias 'diredfl-deletion-file-name) 351 | (put 'diredp-flag-mark-line 'face-alias 'diredfl-flag-mark-line) 352 | (put 'diredp-rare-priv 'face-alias 'diredfl-rare-priv) 353 | (put 'diredp-number 'face-alias 'diredfl-number) 354 | (put 'diredp-exec-priv 'face-alias 'diredfl-exec-priv) 355 | (put 'diredp-file-name 'face-alias 'diredfl-file-name) 356 | (put 'diredp-dir-heading 'face-alias 'diredfl-dir-heading) 357 | (put 'diredp-compressed-file-suffix 'face-alias 'diredfl-compressed-file-suffix) 358 | (put 'diredp-flag-mark 'face-alias 'diredfl-flag-mark) 359 | (put 'diredp-mode-set-explicitly 'face-alias 'diredfl-mode-set-explicitly) 360 | (put 'diredp-executable-tag 'face-alias 'diredfl-executable-tag) 361 | (put 'diredp-global-mode-hook 'face-alias 'diredfl-global-mode-hook) 362 | (put 'diredp-ignore-compressed-flag 'face-alias 'diredfl-ignore-compressed-flag) 363 | (put 'diredp-dir-priv 'face-alias 'diredfl-dir-priv) 364 | (put 'diredp-date-time 'face-alias 'diredfl-date-time) 365 | (put 'diredp-other-priv 'face-alias 'diredfl-other-priv) 366 | (put 'diredp-no-priv 'face-alias 'diredfl-no-priv) 367 | (put 'diredp-link-priv 'face-alias 'diredfl-link-priv) 368 | (put 'diredp-write-priv 'face-alias 'diredfl-write-priv) 369 | (put 'diredp-global-mode-buffers 'face-alias 'diredfl-global-mode-buffers) 370 | (put 'dired-directory 'face-alias 'diredfl-dir-name) 371 | (put 'diredp-read-priv 'face-alias 'diredfl-read-priv)) 372 | #+end_src 373 | 374 | ** syntax highlighting 375 | 376 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/init.el 377 | (use-package json-mode) 378 | 379 | (use-package highlight-indentation 380 | :commands (highlight-indentation-mode) 381 | :init 382 | (defun tom/hl-indent-color () 383 | (set-face-background 384 | 'highlight-indentation-face 385 | (face-attribute 'highlight :background))) 386 | (advice-add 'highlight-indentation-mode :after #'tom/hl-indent-color) 387 | :hook ((python-mode . highlight-indentation-mode) 388 | (python-mode . display-fill-column-indicator-mode))) 389 | 390 | (use-package yaml-mode) 391 | 392 | (use-package csv-mode 393 | :mode "\\.csv$" 394 | :init (setq csv-separators '(";"))) 395 | 396 | (use-package markdown-mode 397 | :commands (markdown-mode) 398 | :mode (("\\.md\\'" . markdown-mode) 399 | ("\\.markdown\\'" . markdown-mode))) 400 | 401 | (use-package nix-mode) 402 | 403 | (use-package rust-mode) 404 | #+end_src 405 | 406 | *** theme 407 | 408 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/init.el 409 | (use-package moe-theme 410 | :config 411 | (load-theme 'moe-dark t)) 412 | 413 | (global-hl-line-mode) 414 | #+end_src 415 | 416 | *** python 417 | 418 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/init.el 419 | (use-package dumb-jump 420 | :config 421 | (setq dumb-jump-selector 'ivy) 422 | :init 423 | (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)) 424 | 425 | (use-package virtualenvwrapper 426 | :init (setq venv-location "~/.conda/envs")) 427 | 428 | (use-package hydra) 429 | 430 | ;; from move-lines package, https://github.com/targzeta/move-lines 431 | (defun move-lines--internal (n) 432 | "Moves the current line or, if region is actives, the lines surrounding 433 | region, of N lines. Down if N is positive, up if is negative" 434 | (let* (text-start 435 | text-end 436 | (region-start (point)) 437 | (region-end region-start) 438 | swap-point-mark 439 | delete-latest-newline) 440 | 441 | (when (region-active-p) 442 | (if (> (point) (mark)) 443 | (setq region-start (mark)) 444 | (exchange-point-and-mark) 445 | (setq swap-point-mark t 446 | region-end (point)))) 447 | 448 | (end-of-line) 449 | (if (< (point) (point-max)) 450 | (forward-char 1) 451 | (setq delete-latest-newline t) 452 | (insert-char ?\n)) 453 | (setq text-end (point) 454 | region-end (- region-end text-end)) 455 | 456 | (goto-char region-start) 457 | (beginning-of-line) 458 | (setq text-start (point) 459 | region-start (- region-start text-end)) 460 | 461 | (let ((text (delete-and-extract-region text-start text-end))) 462 | (forward-line n) 463 | (when (not (= (current-column) 0)) 464 | (insert-char ?\n) 465 | (setq delete-latest-newline t)) 466 | (insert text)) 467 | 468 | (forward-char region-end) 469 | 470 | (when delete-latest-newline 471 | (save-excursion 472 | (goto-char (point-max)) 473 | (delete-char -1))) 474 | 475 | (when (region-active-p) 476 | (setq deactivate-mark nil) 477 | (set-mark (+ (point) (- region-start region-end))) 478 | (if swap-point-mark 479 | (exchange-point-and-mark))))) 480 | 481 | (defun move-lines-up (n) 482 | "Moves the current line or, if region is actives, the lines surrounding 483 | region, up by N lines, or 1 line if N is nil." 484 | (interactive "p") 485 | (if (eq n nil) 486 | (setq n 1)) 487 | (move-lines--internal (- n))) 488 | 489 | (defun move-lines-down (n) 490 | "Moves the current line or, if region is actives, the lines surrounding 491 | region, down by N lines, or 1 line if N is nil." 492 | (interactive "p") 493 | (if (eq n nil) 494 | (setq n 1)) 495 | (move-lines--internal n)) 496 | 497 | (defun tom/shift-left (start end &optional count) 498 | "Shift region left and activate hydra." 499 | (interactive 500 | (if mark-active 501 | (list (region-beginning) (region-end) current-prefix-arg) 502 | (list (line-beginning-position) (line-end-position) current-prefix-arg))) 503 | (python-indent-shift-left start end count) 504 | (tom/hydra-move-lines/body)) 505 | 506 | (defun tom/shift-right (start end &optional count) 507 | "Shift region right and activate hydra." 508 | (interactive 509 | (if mark-active 510 | (list (region-beginning) (region-end) current-prefix-arg) 511 | (list (line-beginning-position) (line-end-position) current-prefix-arg))) 512 | (python-indent-shift-right start end count) 513 | (tom/hydra-move-lines/body)) 514 | 515 | (defun tom/move-lines-p () 516 | "Move lines up once and activate hydra." 517 | (interactive) 518 | (move-lines-up 1) 519 | (tom/hydra-move-lines/body)) 520 | 521 | (defun tom/move-lines-n () 522 | "Move lines down once and activate hydra." 523 | (interactive) 524 | (move-lines-down 1) 525 | (tom/hydra-move-lines/body)) 526 | 527 | (defhydra tom/hydra-move-lines () 528 | "Move one or multiple lines" 529 | ("n" move-lines-down "down") 530 | ("p" move-lines-up "up") 531 | ("<" python-indent-shift-left "left") 532 | (">" python-indent-shift-right "right")) 533 | 534 | (define-key global-map (kbd "C-c n") 'tom/move-lines-n) 535 | (define-key global-map (kbd "C-c p") 'tom/move-lines-p) 536 | (define-key global-map (kbd "C-c <") 'tom/shift-left) 537 | (define-key global-map (kbd "C-c >") 'tom/shift-right) 538 | #+end_src 539 | 540 | *** misc stuff 541 | 542 | #+begin_src elisp :mkdirp yes :tangle ~/.emacs.d/init.el 543 | (use-package transient) 544 | 545 | (use-package xclip 546 | :init (xclip-mode)) 547 | 548 | (use-package which-key 549 | :commands which-key-mode 550 | :init (which-key-mode)) 551 | 552 | ;; useful functions 553 | 554 | (defun tom/unfill-paragraph (&optional region) 555 | "Take REGION and turn it into a single line of text." 556 | (interactive (progn (barf-if-buffer-read-only) '(t))) 557 | (let ((fill-column (point-max)) 558 | (emacs-lisp-docstring-fill-column t)) 559 | (fill-paragraph nil region))) 560 | 561 | (define-key global-map "\M-Q" 'tom/unfill-paragraph) 562 | 563 | (defun tom/increment-number-decimal (&optional arg) 564 | "Increment the number forward from point by 'arg'." 565 | (interactive "p*") 566 | (save-excursion 567 | (save-match-data 568 | (let (inc-by field-width answer) 569 | (setq inc-by (if arg arg 1)) 570 | (skip-chars-backward "0123456789") 571 | (when (re-search-forward "[0-9]+" nil t) 572 | (setq field-width (- (match-end 0) (match-beginning 0))) 573 | (setq answer (+ (string-to-number (match-string 0) 10) inc-by)) 574 | (when (< answer 0) 575 | (setq answer (+ (expt 10 field-width) answer))) 576 | (replace-match (format (concat "%0" (int-to-string field-width) "d") 577 | answer))))))) 578 | 579 | (global-set-key (kbd "C-c x") 'tom/increment-number-decimal) 580 | 581 | ;; other global configurations 582 | 583 | ;; show current function in modeline 584 | (which-function-mode) 585 | 586 | ;; scroll screen 587 | (define-key global-map "\M-n" 'end-of-buffer) 588 | (define-key global-map "\M-p" 'beginning-of-buffer) 589 | 590 | ;; misc iOS fixes 591 | (defun insert-backslash () 592 | (interactive) 593 | (insert "\\")) 594 | 595 | (defun insert-brace-open () 596 | (interactive) 597 | (insert "{")) 598 | 599 | (defun insert-brace-close () 600 | (interactive) 601 | (insert "}")) 602 | 603 | (defun insert-bracket-open () 604 | (interactive) 605 | (insert "[")) 606 | 607 | (defun insert-bracket-close () 608 | (interactive) 609 | (insert "]")) 610 | 611 | (defun insert-et-sign () 612 | (interactive) 613 | (insert "@")) 614 | 615 | (defun insert-dollar-sign () 616 | (interactive) 617 | (insert "$")) 618 | 619 | (global-set-key (kbd "M-+") 'insert-backslash) 620 | (global-set-key (kbd "M-2") 'insert-et-sign) 621 | (global-set-key (kbd "M-4") 'insert-dollar-sign) 622 | (global-set-key (kbd "M-7") 'insert-brace-open) 623 | (global-set-key (kbd "M-8") 'insert-bracket-open) 624 | (global-set-key (kbd "M-9") 'insert-bracket-close) 625 | (global-set-key (kbd "M-0") 'insert-brace-close) 626 | (global-set-key (kbd "C-x C-x") 'set-mark-command) 627 | 628 | ;; change yes/no to y/n 629 | (defalias 'yes-or-no-p 'y-or-n-p) 630 | (setq confirm-kill-emacs 'yes-or-no-p) 631 | 632 | ;; enable winner-mode, previous window config with C-left 633 | (winner-mode 1) 634 | 635 | ;; windmove 636 | (windmove-default-keybindings) 637 | 638 | ;; fonts 639 | (set-face-attribute 'default nil :font "Liberation Mono-14") 640 | (set-face-attribute 'line-number nil :font "Liberation Mono-14") 641 | 642 | ;; disable tool and menu bars 643 | (tool-bar-mode -1) 644 | (menu-bar-mode -1) 645 | (scroll-bar-mode -1) 646 | (blink-cursor-mode -1) 647 | 648 | ;; change gc behavior 649 | (setq gc-cons-threshold 50000000) 650 | 651 | ;; warn when opening large file 652 | (setq large-file-warning-threshold 100000000) 653 | 654 | ;; disable startup screen 655 | (setq inhibit-startup-screen t) 656 | 657 | ;; useful frame title format 658 | (setq frame-title-format 659 | '((:eval (if (buffer-file-name) 660 | (abbreviate-file-name (buffer-file-name)) 661 | "%b")))) 662 | 663 | ;; automatic revert 664 | (global-auto-revert-mode t) 665 | 666 | ;; highlight parenthesis, easier jumping with C-M-n/p 667 | (show-paren-mode 1) 668 | (setq show-paren-style 'expression) 669 | (setq show-paren-delay 0) 670 | 671 | ;; control indentation 672 | (setq-default indent-tabs-mode nil) 673 | (setq tab-width 4) 674 | (setq c-basic-offset 4) 675 | 676 | ;; modify scroll settings 677 | (setq scroll-preserve-screen-position t) 678 | 679 | ;; set default fill width (e.g. M-q) 680 | (setq-default fill-column 79) 681 | 682 | ;; window dividers 683 | (fringe-mode 0) 684 | (setq window-divider-default-places t 685 | window-divider-default-bottom-width 1 686 | window-divider-default-right-width 1) 687 | (window-divider-mode 1) 688 | 689 | ;; display time in modeline 690 | (display-time-mode 1) 691 | 692 | ;; put all backups to same directory to not clutter directories 693 | (setq backup-directory-alist '(("." . "~/.emacs.d/backups"))) 694 | 695 | ;; display line numbers 696 | (global-display-line-numbers-mode) 697 | 698 | ;; browse in chrome 699 | (setq browse-url-browser-function 'browse-url-chrome) 700 | (setq shr-width 80) 701 | 702 | ;; don't fontify latex 703 | (setq font-latex-fontify-script nil) 704 | 705 | ;; set default encodings to utf-8 706 | (prefer-coding-system 'utf-8) 707 | (set-default-coding-systems 'utf-8) 708 | (set-language-environment 'utf-8) 709 | (set-selection-coding-system 'utf-8) 710 | 711 | ;; make Customize to not modify this file 712 | (setq custom-file (make-temp-file "emacs-custom")) 713 | 714 | ;; enable all disabled commands 715 | (setq disabled-command-function nil) 716 | 717 | ;; ediff setup 718 | (setq ediff-window-setup-function 'ediff-setup-windows-plain) 719 | 720 | ;; unbind keys 721 | (unbind-key "C-z" global-map) 722 | 723 | ;; change emacs frame by number 724 | (defun tom/select-frame (n) 725 | "Select frame identified by the number N." 726 | (interactive) 727 | (let ((frame (nth n (reverse (frame-list))))) 728 | (if frame 729 | (select-frame-set-input-focus frame) 730 | (select-frame-set-input-focus (make-frame))))) 731 | 732 | (define-key global-map 733 | (kbd "") 734 | (lambda () (interactive) 735 | (tom/select-frame 0))) 736 | (define-key global-map 737 | (kbd "") 738 | (lambda () (interactive) 739 | (tom/select-frame 1))) 740 | (define-key global-map 741 | (kbd "") 742 | (lambda () (interactive) 743 | (tom/select-frame 2))) 744 | (define-key global-map 745 | (kbd "") 746 | (lambda () (interactive) 747 | (tom/select-frame 3))) 748 | 749 | ;; bind find config 750 | (define-key global-map (kbd "") 751 | (lambda () (interactive) 752 | (find-file "~/src/nixemacs/readme.org"))) 753 | 754 | ;; bind compile 755 | (define-key global-map (kbd "") 'compile) 756 | 757 | ;; load private configurations 758 | (load "~/Dropbox/Config/emacs/private.el" t) 759 | #+end_src 760 | --------------------------------------------------------------------------------