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.

1057 line
35KB

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