init.el 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965
  1. ;;; ====
  2. ;;; GUIX
  3. ;;; ====
  4. ;; Load packages, which are installed via guix.
  5. (setq guix-package-enable-at-startup t)
  6. (require 'guix-init nil t)
  7. ;;; =====
  8. ;;; MELPA
  9. ;;; =====
  10. ;; This adds the melpa stable repository to the list of package
  11. ;; archives.
  12. (require 'package)
  13. (add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t)
  14. (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
  15. (package-initialize)
  16. ;;; =====================
  17. ;;; PACKAGE CONFIFURATION
  18. ;;; =====================
  19. ;;; use-package install
  20. ;; (eval-when-compile
  21. ;; ;; Following line is not needed if use-package.el is in ~/.emacs.d
  22. ;; (add-to-list 'load-path "<path where use-package is installed>")
  23. ;; (require 'use-package))
  24. (require 'use-package)
  25. (defun string-length= (a b)
  26. (= (length a)
  27. (length b)))
  28. (defun string-length< (a b)
  29. (= (length a)
  30. (length b)))
  31. (defun xiaolong/ivy--files-sort-by-length (x y)
  32. "Sort given filenames X and Y according to string length.
  33. However, give directories priority."
  34. (let ((cleaned-x (if (string-suffix-p "/" x) (substring x 0 -1) x))
  35. (cleaned-y (if (string-suffix-p "/" y) (substring y 0 -1) y)))
  36. (let* ((length-equal? (string-length= cleaned-x cleaned-y))
  37. (x-shorter? (string-length< cleaned-x cleaned-y))
  38. (x-wins t)
  39. (y-wins nil))
  40. (let ((result
  41. ;; compare
  42. (if (file-directory-p cleaned-x)
  43. (if (file-directory-p cleaned-y)
  44. ;; If both are a directory, and of same length, let the
  45. ;; default comparison function decide.
  46. (if length-equal?
  47. (ivy-sort-file-function-default x y)
  48. ;; If not of same length, then check if x is shorter and
  49. ;; prefer x if it is shorter.
  50. x-shorter?)
  51. ;; Prefer x if y is not a directory.
  52. x-wins)
  53. (if (file-directory-p cleaned-y)
  54. y-wins
  55. ;; If both are a directory, and of same length, let the
  56. ;; default comparison function decide.
  57. (if length-equal?
  58. (ivy-sort-file-function-default x y)
  59. ;; If not of same length, then check if x is shorter and
  60. ;; prefer x if it is shorter.
  61. x-shorter?)))))
  62. result))))
  63. (defun xiaolong/ivy--commands-sort-by-length (x y)
  64. "Sort given filenames X and Y according to string length.
  65. However, give directories priority."
  66. (let* ((length-equal? (string-length= x y))
  67. (x-shorter? (string-length< x y)))
  68. (let ((result
  69. (if length-equal?
  70. (...default... x y)
  71. ;; If not of same length, then check if x is shorter and
  72. ;; prefer x if it is shorter.
  73. x-shorter?)))
  74. result)))
  75. (use-package counsel
  76. :ensure t
  77. :bind
  78. (("C-x C-f" . #'counsel-find-file)
  79. ("C-x f" . #'counsel-find-file)
  80. ;; ("M-x" . #'counsel-M-x-with-last-command)
  81. ;; ("M-x" . #'command-execute)
  82. ;; ("M-x" . (lambda () (interactive) (execute-extended-command)))
  83. ("M-x" . #'counsel-M-x)
  84. ("C-x b" . #'counsel-switch-buffer))
  85. :config
  86. ;; (use-package flx
  87. ;; :ensure t)
  88. (ivy-mode 1)
  89. (setq ivy-height 10)
  90. (setq ivy-re-builders-alist '((t . ivy--regex-fuzzy)))
  91. ;; Remove the leading `^` from the input of counsel-M-x.
  92. (setcdr (assoc 'counsel-M-x ivy-initial-inputs-alist) "")
  93. ;; Add our own sort function to the association list of sort functions.
  94. (add-to-list 'ivy-sort-functions-alist
  95. '(read-file-name-internal . xiaolong/ivy--files-sort-by-length)))
  96. (use-package swiper
  97. :ensure t
  98. :bind
  99. (("C-s" . 'swiper))
  100. :config
  101. (ivy-mode 1)
  102. (setq ivy-use-virtual-buffers t)
  103. (setq enable-recursive-minibuffers t))
  104. ;;; BASH
  105. (setq shell-file-name "bash")
  106. (setq shell-command-switch "-c")
  107. ;; Use sh instead of GNU Bash. This is done as an attempt to
  108. ;; get literate programming working for GNU Guile.
  109. ;; (setq shell-file-name "sh")
  110. ;; (setq shell-command-switch "-c")
  111. ;; (setq explicit-shell-file-name "/bin/sh")
  112. ;;; TRAMP
  113. (setq tramp-default-method "ssh")
  114. (setq tramp-verbose 5)
  115. (setq password-cache-expiry 86400) ; 1 day
  116. (setq auth-source-debug t)
  117. (setq auth-sources nil)
  118. ;;; GEISER
  119. (require 'geiser)
  120. (require 'geiser-guile)
  121. (setq geiser-guile-binary "guile")
  122. ;; (setq geiser-guile-load-init-file-p t)
  123. (setq geiser-default-implementation 'guile)
  124. (setq geiser-scheme-implementation 'guile)
  125. (setq geiser-active-implementations '(guile))
  126. (defun my-run-guile ()
  127. (interactive)
  128. (let ((shell-file-name "bash")
  129. (shell-command-switch "-ic"))
  130. (run-guile)))
  131. (setq geiser-guile-warning-level 'high)
  132. ;;; SCHEME
  133. (setq scheme-program-name "guile")
  134. (with-eval-after-load 'info-look
  135. (info-lookup-add-help
  136. :mode 'scheme-mode
  137. :regexp "[^()`'‘’,\" \t\n]+"
  138. ;; :doc-spec describes the pages where info-look can find
  139. ;; and how to parse the index of symbols for the
  140. ;; specified mode
  141. :doc-spec '(("(guile) Procedure Index" nil nil nil)
  142. ("(guile) Variable Index" nil nil nil)
  143. ("(guile) R5RS Index" nil nil nil)
  144. ("(guile) Type Index" nil nil nil)
  145. ("(guile) Concept Index" nil nil nil)
  146. ("(r5rs)Index" nil "^[ ]+-+ [^:]+:[ ]*" "\\b"))))
  147. ;; You can find what is already defined by looking up the
  148. ;; info-lookup-alist variable.
  149. ;;; ORG
  150. (setq org-src-fontify-natively t
  151. org-src-window-setup 'current-window ;; edit in current window
  152. org-src-strip-leading-and-trailing-blank-lines t
  153. org-src-preserve-indentation t ;; do not put two spaces on the left
  154. org-src-tab-acts-natively t)
  155. ;; allow usage of shift in some situations
  156. (setq org-support-shift-select t)
  157. ;; agenda files
  158. (setq org-agenda-files '("/home/xiaolong/dev/private-notes/birthdays.org"))
  159. ;; The following enables source blocks of specific
  160. ;; programming languages to be executed. By default only
  161. ;; elisp is allowed to be executed. First we define an
  162. ;; association list of languages to booleans, which enable
  163. ;; or disable support for a language.
  164. (setq org-babel-load-languages
  165. '((emacs-lisp . t)
  166. ;; (elisp . t)
  167. ;; (erlang . t)
  168. ;; (python . t)
  169. (prolog . t)
  170. (scheme . t)
  171. (shell . t)
  172. ;; (haskell . t)
  173. ))
  174. ;; Then we use org-babel-do-load-languages to actually tell
  175. ;; org babel, that the languages should be supported.
  176. (org-babel-do-load-languages
  177. 'org-babel-load-languages
  178. '((prolog . t)
  179. (scheme . t)
  180. (shell . t)
  181. ;; (emacs-lisp . t)
  182. ))
  183. ;; The following defines a procedure, which determins, which
  184. ;; source blocks of programming languages can be run without
  185. ;; confirmation, depending on the language. The procedure
  186. ;; can then be used as org-confirm-babel-evaluate value.
  187. (defun xiaolong/org-confirm-babel-evaluate (lang body)
  188. (not
  189. (or (string= lang "scheme")
  190. ;; (string= lang "emacs-lisp")
  191. ;; (string= lang "elisp")
  192. ;; (string= lang "python")
  193. (string= lang "shell")
  194. )))
  195. ;; Set a procedure predicate for org babel, to determin, which languages can
  196. ;; be run without confirmation.
  197. (setq org-confirm-babel-evaluate 'xiaolong/org-confirm-babel-evaluate)
  198. ;;; EXPORT
  199. (add-hook 'org-mode-hook
  200. (function
  201. (lambda ()
  202. (require 'ox-gfm))))
  203. ;;; COMPANY
  204. (setq company-idle-delay t)
  205. (setq company-require-match nil)
  206. (setq company-show-numbers t)
  207. (setq company-tooltip-idle-delay nil)
  208. (setq company-tooltip-maximum-width 120)
  209. (setq company-tooltip-minimum 3)
  210. (setq company-tooltip-align-annotations t)
  211. ;;; EDITORCONFIG
  212. ;; Editorconfig uses a standardized configuration file to
  213. ;; unify formatting across editors, which have support for
  214. ;; editorconfig, usually via some plugin or extension.
  215. (editorconfig-mode 1)
  216. ;;; MARKDOWN
  217. (add-hook 'markdown-mode-hook
  218. (function
  219. (lambda ()
  220. (setq whitespace-style (delete 'lines-tail whitespace-style)))))
  221. ;;; FLYCHECK
  222. ;; Currently no config for flycheck. Seems to interfere with
  223. ;; line-reminder-mode.
  224. ;;; RACKET
  225. (add-to-list 'auto-mode-alist '("\\.rkt\\'" . racket-mode))
  226. (add-hook 'racket-mode-hook
  227. (function
  228. (lambda ()
  229. (setq indent-tabs-mode nil tab-width 2))))
  230. ;;; IO LANG
  231. (add-to-list 'load-path "~/.emacs.d/packages/io-mode")
  232. (require 'io-mode)
  233. ;;; PROLOG
  234. (require 'prolog)
  235. (add-to-list 'auto-mode-alist '("\\.pl\\'" . prolog-mode))
  236. ;;; GFORTH
  237. ;;; UNDO TREE
  238. (global-undo-tree-mode)
  239. (setq undo-tree-auto-save-history nil)
  240. ;;; ESHELL EXEC PATH FROM SHELL
  241. (when (memq window-system '(mac ns x))
  242. (exec-path-from-shell-initialize))
  243. ;;; NEOTREE
  244. (setq neo-autorefresh nil)
  245. (setq neo-persist-show nil)
  246. (setq neo-show-hidden-files nil)
  247. (setq neo-smart-open t)
  248. (setq neo-theme 'ascii)
  249. (setq neo-vc-integration '(char))
  250. (setq neo-window-fixed-size nil)
  251. ;;; YAML MODE
  252. (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode))
  253. (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode))
  254. (add-hook 'yaml-mode-hook
  255. #'(lambda ()
  256. (define-key yaml-mode-map "\C-m" 'newline-and-indent)))
  257. ;;; YASNIPPET
  258. (yas-global-mode 1)
  259. (setq yas-snippet-dirs
  260. (append yas-snippet-dirs
  261. '("~/.emacs.d/snippets")))
  262. ;;; =====================
  263. ;;; GENERAL CONFIGURATION
  264. ;;; =====================
  265. ;;; TOOLBAR
  266. (tool-bar-mode -1)
  267. ;;; SESSION
  268. (setq desktop-dirname (concat user-emacs-directory "/desktop/")
  269. desktop-base-file-name "emacs.desktop"
  270. desktop-base-lock-name "lock"
  271. desktop-path (list desktop-dirname)
  272. desktop-save t
  273. desktop-files-not-to-save "^$" ;reload tramp paths
  274. desktop-load-locked-desktop nil
  275. desktop-auto-save-timeout 5)
  276. ;;; SAVE DESKTOP
  277. (desktop-save-mode 1)
  278. ;;; FONT
  279. ;; Set default font.
  280. (let ((standard-font "DejaVu Sans Mono:weight=normal:height=110:antialias=1"))
  281. (set-frame-font standard-font))
  282. ;; (let ((standard-font "Monocraft:weight=medium:height=110:antialias=0"))
  283. ;; (set-frame-font standard-font))
  284. (set-face-attribute 'default nil :height 110)
  285. ;; A fontset font seems to be a font, which is used for a specific set of
  286. ;; characters, which can be associated with a particular language. Using fontset
  287. ;; font settings, it should be possible to set a font per langugage, as is
  288. ;; probably done on the Emacs HELLO page.
  289. (let ((chinese-font "WenQuanYi Micro Hei Mono:weight=normal:height=140:antialias=1"))
  290. (dolist (charset '(kana han symbol cjk-misc bopomofo))
  291. (set-fontset-font "fontset-default"
  292. charset
  293. chinese-font)))
  294. ;;; MATCHING PARENS
  295. ;; highlight matching parenthesis
  296. (show-paren-mode 1)
  297. (setq-default show-paren-delay 0) ;; 0 delay
  298. (setq-default show-paren-style 'parenthesis) ;;'parenthesis is another possible value, only highlighting the brackets
  299. ;;; TABS AND SPACES
  300. (setq-default tab-width 4)
  301. (setq-default indent-tabs-mode nil)
  302. (setq-default tab-stop-list (number-sequence 4 200 4))
  303. ;;; WHITESPACE
  304. (add-hook 'before-save-hook 'delete-trailing-whitespace)
  305. (add-hook 'before-save-hook 'whitespace-cleanup)
  306. ;;; SCROLL BEHAVIOR
  307. (setq-default mouse-wheel-scroll-amount '(5 ((shift) . 5))) ;; two lines at a time
  308. (setq-default mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling
  309. (setq-default mouse-wheel-follow-mouse 't) ;; scroll window under mouse
  310. (setq-default scroll-step 5) ;; keyboard scroll one line at a time
  311. (scroll-bar-mode -1)
  312. (setq-default scroll-conservatively 10000)
  313. ;; (setq-default scroll-margin 4)
  314. ;;; INITIAL FRAME RESIZING
  315. (setq frame-inhibit-implied-resize t)
  316. ;;; DELETE SELECTED TEXT WHEN TYPING
  317. (delete-selection-mode 1)
  318. ;;; COMPLETION FUNCTION PREVALENCE
  319. (setq hippie-expand-try-functions-list
  320. '(try-expand-dabbrev
  321. try-expand-dabbrev-all-buffers
  322. try-expand-dabbrev-from-kill
  323. ;; try-complete-file-name-partially
  324. ;; try-complete-file-name
  325. try-expand-all-abbrevs
  326. ;; try-expand-list
  327. ;; try-expand-line
  328. try-complete-lisp-symbol-partially
  329. ;;try-complete-lisp-symbol)
  330. ))
  331. ;;; PREFERRED ENCODING
  332. (prefer-coding-system 'utf-8)
  333. (set-language-environment "UTF-8")
  334. (set-default-coding-systems 'utf-8)
  335. ;;; FRINGE
  336. ;; previous config:
  337. (fringe-mode '(8 . 1))
  338. ;;; BACKUP FILES
  339. (setq backup-directory-alist `(("." . "~/.emacs-backups")))
  340. (setq backup-by-copying t)
  341. (setq delete-old-versions t
  342. kept-new-versions 6
  343. kept-old-versions 10
  344. version-control t)
  345. ;;; TERMINAL
  346. (setq ansi-color-for-comint-mode-on t)
  347. ;; vterm
  348. (setq vterm-ignore-blink-cursor t)
  349. (setq vterm-max-scrollback 100000)
  350. ;;; CALENDAR
  351. (setq calendar-holidays nil)
  352. ;;; LINE NUMBERS
  353. ;; copied from: https://www.emacswiki.org/emacs/LineNumbers#h5o-1
  354. ;; (defcustom display-line-numbers-exempt-modes
  355. ;; '(vterm-mode eshell-mode shell-mode term-mode ansi-term-mode org-mode)
  356. ;; "Major modes on which to disable line numbers."
  357. ;; :group 'display-line-numbers
  358. ;; :type 'list
  359. ;; :version "green")
  360. ;; (defun display-line-numbers--turn-on ()
  361. ;; "Turn on line numbers except for certain major modes.
  362. ;; Exempt major modes are defined in
  363. ;; `display-line-numbers-exempt-modes'."
  364. ;; (unless (or (minibufferp)
  365. ;; (member major-mode display-line-numbers-exempt-modes))
  366. ;; (display-line-numbers-mode)))
  367. ;; (global-display-line-numbers-mode)
  368. ;; only in programming modes
  369. ;; (add-hook 'prog-mode-hook (function (lambda () (display-line-numbers-mode))))
  370. (defun xiaolong/line-numbers ()
  371. (interactive)
  372. (display-line-numbers-mode 'toggle))
  373. ;;; COLUMN NUMBERS
  374. (column-number-mode)
  375. ;;; PDF VIEWING
  376. (setq-default doc-view-pdfdraw-program "mudraw")
  377. (setq-default doc-view-continuous t)
  378. ;;; MINIBUFFER COMPLETION
  379. ;; case-insensitive minibuffer completion
  380. (setq read-buffer-completion-ignore-case t)
  381. (setq read-file-name-completion-ignore-case t)
  382. ;; ESHELL
  383. (defun shorten-filename (filename limit)
  384. (let ((loc (if (string= filename (getenv "HOME"))
  385. "~"
  386. filename)))
  387. (let ((loc-length (length loc)))
  388. (if (> loc-length limit)
  389. (concat "..." (substring loc (- loc-length limit)))
  390. loc))))
  391. ;; change eshell prompt
  392. (defun set-eshell-prompt-function ()
  393. (setq eshell-prompt-function
  394. (function
  395. (lambda ()
  396. (concat
  397. (propertize (format-time-string "%H:%M:%S" (current-time))
  398. 'face
  399. `(:foreground "#A0A0A0"))
  400. "::"
  401. ;; (propertize (concat "[" (number-to-string (eshell-last-command-status)) "]")
  402. ;; 'face
  403. ;; `(:foreground "#A0A0A0"))
  404. ;; "::"
  405. ;; (propertize (concat "[" (number-to-string $?) "]")
  406. ;; 'face
  407. ;; `(:foreground "#A0A0A0"))
  408. ;; "::"
  409. (propertize (user-login-name)
  410. 'face
  411. `(:foreground "#FF9080"))
  412. "@"
  413. (propertize (let ((sys-name (system-name)))
  414. (let ((sys-name-len (length sys-name)))
  415. (if (> sys-name-len 8)
  416. (concat (substring sys-name 0 8) "...")
  417. sys-name)))
  418. 'face
  419. `(:foreground "#FF9080"))
  420. "::"
  421. (propertize (shorten-filename (eshell/pwd) 36)
  422. 'face
  423. `(:foreground "#FF9080"))
  424. "::"
  425. (propertize (concat "("
  426. (if-let ((status eshell-last-command-status))
  427. (if (= status 0)
  428. "0"
  429. (format "%s" status)))
  430. ")")
  431. 'face
  432. `(:foreground "#FF9080"))
  433. (if (= (user-uid) 0)
  434. "# "
  435. "$ ")))))
  436. (setq eshell-highlight-prompt t)
  437. ;; The prompt is:
  438. ;; + anything except '#', '$', and '\n' an arbitrary number of times followed by
  439. ;; + '#' or '$' followed by
  440. ;; + ' '.
  441. (setq eshell-prompt-regexp "^[^#$\n]*[#$] "))
  442. (set-eshell-prompt-function)
  443. ;;; =================
  444. ;;; PROGRAMMING MODES
  445. ;;; =================
  446. (require 'indicators)
  447. ;; (use-package line-reminder
  448. ;; :ensure t
  449. ;; :init
  450. ;; (setq line-reminder-show-option 'indicators)
  451. ;; ;; Customize the modified sign.
  452. ;; ;; (setq line-reminder-modified-sign "▐")
  453. ;; ;;Customize the saved sign.
  454. ;; ;; (setq line-reminder-saved-sign "▐")
  455. ;; ;;Customize string on the right/left side of the line number.
  456. ;; (setq line-reminder-linum-left-string "")
  457. ;; (setq line-reminder-linum-right-string " ")
  458. ;; :config
  459. ;; (custom-set-faces
  460. ;; '(line-reminder-modified-sign-face ((t (:foreground "gold"))))
  461. ;; '(line-reminder-saved-sign-face ((t (:foreground "#60FA6A")))))
  462. ;; (add-hook 'prog-mode-hook
  463. ;; (function
  464. ;; (lambda ()
  465. ;; (line-reminder-mode t)
  466. ;; (setq line-reminder-show-option 'indicators)))))
  467. ;;; ============
  468. ;;; KEY BINDINGS
  469. ;;; ============
  470. ;;; UNSET SOME
  471. (dolist (key '("\C-g")
  472. '("\C-x f"))
  473. (global-unset-key key))
  474. (dolist (key '("\C-k"))
  475. (global-unset-key key))
  476. ;; Avoid annoying exit shortcut.
  477. (global-unset-key (kbd "C-x C-c"))
  478. ;;; DEFINE MY OWN
  479. (define-key global-map (kbd "RET") 'newline-and-indent)
  480. (define-key global-map (kbd "<C-return>") 'newline)
  481. (global-set-key (kbd "<C-mouse-5>")
  482. (lambda () (interactive) (text-scale-decrease 1)))
  483. (global-set-key (kbd "<C-mouse-4>")
  484. (lambda () (interactive) (text-scale-increase 1)))
  485. (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines) ; TODO: remove
  486. (global-set-key (kbd "C-n") 'set-mark-command)
  487. (global-set-key (kbd "C->") 'xiaolong/indent-region)
  488. (global-set-key (kbd "C-<") 'xiaolong/unindent-region)
  489. (global-set-key (kbd "<C-tab>") 'hippie-expand)
  490. (global-set-key (kbd "C-~") 'xiaolong/toggle-case)
  491. (global-set-key (kbd "C-d") 'kill-whole-line)
  492. (global-set-key (kbd "M-<left>") 'backward-sexp)
  493. (global-set-key (kbd "M-<right>") 'forward-sexp)
  494. ;; moving s-expressions
  495. (global-set-key (kbd "C-c C-<right>") 'transpose-sexps)
  496. (global-set-key (kbd "C-c C-<left>") 'xiaolong/reverse-transpose-sexps)
  497. ;; moving between windows
  498. (global-set-key (kbd "s-<left>") 'windmove-left)
  499. (global-set-key (kbd "s-<right>") 'windmove-right)
  500. (global-set-key (kbd "s-<up>") 'windmove-up)
  501. (global-set-key (kbd "s-<down>") 'windmove-down)
  502. ;; rebinding combination for zap-to-char to the installed zop-to-char
  503. (global-set-key [remap zap-to-char] 'zop-up-to-char) ; TODO: move to use-package def
  504. ;; spelling change dictionary
  505. (global-set-key (kbd "C-c d") 'switch-dictionary-de-en)
  506. (global-set-key (kbd "C-c S-h") 'highlight-regexp)
  507. (global-set-key (kbd "C-c h") 'highlight-phrase)
  508. (global-set-key (kbd "C-c u") 'unhighlight-regexp)
  509. ;; multiple cursor bindings with ctrl+c and m
  510. (global-set-key (kbd "C-c m") 'set-rectangular-region-anchor)
  511. ;; reload file
  512. (global-set-key (kbd "C-c r") 'xiaolong/revert-buffer-no-confirm)
  513. (global-set-key (kbd "C-c a") 'org-agenda)
  514. ;; wrap selection in enclosing characters
  515. (global-set-key (kbd "C-c w (") 'insert-pair)
  516. (global-set-key (kbd "C-c w [") 'insert-pair)
  517. (global-set-key (kbd "C-c w {") 'insert-pair)
  518. (global-set-key (kbd "C-c w \"") 'insert-pair)
  519. (global-set-key (kbd "C-c w \'") 'insert-pair)
  520. ;; move windows (buffers)
  521. ;; (global-set-key (kbd "M-s-<up>") 'windmove-up)
  522. ;; (global-set-key (kbd "M-s-<down>") 'windmove-down)
  523. ;; (global-set-key (kbd "M-s-<left>") 'windmove-left)
  524. ;; (global-set-key (kbd "M-s-<right>") 'windmove-right)
  525. ;; text moving
  526. (global-set-key (kbd "M-<up>") 'move-text-up)
  527. (global-set-key (kbd "M-<down>") 'move-text-down)
  528. ;; buffers
  529. (global-set-key (kbd "C-x a k") 'xiaolong/close-all-buffers)
  530. (global-set-key (kbd "C-x a o") 'xiaolong/kill-other-buffers)
  531. (global-set-key (kbd "C-k") 'kill-this-buffer)
  532. (global-set-key (kbd "C-x f") 'find-file)
  533. (global-set-key (kbd "C-a") 'mark-whole-buffer)
  534. ;; zooming
  535. (global-set-key (kbd "C-+") 'text-scale-increase)
  536. (global-set-key (kbd "C--") 'text-scale-decrease)
  537. ;; company mode keys
  538. (global-set-key (kbd "C-c C-f") 'xiaolong/beautify-json)
  539. ;; make use of additional mouse keys
  540. (global-set-key (kbd "<drag-mouse-8>") 'previous-buffer)
  541. (global-set-key (kbd "<drag-mouse-9>") 'next-buffer)
  542. (global-set-key (kbd "<mouse-8>") 'previous-buffer)
  543. (global-set-key (kbd "<mouse-9>") 'next-buffer)
  544. (global-set-key (kbd "C-c t") 'toggle-truncate-lines)
  545. (global-set-key (kbd "C-g l") 'goto-last-change)
  546. (global-set-key (kbd "<f8>") 'neotree-toggle)
  547. ;; allow input of dead keys
  548. (define-key key-translation-map [dead-grave] "`")
  549. (define-key key-translation-map [dead-acute] "'")
  550. (define-key key-translation-map [dead-circumflex] "^")
  551. (define-key key-translation-map [dead-diaeresis] "\"")
  552. (define-key key-translation-map [dead-tilde] "~")
  553. ;;; ================
  554. ;;; CUSTOM FUNCTIONS
  555. ;;; ================
  556. ;;; KEYBOARD MACROS
  557. (defun xiaolong/save-macro (name)
  558. "Save a macro. Take a NAME as argument and save the last
  559. defined macro under this name at the end of your .emacs."
  560. (interactive "SName of the macro: ") ; ask for the name of the macro
  561. (kmacro-name-last-macro name) ; use this name for the macro
  562. (find-file user-init-file) ; open ~/.emacs or other user init file
  563. (goto-char (point-max)) ; go to the end of the .emacs
  564. (newline) ; insert a newline
  565. (insert-kbd-macro name) ; copy the macro
  566. (newline) ; insert a newline
  567. (switch-to-buffer nil)) ; return to the initial buffer
  568. ;;; FONTS
  569. (defun xiaolong/buffer-face-mode-variable-width ()
  570. (interactive)
  571. ;; "DejaVu Sans:weight=normal:height=110:antialias=1"
  572. (setq buffer-face-mode-face
  573. '(:family "DejaVu Sans" :height 110 :width semi-condensed :weight normal))
  574. (buffer-face-mode))
  575. (defun xiaolong/buffer-face-mode-same-width ()
  576. (interactive)
  577. ;; "DejaVu Sans Mono:weight=normal:height=110:antialias=1"
  578. (setq buffer-face-mode-face
  579. '(:family "DejaVu Sans Mono" :height 140 :width semi-condensed :weight normal))
  580. (buffer-face-mode))
  581. ;;; DATA AND TIME
  582. (defun now ()
  583. "Insert the current datetime."
  584. (interactive)
  585. (insert (format-time-string "%Y-%m-%d %H:%M:%S (%A)"))) ;
  586. (defun today ()
  587. "Insert current date."
  588. (interactive)
  589. (insert (format-time-string "%A %Y-%m-%d")))
  590. ;;; INDENT
  591. (defun xiaolong/indent-region (N)
  592. "Indent a region by a number (as N) indentation units."
  593. (interactive "p")
  594. (if (use-region-p)
  595. (progn (indent-rigidly (region-beginning) (region-end) (* N 4))
  596. (setq deactivate-mark nil))
  597. (self-insert-command N)))
  598. (defun xiaolong/unindent-region (N)
  599. "Unindent a region by a number (as N) indentation units."
  600. (interactive "p")
  601. (if (use-region-p)
  602. (progn (indent-rigidly (region-beginning) (region-end) (* N -4))
  603. (setq deactivate-mark nil))
  604. (self-insert-command N)))
  605. (defun xiaolong/indent-buffer ()
  606. "Indent current buffer according to major mode."
  607. (interactive)
  608. (indent-region (point-min) (point-max)))
  609. ;;; TOGGLE CASE
  610. ;; This function toggles the case of the selected text.
  611. (defun xiaolong/toggle-case ()
  612. "Toggle case."
  613. (interactive)
  614. (when (region-active-p)
  615. (let
  616. ((i 0)
  617. (return-string "")
  618. (input (buffer-substring-no-properties (region-beginning) (region-end))))
  619. (while (< i (- (region-end) (region-beginning)))
  620. (let
  621. ((current-char (substring input i (+ i 1))))
  622. (if
  623. (string= (substring input i (+ i 1)) (downcase (substring input i (+ i 1))))
  624. (setq return-string
  625. (concat return-string (upcase (substring input i (+ i 1)))))
  626. (setq return-string
  627. (concat return-string (downcase (substring input i (+ i 1)))))))
  628. (setq i (+ i 1)))
  629. (delete-region (region-beginning) (region-end))
  630. (insert return-string))))
  631. ;;; REVERT
  632. ;; Source: http://www.emacswiki.org/emacs-en/download/misc-cmds.el
  633. (defun xiaolong/revert-buffer-no-confirm ()
  634. "Revert buffer without confirmation."
  635. (interactive)
  636. (revert-buffer :ignore-auto :noconfirm))
  637. ;;; BUFFER MANAGEMENT
  638. (defun xiaolong/close-all-buffers ()
  639. "Close all open buffers."
  640. (interactive)
  641. (mapc 'kill-buffer (buffer-list)))
  642. (defun xiaolong/kill-other-buffers ()
  643. "Kill all other buffers."
  644. (interactive)
  645. (mapc 'kill-buffer (delq (current-buffer) (buffer-list))))
  646. ;;; JSON
  647. (defun xiaolong/beautify-json ()
  648. "Display JSON in a pretty way."
  649. (interactive)
  650. (let ((b (if mark-active (min (point) (mark)) (point-min)))
  651. (e (if mark-active (max (point) (mark)) (point-max))))
  652. (shell-command-on-region b
  653. e
  654. "python -mjson.tool" (current-buffer) t)))
  655. ;;; CONFIG
  656. (defun xiaolong/open-config ()
  657. "Open the Emacs init config."
  658. (interactive)
  659. (let ((config-file-path "~/.emacs.d/init.el"))
  660. (find-file config-file-path)))
  661. ;;; OTHER
  662. (defun xiaolong/describe-last-function()
  663. (interactive)
  664. (describe-function last-command))
  665. (defun xiaolong/reverse-transpose-sexps (arg)
  666. (interactive "*p")
  667. (transpose-sexps (- arg))
  668. ;; when transpose-sexps can no longer transpose, it throws an error and code
  669. ;; below this line won't be executed. So, we don't have to worry about side
  670. ;; effects of backward-sexp and forward-sexp.
  671. (backward-sexp (1+ arg))
  672. (forward-sexp 1)) ; transpose-sexps already exists
  673. (defun xiaolong/get-package-version (name)
  674. (when (member name package-activated-list)
  675. (package-desc-vers (cdr (assoc name package-alist)))))
  676. ;; ESHELL
  677. (defun eshell/e (file)
  678. "Open the FILE in the current buffer."
  679. (find-file file))
  680. (defun eshell/ee (file)
  681. "Open the FILE in a new buffer."
  682. (find-file-other-window file))
  683. (defun eshell/clear ()
  684. "Clear the eshell buffer."
  685. (let ((inhibit-read-only t))
  686. (erase-buffer)
  687. (eshell-send-input)))
  688. (defun eshell/x ()
  689. "Exit the shell."
  690. (insert "exit")
  691. (eshell-send-input)
  692. (delete-window))
  693. (defun eshell-org-file-tags ()
  694. "Help the eshell parse the text the point is currently on, looking for parameters surrounded in single quotes. Return a function that takes a FILE and return nil if the file given to it does not contain the 'org-mode' #+TAGS: entry specified."
  695. ;; Step 1. Parse the eshell buffer for our tag between quotes
  696. ;; Make sure to move point to the end of the match:
  697. (if (looking-at "'\\([^)']+\\)'")
  698. (let* ((tag (match-string 1))
  699. (reg (concat "^#\\+TAGS:.* " tag "\\b")))
  700. (goto-char (match-end 0))
  701. ;; Step 2. Return the predicate function:
  702. ;; Careful when accessing the `reg' variable.
  703. `(lambda (file)
  704. (with-temp-buffer
  705. (insert-file-contents file)
  706. (re-search-forward ,reg nil t 1))))
  707. (error "The `T' predicate takes an org-mode tag value in single quotes.")))
  708. (defun eshell/ll ()
  709. "Print all files with permissions in a list."
  710. (insert "ls -al")
  711. (eshell-send-input))
  712. (defun eshell/l ()
  713. "Print all files with permissions in a list."
  714. (insert "ls -CF")
  715. (eshell-send-input))
  716. (defun eshell/did ()
  717. "Open the did file."
  718. (interactive)
  719. (find-file "~/development/Notes/did.org")
  720. (let ((current-date-time-format "%Y-%m-%d: %a %b %d: %H:%M:%S %Z"))
  721. ;; insert an additional new line if the current line is not empty
  722. (if (save-excursion (beginning-of-line)
  723. (looking-at "[[:space:]]*$"))
  724. (insert "\n")
  725. (insert "\n\n"))
  726. (insert (concat "* "
  727. (format-time-string current-date-time-format (current-time))))
  728. (insert "\n")))
  729. ;;; =============
  730. ;;; CUSTOM COLORS
  731. ;;; =============
  732. (custom-set-faces
  733. ;; custom-set-faces was added by Custom.
  734. ;; If you edit it by hand, you could mess it up, so be careful.
  735. ;; Your init file should contain only one such instance.
  736. ;; If there is more than one, they won't work right.
  737. '(cursor ((t (:foreground "orange red" :inverse-video t :underline t :weight bold))))
  738. '(hl-line ((t (:extend t))))
  739. '(org-hide ((t (:foreground "gray30"))))
  740. '(region ((t (:inherit highlight :extend t :background "#434546" :foreground "spring green")))))
  741. ;;; =============
  742. ;;; OPTIMIZATIONS
  743. ;;; =============
  744. ;; deactivate a time consuming step we might not need, to improve long
  745. ;; line performance
  746. ;; (setq-default bidi-display-reordering nil)
  747. (setq bidi-paragraph-direction 'left-to-right)
  748. ;;; ==============
  749. ;;; EMACS SETTINGS
  750. ;;; ==============
  751. (custom-set-variables
  752. ;; custom-set-variables was added by Custom.
  753. ;; If you edit it by hand, you could mess it up, so be careful.
  754. ;; Your init file should contain only one such instance.
  755. ;; If there is more than one, they won't work right.
  756. '(cursor-type '(hbar . 3))
  757. '(custom-enabled-themes '(sanityinc-tomorrow-eighties))
  758. '(custom-safe-themes
  759. '("628278136f88aa1a151bb2d6c8a86bf2b7631fbea5f0f76cba2a0079cd910f7d" "1711947b59ea934e396f616b81f8be8ab98e7d57ecab649a97632339db3a3d19" "7675ffd2f5cb01a7aab53bcdd702fa019b56c764900f2eea0f74ccfc8e854386" "ae65ccecdcc9eb29ec29172e1bfb6cadbe68108e1c0334f3ae52414097c501d2" "7923541211298e4fd1db76c388b1d2cb10f6a5c853c3da9b9c46a02b7f78c882" "9abe2b502db3ed511fea7ab84b62096ba15a3a71cdb106fd989afa179ff8ab8d" "95b0bc7b8687101335ebbf770828b641f2befdcf6d3c192243a251ce72ab1692" default))
  760. '(global-hl-line-mode t)
  761. '(package-selected-packages
  762. '(line-reminder ob-prolog color-theme-sanityinc-tomorrow kaolin-themes zeno-theme melancholy-theme afternoon-theme gruber-darker-theme fuel forth-mode ob-async auto-complete company dockerfile-mode editorconfig flycheck jinja2-mode undercover json-reformat json-mode neotree python-environment undo-tree monokai-theme exec-path-from-shell erlang ox-gfm typescript-mode goto-chg multiple-cursors sml-mode toml-mode web-mode yaml-mode yasnippet magit markdown-mode s pos-tip paredit faceup racket-mode))
  763. '(warning-suppress-types '((comp))))
  764. (put 'downcase-region 'disabled nil)
  765. (put 'erase-buffer 'disabled nil)
  766. (put 'upcase-region 'disabled nil)
  767. (set-cursor-color "#13ff00")
  768. (server-start)