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.

1040 lines
34KB

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