Linux install and configuration management utilities
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

config.org 39KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320
  1. #+PROPERTY: header-args:emacs-lisp :lexical t
  2. #+title: Config
  3. * Setup
  4. ** Lexical Binding
  5. #+BEGIN_SRC elisp
  6. ;;; -*- lexical-binding: t; -*-
  7. #+END_SRC
  8. ** Environment Variables
  9. #+BEGIN_SRC elisp
  10. (doom-load-envvars-file (concat doom-user-dir "env.el"))
  11. #+END_SRC
  12. ** Doom configuration
  13. #+BEGIN_SRC elisp
  14. (setq doom-modeline-major-mode-icon t)
  15. #+END_SRC
  16. * Lisp
  17. ** Web
  18. #+BEGIN_SRC elisp
  19. (use-package request
  20. :commands request)
  21. #+END_SRC
  22. #+BEGIN_SRC elisp
  23. (defmacro request! (url plist success &optional error)
  24. "Makes an HTTP request with `request`, running SUCCESS on success, and
  25. ERROR on error if specified.
  26. Any arguments of LAMBDA are bound to the corresponding plist keys
  27. returned by `request`."
  28. (let ((handler (lambda (fn)
  29. ;; Wraps a lambda in `cl-function`,
  30. ;; and converts args (foo) into (&key foo &allow-other-keys)
  31. `(cl-function
  32. (lambda
  33. ,(append
  34. (mapcan (lambda (arg) `(&key ,arg))
  35. (cadr fn))
  36. '(&allow-other-keys))
  37. ,@(cddr fn))))))
  38. `(request ,url
  39. ,@plist
  40. :success ,(funcall handler success)
  41. ,@(if error `(:error ,(funcall handler error))))))
  42. #+END_SRC
  43. ** Editing
  44. #+BEGIN_SRC elisp
  45. (defun my/line ()
  46. (buffer-substring-no-properties
  47. (line-beginning-position)
  48. (line-end-position)))
  49. (defun my/line-match-p (regexp)
  50. (string-match-p regexp (my/line)))
  51. #+END_SRC
  52. #+BEGIN_SRC elisp
  53. (defun my/insert-mode-p ()
  54. (eq evil-state 'insert))
  55. (defun my/normal-mode-p ()
  56. (eq evil-state 'normal))
  57. #+END_SRC
  58. ** Keybindings
  59. #+BEGIN_SRC elisp
  60. (defun my/kbd-replace (str)
  61. "Convert STR into a keyboard macro string by replacing terminal key sequences with GUI keycodes."
  62. (let ((kbd-regex '(("ESC" . "<escape>")
  63. ("DEL" . "<delete>" )
  64. ("BS" . "<backspace>")
  65. ("RET" . "<return>")
  66. ("SPC" . "<SPC>")
  67. ("TAB" . "<tab>"))))
  68. (my/replace-regexps-in-string str kbd-regex)))
  69. (setq my//vim!-p nil)
  70. (defun my/vim!-p () (eq my//vim!-p t))
  71. (defun vim! (str)
  72. "Execute the key sequence defined by STR like a VIM macro."
  73. (let ((minibuffer-message-timeout 0))
  74. (when (not (my/vim!-p))
  75. (setq my//vim!-p t)
  76. (execute-kbd-macro (read-kbd-macro (my/kbd-replace str)))
  77. (setq my//vim!-p nil))))
  78. #+END_SRC
  79. #+BEGIN_SRC elisp
  80. (defun my/buffer-local-set-key (key fn)
  81. (let ((mode (intern (format "%s-local-mode" (buffer-name))))
  82. (map (intern (format "%s-local-mode-map" (buffer-name)))))
  83. (unless (boundp map)
  84. (set map (make-sparse-keymap))
  85. (evil-make-overriding-map map 'normal))
  86. (eval
  87. `(define-minor-mode ,mode
  88. "A minor mode for buffer-local keybinds."
  89. :keymap ,map))
  90. (eval
  91. `(define-key ,map ,key #',fn))
  92. (funcall mode t)))
  93. #+END_SRC
  94. ** Regex
  95. #+BEGIN_SRC elisp
  96. (defun my/replace-regexps-in-string (str regexps)
  97. "Replace all pairs of (regex . replacement) defined by REGEXPS in STR."
  98. (if (null regexps)
  99. str
  100. (my/replace-regexps-in-string
  101. (replace-regexp-in-string (caar regexps) (cdar regexps) str t)
  102. (cdr regexps))))
  103. #+END_SRC
  104. ** Auth
  105. #+BEGIN_SRC elisp
  106. (setq auth-sources '("~/.authinfo.gpg"))
  107. (use-package auth-source :commands auth-source-search)
  108. (defmacro my/with-credential (query name &rest body)
  109. "Evaluates BODY with NAME bound as the secret from AUTH-SOURCES matching criteria QUERY."
  110. `
  111. (let* ((entry (nth 0 (auth-source-search ,@query)))
  112. (,name (when entry
  113. (let ((secret (plist-get entry :secret)))
  114. (if (functionp secret)
  115. (funcall secret)
  116. secret)))))
  117. ,@body))
  118. #+END_SRC
  119. ** Two Sigma
  120. #+BEGIN_SRC elisp
  121. (defun ts/proxy-on ()
  122. (interactive)
  123. (setq url-proxy-services
  124. '(("http" . "127.0.0.1:20001")
  125. ("https" . "127.0.0.1:20001")
  126. ("no_proxy" . "^.*twosigma\\.com"))))
  127. (defun ts/proxy-off ()
  128. (interactive)
  129. (setq url-proxy-services nil))
  130. #+END_SRC
  131. #+BEGIN_SRC elisp
  132. (setq sourcegraph-url "https://sourcegraph.app.twosigma.com")
  133. (defun ts/sourcegraph-search ()
  134. (interactive)
  135. (call-interactively #'sourcegraph-search))
  136. (defun ts/sourcegraph-browse ()
  137. (interactive)
  138. (call-interactively #'sourcegraph-open-in-browser))
  139. #+END_SRC
  140. #+BEGIN_SRC elisp
  141. (setq ts/search-url "https://search.app.twosigma.com/?q=%s")
  142. (defun ts/search (query)
  143. (interactive "sQuery: ")
  144. (browse-url (format ts/search-url query)))
  145. #+END_SRC
  146. #+BEGIN_SRC elisp
  147. (defun ts/repo/root (&optional dir)
  148. (locate-dominating-file ($cwd dir) ".base_universe"))
  149. (defun ts/repo/codebase (&optional dir)
  150. (locate-dominating-file ($cwd dir) ".git"))
  151. (defun ts/repo/p (&optional dir)
  152. (when (ts/repo/root dir) t))
  153. #+END_SRC
  154. ** Magic functions
  155. #+BEGIN_SRC elisp
  156. (defun shell! (fmt &rest args)
  157. (let* ((cmd (apply #'format (cons fmt args)))
  158. (cmd (format "%s 2>/dev/null" cmd))
  159. (result (shell-command-to-string cmd))
  160. (result (replace-regexp-in-string
  161. "\r?\n$" ""
  162. result)))
  163. (if (equal result "")
  164. nil
  165. result)))
  166. #+END_SRC
  167. #+BEGIN_SRC elisp
  168. (defun locate! (file &optional dir)
  169. (locate-dominating-file ($cwd dir) file))
  170. #+END_SRC
  171. #+BEGIN_SRC elisp
  172. (defun path! (&rest components)
  173. (apply #'f-join components))
  174. (defun home! (&rest components)
  175. (apply #'path! (cons ($home) components)))
  176. #+END_SRC
  177. #+BEGIN_SRC elisp
  178. (defun advice! (fn components)
  179. (apply #'f-join components))
  180. #+END_SRC
  181. ** Magic Vars
  182. #+BEGIN_SRC elisp
  183. (defun $file () buffer-file-name)
  184. (defun $ext (&optional dot) (f-ext ($file) dot))
  185. (defun $cwd (&optional dir)
  186. (if dir
  187. dir
  188. (f-dirname ($file))))
  189. (defun $home ()
  190. (expand-file-name "~/"))
  191. #+END_SRC
  192. * Appearance
  193. Set a nice theme and font.
  194. #+BEGIN_SRC elisp
  195. (setq doom-theme 'doom-catppuccin)
  196. (setq doom-font (font-spec :family "monospace" :size 13)
  197. doom-big-font (font-spec :family "monospace" :size 13)
  198. doom-variable-pitch-font (font-spec :family "sans-serif" :size 13))
  199. #+END_SRC
  200. Sprinkle in a little background transparency. Instead of making the entire frame
  201. transparent (including the text) with =alpha=, we use the =alpha-background=
  202. frame parameter which just landed in the Emacs 29 development branch.
  203. #+BEGIN_SRC elisp
  204. (set-frame-parameter (selected-frame) 'alpha-background 85)
  205. (add-to-list 'default-frame-alist '(alpha-background . 85))
  206. #+END_SRC
  207. * Editing
  208. ** Evil
  209. #+BEGIN_SRC elisp
  210. (setq evil-want-fine-undo t)
  211. #+END_SRC
  212. #+BEGIN_SRC elisp
  213. (defun my/scroll-up ()
  214. (interactive)
  215. (evil-scroll-line-up 2))
  216. (defun my/scroll-down ()
  217. (interactive)
  218. (evil-scroll-line-down 2))
  219. (defun my/scroll-up-bigly ()
  220. (interactive)
  221. (evil-scroll-line-up 5))
  222. (defun my/scroll-down-bigly ()
  223. (interactive)
  224. (evil-scroll-line-down 5))
  225. #+END_SRC
  226. Auto center the point after jumping.
  227. #+BEGIN_SRC elisp
  228. (defmacro my//center-cmd (name &rest body)
  229. `(defun ,name ()
  230. (interactive)
  231. ,@body
  232. (call-interactively #'evil-scroll-line-to-center)))
  233. (my//center-cmd my/jump-forward (better-jumper-jump-forward))
  234. (my//center-cmd my/jump-backward (better-jumper-jump-backward))
  235. (my//center-cmd my/search-next (evil-ex-search-next))
  236. (my//center-cmd my/search-prev (evil-ex-search-previous))
  237. (my//center-cmd my/forward-paragraph (evil-forward-paragraph))
  238. (my//center-cmd my/backward-paragraph (evil-backward-paragraph))
  239. (my//center-cmd my/forward-section-begin (evil-forward-section-begin))
  240. (my//center-cmd my/forward-section-end (evil-forward-section-end))
  241. (my//center-cmd my/backward-section-begin (evil-backward-section-begin))
  242. (my//center-cmd my/backward-section-end (evil-backward-section-end))
  243. #+END_SRC
  244. #+BEGIN_SRC elisp
  245. (defun my/duplicate-and-comment-line ()
  246. (interactive)
  247. (vim! "yyp k gcc j"))
  248. #+END_SRC
  249. #+BEGIN_SRC elisp
  250. (setq search-invisible t)
  251. #+END_SRC
  252. *** Line Numbers
  253. Use relative line numbers in normal mode, and absolute line numbers in insert
  254. mode.
  255. #+BEGIN_SRC emacs-lisp
  256. (defun my/line-numbers-relative ()
  257. (setq display-line-numbers 'relative))
  258. (defun my/line-numbers-absolute ()
  259. (setq display-line-numbers 'absolute))
  260. (add-hook 'evil-insert-state-entry-hook #'my/line-numbers-absolute)
  261. (add-hook 'evil-insert-state-exit-hook #'my/line-numbers-relative)
  262. #+END_SRC
  263. *** Undo Tree
  264. #+BEGIN_SRC elisp
  265. (global-undo-tree-mode)
  266. (add-hook 'evil-local-mode-hook 'turn-on-undo-tree-mode)
  267. #+END_SRC
  268. ** Copilot
  269. Add support for GitHub Copilot ([[*Copilot][keybinds]]).
  270. #+BEGIN_SRC elisp
  271. (use-package copilot
  272. :commands (copilot-complete))
  273. (defun my/copilot-complete ()
  274. (interactive)
  275. (copilot-complete)
  276. (my/hydra-copilot/body)
  277. (copilot-clear-overlay))
  278. (defhydra my/hydra-copilot ()
  279. "Copilot"
  280. ("<return>" copilot-accept-completion "Accept" :color blue )
  281. ("<tab>" copilot-next-completion "Next" )
  282. ("<backtab>" copilot-previous-completion "Prev")
  283. ("<escape>" copilot-clear-overlay "Cancel" :color blue))
  284. #+END_SRC
  285. ** Scratch
  286. Use =lisp-interaction-mode= by default for the scratch buffer.
  287. #+BEGIN_SRC elisp
  288. (setq doom-scratch-initial-major-mode 'lisp-interaction-mode)
  289. #+END_SRC
  290. ** Abbreviations
  291. #+BEGIN_SRC elisp
  292. (use-package abbrev-mode
  293. :hook text-mode)
  294. (setq +abbrev-file (concat doom-user-dir "abbrevs.el"))
  295. (setq abbrev-file-name +abbrev-file)
  296. #+END_SRC
  297. * Keybinds
  298. ** Unmaps
  299. Unmap a bunch of the default keybindings.
  300. #+BEGIN_SRC elisp
  301. #+END_SRC
  302. #+BEGIN_SRC elisp
  303. (map! :leader
  304. ":" nil
  305. "b" nil
  306. "f" nil
  307. "h" nil
  308. "p" nil
  309. "t" nil
  310. "w" nil
  311. "c" nil)
  312. (map! :map evil-org-mode-map
  313. :n "zc" nil)
  314. #+END_SRC
  315. ** Global
  316. *** Font Size
  317. #+BEGIN_SRC elisp
  318. (map!
  319. :desc "Increase font size" :ni "C-=" #'text-scale-increase
  320. :desc "Decrease font size" :ni "C--" #'text-scale-decrease
  321. :desc "Reset font size" :ni "C-+" #'my/text-scale-reset)
  322. (defun my/text-scale-reset ()
  323. (interactive)
  324. (text-scale-set 0))
  325. #+END_SRC
  326. *** Copilot
  327. #+BEGIN_SRC elisp
  328. (map!
  329. :desc "Copilot" :i "C-?" #'my/copilot-complete)
  330. #+END_SRC
  331. *** LSP
  332. #+BEGIN_SRC elisp
  333. (map! :map lsp-mode-map
  334. :desc "Apply code action" :ni "C-/" #'lsp-execute-code-action
  335. :desc "Show definitions" :ni "C-." #'+lookup/definition
  336. :desc "Show references" :ni "C->" #'my/lsp/lookup-references
  337. :desc "Jump backward" :ni "C-," #'better-jumper-jump-backward
  338. :desc "Jump backward" :ni "C-<" #'better-jumper-jump-forward)
  339. (defun my/lsp/lookup-references ()
  340. (interactive)
  341. (lsp-treemacs-references t))
  342. #+END_SRC
  343. *** Minibuffer
  344. #+BEGIN_SRC elisp
  345. (map! :map minibuffer-mode-map
  346. :desc "Next history" "C-j" #'next-history-element
  347. :desc "Prev history" "C-k" #'previous-history-element)
  348. #+END_SRC
  349. *** Files
  350. #+BEGIN_SRC elisp
  351. (map!
  352. :desc "Save file" "C-s" #'save-buffer)
  353. #+END_SRC
  354. *** Evil
  355. #+BEGIN_SRC elisp
  356. (map!
  357. :desc "Scroll up" :ni "C-k" #'my/scroll-up
  358. :desc "Scroll down" :ni "C-j" #'my/scroll-down
  359. :desc "Scroll up bigly" :ni "C-S-k" #'my/scroll-up-bigly
  360. :desc "Scroll down bigly" :ni "C-S-j" #'my/scroll-down-bigly
  361. :desc "Jump forward" :n "C-o" #'my/jump-forward
  362. :desc "Jump backward" :n "C-o" #'my/jump-backward
  363. :desc "Search next" :n "n" #'my/search-next
  364. :desc "Search prev" :n "N" #'my/search-prev
  365. :desc "Forward paragraph" :n "}" #'my/forward-paragraph
  366. :desc "Backward paragraph" :n "{" #'my/backward-paragraph
  367. :desc "Forward section begin" :n "]]" #'my/forward-section-begin
  368. :desc "Forward section end" :n "][" #'my/forward-section-end
  369. :desc "Backward section begin" :n "[]" #'my/backward-section-begin
  370. :desc "Backward section end" :n "[[" #'my/backward-section-end)
  371. #+END_SRC
  372. #+BEGIN_SRC elisp
  373. (map!
  374. :desc "Undo tree visualizer" :n "U" #'undo-tree-visualize)
  375. #+END_SRC
  376. #+BEGIN_SRC elisp
  377. (map!
  378. :desc "Duplicate and comment line" :n "gC" #'my/duplicate-and-comment-line)
  379. #+END_SRC
  380. ** Leader
  381. *** Root
  382. **** Eval
  383. #+BEGIN_SRC elisp
  384. (map! :leader
  385. :desc "M-x" "x" #'counsel-M-x
  386. :desc "M-:" ";" #'pp-eval-expression)
  387. #+END_SRC
  388. **** Files
  389. #+BEGIN_SRC elisp
  390. (map! :leader
  391. :desc "Find file" "." #'counsel-find-file
  392. :desc "Find dir" ">" #'+default/dired
  393. :desc "Find in project" "SPC" #'+ivy/projectile-find-file
  394. :desc "Find in project uncached" "C-SPC" #'my/projectile-find-file-nocache)
  395. (defun my/projectile-find-file-nocache ()
  396. (interactive)
  397. (projectile-invalidate-cache nil)
  398. (+ivy/projectile-find-file))
  399. #+END_SRC
  400. **** Buffers
  401. #+BEGIN_SRC elisp
  402. (map! :leader
  403. :desc "Switch buffer" "," #'+vertico/switch-workspace-buffer
  404. :desc "Switch all buffers" "<" #'consult-buffer)
  405. #+END_SRC
  406. **** Search
  407. #+BEGIN_SRC elisp
  408. (map! :leader
  409. :desc "Search online" "/" #'my/counsel-search)
  410. #+END_SRC
  411. *** b: Buffers
  412. #+BEGIN_SRC elisp
  413. (map! :leader
  414. :prefix ("b" . "buffers")
  415. :desc "Switch buffer" "b" #'consult-buffer
  416. :desc "ibuffer" "i" #'ibuffer
  417. :desc "Kill buffer" "d" #'kill-current-buffer
  418. :desc "Kill all buffers" "D" #'doom/kill-all-buffers
  419. :desc "Rename buffer" "r" #'my/rename-buffer)
  420. #+END_SRC
  421. #+BEGIN_SRC elisp
  422. (defun my/rename-buffer (name)
  423. (interactive (list (read-string "Rename: " (buffer-name))))
  424. (rename-buffer name))
  425. #+END_SRC
  426. *** c: Code
  427. #+BEGIN_SRC elisp
  428. (map! :leader
  429. :prefix ("c" . "code")
  430. :desc "Format region/buffer" "f" #'+format/region-or-buffer
  431. :desc "Format imports" "F" #'lsp-organize-imports
  432. :desc "Rename symbol" "r" #'lsp-rename
  433. :desc "Show errors list" "x" #'+default/diagnostics
  434. :desc "Show errors tree" "X" #'lsp-treemacs-errors-list
  435. :desc "Show symbols tree" "s" #'lsp-treemacs-symbols
  436. :desc "Visit lens" "l" #'lsp-avy-lens
  437. :desc "Restart LSP" "q" #'lsp-restart-workspace)
  438. #+END_SRC
  439. *** f: Files
  440. #+BEGIN_SRC elisp
  441. (map! :leader
  442. :prefix ("f" . "files")
  443. :desc "Recent files" "r" #'consult-recent-file
  444. :desc "Find file" "f" #'counsel-find-file
  445. :desc "Find file as root" "u" #'doom/sudo-find-file
  446. :desc "Find package" "p" #'counsel-find-library
  447. :desc "Copy this file" "c" #'doom/copy-this-file
  448. :desc "Delete this file" "d" #'doom/delete-this-file
  449. :desc "Delete file" "D" #'delete-file
  450. :desc "Move this file" "m" #'doom/move-this-file
  451. :desc "Revert this file" "l" #'revert-buffer
  452. :desc "Copy file path" "y" #'+default/yank-buffer-path
  453. :desc "Copy project file path" "Y" #'+default/yank-buffer-path-relative-to-project
  454. :desc "Open scratch" "x" #'doom/open-scratch-buffer)
  455. #+END_SRC
  456. **** a: Abbrevs
  457. #+BEGIN_SRC emacs-lisp
  458. (map! :leader
  459. :prefix ("f a" . "abbrevs")
  460. :desc "Edit abbrevs" "e" #'my/abbrev-edit
  461. :desc "Reload abbrevs" "r" #'my/abbrev-reload
  462. :desc "Add global abbrev" "a" #'my/abbrev-add-global
  463. :desc "Add mode abbrev" "m" #'my/abbrev-add-mode)
  464. #+END_SRC
  465. #+BEGIN_SRC elisp
  466. (defun my/abbrev-edit ()
  467. (interactive)
  468. (find-file-other-window +abbrev-file))
  469. (defun my/abbrev-reload ()
  470. (interactive)
  471. (read-abbrev-file +abbrev-file))
  472. (defun my/abbrev-save ()
  473. (interactive)
  474. (write-abbrev-file +abbrev-file))
  475. (defun my/abbrev-add-global ()
  476. (interactive)
  477. (call-interactively #'inverse-add-global-abbrev)
  478. (my/abbrev-save))
  479. (defun my/abbrev-add-mode ()
  480. (interactive)
  481. (call-interactively #'inverse-add-mode-abbrev)
  482. (my/abbrev-save))
  483. #+END_SRC
  484. **** e: Emacs Files
  485. #+BEGIN_SRC elisp
  486. (map! :leader
  487. :prefix ("f e" . "emacs")
  488. :desc "Find in config" "f" #'doom/find-file-in-private-config
  489. :desc "Reload config" "r" #'doom/reload
  490. :desc "Edit config" "c" #'my/edit-config
  491. :desc "Edit packages" "p" #'my/edit-packages
  492. :desc "Edit env" "e" #'my/edit-env
  493. :desc "Edit init" "i" #'my/edit-init)
  494. #+END_SRC
  495. #+BEGIN_SRC elisp
  496. (defun my/edit-config ()
  497. (interactive)
  498. (find-file (concat doom-user-dir "config.org")))
  499. (defun my/edit-packages ()
  500. (interactive)
  501. (find-file (concat doom-user-dir "packages.el")))
  502. (defun my/edit-init ()
  503. (interactive)
  504. (find-file (concat doom-user-dir "init.el")))
  505. (defun my/edit-env ()
  506. (interactive)
  507. (find-file (concat doom-user-dir "env.el")))
  508. #+END_SRC
  509. Define a derived mode for editing the literate config so we can specify some
  510. keybindings specific to =config.org=.
  511. #+BEGIN_SRC elisp
  512. (define-derived-mode org-config-mode org-mode "Org config mode")
  513. (add-to-list 'auto-mode-alist '("config\\.org" . org-config-mode))
  514. #+END_SRC
  515. **** s: Snippets
  516. #+BEGIN_SRC emacs-lisp
  517. (map! :leader
  518. :prefix ("f s" . "snippets")
  519. :desc "Find snippet" "f" #'my/yas-find-snippet
  520. :desc "New snippet" "n" #'yas/new-snippet
  521. :desc "Edit snippet" "e" #'my/yas-edit-snippet
  522. :desc "Describe snippets" "d" #'yas/describe-tables
  523. :desc "Reload snippets" "r" #'yas/reload-all
  524. :desc "Browse docs" "?" #'my/yas-browse-docs)
  525. #+END_SRC
  526. Add a command to open the YASnippet docs.
  527. #+BEGIN_SRC elisp
  528. (defun my/yas-browse-docs ()
  529. (interactive)
  530. (browse-url "https://joaotavora.github.io/yasnippet"))
  531. #+END_SRC
  532. #+BEGIN_SRC elisp
  533. (defun my/yas-edit-snippet ()
  534. (interactive)
  535. (call-interactively #'yas/visit-snippet-file))
  536. (defun my/yas-find-snippet ()
  537. (interactive)
  538. (counsel-find-file nil +snippets-dir))
  539. #+END_SRC
  540. *** h: Help
  541. #+BEGIN_SRC elisp
  542. (map! :leader
  543. :prefix ("h" . "help")
  544. :desc "Apropos" "/" #'consult-apropos
  545. :desc "Apropos docs" "?" #'apropos-documentation
  546. :desc "Help at point" "p" #'helpful-at-point
  547. :desc "Help info" "h" #'info
  548. :desc "Help for help" "H" #'help-for-help
  549. :desc "Describe mode" "m" #'describe-mode
  550. :desc "Describe minor modes" "M" #'doom/describe-active-minor-mode
  551. :desc "Describe function" "f" #'counsel-describe-function
  552. :desc "Describe function key" "F" #'where-is
  553. :desc "Describe variable" "v" #'counsel-describe-variable
  554. :desc "Describe custom variable" "V" #'doom/help-custom-variable
  555. :desc "Describe command" "x" #'helpful-command
  556. :desc "Describe key" "k" #'describe-key-briefly
  557. :desc "Describe key fully" "K" #'describe-key
  558. :desc "Describe char" "'" #'describe-char
  559. :desc "Describe coding system" "\"" #'describe-coding-system
  560. :desc "Describe input method" "i" #'describe-input-method
  561. :desc "Emacs manual" "e" #'info-emacs-manual
  562. :desc "ASCII table" "a" #'my/ascii-table
  563. :desc "View messages" "e" #'view-echo-area-messages
  564. :desc "View keystrokes" "l" #'view-lossage)
  565. #+END_SRC
  566. **** a: Ascii Table
  567. #+BEGIN_SRC elisp
  568. (defface my/ascii-table-highlight-face
  569. '((t (:foreground "pink")))
  570. "Face for highlighting ASCII chars.")
  571. (defun my/ascii-table ()
  572. "Display basic ASCII table (0 thru 128)."
  573. (interactive)
  574. (pop-to-buffer "*ASCII*")
  575. (erase-buffer)
  576. (setq buffer-read-only nil)
  577. (my/buffer-local-set-key "q" #'+popup/quit-window)
  578. (setq lower32 '("nul" "soh" "stx" "etx" "eot" "enq" "ack" "bel"
  579. "bs" "ht" "nl" "vt" "np" "cr" "so" "si"
  580. "dle" "dc1" "dc2" "dc3" "dc4" "nak" "syn" "etb"
  581. "can" "em" "sub" "esc" "fs" "gs" "rs" "us"))
  582. (save-excursion (let ((i -1))
  583. (insert " Hex Dec Char | Hex Dec Char | Hex Dec Char | Hex Dec Char\n")
  584. (insert " ---------------+-----------------+-----------------+----------------\n")
  585. (while (< i 31)
  586. (insert (format "%4x %4d %4s | %4x %4d %4s | %4x %4d %4s | %4x %4d %4s\n"
  587. (setq i (+ 1 i)) i (elt lower32 i)
  588. (setq i (+ 32 i)) i (single-key-description i)
  589. (setq i (+ 32 i)) i (single-key-description i)
  590. (setq i (+ 32 i)) i (single-key-description i)))
  591. (overlay-put (make-overlay (- (point) 4) (- (point) 1)) 'face 'my/ascii-table-highlight-face)
  592. (overlay-put (make-overlay (- (point) 22) (- (point) 19)) 'face 'my/ascii-table-highlight-face)
  593. (overlay-put (make-overlay (- (point) 40) (- (point) 37)) 'face 'my/ascii-table-highlight-face)
  594. (overlay-put (make-overlay (- (point) 58) (- (point) 55)) 'face 'my/ascii-table-highlight-face)
  595. (setq i (- i 96))
  596. ))))
  597. (set-popup-rule! "^\\*ASCII"
  598. :side 'right
  599. :select t
  600. :width 70)
  601. #+END_SRC
  602. **** d: Doom
  603. #+BEGIN_SRC elisp
  604. (map! :leader
  605. :prefix ("h d" . "doom")
  606. :desc "Doom manual" "d" #'doom/help
  607. :desc "Doom FAQ" "f" #'doom/help-faq
  608. :desc "Doom modules" "m" #'doom/help-modules
  609. :desc "Doom news" "n" #'doom/help-news
  610. :desc "Doom help search" "/" #'doom/help-search-headings
  611. :desc "Doom version" "v" #'doom/version
  612. :desc "Doom package configuration" "p" #'doom/help-package-config
  613. :desc "Doom sandbox" "x" #'doom/sandbox)
  614. #+END_SRC
  615. *** l: Ligma
  616. #+BEGIN_SRC elisp
  617. (map! :leader
  618. :prefix ("l" . "ligma")
  619. :desc "Search" "s" #'ts/search
  620. :desc "Sourcegraph search" "g" #'ts/sourcegraph-search
  621. :desc "Sourcegraph browse" "G" #'ts/sourcegraph-browse)
  622. #+END_SRC
  623. *** TODO o: Open
  624. *** p: Projects
  625. #+BEGIN_SRC elisp
  626. (map! :leader
  627. :prefix ("p" . "projects")
  628. :desc "Switch project" "p" #'my/projectile-switch-project
  629. :desc "Add new project" "a" #'projectile-add-known-project
  630. :desc "Remove project" "d" #'projectile-remove-known-project
  631. :desc "Find in project root" "." #'counsel-projectile-find-file
  632. :desc "Search in project" "/" #'+default/search-project
  633. :desc "Invalidate project cache" "i" #'projectile-invalidate-cache
  634. :desc "Run cmd in project root" "!" #'projectile-run-shell-command-in-root
  635. :desc "Run async cmd in project root" "&" #'projectile-run-async-shell-command-in-root)
  636. (defun my/projectile-find-in-root ()
  637. (interactive)
  638. (counsel-find-file nil projectile-project-root))
  639. #+END_SRC
  640. *** t: Toggle
  641. #+BEGIN_SRC elisp
  642. (map! :leader
  643. :prefix ("t" . "toggle")
  644. ;; Wrap
  645. :desc "Auto Wrap" "a" #'auto-fill-mode
  646. :desc "Wrap Indicator" "c" #'global-display-fill-column-indicator-mode
  647. :desc "Wrap Column" "C" #'set-fill-column
  648. :desc "Line Wrap" "w" #'visual-line-mode
  649. ;; Modes
  650. :desc "Flycheck" "f" #'flycheck-mode
  651. :desc "Keycast" "k" #'keycast-mode
  652. ;; Files
  653. :desc "Read-only" "r" #'read-only-mode)
  654. #+END_SRC
  655. #+BEGIN_SRC elisp
  656. (defun my/auto-fill-mode (cols)
  657. (interactive))
  658. #+END_SRC
  659. *** w: Window
  660. #+BEGIN_SRC elisp
  661. (map! :leader
  662. :prefix-map ("w" . "window")
  663. ;; Navigation
  664. :desc "Go..." "w" #'ace-window
  665. :desc "Go left" "h" #'evil-window-left
  666. :desc "Go down" "j" #'evil-window-down
  667. :desc "Go up" "k" #'evil-window-up
  668. :desc "Go right" "l" #'evil-window-right
  669. :desc "Go other" "o" #'other-window
  670. ;; Layout
  671. :desc "Move left" "H" #'+evil/window-move-left
  672. :desc "Move down" "J" #'+evil/window-move-down
  673. :desc "Move up" "K" #'+evil/window-move-up
  674. :desc "Move right" "L" #'+evil/window-move-right
  675. ;; Splits
  676. :desc "VSplit" "=" #'+evil/window-vsplit-and-follow
  677. :desc "HSplit" "-" #'+evil/window-split-and-follow
  678. :desc "Tear off" "t" #'tear-off-window
  679. ;; History
  680. :desc "Undo" "u" #'winner-undo
  681. :desc "Redo" "U" #'winner-redo
  682. ;; Misc
  683. :desc "Resize..." "r" #'my/hydra-window-resize/body
  684. :desc "Rotate..." "R" #'my/hydra-window-rotate/body
  685. :desc "Balance" "b" #'balance-windows
  686. ;; Management
  687. :desc "Kill window" "d" #'+workspace/close-window-or-workspace)
  688. ;; TODO: Maybe check out:
  689. ;; evil-window-mru
  690. #+END_SRC
  691. #+BEGIN_SRC elisp
  692. (setq my/window-resize-step 3)
  693. (defun my/window-increase-height ()
  694. (interactive)
  695. (evil-window-increase-height my/window-resize-step))
  696. (defun my/window-decrease-height ()
  697. (interactive)
  698. (evil-window-decrease-height my/window-resize-step))
  699. (defun my/window-increase-width ()
  700. (interactive)
  701. (evil-window-increase-width my/window-resize-step))
  702. (defun my/window-decrease-width ()
  703. (interactive)
  704. (evil-window-decrease-width my/window-resize-step))
  705. (defhydra my/hydra-window-resize ()
  706. "Resize window"
  707. ("k" my/window-increase-height "++Height")
  708. ("j" my/window-decrease-height "--Height")
  709. ("h" my/window-decrease-width "--Width")
  710. ("l" my/window-increase-width "++Width")
  711. ("ESC" nil "Quit" :color blue))
  712. #+END_SRC
  713. #+BEGIN_SRC elisp
  714. (defhydra my/hydra-window-rotate ()
  715. "Rotate window"
  716. ("h" +evil/window-move-left "Move left")
  717. ("j" +evil/window-move-down "Move down")
  718. ("k" +evil/window-move-up "Move up")
  719. ("l" +evil/window-move-right "Move right")
  720. ("H" evil-window-move-far-left "Move far left")
  721. ("J" evil-window-rotate-downwards "Rotate Down")
  722. ("K" evil-window-rotate-upwards "Rotate Up")
  723. ("L" evil-window-move-far-right "Move far right"))
  724. #+END_SRC
  725. ** Local Leader
  726. *** Org Config
  727. #+BEGIN_SRC elisp
  728. (map! :map org-config-mode-map
  729. :localleader
  730. :v :desc "Eval Region" "e" #'eval-region
  731. :n :desc "Eval Source" "e" #'my/org-config-eval-source)
  732. (defun my/org-config-eval-source ()
  733. (interactive)
  734. (org-ctrl-c-ctrl-c)
  735. (org-babel-remove-result))
  736. #+END_SRC
  737. *** Rust
  738. #+BEGIN_SRC elisp
  739. ;; (map! :map rustic-mode-map
  740. ;; :localleader
  741. ;; "b" nil
  742. ;; "t" nil)
  743. ;; (map! :map rustic-mode-map
  744. ;; :localleader
  745. ;; :desc "Edit Cargo.toml" "t" #'my/rust/edit-cargo-toml)
  746. ;; (map! :map rustic-mode-map
  747. ;; :leader
  748. ;; :prefix ("c" . "code")
  749. ;; :desc "Expand macro" "m" #'lsp-rust-analyzer-expand-macro
  750. ;; :desc "Open docs" "h" #'lsp-rust-analyzer-open-external-docs)
  751. ;; (map! :map rustic-mode-map
  752. ;; :localleader
  753. ;; :prefix ("b" . "build")
  754. ;; :desc "Build" "b" #'rustic-cargo-check
  755. ;; :desc "Check" "c" #'rustic-cargo-check
  756. ;; :desc "Debug" "d" #'my/rust/dap-hydra/body
  757. ;; :desc "Run" "r" #'rustic-cargo-run
  758. ;; :desc "Bench" "B" #'rustic-cargo-bench
  759. ;; :desc "Test current" "t" #'rustic-cargo-current-test
  760. ;; :desc "Test all" "T" #'rustic-cargo-test)
  761. (map! :map rustic-mode-map
  762. :desc "Pluralize import" "," #'my/rust/import-pluralize
  763. :desc "Singularize import" "<backspace>" #'my/rust/import-singularize
  764. :desc "Singularize import" "C-<backspace>" #'my/rust/import-c-singularize
  765. :desc "Singularize import" "C-<delete>" #'my/rust/import-rev-singularize)
  766. #+END_SRC
  767. **** Debugging
  768. #+BEGIN_SRC elisp
  769. (defhydra my/rust/dap-hydra (:color pink :hint nil :foreign-keys run)
  770. "
  771. ^Stepping^ ^Switch^ ^Breakpoints^ ^Debug^ ^Eval
  772. ^^^^^^^^----------------------------------------------------------------------------------------------------------------
  773. _n_: Next _ss_: Session _bb_: Toggle _dd_: Debug binary _ee_: Eval
  774. _i_: Step in _st_: Thread _bd_: Delete _dr_: Restart debugging _es_: Eval thing at point
  775. _o_: Step out _sf_: Stack frame _ba_: Add _ea_: Add expression
  776. _c_: Continue _su_: Up stack frame _bc_: Set condition
  777. _Q_: Disconnect _sd_: Down stack frame _bh_: Set hit count
  778. _sl_: List locals _bl_: Set log message
  779. _sb_: List breakpoints
  780. _sS_: List sessions
  781. "
  782. ("n" dap-next)
  783. ("i" dap-step-in)
  784. ("o" dap-step-out)
  785. ("c" dap-continue)
  786. ("r" dap-restart-frame)
  787. ("ss" dap-switch-session)
  788. ("st" dap-switch-thread)
  789. ("sf" dap-switch-stack-frame)
  790. ("su" dap-up-stack-frame)
  791. ("sd" dap-down-stack-frame)
  792. ("sl" dap-ui-locals)
  793. ("sb" dap-ui-breakpoints)
  794. ("sS" dap-ui-sessions)
  795. ("bb" dap-breakpoint-toggle)
  796. ("ba" dap-breakpoint-add)
  797. ("bd" dap-breakpoint-delete)
  798. ("bc" dap-breakpoint-condition)
  799. ("bh" dap-breakpoint-hit-condition)
  800. ("bl" dap-breakpoint-log-message)
  801. ("dd" my/rust/debug-binary)
  802. ("dr" dap-debug-restart)
  803. ("ee" dap-eval)
  804. ("ea" dap-ui-expressions-add)
  805. ("es" dap-eval-thing-at-point)
  806. ("q" nil "quit" :color blue)
  807. ("Q" dap-disconnect :color red))
  808. #+END_SRC
  809. **** Cargo.toml
  810. #+BEGIN_SRC elisp
  811. (map! :map cargo-toml-mode-map
  812. :localleader
  813. :desc "Add crate (semver)" "a" #'my/rust/cargo-toml-add-crate-semver
  814. :desc "Add crate (exact)" "A" #'my/rust/cargo-toml-add-crate)
  815. #+END_SRC
  816. ** Modes
  817. *** Evil
  818. **** z
  819. #+BEGIN_SRC elisp
  820. (map! :prefix "z"
  821. :desc "Kill buffer" :n "x" #'kill-current-buffer
  822. :desc "Kill window" :n "c" #'+workspace/close-window-or-workspace)
  823. #+END_SRC
  824. **** g
  825. **** [
  826. #+BEGIN_SRC elisp
  827. (map! :prefix "["
  828. :desc "Start of fn" :n "f" #'beginning-of-defun)
  829. (map! :prefix "]"
  830. :desc "End of fn" :n "f" #'end-of-defun)
  831. #+END_SRC
  832. *** Dap
  833. #+BEGIN_SRC elisp
  834. #+END_SRC
  835. * Languages
  836. ** Rust
  837. *** General
  838. #+BEGIN_SRC elisp
  839. (add-to-list 'projectile-globally-ignored-files "Cargo.lock")
  840. #+END_SRC
  841. #+BEGIN_SRC elisp
  842. (setq lsp-rust-analyzer-inlay-hints-mode t)
  843. (setq lsp-rust-analyzer-server-display-inlay-hints t)
  844. (setq lsp-rust-analyzer-display-closure-return-type-hints t)
  845. (setq lsp-rust-analyzer-display-lifetime-elision-hints-enable "skip_trivial")
  846. (setq lsp-rust-analyzer-display-lifetime-elision-hints-use-parameter-names nil)
  847. (setq lsp-rust-analyzer-display-chaining-hints t)
  848. (setq lsp-rust-analyzer-display-reborrow-hints t)
  849. #+END_SRC
  850. *** Editing
  851. When editing a list of "use" imports, automatically add and remove braces when typing or removing commas
  852. #+BEGIN_SRC elisp
  853. (rx-let ((crate (or alphanumeric "_" "*")))
  854. (setq my//rust/import-singular-rx
  855. ;; use foo::bar::baz;
  856. (rx "use "
  857. (+ (+ crate) "::")
  858. (+ crate)
  859. (? ";") line-end))
  860. (setq my//rust/import-plural-rx
  861. ;; use foo::bar::baz::{qux::quo, };
  862. (rx "use "
  863. (+ (+ crate) "::")
  864. "{" (* (+ crate) "::") (+ crate) "," (* whitespace) "}"
  865. (? ";") line-end))
  866. (setq my//rust/import-plural-rev-rx
  867. ;; use foo::bar::baz::{, qux::quo};
  868. (rx "use "
  869. (+ (+ crate) "::")
  870. "{," (* whitespace) (* (+ crate) "::") (+ crate) "}"
  871. (? ";") line-end)))
  872. (defun my/rust/import-pluralize ()
  873. "Convert a singular import into a brace-wrapped plural import."
  874. (interactive)
  875. (if (and
  876. (my/insert-mode-p)
  877. (my/line-match-p my//rust/import-singular-rx))
  878. (vim! "ESC vb S} f} i,")
  879. (insert ",")))
  880. (defun my/rust/import-singularize ()
  881. "Convert a brace-wrapped plural import into a singular import."
  882. (interactive)
  883. (if (and
  884. (my/insert-mode-p)
  885. (my/line-match-p my//rust/import-plural-rx))
  886. (vim! "ESC l dF, ds} $i")
  887. (evil-delete-backward-char-and-join 1)))
  888. (defun my/rust/import-c-singularize ()
  889. "Convert a brace-wrapped plural import into a singular import."
  890. (interactive)
  891. (if (and
  892. (my/insert-mode-p)
  893. (my/line-match-p my//rust/import-plural-rx))
  894. (vim! "ESC l dF, ds} $i")
  895. (backward-kill-word 1)))
  896. (defun my/rust/import-rev-singularize ()
  897. "Convert a brace-wrapped plural import into a singular import."
  898. (interactive)
  899. (if (and
  900. (my/insert-mode-p)
  901. (my/line-match-p my//rust/import-plural-rev-rx))
  902. (vim! "ESC ds} dw $i")
  903. (kill-word 1)))
  904. #+END_SRC
  905. *** Debugging
  906. #+BEGIN_SRC elisp
  907. (defun my/rust/debug-config (args)
  908. (append
  909. `(:type "lldb-vscode"
  910. ;; `(:type "lldb"
  911. :request "launch"
  912. :dap-server-path ,(list (executable-find "lldb-vscode"))
  913. ;; :dap-server-path ,(list (executable-find "rust-lldb"))
  914. ,@args)))
  915. ;; use a::TestThin
  916. ;; (:MIMode "gdb"
  917. ;; :miDebuggerPath "gdb"
  918. ;; :stopAtEntry t
  919. ;; :externalConsole
  920. ;; :json-false
  921. ;; :type "cppdbg"
  922. ;; :request "launch"
  923. ;; :name "test test2"
  924. ;; :args ["test2" "--exact" "--nocapture"]
  925. ;; :cwd "/home/lain/Code/test/rust/debug"
  926. ;; :sourceLanguages ["rust"]
  927. ;; :program "/home/lain/Code/test/rust/debug/target/debug/deps/...")
  928. ;; (require 'dap-cpptools)
  929. (defun my/rust/debug-binary (args)
  930. (interactive "sArgs: ")
  931. (let* ((root (projectile-project-root))
  932. (name (projectile-project-name))
  933. (target (concat root "target/debug/" name)))
  934. ;; (rustic-cargo-build)
  935. (dap-debug
  936. (my/rust/debug-config
  937. `(:program ,target
  938. :cwd ,root
  939. :args ,(apply #'vector (split-string-and-unquote args)))))))
  940. (defun my/rust/debug-lsp-runnable (runnable)
  941. "Select and debug a RUNNABLE action."
  942. (interactive (list (lsp-rust-analyzer--select-runnable)))
  943. (-let (((&rust-analyzer:Runnable
  944. :args (&rust-analyzer:RunnableArgs :cargo-args :workspace-root? :executable-args)
  945. :label) runnable))
  946. (pcase (aref cargo-args 0)
  947. ("run" (aset cargo-args 0 "build"))
  948. ("test" (when (-contains? (append cargo-args ()) "--no-run")
  949. (cl-callf append cargo-args (list "--no-run")))))
  950. (->> (append (list (executable-find "cargo"))
  951. cargo-args
  952. (list "--message-format=json"))
  953. (s-join " ")
  954. (shell-command-to-string)
  955. (s-lines)
  956. (-keep (lambda (s)
  957. (condition-case nil
  958. (-let* ((json-object-type 'plist)
  959. ((msg &as &plist :reason :executable) (json-read-from-string s)))
  960. (when (and executable (string= "compiler-artifact" reason))
  961. executable))
  962. (error))))
  963. (funcall
  964. (lambda (artifact-spec)
  965. (pcase artifact-spec
  966. (`() (user-error "No compilation artifacts or obtaining the runnable artifacts failed"))
  967. (`(,spec) spec)
  968. (_ (user-error "Multiple compilation artifacts are not supported")))))
  969. (list :name label
  970. :args executable-args
  971. :cwd workspace-root?
  972. ;; :sourceLanguages ["rust"]
  973. :stopAtEntry t
  974. :stopAtEntry :json-true
  975. :externalConsole :json-false
  976. :program)
  977. (my/rust/debug-config)
  978. (dap-debug))))
  979. (advice-add #'lsp-rust-analyzer-debug :override #'my/rust/debug-lsp-runnable)
  980. #+END_SRC
  981. *** Cargo.toml
  982. Define a derived mode for =conf-toml-mode= so we can specify some
  983. keybindings specific to =Cargo.toml= files.
  984. #+BEGIN_SRC elisp
  985. (define-derived-mode cargo-toml-mode conf-toml-mode "Cargo.toml mode")
  986. (add-to-list 'auto-mode-alist '("Cargo\\.toml" . cargo-toml-mode))
  987. #+END_SRC
  988. Define a wrapper function for visiting the closest Cargo.toml in a new window.
  989. #+BEGIN_SRC elisp
  990. (defun my/rust/edit-cargo-toml ()
  991. (interactive)
  992. (lsp-rust-analyzer-open-cargo-toml))
  993. #+END_SRC
  994. Define a helper for pulling the latest versions of crates from crates.io
  995. #+BEGIN_SRC elisp :lexical t
  996. (defun my/rust/get-latest-crate-version (crate callback)
  997. (request! (format "https://crates.io/api/v1/crates/%s/versions" crate)
  998. (:type "GET" :parser 'json-read)
  999. (lambda (data)
  1000. (let* ((versions (alist-get 'versions data))
  1001. (target (elt versions 0))
  1002. (num (alist-get 'num target)))
  1003. (funcall callback num)))
  1004. (lambda ()
  1005. (message "Crate not found: %s" crate))))
  1006. (defun my/rust/cargo-toml-add-crate (crate)
  1007. "Insert `crate = version` with the latest available version of a crate."
  1008. (interactive "sCrate: ")
  1009. (my/rust/get-latest-crate-version
  1010. crate
  1011. (lambda (version)
  1012. (insert (format "%s = \"%s\"" crate version)))))
  1013. (defun my/rust/cargo-toml-add-crate-semver (crate)
  1014. "Insert `crate = version` with the latest available version of a crate.
  1015. Use any semver compatible version with either the current major release,
  1016. or the minor release if the major version is still 0."
  1017. (interactive "sCrate: ")
  1018. (my/rust/get-latest-crate-version
  1019. crate
  1020. (lambda (version)
  1021. (let* ((parts (split-string version "\\."))
  1022. (major (nth 0 parts))
  1023. (minor (nth 1 parts))
  1024. (patch (nth 2 parts))
  1025. (semver (if (equal major "0")
  1026. (format "%s.%s" major minor)
  1027. (format "%s" major))))
  1028. (insert (format "%s = \"%s\"" crate semver))))))
  1029. #+END_SRC
  1030. *** Lisp
  1031. #+BEGIN_SRC elisp
  1032. (defun my/rust/cargo-toml (&optional dir)
  1033. (path! (locate! "Cargo.toml" dir) "Cargo.toml"))
  1034. (defun my/rust/workspace-root (&optional dir)
  1035. (shell! "%s | jq -r '.workspace_root'"
  1036. (cargo! "metadata --no-deps --format-version 1" dir)))
  1037. (defun cargo! (cmd &optional dir)
  1038. (format "cargo %s --manifest-path \"%s\""
  1039. cmd
  1040. (my/rust/cargo-toml dir)))
  1041. #+END_SRC
  1042. ** Go
  1043. *** Debugging
  1044. Setup: run =M-x dap-go-setup=
  1045. * Tools
  1046. ** Org
  1047. ** Projectile
  1048. #+BEGIN_SRC elisp
  1049. ;; (setq projectile-project-search-path
  1050. ;; '("~/Code"))
  1051. (defun my/project-ignored-p (root)
  1052. (or (doom-project-ignored-p root)
  1053. (f-descendant-of-p root (home! ".rustup"))
  1054. (f-descendant-of-p root "/opt/ts/fuse/artfs_mounts")
  1055. (f-descendant-of-p root "/home/tsdist/vats_deployments")))
  1056. (setq projectile-ignored-project-function #'my/project-ignored-p)
  1057. (defun my/projectile-switch-project ()
  1058. (interactive)
  1059. ;; Prune projects which no longer exist
  1060. (when (boundp 'projectile-known-projects)
  1061. (dolist (project projectile-known-projects)
  1062. (unless (f-dir-p project)
  1063. (projectile-remove-known-project project))))
  1064. (call-interactively #'counsel-projectile-switch-project))
  1065. #+END_SRC
  1066. ** LSP
  1067. #+BEGIN_SRC elisp
  1068. (setq lsp-ui-doc-show-with-mouse t)
  1069. (setq lsp-headerline-breadcrumb-enable t)
  1070. (setq lsp-headerline-breadcrumb-segments '(symbols))
  1071. #+END_SRC
  1072. #+BEGIN_SRC elisp
  1073. (defun my/lsp-find-root (&rest args)
  1074. (or
  1075. (pcase ($ext t)
  1076. (".rs" (my/rust/workspace-root))
  1077. (_ nil))))
  1078. (advice-add 'lsp--find-root-interactively :before-until #'my/lsp-find-root)
  1079. (defun my/lsp-buffer-killed ()
  1080. (when (bound-and-true-p lsp-mode)
  1081. (let ((root (lsp-find-session-folder (lsp-session) ($cwd))))
  1082. ;; If we're in an ignored project, remove it from the LSP session
  1083. (when (my/project-ignored-p root)
  1084. (lsp-workspace-folders-remove root)))))
  1085. (add-hook 'kill-buffer-hook #'my/lsp-buffer-killed)
  1086. #+END_SRC
  1087. ** Counsel Search
  1088. #+BEGIN_SRC elisp
  1089. (defun my/counsel-search ()
  1090. (interactive)
  1091. (unless (boundp 'my/kagi-found)
  1092. (my/with-credential
  1093. (:host "kagi.com") token
  1094. (if token
  1095. (progn
  1096. (setq my/kagi-found (if token t nil))
  1097. (setq counsel-search-engines-alist
  1098. `((kagi
  1099. "https://duckduckgo.com/ac/"
  1100. ,(format "https://kagi.com/search?token=%s&q=" token)
  1101. counsel--search-request-data-ddg)))
  1102. (setq counsel-search-engine 'kagi))
  1103. (warn "Token for kagi.com not found in authinfo. Falling back to default search engine."))))
  1104. (call-interactively #'counsel-search))
  1105. #+END_SRC
  1106. ** Keycast
  1107. #+BEGIN_SRC elisp
  1108. (after! keycast
  1109. (define-minor-mode keycast-mode
  1110. "Show current command and its key binding in the mode line."
  1111. :global t
  1112. (if keycast-mode
  1113. (progn
  1114. (add-to-list 'global-mode-string '("" keycast-mode-line))
  1115. (add-hook 'pre-command-hook 'keycast--update t))
  1116. (progn
  1117. (setq global-mode-string (delete '("" keycast-mode-line) global-mode-string))
  1118. (remove-hook 'pre-command-hook 'keycast--update))))
  1119. (dolist (input '(self-insert-command
  1120. org-self-insert-command))
  1121. (add-to-list 'keycast-substitute-alist `(,input nil)))
  1122. (dolist (event '(mouse-event-p
  1123. mouse-movement-p
  1124. mwheel-scroll
  1125. lsp-ui-doc--handle-mouse-movement
  1126. ignore))
  1127. (add-to-list 'keycast-substitute-alist `(,event nil))))
  1128. #+END_SRC
  1129. ** SourceGraph
  1130. #+BEGIN_SRC elisp
  1131. (use-package sourcegraph
  1132. :hook (prog-mode . sourcegraph-mode))
  1133. (setq sourcegraph-url "https://sourcegraph.app.twosigma.com")
  1134. #+END_SRC
  1135. ** Rmsbolt
  1136. * Apps
  1137. ** Emacs Everywhere
  1138. #+BEGIN_SRC elisp
  1139. (load! "lisp/emacs-everywhere.el")
  1140. (setq emacs-everywhere-paste-command '("xdotool" "key" "--clearmodifiers" "ctrl+v"))
  1141. (setq emacs-everywhere-frame-parameters
  1142. '((title . "Emacs Everywhere")
  1143. (width . 120)
  1144. (height . 36)))
  1145. #+END_SRC