From d88fb3194f2a50efa6d407e85d47d14da3700ff3 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Thu, 29 Mar 2018 18:10:07 -0400 Subject: Initial commit --- +bindings.el | 1026 ++++++++++++++++++++++++++++++ +commands.el | 119 ++++ .gitignore | 2 + autoload/evil.el | 37 ++ autoload/hlissner.el | 53 ++ config.el | 409 ++++++++++++ init.el | 247 +++++++ packages.el | 58 ++ slack-snippets.el | 216 +++++++ snippets/haskell-mode/benchmark-module | 26 + snippets/haskell-mode/header | 6 + snippets/haskell-mode/hedgehog-generator | 8 + snippets/haskell-mode/hedgehog-property | 9 + snippets/haskell-mode/lens.field | 7 + snippets/haskell-mode/module | 32 + snippets/haskell-mode/test-module | 21 + snippets/haskell-mode/undefined | 6 + snippets/org-mode/date | 5 + snippets/org-mode/date-time | 5 + snippets/org-mode/nologdone | 5 + snippets/org-mode/source-block | 8 + snippets/snippet-mode/indent | 5 + snippets/text-mode/date | 5 + splitjoin.el | 192 ++++++ tests/splitjoin_test.el | 68 ++ themes/grfn-solarized-light-theme.el | 85 +++ utils.el | 92 +++ 27 files changed, 2752 insertions(+) create mode 100644 +bindings.el create mode 100644 +commands.el create mode 100644 .gitignore create mode 100644 autoload/evil.el create mode 100644 autoload/hlissner.el create mode 100644 config.el create mode 100644 init.el create mode 100644 packages.el create mode 100644 slack-snippets.el create mode 100644 snippets/haskell-mode/benchmark-module create mode 100644 snippets/haskell-mode/header create mode 100644 snippets/haskell-mode/hedgehog-generator create mode 100644 snippets/haskell-mode/hedgehog-property create mode 100644 snippets/haskell-mode/lens.field create mode 100644 snippets/haskell-mode/module create mode 100644 snippets/haskell-mode/test-module create mode 100644 snippets/haskell-mode/undefined create mode 100644 snippets/org-mode/date create mode 100644 snippets/org-mode/date-time create mode 100644 snippets/org-mode/nologdone create mode 100644 snippets/org-mode/source-block create mode 100644 snippets/snippet-mode/indent create mode 100644 snippets/text-mode/date create mode 100644 splitjoin.el create mode 100644 tests/splitjoin_test.el create mode 100644 themes/grfn-solarized-light-theme.el create mode 100644 utils.el diff --git a/+bindings.el b/+bindings.el new file mode 100644 index 0000000000..6609c9010c --- /dev/null +++ b/+bindings.el @@ -0,0 +1,1026 @@ +;; private/grfn/+bindings.el -*- lexical-binding: t; -*- + +(load! utils) +(require 'f) + +(defmacro find-file-in! (path &optional project-p) + "Returns an interactive function for searching files." + `(lambda () (interactive) + (let ((default-directory ,path)) + (call-interactively + ',(command-remapping + (if project-p + #'projectile-find-file + #'find-file)))))) + +(defun dired-mode-p () (eq 'dired-mode major-mode)) + +(defun grfn/dired-minus () + (interactive) + (if (dired-mode-p) + (dired-up-directory) + (when buffer-file-name + (-> (buffer-file-name) + (f-dirname) + (dired))))) + +(defmacro define-move-and-insert + (name &rest body) + `(defun ,name (count &optional vcount skip-empty-lines) + ;; Following interactive form taken from the source for `evil-insert' + (interactive + (list (prefix-numeric-value current-prefix-arg) + (and (evil-visual-state-p) + (memq (evil-visual-type) '(line block)) + (save-excursion + (let ((m (mark))) + ;; go to upper-left corner temporarily so + ;; `count-lines' yields accurate results + (evil-visual-rotate 'upper-left) + (prog1 (count-lines evil-visual-beginning evil-visual-end) + (set-mark m))))) + (evil-visual-state-p))) + (atomic-change-group + ,@body + (evil-insert count vcount skip-empty-lines)))) + +(define-move-and-insert grfn/insert-at-sexp-end + (when (not (equal (get-char) "(")) + (backward-up-list)) + (forward-sexp) + (backward-char)) + +(define-move-and-insert grfn/insert-at-sexp-start + (backward-up-list) + (forward-char)) + +(define-move-and-insert grfn/insert-at-form-start + (backward-sexp) + (backward-char) + (insert " ")) + +(define-move-and-insert grfn/insert-at-form-end + (forward-sexp) + (insert " ")) + +(load! splitjoin) + +(defun +hlissner/install-snippets () + "Install my snippets from https://github.com/hlissner/emacs-snippets into +private/hlissner/snippets." + (interactive) + (doom-fetch :github "hlissner/emacs-snippets" + (expand-file-name "snippets" (doom-module-path :private 'hlissner)))) + +(defun +hlissner/yank-buffer-filename () + "Copy the current buffer's path to the kill ring." + (interactive) + (if-let* ((filename (or buffer-file-name (bound-and-true-p list-buffers-directory)))) + (message (kill-new (abbreviate-file-name filename))) + (error "Couldn't find filename in current buffer"))) + +(defmacro +hlissner-def-finder! (name dir) + "Define a pair of find-file and browse functions." + `(progn + (defun ,(intern (format "+hlissner/find-in-%s" name)) () + (interactive) + (let ((default-directory ,dir) + projectile-project-name + projectile-require-project-root + projectile-cached-buffer-file-name + projectile-cached-project-root) + (call-interactively (command-remapping #'projectile-find-file)))) + (defun ,(intern (format "+hlissner/browse-%s" name)) () + (interactive) + (let ((default-directory ,dir)) + (call-interactively (command-remapping #'find-file)))))) + +(+hlissner-def-finder! templates +file-templates-dir) +(+hlissner-def-finder! snippets +grfn-snippets-dir) +(+hlissner-def-finder! dotfiles (expand-file-name ".dotfiles" "~")) +(+hlissner-def-finder! doomd (expand-file-name ".doom.d" "~")) +(+hlissner-def-finder! notes +org-dir) + +;;; + +(map! + [remap evil-jump-to-tag] #'projectile-find-tag + [remap find-tag] #'projectile-find-tag + ;; ensure there are no conflicts + :nmvo doom-leader-key nil + :nmvo doom-localleader-key nil) + +(map! + ;; --- Global keybindings --------------------------- + ;; Make M-x available everywhere + :gnvime "M-x" #'execute-extended-command + :gnvime "A-x" #'execute-extended-command + ;; Emacs debug utilities + :gnvime "M-;" #'eval-expression + :gnvime "M-:" #'doom/open-scratch-buffer + ;; Text-scaling + "M-+" (λ! (text-scale-set 0)) + "M-=" #'text-scale-increase + "M--" #'text-scale-decrease + ;; Simple window navigation/manipulation + "C-`" #'doom/popup-toggle + "C-~" #'doom/popup-raise + "M-t" #'+workspace/new + "M-T" #'+workspace/display + "M-w" #'delete-window + "M-W" #'+workspace/close-workspace-or-frame + "M-n" #'evil-buffer-new + "M-N" #'make-frame + "M-1" (λ! (+workspace/switch-to 0)) + "M-2" (λ! (+workspace/switch-to 1)) + "M-3" (λ! (+workspace/switch-to 2)) + "M-4" (λ! (+workspace/switch-to 3)) + "M-5" (λ! (+workspace/switch-to 4)) + "M-6" (λ! (+workspace/switch-to 5)) + "M-7" (λ! (+workspace/switch-to 6)) + "M-8" (λ! (+workspace/switch-to 7)) + "M-9" (λ! (+workspace/switch-to 8)) + "M-0" #'+workspace/switch-to-last + ;; Other sensible, textmate-esque global bindings + :ne "M-r" #'+eval/buffer + :ne "M-R" #'+eval/region-and-replace + :ne "M-b" #'+eval/build + :ne "M-a" #'mark-whole-buffer + :ne "M-c" #'evil-yank + :ne "M-q" (if (daemonp) #'delete-frame #'save-buffers-kill-emacs) + :ne "M-f" #'swiper + :ne "C-M-f" #'doom/toggle-fullscreen + :n "M-s" #'save-buffer + :m "A-j" #'+hlissner:multi-next-line + :m "A-k" #'+hlissner:multi-previous-line + :nv "C-SPC" #'+evil:fold-toggle + :gnvimer "M-v" #'clipboard-yank + ;; Easier window navigation + :en "C-h" #'evil-window-left + :en "C-j" #'evil-window-down + :en "C-k" #'evil-window-up + :en "C-l" #'evil-window-right + :n "U" #'undo-tree-visualize + + "C-x p" #'doom/other-popup + + :n "K" #'+lookup/documentation + :n "g d" #'+lookup/definition + + + ;; --- ------------------------------------- + (:leader + :desc "Ex command" :nv ";" #'evil-ex + :desc "M-x" :nv ":" #'execute-extended-command + :desc "Pop up scratch buffer" :nv "x" #'doom/open-scratch-buffer + :desc "Org Capture" :nv "X" #'org-capture + :desc "Org Capture" :nv "a" #'+org-capture/open + + ;; Most commonly used + :desc "Find file in project" :n "SPC" #'projectile-find-file + :desc "Switch workspace buffer" :n "," #'persp-switch-to-buffer + :desc "Switch buffer" :n "<" #'switch-to-buffer + :desc "Browse files" :n "." #'find-file + :desc "Toggle last popup" :n "~" #'doom/popup-toggle + :desc "Eval expression" :n "`" #'eval-expression + :desc "Blink cursor line" :n "DEL" #'+doom/blink-cursor + :desc "Jump to bookmark" :n "RET" #'bookmark-jump + + ;; C-u is used by evil + :desc "Universal argument" :n "u" #'universal-argument + :desc "window" :n "w" evil-window-map + + (:desc "previous..." :prefix "[" + :desc "Text size" :nv "[" #'text-scale-decrease + :desc "Buffer" :nv "b" #'doom/previous-buffer + :desc "Diff Hunk" :nv "d" #'git-gutter:previous-hunk + :desc "Todo" :nv "t" #'hl-todo-previous + :desc "Error" :nv "e" #'previous-error + :desc "Workspace" :nv "w" #'+workspace/switch-left + :desc "Smart jump" :nv "h" #'smart-backward + :desc "Spelling error" :nv "s" #'evil-prev-flyspell-error + :desc "Spelling correction" :n "S" #'flyspell-correct-previous-word-generic + :desc "Git conflict" :n "n" #'smerge-prev) + + (:desc "next..." :prefix "]" + :desc "Text size" :nv "]" #'text-scale-increase + :desc "Buffer" :nv "b" #'doom/next-buffer + :desc "Diff Hunk" :nv "d" #'git-gutter:next-hunk + :desc "Todo" :nv "t" #'hl-todo-next + :desc "Error" :nv "e" #'next-error + :desc "Workspace" :nv "w" #'+workspace/switch-right + :desc "Smart jump" :nv "l" #'smart-forward + :desc "Spelling error" :nv "s" #'evil-next-flyspell-error + :desc "Spelling correction" :n "S" #'flyspell-correct-word-generic + :desc "Git conflict" :n "n" #'smerge-next) + + (:desc "search" :prefix "/" + :desc "Swiper" :nv "/" #'swiper + :desc "Imenu" :nv "i" #'imenu + :desc "Imenu across buffers" :nv "I" #'imenu-anywhere + :desc "Online providers" :nv "o" #'+lookup/online-select) + + (:desc "workspace" :prefix "TAB" + :desc "Display tab bar" :n "TAB" #'+workspace/display + :desc "New workspace" :n "n" #'+workspace/new + :desc "Load workspace from file" :n "l" #'+workspace/load + :desc "Load last session" :n "L" (λ! (+workspace/load-session)) + :desc "Save workspace to file" :n "s" #'+workspace/save + :desc "Autosave current session" :n "S" #'+workspace/save-session + :desc "Switch workspace" :n "." #'+workspace/switch-to + :desc "Kill all buffers" :n "x" #'doom/kill-all-buffers + :desc "Delete session" :n "X" #'+workspace/kill-session + :desc "Delete this workspace" :n "d" #'+workspace/delete + :desc "Load session" :n "L" #'+workspace/load-session + :desc "Next workspace" :n "]" #'+workspace/switch-right + :desc "Previous workspace" :n "[" #'+workspace/switch-left + :desc "Switch to 1st workspace" :n "1" (λ! (+workspace/switch-to 0)) + :desc "Switch to 2nd workspace" :n "2" (λ! (+workspace/switch-to 1)) + :desc "Switch to 3rd workspace" :n "3" (λ! (+workspace/switch-to 2)) + :desc "Switch to 4th workspace" :n "4" (λ! (+workspace/switch-to 3)) + :desc "Switch to 5th workspace" :n "5" (λ! (+workspace/switch-to 4)) + :desc "Switch to 6th workspace" :n "6" (λ! (+workspace/switch-to 5)) + :desc "Switch to 7th workspace" :n "7" (λ! (+workspace/switch-to 6)) + :desc "Switch to 8th workspace" :n "8" (λ! (+workspace/switch-to 7)) + :desc "Switch to 9th workspace" :n "9" (λ! (+workspace/switch-to 8)) + :desc "Switch to last workspace" :n "0" #'+workspace/switch-to-last) + + (:desc "buffer" :prefix "b" + :desc "New empty buffer" :n "n" #'evil-buffer-new + :desc "Switch workspace buffer" :n "b" #'persp-switch-to-buffer + :desc "Switch buffer" :n "B" #'switch-to-buffer + :desc "Kill buffer" :n "k" #'doom/kill-this-buffer + :desc "Kill other buffers" :n "o" #'doom/kill-other-buffers + :desc "Save buffer" :n "s" #'save-buffer + :desc "Pop scratch buffer" :n "x" #'doom/open-scratch-buffer + :desc "Bury buffer" :n "z" #'bury-buffer + :desc "Next buffer" :n "]" #'doom/next-buffer + :desc "Previous buffer" :n "[" #'doom/previous-buffer + :desc "Sudo edit this file" :n "S" #'doom/sudo-this-file) + + (:desc "code" :prefix "c" + :desc "List errors" :n "x" #'flycheck-list-errors + :desc "Evaluate buffer/region" :n "e" #'+eval/buffer + :v "e" #'+eval/region + :desc "Evaluate & replace region" :nv "E" #'+eval:replace-region + :desc "Build tasks" :nv "b" #'+eval/build + :desc "Jump to definition" :n "d" #'+lookup/definition + :desc "Jump to references" :n "D" #'+lookup/references + :desc "Open REPL" :n "r" #'+eval/open-repl + :v "r" #'+eval:repl) + + (:desc "file" :prefix "f" + :desc "Find file" :n "." #'find-file + :desc "Sudo find file" :n ">" #'doom/sudo-find-file + :desc "Find file in project" :n "/" #'projectile-find-file + :desc "Find file from here" :n "?" #'counsel-file-jump + :desc "Find other file" :n "a" #'projectile-find-other-file + :desc "Open project editorconfig" :n "c" #'editorconfig-find-current-editorconfig + :desc "Find file in dotfiles" :n "d" #'+hlissner/find-in-dotfiles + :desc "Browse dotfiles" :n "D" #'+hlissner/browse-dotfiles + :desc "Find file in emacs.d" :n "e" #'+hlissner/find-in-doomd + :desc "Browse emacs.d" :n "E" #'+hlissner/browse-doomd + :desc "Recent files" :n "r" #'recentf-open-files + :desc "Recent project files" :n "R" #'projectile-recentf + :desc "Yank filename" :n "y" #'+hlissner/yank-buffer-filename) + + (:desc "git" :prefix "g" + :desc "Git status" :n "S" #'magit-status + :desc "Git blame" :n "b" #'magit-blame + :desc "Git time machine" :n "t" #'git-timemachine-toggle + :desc "Git stage hunk" :n "s" #'git-gutter:stage-hunk + :desc "Git revert hunk" :n "r" #'git-gutter:revert-hunk + :desc "Git revert buffer" :n "R" #'vc-revert + ;; :desc "List gists" :n "g" #'+gist:list + :desc "Git grep" :n "g" #'counsel-git-grep + :desc "Checkout Branch" :n "c" #'counsel-git-checkout + :desc "Next hunk" :nv "]" #'git-gutter:next-hunk + :desc "Previous hunk" :nv "[" #'git-gutter:previous-hunk) + + (:desc "help" :prefix "h" + :n "h" help-map + :desc "Apropos" :n "a" #'apropos + :desc "Reload theme" :n "R" #'doom//reload-theme + :desc "Find library" :n "l" #'find-library + :desc "Toggle Emacs log" :n "m" #'doom/popup-toggle-messages + :desc "Command log" :n "L" #'global-command-log-mode + :desc "Describe function" :n "f" #'describe-function + :desc "Describe key" :n "k" #'describe-key + :desc "Describe char" :n "c" #'describe-char + :desc "Describe mode" :n "M" #'describe-mode + :desc "Describe variable" :n "v" #'describe-variable + :desc "Describe face" :n "F" #'describe-face + :desc "Describe DOOM setting" :n "s" #'doom/describe-setting + :desc "Describe DOOM module" :n "d" #'doom/describe-module + :desc "Find definition" :n "." #'+lookup/definition + :desc "Find references" :n "/" #'+lookup/references + :desc "Find documentation" :n "h" #'+lookup/documentation + :desc "What face" :n "'" #'doom/what-face + :desc "What minor modes" :n ";" #'doom/what-minor-mode + :desc "Info" :n "i" #'info + :desc "Toggle profiler" :n "p" #'doom/toggle-profiler) + + (:desc "insert" :prefix "i" + :desc "From kill-ring" :nv "y" #'counsel-yank-pop + :desc "From snippet" :nv "s" #'yas-insert-snippet) + + (:desc "notes" :prefix "n" + :desc "Agenda" :n "a" #'org-agenda + :desc "Find file in notes" :n "n" #'+hlissner/find-in-notes + :desc "Store link" :n "l" #'org-store-link + :desc "Browse notes" :n "N" #'+hlissner/browse-notes + :desc "Org capture" :n "x" #'+org-capture/open + :desc "Browse mode notes" :n "m" #'+org/browse-notes-for-major-mode + :desc "Browse project notes" :n "p" #'+org/browse-notes-for-project + :desc "Create clubhouse story" :n "c" #'org-clubhouse-create-story + :desc "Archive subtree" :n "k" #'org-archive-subtree) + + (:desc "open" :prefix "o" + :desc "Default browser" :n "b" #'browse-url-of-file + :desc "Debugger" :n "d" #'+debug/open + :desc "REPL" :n "r" #'+eval/open-repl + :v "r" #'+eval:repl + :desc "Neotree" :n "n" #'+neotree/toggle + :desc "Terminal" :n "t" #'+term/open-popup + :desc "Terminal in project" :n "T" #'+term/open-popup-in-project + + :desc "Slack IM" :n "i" #'slack-im-select + :desc "Slack Channel" :n "c" #'slack-channel-select + :desc "Slack Unreads" :n "u" #'slack-channel-select + + ;; applications + :desc "APP: elfeed" :n "E" #'=rss + :desc "APP: email" :n "M" #'=email + :desc "APP: twitter" :n "T" #'=twitter + :desc "APP: regex" :n "X" #'=regex + + ;; macos + (:when IS-MAC + :desc "Reveal in Finder" :n "o" #'+macos/reveal-in-finder + :desc "Reveal project in Finder" :n "O" #'+macos/reveal-project-in-finder + :desc "Send to Transmit" :n "u" #'+macos/send-to-transmit + :desc "Send project to Transmit" :n "U" #'+macos/send-project-to-transmit + :desc "Send to Launchbar" :n "l" #'+macos/send-to-launchbar + :desc "Send project to Launchbar" :n "L" #'+macos/send-project-to-launchbar)) + + (:desc "project" :prefix "p" + :desc "Browse project" :n "." (find-file-in! (doom-project-root)) + :desc "Find file in project" :n "/" #'projectile-find-file + :desc "Run cmd in project root" :nv "!" #'projectile-run-shell-command-in-root + :desc "Switch project" :n "p" #'projectile-switch-project + :desc "Recent project files" :n "r" #'projectile-recentf + :desc "List project tasks" :n "t" #'+ivy/tasks + :desc "Pop term in project" :n "o" #'+term/open-popup-in-project + :desc "Invalidate cache" :n "x" #'projectile-invalidate-cache) + + (:desc "quit" :prefix "q" + :desc "Quit" :n "q" #'evil-save-and-quit + :desc "Quit (forget session)" :n "Q" #'+workspace/kill-session-and-quit) + + (:desc "remote" :prefix "r" + :desc "Upload local" :n "u" #'+upload/local + :desc "Upload local (force)" :n "U" (λ! (+upload/local t)) + :desc "Download remote" :n "d" #'+upload/remote-download + :desc "Diff local & remote" :n "D" #'+upload/diff + :desc "Browse remote files" :n "." #'+upload/browse + :desc "Detect remote changes" :n ">" #'+upload/check-remote) + + (:desc "snippets" :prefix "s" + :desc "New snippet" :n "n" #'yas-new-snippet + :desc "Insert snippet" :nv "i" #'yas-insert-snippet + :desc "Find snippet for mode" :n "s" #'yas-visit-snippet-file + :desc "Find snippet" :n "S" #'+hlissner/find-in-snippets) + + (:desc "toggle" :prefix "t" + :desc "Flyspell" :n "s" #'flyspell-mode + :desc "Flycheck" :n "f" #'flycheck-mode + :desc "Line numbers" :n "l" #'doom/toggle-line-numbers + :desc "Fullscreen" :n "f" #'doom/toggle-fullscreen + :desc "Indent guides" :n "i" #'highlight-indentation-mode + :desc "Indent guides (column)" :n "I" #'highlight-indentation-current-column-mode + :desc "Impatient mode" :n "h" #'+impatient-mode/toggle + :desc "Big mode" :n "b" #'doom-big-font-mode + :desc "Evil goggles" :n "g" #'+evil-goggles/toggle)) + + + ;; --- vim-vinegar + :n "-" #'grfn/dired-minus + (:after dired-mode + (:map dired-mode-map + "-" #'grfn/dired-minus)) + + ;; --- vim-sexp-mappings-for-regular-people + (:after paxedit + (:map paxedit-mode-map + :n [remap evil-yank-line] #'paxedit-copy + :n [remap evil-delete-line] #'paxedit-delete + :n "go" #'paxedit-sexp-raise + :n [remap evil-join-whitespace] #'paxedit-compress + :n "gS" #'paxedit-format-1)) + + ;; --- vim-splitjoin + :n [remap evil-join-whitespace] #'+splitjoin/join + :n "gS" #'+splitjoin/split + + ;; --- Personal vim-esque bindings ------------------ + :n "zx" #'doom/kill-this-buffer + :n "ZX" #'bury-buffer + :n "]b" #'doom/next-buffer + :n "[b" #'doom/previous-buffer + :n "]w" #'+workspace/switch-right + :n "[w" #'+workspace/switch-left + :m "gt" #'+workspace/switch-right + :m "gT" #'+workspace/switch-left + :m "gd" #'+lookup/definition + :m "gD" #'+lookup/references + :m "K" #'+lookup/documentation + :n "gp" #'+evil/reselect-paste + :n "gr" #'+eval:region + :n "gR" #'+eval/buffer + :v "gR" #'+eval:replace-region + :v "@" #'+evil:macro-on-all-lines + :n "g@" #'+evil:macro-on-all-lines + ;; repeat in visual mode (FIXME buggy) + :v "." #'evil-repeat + ;; don't leave visual mode after shifting + :v "<" #'+evil/visual-dedent ; vnoremap < " #'+evil/visual-indent ; vnoremap > >gv + ;; paste from recent yank register (which isn't overwritten) + :v "C-p" "\"0p" + + (:map evil-window-map ; prefix "C-w" + ;; Navigation + "C-h" #'evil-window-left + "C-j" #'evil-window-down + "C-k" #'evil-window-up + "C-l" #'evil-window-right + "C-w" #'ace-window + ;; Swapping windows + "H" #'+evil/window-move-left + "J" #'+evil/window-move-down + "K" #'+evil/window-move-up + "L" #'+evil/window-move-right + "C-S-w" #'ace-swap-window + ;; Window undo/redo + "u" #'winner-undo + "C-u" #'winner-undo + "C-r" #'winner-redo + "o" #'doom/window-enlargen + ;; Delete window + "c" #'+workspace/close-window-or-workspace + "C-C" #'ace-delete-window + ;; Popups + "p" #'doom/popup-toggle + "m" #'doom/popup-toggle-messages + "P" #'doom/popup-close-all) + + + ;; --- Plugin bindings ------------------------------ + ;; auto-yasnippet + :i [C-tab] #'aya-expand + :nv [C-tab] #'aya-create + + ;; company-mode (vim-like omnicompletion) + :i "C-SPC" #'+company/complete + (:prefix "C-x" + :i "C-l" #'+company/whole-lines + :i "C-k" #'+company/dict-or-keywords + :i "C-f" #'company-files + :i "C-]" #'company-etags + :i "s" #'company-ispell + :i "C-s" #'company-yasnippet + :i "C-o" #'company-capf + :i "C-n" #'company-dabbrev-code + :i "C-p" #'+company/dabbrev-code-previous) + (:after company + (:map company-active-map + ;; Don't interfere with `evil-delete-backward-word' in insert mode + "C-w" nil + "C-o" #'company-search-kill-others + "C-n" #'company-select-next + "C-p" #'company-select-previous + "C-h" #'company-quickhelp-manual-begin + "C-S-h" #'company-show-doc-buffer + "C-S-s" #'company-search-candidates + "C-s" #'company-filter-candidates + "C-SPC" #'company-complete-common + "C-h" #'company-quickhelp-manual-begin + [tab] #'company-complete-common-or-cycle + [backtab] #'company-select-previous + [escape] (λ! (company-abort) (evil-normal-state 1))) + ;; Automatically applies to `company-filter-map' + (:map company-search-map + "C-n" #'company-search-repeat-forward + "C-p" #'company-search-repeat-backward + "C-s" (λ! (company-search-abort) (company-filter-candidates)) + [escape] #'company-search-abort)) + + ;; counsel + (:after counsel + (:map counsel-ag-map + [backtab] #'+ivy/wgrep-occur ; search/replace on results + "C-SPC" #'ivy-call-and-recenter ; preview + "M-RET" (+ivy-do-action! #'+ivy-git-grep-other-window-action))) + + ;; evil-commentary + :n "gc" #'evil-commentary + + ;; evil-exchange + :n "gx" #'evil-exchange + + ;; evil-matchit + :nv [tab] #'+evil/matchit-or-toggle-fold + + ;; evil-magit + (:after evil-magit + :map (magit-status-mode-map magit-revision-mode-map) + :n "C-j" nil + :n "C-k" nil) + + ;; Smerge + :n "]n" #'smerge-next + :n "[n" #'smerge-prev + + ;; evil-mc + (:prefix "gz" + :nv "m" #'evil-mc-make-all-cursors + :nv "u" #'evil-mc-undo-all-cursors + :nv "z" #'+evil/mc-make-cursor-here + :nv "t" #'+evil/mc-toggle-cursors + :nv "n" #'evil-mc-make-and-goto-next-cursor + :nv "p" #'evil-mc-make-and-goto-prev-cursor + :nv "N" #'evil-mc-make-and-goto-last-cursor + :nv "P" #'evil-mc-make-and-goto-first-cursor + :nv "d" #'evil-mc-make-and-goto-next-match + :nv "D" #'evil-mc-make-and-goto-prev-match) + (:after evil-mc + :map evil-mc-key-map + :nv "C-n" #'evil-mc-make-and-goto-next-cursor + :nv "C-N" #'evil-mc-make-and-goto-last-cursor + :nv "C-p" #'evil-mc-make-and-goto-prev-cursor + :nv "C-P" #'evil-mc-make-and-goto-first-cursor) + + ;; evil-multiedit + :v "R" #'evil-multiedit-match-all + :n "M-d" #'evil-multiedit-match-symbol-and-next + :n "M-D" #'evil-multiedit-match-symbol-and-prev + :v "M-d" #'evil-multiedit-match-and-next + :v "M-D" #'evil-multiedit-match-and-prev + :nv "C-M-d" #'evil-multiedit-restore + (:after evil-multiedit + (:map evil-multiedit-state-map + "M-d" #'evil-multiedit-match-and-next + "M-D" #'evil-multiedit-match-and-prev + "RET" #'evil-multiedit-toggle-or-restrict-region) + (:map (evil-multiedit-state-map evil-multiedit-insert-state-map) + "C-n" #'evil-multiedit-next + "C-p" #'evil-multiedit-prev)) + + ;; evil-snipe + (:after evil-snipe + ;; Binding to switch to evil-easymotion/avy after a snipe + :map evil-snipe-parent-transient-map + "C-;" (λ! (require 'evil-easymotion) + (call-interactively + (evilem-create #'evil-snipe-repeat + :bind ((evil-snipe-scope 'whole-buffer) + (evil-snipe-enable-highlight) + (evil-snipe-enable-incremental-highlight)))))) + + ;; evil-surround + :v "S" #'evil-surround-region + :o "s" #'evil-surround-edit + :o "S" #'evil-Surround-edit + + ;; expand-region + :v "v" #'er/expand-region + :v "V" #'er/contract-region + + ;; flycheck + :m "]e" #'next-error + :m "[e" #'previous-error + (:after flycheck + :map flycheck-error-list-mode-map + :n "C-n" #'flycheck-error-list-next-error + :n "C-p" #'flycheck-error-list-previous-error + :n "j" #'flycheck-error-list-next-error + :n "k" #'flycheck-error-list-previous-error + :n "RET" #'flycheck-error-list-goto-error) + + ;; flyspell + :m "]S" #'flyspell-correct-word-generic + :m "[S" #'flyspell-correct-previous-word-generic + + ;; git-gutter + :m "]d" #'git-gutter:next-hunk + :m "[d" #'git-gutter:previous-hunk + + ;; git-timemachine + (:after git-timemachine + (:map git-timemachine-mode-map + :n "C-p" #'git-timemachine-show-previous-revision + :n "C-n" #'git-timemachine-show-next-revision + :n "[[" #'git-timemachine-show-previous-revision + :n "]]" #'git-timemachine-show-next-revision + :n "q" #'git-timemachine-quit + :n "gb" #'git-timemachine-blame)) + + ;; gist + (:after gist + :map gist-list-menu-mode-map + :n "RET" #'+gist/open-current + :n "b" #'gist-browse-current-url + :n "c" #'gist-add-buffer + :n "d" #'gist-kill-current + :n "f" #'gist-fork + :n "q" #'quit-window + :n "r" #'gist-list-reload + :n "s" #'gist-star + :n "S" #'gist-unstar + :n "y" #'gist-print-current-url) + + ;; helm + (:after helm + (:map helm-map + "ESC" nil + "C-S-n" #'helm-next-source + "C-S-p" #'helm-previous-source + "C-u" #'helm-delete-minibuffer-contents + "C-w" #'backward-kill-word + "C-r" #'evil-paste-from-register ; Evil registers in helm! Glorious! + "C-b" #'backward-word + [left] #'backward-char + [right] #'forward-char + [escape] #'helm-keyboard-quit + [tab] #'helm-execute-persistent-action) + + (:after helm-files + (:map helm-generic-files-map + :e "ESC" #'helm-keyboard-quit) + (:map helm-find-files-map + "C-w" #'helm-find-files-up-one-level + "TAB" #'helm-execute-persistent-action)) + + (:after helm-ag + (:map helm-ag-map + "" #'helm-ag-edit))) + + ;; hl-todo + :m "]t" #'hl-todo-next + :m "[t" #'hl-todo-previous + + ;; ivy + (:after ivy + :map ivy-minibuffer-map + [escape] #'keyboard-escape-quit + "C-SPC" #'ivy-call-and-recenter + "TAB" #'ivy-partial + "M-v" #'yank + "M-z" #'undo + "C-r" #'evil-paste-from-register + "C-k" #'ivy-previous-line + "C-j" #'ivy-next-line + "C-l" #'ivy-alt-done + "C-w" #'ivy-backward-kill-word + "C-u" #'ivy-kill-line + "C-b" #'backward-word + "C-f" #'forward-word) + + ;; neotree + (:after neotree + :map neotree-mode-map + :n "g" nil + :n [tab] #'neotree-quick-look + :n "RET" #'neotree-enter + :n [backspace] #'evil-window-prev + :n "c" #'neotree-create-node + :n "r" #'neotree-rename-node + :n "d" #'neotree-delete-node + :n "j" #'neotree-next-line + :n "k" #'neotree-previous-line + :n "n" #'neotree-next-line + :n "p" #'neotree-previous-line + :n "h" #'+neotree/collapse-or-up + :n "l" #'+neotree/expand-or-open + :n "J" #'neotree-select-next-sibling-node + :n "K" #'neotree-select-previous-sibling-node + :n "H" #'neotree-select-up-node + :n "L" #'neotree-select-down-node + :n "G" #'evil-goto-line + :n "gg" #'evil-goto-first-line + :n "v" #'neotree-enter-vertical-split + :n "s" #'neotree-enter-horizontal-split + :n "q" #'neotree-hide + :n "R" #'neotree-refresh) + + ;; realgud + (:after realgud + :map realgud:shortkey-mode-map + :n "j" #'evil-next-line + :n "k" #'evil-previous-line + :n "h" #'evil-backward-char + :n "l" #'evil-forward-char + :m "n" #'realgud:cmd-next + :m "b" #'realgud:cmd-break + :m "B" #'realgud:cmd-clear + :n "c" #'realgud:cmd-continue) + + ;; rotate-text + :n "gs" #'rotate-text + + ;; smart-forward + :m "g]" #'smart-forward + :m "g[" #'smart-backward + + ;; undo-tree -- undo/redo for visual regions + :v "C-u" #'undo-tree-undo + :v "C-r" #'undo-tree-redo + + ;; yasnippet + (:after yasnippet + (:map yas-keymap + "C-e" #'+snippets/goto-end-of-field + "C-a" #'+snippets/goto-start-of-field + "" #'+snippets/goto-end-of-field + "" #'+snippets/goto-start-of-field + "" #'+snippets/delete-to-start-of-field + [escape] #'evil-normal-state + [backspace] #'+snippets/delete-backward-char + [delete] #'+snippets/delete-forward-char-or-field) + (:map yas-minor-mode-map + :i "" yas-maybe-expand + :v "" #'+snippets/expand-on-region)) + + + ;; --- Major mode bindings -------------------------- + + ;; Markdown + (:after markdown-mode + (:map markdown-mode-map + ;; fix conflicts with private bindings + "" nil + "" nil + "" nil)) + + ;; Rust + (:after rust + (:map rust-mode-map + "K" #'racer-describe + "g RET" #'cargo-process-test)) + + ;; Elixir + (:after alchemist + (:map elixir-mode-map + :n "K" #'alchemist-help-search-at-point + :n "g RET" #'alchemist-project-run-tests-for-current-file + :n "g \\" #'alchemist-mix-test-at-point + :n "g SPC" #'alchemist-mix-compile)) + + ;; Haskell + (:after haskell-mode + (:map haskell-mode-map + :n "K" #'intero-info + :n "g d" #'lsp-ui-peek-find-definitions + :n "g SPC" #'intero-repl-load + :n "g y" #'intero-type-at)) + + ;; Javascript + ;; (:after rjsx-mode + ;; (:map rjsx-mode-map + ;; :n "g d" #'flow-minor-jump-to-definition + ;; :n "K" #'flow-minor-type-at-pos)) + + (:after js2-mode + (:map js2-mode-map + :n "g d" #'flow-minor-jump-to-definition + :n "K" #'flow-minor-type-at-pos)) + + ;; Elisp + (:map emacs-lisp-mode-map + :n "g SPC" #'eval-buffer) + + + ;; --- Custom evil text-objects --------------------- + :textobj "a" #'evil-inner-arg #'evil-outer-arg + :textobj "B" #'evil-textobj-anyblock-inner-block #'evil-textobj-anyblock-a-block + :textobj "i" #'evil-indent-plus-i-indent #'evil-indent-plus-a-indent + :textobj "I" #'evil-indent-plus-i-indent-up #'evil-indent-plus-a-indent-up + :textobj "J" #'evil-indent-plus-i-indent-up-down #'evil-indent-plus-a-indent-up-down + + + ;; --- Built-in plugins ----------------------------- + (:after comint + ;; TAB auto-completion in term buffers + :map comint-mode-map [tab] #'company-complete) + + (:after debug + ;; For elisp debugging + :map debugger-mode-map + :n "RET" #'debug-help-follow + :n "e" #'debugger-eval-expression + :n "n" #'debugger-step-through + :n "c" #'debugger-continue) + + (:map help-mode-map + :n "[[" #'help-go-back + :n "]]" #'help-go-forward + :n "o" #'ace-link-help + :n "q" #'quit-window + :n "Q" #'+ivy-quit-and-resume) + + (:after vc-annotate + :map vc-annotate-mode-map + :n "q" #'kill-this-buffer + :n "d" #'vc-annotate-show-diff-revision-at-line + :n "D" #'vc-annotate-show-changeset-diff-revision-at-line + :n "SPC" #'vc-annotate-show-log-revision-at-line + :n "]]" #'vc-annotate-next-revision + :n "[[" #'vc-annotate-prev-revision + :n "TAB" #'vc-annotate-toggle-annotation-visibility + :n "RET" #'vc-annotate-find-revision-at-line)) + +;; evil-easymotion +(after! evil-easymotion + (let ((prefix (concat doom-leader-key " /"))) + ;; NOTE `evilem-default-keybinds' unsets all other keys on the prefix (in + ;; motion state) + (evilem-default-keybindings prefix) + (evilem-define (kbd (concat prefix " n")) #'evil-ex-search-next) + (evilem-define (kbd (concat prefix " N")) #'evil-ex-search-previous) + (evilem-define (kbd (concat prefix " s")) #'evil-snipe-repeat + :pre-hook (save-excursion (call-interactively #'evil-snipe-s)) + :bind ((evil-snipe-scope 'buffer) + (evil-snipe-enable-highlight) + (evil-snipe-enable-incremental-highlight))) + (evilem-define (kbd (concat prefix " S")) #'evil-snipe-repeat-reverse + :pre-hook (save-excursion (call-interactively #'evil-snipe-s)) + :bind ((evil-snipe-scope 'buffer) + (evil-snipe-enable-highlight) + (evil-snipe-enable-incremental-highlight))))) + + +;; +;; Keybinding fixes +;; + +;; This section is dedicated to "fixing" certain keys so that they behave +;; properly, more like vim, or how I like it. + +(map! (:map input-decode-map + [S-iso-lefttab] [backtab] + (:unless window-system "TAB" [tab])) ; Fix TAB in terminal + + ;; I want C-a and C-e to be a little smarter. C-a will jump to + ;; indentation. Pressing it again will send you to the true bol. Same goes + ;; for C-e, except it will ignore comments and trailing whitespace before + ;; jumping to eol. + :i "C-a" #'doom/backward-to-bol-or-indent + :i "C-e" #'doom/forward-to-last-non-comment-or-eol + :i "C-u" #'doom/backward-kill-to-bol-and-indent + + ;; textmate-esque newline insertion + :i [M-return] #'evil-open-below + :i [S-M-return] #'evil-open-above + ;; textmate-esque deletion + [M-backspace] #'doom/backward-kill-to-bol-and-indent + :i [backspace] #'delete-backward-char + :i [M-backspace] #'doom/backward-kill-to-bol-and-indent + ;; Emacsien motions for insert mode + :i "C-b" #'backward-word + :i "C-f" #'forward-word + + ;; Highjacks space/backspace to: + ;; a) balance spaces inside brackets/parentheses ( | ) -> (|) + ;; b) delete space-indented blocks intelligently + ;; c) do none of this when inside a string + ;; :i "SPC" #'doom/inflate-space-maybe + ;; :i [remap delete-backward-char] #'doom/deflate-space-maybe + ;; :i [remap newline] #'doom/newline-and-indent + + (:after org + (:map org-mode-map + :i [remap doom/inflate-space-maybe] #'org-self-insert-command + :i "C-e" #'org-end-of-line + :i "C-a" #'org-beginning-of-line)) + + ;; Restore common editing keys (and ESC) in minibuffer + (:map (minibuffer-local-map + minibuffer-local-ns-map + minibuffer-local-completion-map + minibuffer-local-must-match-map + minibuffer-local-isearch-map + evil-ex-completion-map + evil-ex-search-keymap + read-expression-map) + [escape] #'abort-recursive-edit + "C-r" #'evil-paste-from-register + "C-a" #'move-beginning-of-line + "C-w" #'doom/minibuffer-kill-word + "C-u" #'doom/minibuffer-kill-line + "C-b" #'backward-word + "C-f" #'forward-word + "M-z" #'doom/minibuffer-undo) + + (:map messages-buffer-mode-map + "M-;" #'eval-expression + "A-;" #'eval-expression) + + (:map tabulated-list-mode-map + [remap evil-record-macro] #'doom/popup-close-maybe) + + (:after view + (:map view-mode-map "" #'View-quit-all))) + +(defun +sexp-transpose () + (interactive) + (case evil-this-operator + ('evil-shift-right (paxedit-transpose-forward)) + ('evil-shift-left (paxedit-transpose-backward)))) + +;; (defun nmap (&rest keys-and-ops) +;; (->> +;; (seq-partition keys-and-ops 2) +;; (seq-map +;; (lambda (k-op) +;; (let* ((k (car k-op)) +;; (op (cadr k-op)) +;; (prefix (substring k 0 1)) +;; (prefix-sym (lookup-key evil-normal-state-map prefix)) +;; (keyseq (substring k 1))) +;; (list keyseq prefix-sym op)))) +;; (seq-group-by #'car) +;; (seq-map +;; (lambda (k-ops) +;; (let* ((keyseq (car k-ops)) +;; (ops (cdr k-ops)) +;; (existing-binding (lookup-key evil-operator-state-map keyseq)) +;; (handler (λ! () +;; (if-let +;; ((oplist +;; (seq-find (lambda (op) +;; (equal (nth 1 op) +;; evil-this-operator)) +;; ops))) +;; (message "calling oplist") +;; (->> oplist (nth 2) funcall) +;; (when existing-binding +;; (funcall existing-binding)))))) +;; (if existing-binding +;; (progn +;; (define-key evil-operator-state-map +;; (vector 'remap existing-binding) +;; handler) +;; (define-key evil-motion-state-map +;; (vector 'remap existing-binding) +;; handler)) +;; (define-key evil-operator-state-map keyseq handler))))))) + +;; (nmap +;; ">e" #'paxedit-transpose-forward +;; "" (general-key-dispatch 'evil-shift-right + "e" 'paxedit-transpose-forward + ")" 'sp-forward-slurp-sexp + "(" 'sp-backward-barf-sexp + "I" 'grfn/insert-at-sexp-end + "a" 'grfn/insert-at-form-end)) + +(nmap :keymaps 'paxedit-mode-map + "<" (general-key-dispatch 'evil-shift-left + "e" 'paxedit-transpose-backward + ")" 'sp-forward-barf-sexp + "(" 'sp-backward-slurp-sexp + "I" 'grfn/insert-at-sexp-start + "a" 'grfn/insert-at-form-start)) + +;; (require 'doom-themes) +(require 'haskell) + +(defun grfn/haskell-test-file-p () + (string-match-p (rx (and "Spec.hs" eol)) + (buffer-file-name))) + +(defun grfn/intero-run-main () + (interactive) + (intero-repl-load) + (intero-with-repl-buffer nil + (comint-simple-send + (get-buffer-process (current-buffer)) + "main"))) + +(map! + (:map haskell-mode-map + :n "K" 'intero-info + :n "g d" 'intero-goto-definition + :n "g SPC" 'intero-repl-load + :n "g \\" 'intero-repl + :n "g y" 'intero-type-at + :n "gET" 'grfn/intero-run-main)) + diff --git a/+commands.el b/+commands.el new file mode 100644 index 0000000000..87123ed3c8 --- /dev/null +++ b/+commands.el @@ -0,0 +1,119 @@ +;;; private/grfn/+commands.el -*- lexical-binding: t; -*- + +(defalias 'ex! 'evil-ex-define-cmd) + +(defun delete-file-and-buffer () + "Kill the current buffer and deletes the file it is visiting." + (interactive) + (let ((filename (buffer-file-name))) + (when filename + (if (vc-backend filename) + (vc-delete-file filename) + (progn + (delete-file filename) + (message "Deleted file %s" filename) + (kill-buffer)))))) + +;;; Commands defined elsewhere +;;(ex! "al[ign]" #'+evil:align) +;;(ex! "g[lobal]" #'+evil:global) + +;;; Custom commands +;; Editing +(ex! "@" #'+evil:macro-on-all-lines) ; TODO Test me +(ex! "al[ign]" #'+evil:align) +(ex! "enhtml" #'+web:encode-html-entities) +(ex! "dehtml" #'+web:decode-html-entities) +(ex! "mc" #'+evil:mc) +(ex! "iedit" #'evil-multiedit-ex-match) +(ex! "na[rrow]" #'+evil:narrow-buffer) +(ex! "retab" #'+evil:retab) + +;; External resources +;; TODO (ex! "db" #'doom:db) +;; TODO (ex! "dbu[se]" #'doom:db-select) +;; TODO (ex! "go[ogle]" #'doom:google-search) +(ex! "lo[okup]" #'+jump:online) +(ex! "dash" #'+lookup:dash) +(ex! "dd" #'+lookup:devdocs) +(ex! "http" #'httpd-start) ; start http server +(ex! "repl" #'+eval:repl) ; invoke or send to repl +;; TODO (ex! "rx" 'doom:regex) ; open re-builder +(ex! "sh[ell]" #'+eshell:run) +(ex! "t[mux]" #'+tmux:run) ; send to tmux +(ex! "tcd" #'+tmux:cd-here) ; cd to default-directory in tmux +(ex! "x" #'doom/open-project-scratch-buffer) + +;; GIT +(ex! "gist" #'+gist:send) ; send current buffer/region to gist +(ex! "gistl" #'+gist:list) ; list gists by user +(ex! "gbrowse" #'+vcs/git-browse) ; show file in github/gitlab +(ex! "gissues" #'+vcs/git-browse-issues) ; show github issues +(ex! "git" #'magit-status) ; open magit status window +(ex! "gstage" #'magit-stage) +(ex! "gunstage" #'magit-unstage) +(ex! "gblame" #'magit-blame) +(ex! "grevert" #'git-gutter:revert-hunk) + +;; Dealing with buffers +(ex! "clean[up]" #'doom/cleanup-buffers) +(ex! "k[ill]" #'doom/kill-this-buffer) +(ex! "k[ill]all" #'+hlissner:kill-all-buffers) +(ex! "k[ill]m" #'+hlissner:kill-matching-buffers) +(ex! "k[ill]o" #'doom/kill-other-buffers) +(ex! "l[ast]" #'doom/popup-restore) +(ex! "m[sg]" #'view-echo-area-messages) +(ex! "pop[up]" #'doom/popup-this-buffer) + +;; Project navigation +(ex! "a" #'projectile-toggle-between-implementation-and-test) +(ex! "as" #'projectile-find-implementation-or-test-other-window) +(ex! "av" #'projectile-find-implementation-or-test-other-window) +(ex! "cd" #'+hlissner:cd) +(cond ((featurep! :completion ivy) + (ex! "ag" #'+ivy:ag) + (ex! "agc[wd]" #'+ivy:ag-cwd) + (ex! "rg" #'+ivy:rg) + (ex! "rgc[wd]" #'+ivy:rg-cwd) + (ex! "sw[iper]" #'+ivy:swiper) + (ex! "todo" #'+ivy:todo)) + ((featurep! :completion helm) + (ex! "ag" #'+helm:ag) + (ex! "agc[wd]" #'+helm:ag-cwd) + (ex! "rg" #'+helm:rg) + (ex! "rgc[wd]" #'+helm:rg-cwd) + (ex! "sw[oop]" #'+helm:swoop) + (ex! "todo" #'+helm:todo))) + +;; Project tools +(ex! "build" #'+eval/build) +(ex! "debug" #'+debug/run) +(ex! "er[rors]" #'flycheck-list-errors) + +;; File operations +(ex! "cp" #'+evil:copy-this-file) +(ex! "mv" #'+evil:move-this-file) +(ex! "rm" #'+evil:delete-this-file) + +;; Sessions/tabs +(ex! "sclear" #'+workspace/kill-session) +(ex! "sl[oad]" #'+workspace:load-session) +(ex! "ss[ave]" #'+workspace:save-session) +(ex! "tabcl[ose]" #'+workspace:delete) +(ex! "tabclear" #'doom/kill-all-buffers) +(ex! "tabl[ast]" #'+workspace/switch-to-last) +(ex! "tabload" #'+workspace:load) +(ex! "tabn[ew]" #'+workspace:new) +(ex! "tabn[ext]" #'+workspace:switch-next) +(ex! "tabp[rev]" #'+workspace:switch-previous) +(ex! "tabr[ename]" #'+workspace:rename) +(ex! "tabs" #'+workspace/display) +(ex! "tabsave" #'+workspace:save) + +;; Org-mode +(ex! "cap" #'+org-capture/dwim) + +;; Elixir +(add-hook! elixir-mode + (ex! "AV" #'alchemist-project-toggle-file-and-tests-other-window) + (ex! "A" #'alchemist-project-toggle-file-and-tests)) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..1fd0e39887 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.authinfo.gpg ++private.el diff --git a/autoload/evil.el b/autoload/evil.el new file mode 100644 index 0000000000..319c93c05e --- /dev/null +++ b/autoload/evil.el @@ -0,0 +1,37 @@ +;;; /autoload/evil.el -*- lexical-binding: t; -*- +;;;###if (featurep! :feature evil) + +;;;###autoload (autoload '+hlissner:multi-next-line "/autoload/evil" nil t) +(evil-define-motion +hlissner:multi-next-line (count) + "Move down 6 lines." + :type line + (let ((line-move-visual (or visual-line-mode (derived-mode-p 'text-mode)))) + (evil-line-move (* 6 (or count 1))))) + +;;;###autoload (autoload '+hlissner:multi-previous-line "/autoload/evil" nil t) +(evil-define-motion +hlissner:multi-previous-line (count) + "Move up 6 lines." + :type line + (let ((line-move-visual (or visual-line-mode (derived-mode-p 'text-mode)))) + (evil-line-move (- (* 6 (or count 1)))))) + +;;;###autoload (autoload '+hlissner:cd "/autoload/evil" nil t) +(evil-define-command +hlissner:cd () + "Change `default-directory' with `cd'." + (interactive "") + (cd input)) + +;;;###autoload (autoload '+hlissner:kill-all-buffers "/autoload/evil" nil t) +(evil-define-command +hlissner:kill-all-buffers (&optional bang) + "Kill all buffers. If BANG, kill current session too." + (interactive "") + (if bang + (+workspace/kill-session) + (doom/kill-all-buffers))) + +;;;###autoload (autoload '+hlissner:kill-matching-buffers "/autoload/evil" nil t) +(evil-define-command +hlissner:kill-matching-buffers (&optional bang pattern) + "Kill all buffers matching PATTERN regexp. If BANG, only match project +buffers." + (interactive "") + (doom/kill-matching-buffers pattern bang)) diff --git a/autoload/hlissner.el b/autoload/hlissner.el new file mode 100644 index 0000000000..87b2236d12 --- /dev/null +++ b/autoload/hlissner.el @@ -0,0 +1,53 @@ +;;; autoload/hlissner.el -*- lexical-binding: t; -*- + +;;;###autoload +(defun +hlissner/install-snippets () + "Install my snippets from https://github.com/hlissner/emacs-snippets into +private/hlissner/snippets." + (interactive) + (doom-fetch :github "hlissner/emacs-snippets" + (expand-file-name "snippets" (doom-module-path :private 'hlissner)))) + +;;;###autoload +(defun +hlissner/yank-buffer-filename () + "Copy the current buffer's path to the kill ring." + (interactive) + (if-let* ((filename (or buffer-file-name (bound-and-true-p list-buffers-directory)))) + (message (kill-new (abbreviate-file-name filename))) + (error "Couldn't find filename in current buffer"))) + +(defmacro +hlissner-def-finder! (name dir) + "Define a pair of find-file and browse functions." + `(progn + (defun ,(intern (format "+hlissner/find-in-%s" name)) () + (interactive) + (let ((default-directory ,dir) + projectile-project-name + projectile-require-project-root + projectile-cached-buffer-file-name + projectile-cached-project-root) + (call-interactively (command-remapping #'projectile-find-file)))) + (defun ,(intern (format "+hlissner/browse-%s" name)) () + (interactive) + (let ((default-directory ,dir)) + (call-interactively (command-remapping #'find-file)))))) + +;;;###autoload (autoload '+hlissner/find-in-templates "autoload/hlissner" nil t) +;;;###autoload (autoload '+hlissner/browse-templates "autoload/hlissner" nil t) +(+hlissner-def-finder! templates +file-templates-dir) + +;;;###autoload (autoload '+hlissner/find-in-snippets "autoload/hlissner" nil t) +;;;###autoload (autoload '+hlissner/browse-snippets "autoload/hlissner" nil t) +(+hlissner-def-finder! snippets +hlissner-snippets-dir) + +;;;###autoload (autoload '+hlissner/find-in-dotfiles "autoload/hlissner" nil t) +;;;###autoload (autoload '+hlissner/browse-dotfiles "autoload/hlissner" nil t) +(+hlissner-def-finder! dotfiles (expand-file-name ".dotfiles" "~")) + +;;;###autoload (autoload '+hlissner/find-in-emacsd "autoload/hlissner" nil t) +;;;###autoload (autoload '+hlissner/browse-emacsd "autoload/hlissner" nil t) +(+hlissner-def-finder! emacsd doom-emacs-dir) + +;;;###autoload (autoload '+hlissner/find-in-notes "autoload/hlissner" nil t) +;;;###autoload (autoload '+hlissner/browse-notes "autoload/hlissner" nil t) +(+hlissner-def-finder! notes +org-dir) diff --git a/config.el b/config.el new file mode 100644 index 0000000000..595faa6d33 --- /dev/null +++ b/config.el @@ -0,0 +1,409 @@ +;;; private/grfn/config.el -*- lexical-binding: t; -*- + +(defvar +grfn-dir (file-name-directory load-file-name)) +(defvar +grfn-snippets-dir (expand-file-name "snippets/" +grfn-dir)) + +;; +(when (featurep! :feature evil) + (load! +bindings) + (load! +commands)) + +(load! +private) + +(require 'dash) + + +;; +;; Global config +;; + +(setq +doom-modeline-buffer-file-name-style 'relative-to-project) + +;; +;; Modules +;; + +(after! smartparens + ;; Auto-close more conservatively and expand braces on RET + (let ((unless-list '(sp-point-before-word-p + sp-point-after-word-p + sp-point-before-same-p))) + (sp-pair "'" nil :unless unless-list) + (sp-pair "\"" nil :unless unless-list)) + (sp-pair "{" nil :post-handlers '(("||\n[i]" "RET") ("| " " ")) + :unless '(sp-point-before-word-p sp-point-before-same-p)) + (sp-pair "(" nil :post-handlers '(("||\n[i]" "RET") ("| " " ")) + :unless '(sp-point-before-word-p sp-point-before-same-p)) + (sp-pair "[" nil :post-handlers '(("| " " ")) + :unless '(sp-point-before-word-p sp-point-before-same-p))) + +;; feature/evil +(after! evil-mc + ;; Make evil-mc resume its cursors when I switch to insert mode + (add-hook! 'evil-mc-before-cursors-created + (add-hook 'evil-insert-state-entry-hook #'evil-mc-resume-cursors nil t)) + (add-hook! 'evil-mc-after-cursors-deleted + (remove-hook 'evil-insert-state-entry-hook #'evil-mc-resume-cursors t))) + +;; feature/snippets +(after! yasnippet + ;; Don't use default snippets, use mine. + (setq yas-snippet-dirs + (append (list '+grfn-snippets-dir) + (delq 'yas-installed-snippets-dir yas-snippet-dirs)))) + +;; completion/helm +(after! helm + ;; Hide header lines in helm. I don't like them + (set-face-attribute 'helm-source-header nil :height 0.1)) + +(after! company + (setq company-idle-delay 0.2 + company-minimum-prefix-length 1)) + +(setq +doom-modeline-height 10) + +;; lang/org +;; (after! org-bullets +;; ;; The standard unicode characters are usually misaligned depending on the +;; ;; font. This bugs me. Personally, markdown #-marks for headlines are more +;; ;; elegant, so we use those. +;; (setq org-bullets-bullet-list '("#"))) + +;; (defmacro faces! (mode &rest forms) +;; (let ((hook-name (-> mode symbol-name (concat "-hook")))) +;; (if-let ((hook-sym (intern-soft hook-name))) +;; `(add-hook! ,hook-sym +;; (message "HELLO I AM MACRO TIME") +;; ,@(-> +;; forms +;; (seq-partition 2) +;; (->> (seq-map +;; (lambda (pair) +;; (let ((face (car pair)) +;; (color (cadr pair))) +;; `(set-face-foreground ,face ,color))))))) +;; (warn "Hook name %s (for mode %s) does not exist as symbol!" +;; (hook-name) +;; (symbol-name mode))))) + +(def-package! org-clubhouse) + +(setq solarized-use-variable-pitch nil + solarized-scale-org-headlines nil) + +; (require 'doom-themes) + +;; Should really figure out which of these is correct, eventually + +(after! doom-theme + (set-face-foreground 'font-lock-doc-face +solarized-s-base1) + (set-face-foreground 'org-block +solarized-s-base00) + (set-face-foreground 'slack-message-output-header +solarized-s-base01) + (set-face-attribute 'slack-message-output-header nil :underline nil) + (set-face-attribute 'slack-message-output-text nil :height 1.0) + ) + +(after! solarized-theme + (set-face-foreground 'font-lock-doc-face +solarized-s-base1) + (set-face-foreground 'org-block +solarized-s-base00) + + (set-face-foreground 'slack-message-output-header +solarized-s-base01) + (set-face-attribute 'slack-message-output-header nil :underline nil) + (set-face-attribute 'slack-message-output-text nil :height 1.0) + ) + +(after! slack + (set-face-foreground 'slack-message-output-header +solarized-s-base01) + (set-face-attribute 'slack-message-output-header nil :underline nil) + (set-face-attribute 'slack-message-output-text nil :height 1.0)) + +(after! evil + (setq evil-shift-width 2)) + +(after! org + (setq + org-directory (expand-file-name "~/notes") + +org-dir (expand-file-name "~/notes") + org-default-notes-file (concat org-directory "/inbox.org") + +org-default-todo-file (concat org-directory "/inbox.org") + org-agenda-files (list (expand-file-name "~/notes")) + org-refile-targets '((org-agenda-files :maxlevel . 1)) + org-file-apps `((auto-mode . emacs) + (,(rx (or (and "." (optional "x") (optional "htm") (optional "l") buffer-end) + (and buffer-start "http" (optional "s") "://"))) + . "firefox %s") + (,(rx ".pdf" buffer-end) . "apvlv %s") + (,(rx "." (or "png" + "jpg" + "jpeg" + "gif" + "tif" + "tiff") + buffer-end) + . "feh %s")) + org-log-done 'time + org-archive-location "~/notes/trash::* From %s" + org-cycle-separator-lines 2 + org-hidden-keywords '(title) + org-tags-column -130 + org-ellipsis "⤵" + org-capture-templates + '(("t" "Todo" entry + (file+headline +org-default-todo-file "Inbox") + "* TODO %?\n%i" :prepend t :kill-buffer t) + + ("n" "Notes" entry + (file+headline +org-default-notes-file "Inbox") + "* %u %?\n%i" :prepend t :kill-buffer t)) + org-deadline-warning-days 1 + org-agenda-skip-scheduled-if-deadline-is-shown 't) + (set-face-foreground 'org-block +solarized-s-base00) + (add-hook! org-mode + (add-hook! evil-normal-state-entry-hook + #'org-align-all-tags)) + (setf (alist-get 'file org-link-frame-setup) 'find-file-other-window) + (set-face-foreground 'org-block +solarized-s-base00)) + +(after! magit + (setq git-commit-summary-max-length 50) + (require 'magit-gh-pulls) + (add-hook 'magit-mode-hook 'turn-on-magit-gh-pulls)) + +(comment + + (string-match-p "(?!foo).*" "bar") + ) + +(after! ivy + (setq ivy-re-builders-alist + '((t . ivy--regex-fuzzy)))) + +(setq doom-font (font-spec :family "Meslo LGSDZ Nerd Font" :size 14) + doom-big-font (font-spec :family "Meslo LGSDZ Nerd Font" :size 19) + doom-variable-pitch-font (font-spec :family "DejaVu Sans") + doom-unicode-font (font-spec :family "Meslo LG S DZ")) + +(add-hook 'before-save-hook 'delete-trailing-whitespace) + +(after! paxedit + (add-hook! emacs-lisp-mode #'paxedit-mode) + (add-hook! clojure-mode #'paxedit-mode)) + +(require 'haskell) + +(let ((m-symbols + '(("`mappend`" . "⊕") + ("<>" . "⊕")))) + (dolist (item m-symbols) (add-to-list 'haskell-font-lock-symbols-alist item))) + +(setq haskell-font-lock-symbols t) + + +(add-hook! haskell-mode + (intero-mode) + (flycheck-add-next-checker + 'intero + 'haskell-hlint) + (set-fill-column 100)) + +;; (load! org-clubhouse) +(add-hook! org-mode #'org-clubhouse-mode) + +(load! slack-snippets) + +(after! magit + (require 'evil-magit) + (require 'magithub) + ) + +; (require 'auth-password-store) +; (auth-pass-enable) +(auth-source-pass-enable) + +(require 'fill-column-indicator) +;;; * Column Marker +(defun sanityinc/fci-enabled-p () (symbol-value 'fci-mode)) + +(defvar sanityinc/fci-mode-suppressed nil) +(make-variable-buffer-local 'sanityinc/fci-mode-suppressed) + +(defadvice popup-create (before suppress-fci-mode activate) + "Suspend fci-mode while popups are visible" + (let ((fci-enabled (sanityinc/fci-enabled-p))) + (when fci-enabled + (setq sanityinc/fci-mode-suppressed fci-enabled) + (turn-off-fci-mode)))) + +(defadvice popup-delete (after restore-fci-mode activate) + "Restore fci-mode when all popups have closed" + (when (and sanityinc/fci-mode-suppressed + (null popup-instances)) + (setq sanityinc/fci-mode-suppressed nil) + (turn-on-fci-mode))) + + +;; https://github.com/alpaker/Fill-Column-Indicator/issues/67#issuecomment-195611974 +(add-hook 'prog-mode-hook #'fci-mode) +(after! fill-column-indicator + (add-hook 'prog-mode-hook #'fci-mode) + (defvar eos/fci-disabled nil) + (make-variable-buffer-local 'eos/fci-disabled) + + ;; Add a hook that disables fci if enabled when the window changes and it + ;; isn't wide enough to display it. + (defun eos/maybe-disable-fci () + (interactive) + ;; Disable FCI if necessary + (when (and fci-mode + (< (window-width) (or fci-rule-column fill-column))) + (fci-mode -1) + (setq-local eos/fci-disabled t)) + ;; Enable FCI if necessary + (when (and eos/fci-disabled + (eq fci-mode nil) + (> (window-width) (or fci-rule-column fill-column))) + (fci-mode 1) + (setq-local eos/fci-disabled nil))) + + (defun eos/add-fci-disabling-hook () + (interactive) + (add-hook 'window-configuration-change-hook + #'eos/maybe-disable-fci)) + + (add-hook 'prog-mode-hook #'eos/add-fci-disabling-hook)) + + +;;; Javascript + +(setq js-indent-level 2) + +(require 'prettier-js) +(after! prettier-js + (add-hook! rjsx-mode #'prettier-js-mode) + (add-hook! js2-mode #'prettier-js-mode) + (add-hook! json-mode #'prettier-js-mode) + (add-hook! css-mode #'prettier-js-mode)) + +(require 'flycheck-flow) +(with-eval-after-load 'flycheck + (flycheck-add-mode 'javascript-flow 'rjsx-mode) + (flycheck-add-mode 'javascript-flow 'flow-minor-mode) + (flycheck-add-mode 'javascript-eslint 'flow-minor-mode) + (flycheck-add-next-checker 'javascript-flow 'javascript-eslint)) + +(require 'flow-minor-mode) + + +;; Auto-format Haskell on save, with a combination of hindent + brittany + +(define-minor-mode brittany-haskell-mode + :init-value nil + :group 'haskell + :lighter "Brittany-Haskell" + :keymap '() + ) + + +(defun urbint/format-haskell-source () + (interactive) + (let ((output-buffer (generate-new-buffer "brittany-out")) + (config-file-path + (concat (string-trim + (shell-command-to-string "stack path --project-root")) + "/brittany.yaml"))) + (when (= 0 (call-process-region + (point-min) (point-max) + "stack" + nil output-buffer nil + "exec" "--" "brittany" "--config-file" config-file-path)) + (let ((pt (point)) + (wst (window-start)) + (formatted-source (with-current-buffer output-buffer + (buffer-string)))) + (erase-buffer) + (insert formatted-source) + (goto-char pt) + (set-window-start nil wst))))) + +(add-hook + 'before-save-hook + (lambda () + (when (and (eq major-mode 'haskell-mode) + (bound-and-true-p brittany-haskell-mode)) + (urbint/format-haskell-source)))) + +(require 'slack) +(setq slack-buffer-emojify 't + slack-prefer-current-team 't) +(require 'alert) +(setq alert-default-style 'libnotify) + +;; (setq slack-buffer-function #'switch-to-buffer) + +(setq projectile-test-suffix-function + (lambda (project-type) + (case project-type + ('haskell-stack "Test") + ('npm ".test") + (otherwise (projectile-test-suffix project-type))))) + +(defun magit-commit-wip () + (interactive) + (magit-commit "-m wip")) + +;; (magit-define-popup-action 'magit-commit-popup +;; ?w "WIP" 'magit-commit-wip) + +;; (defun grfn/split-window-more-sensibly (&optional window) +;; (let ((window (or window (selected-window)))) +;; (or (and (window-splittable-p window) +;; ;; Split window vertically. +;; (with-selected-window window +;; (split-window-right))) +;; (and (window-splittable-p window t) +;; ;; Split window horizontally. +;; (with-selected-window window +;; (split-window-right))) +;; (and (eq window (frame-root-window (window-frame window))) +;; (not (window-minibuffer-p window)) +;; ;; If WINDOW is the only window on its frame and is not the +;; ;; minibuffer window, try to split it vertically disregarding +;; ;; the value of `split-height-threshold'. +;; (let ((split-height-threshold 0)) +;; (when (window-splittable-p window) +;; (with-selected-window window +;; (split-window-below)))))))) + +;; (def-package! lsp-mode +;; :after (:any haskell-mode) +;; :config +;; (lsp-mode)) + +;; (def-package! lsp-ui +;; :after lsp-mode +;; :config +;; (setq lsp-ui-flycheck-enable t) +;; (setq imenu-auto-rescan t) +;; (set-face-background 'lsp-ui-doc-background +solarized-s-base2) +;; (set-face-background 'lsp-face-highlight-read +solarized-s-base2) +;; (set-face-background 'lsp-face-highlight-orite +solarized-s-base2) +;; :hook +;; (lsp-mode . lsp-ui-mode) +;; (lsp-ui-mode . flycheck-mode)) + +;; (def-package! company-lsp +;; :after (lsp-mode lsp-ui) +;; :config +;; (setq company-backends '(company-lsp)) +;; (setq company-lsp-async t)) + +;; (def-package! lsp-haskell +;; :after (lsp-mode lsp-ui haskell-mode) +;; :hook +;; (haskell-mode . lsp-haskell-enable)) + +(def-package! evil-magit + :after (magit)) + +(def-package! writeroom-mode) diff --git a/init.el b/init.el new file mode 100644 index 0000000000..c07ce23ffe --- /dev/null +++ b/init.el @@ -0,0 +1,247 @@ +;;; private/grfn/init.el -*- lexical-binding: t; -*- + +;; An extra measure to prevent the flash of unstyled mode-line while Emacs is +;; booting up (when Doom is byte-compiled). +(setq-default mode-line-format nil) + + +;; I've swapped these keys on my keyboard +(setq x-super-keysym 'alt + x-alt-keysym 'meta) + +(setq user-mail-address "root@gws.fyi" + user-full-name "Griffin Smith") + +(add-hook! doom-big-font-mode + (setq +doom-modeline-height (if doom-big-font-mode 37 29))) + +; (def-package-hook! doom-themes :disable) + +(after! rust + (setq rust-format-on-save t)) + +; (defconst rust-src-path +; (-> "/Users/griffin/.cargo/bin/rustc --print sysroot" +; shell-command-to-string +; string-trim +; (concat "/lib/rustlib/src/rust/src"))) +; +; (setenv "RUST_SRC_PATH" rust-src-path) +; +; (after! racer +; (setq racer-rust-src-path rust-src-path)) +; +(add-hook! rust-mode + (flycheck-rust-setup) + (flycheck-mode) + (racer-mode) + (cargo-minor-mode)) + +(add-hook! elixir-mode + (require 'flycheck-credo) + (setq flycheck-elixir-credo-strict t) + (flycheck-credo-setup) + + (require 'flycheck-mix) (flycheck-mix-setup) + + (require 'flycheck-dialyxir) (flycheck-dialyxir-setup) + + (flycheck-mode)) + +(setq exec-path (append exec-path '("/Users/griffin/.cargo/bin"))) + +(after! cargo + (setq cargo-process--custom-path-to-bin "/Users/griffin/.cargo/bin/cargo")) + +(setq +solarized-s-base03 "#002b36" + +solarized-s-base02 "#073642" + ;; emphasized content + +solarized-s-base01 "#586e75" + ;; primary content + +solarized-s-base00 "#657b83" + +solarized-s-base0 "#839496" + ;; comments + +solarized-s-base1 "#93a1a1" + ;; background highlight light + +solarized-s-base2 "#eee8d5" + ;; background light + +solarized-s-base3 "#fdf6e3" + + ;; Solarized accented colors + +solarized-yellow "#b58900" + +solarized-orange "#cb4b16" + +solarized-red "#dc322f" + +solarized-magenta "#d33682" + +solarized-violet "#6c71c4" + +solarized-blue "#268bd2" + +solarized-cyan "#2aa198" + +solarized-green "#859900" + + ;; Darker and lighter accented colors + ;; Only use these in exceptional circumstances! + +solarized-yellow-d "#7B6000" + +solarized-yellow-l "#DEB542" + +solarized-orange-d "#8B2C02" + +solarized-orange-l "#F2804F" + +solarized-red-d "#990A1B" + +solarized-red-l "#FF6E64" + +solarized-magenta-d "#93115C" + +solarized-magenta-l "#F771AC" + +solarized-violet-d "#3F4D91" + +solarized-violet-l "#9EA0E5" + +solarized-blue-d "#00629D" + +solarized-blue-l "#69B7F0" + +solarized-cyan-d "#00736F" + +solarized-cyan-l "#69CABF" + +solarized-green-d "#546E00" + +solarized-green-l "#B4C342") + +(defadvice load-theme (after theme-set-overrides activate) + (dolist (theme-settings theme-overrides) + (let ((theme (car theme-settings)) + (faces (cadr theme-settings))) + (if (member theme custom-enabled-themes) + (dolist (face faces) + (custom-theme-set-faces theme face)))))) + +(defcustom theme-overrides nil + "Association list of override faces to set for different custom themes.") + +(defun alist-set (alist-symbol key value) + "Set VALUE of a KEY in ALIST-SYMBOL." + (set alist-symbol (cons (list key value) (assq-delete-all key (eval alist-symbol))))) + +(alist-set 'theme-overrides 'grfn-solarized-light + `((font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) + (font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) + (font-lock-keyword-face ((t (:foreground ,+solarized-green)))) + + (elixir-attribute-face ((t (:foreground ,+solarized-blue)))) + (elixir-atom-face ((t (:foreground ,+solarized-cyan)))) + (linum ((t (:background ,+solarized-s-base2 :foreground ,+solarized-s-base1)))) + (line-number ((t (:background ,+solarized-s-base2 :foreground ,+solarized-s-base1)))) + + (haskell-operator-face ((t (:foreground ,+solarized-green)))) + (haskell-keyword-face ((t (:foreground ,+solarized-cyan)))))) + +(add-to-list 'custom-theme-load-path "~/.doom.d/themes") +(load-theme 'grfn-solarized-light t) + +(defface haskell-import-face `((t (:foreground ,+solarized-magenta))) "") + +(setq doom-theme 'grfn-solarized-light) +; (setq doom-theme 'doom-solarized-light) + +(add-hook! doom-post-init + (set-face-attribute 'bold nil :weight 'ultra-light) + (set-face-bold-p 'bold nil)) + +(defun rx-words (&rest words) + (rx-to-string + `(and symbol-start (group (or ,@words)) symbol-end))) + +(font-lock-add-keywords + 'elixir-mode + `((,(rx-words "def" + "defp" + "test" + "describe" + "property" + "defrecord" + "defmodule" + "defstruct" + "defdelegate" + "defprotocol" + "defimpl" + "use" + "import" + "alias" + "require" + "assert" + "refute" + "assert_raise") + . + 'font-lock-preprocessor-face))) + +(font-lock-add-keywords + 'elixir-mode + `((,(rx-words "def" + "defp" + "test" + "describe" + "property" + "defrecord" + "defmodule" + "defstruct" + "defdelegate" + "use" + "import" + "alias" + "require" + "assert" + "refute" + "assert_raise") + . + 'font-lock-preprocessor-face))) + +(font-lock-add-keywords + 'haskell-mode + `((,(rx-words "import") . 'haskell-import-face))) + +;; (font-lock-add-keywords +;; 'haskell-mode +;; `((,(rx "-- |") . 'haskell-keyword-face))) + +;;; * Column Marker +(defun sanityinc/fci-enabled-p () (symbol-value 'fci-mode)) + +(defvar sanityinc/fci-mode-suppressed nil) +(make-variable-buffer-local 'sanityinc/fci-mode-suppressed) + +(defadvice popup-create (before suppress-fci-mode activate) + "Suspend fci-mode while popups are visible" + (let ((fci-enabled (sanityinc/fci-enabled-p))) + (when fci-enabled + (setq sanityinc/fci-mode-suppressed fci-enabled) + (turn-off-fci-mode)))) + +(defadvice popup-delete (after restore-fci-mode activate) + "Restore fci-mode when all popups have closed" + (when (and sanityinc/fci-mode-suppressed + (null popup-instances)) + (setq sanityinc/fci-mode-suppressed nil) + (turn-on-fci-mode))) + + +;; https://github.com/alpaker/Fill-Column-Indicator/issues/67#issuecomment-195611974 +(after! fill-column-indicator + (add-hook 'prog-mode-hook #'fci-mode) + (defvar eos/fci-disabled nil) + (make-variable-buffer-local 'eos/fci-disabled) + + ;; Add a hook that disables fci if enabled when the window changes and it + ;; isn't wide enough to display it. + (defun eos/maybe-disable-fci () + (interactive) + ;; Disable FCI if necessary + (when (and fci-mode + (< (window-width) (or fci-rule-column fill-column))) + (fci-mode -1) + (setq-local eos/fci-disabled t)) + ;; Enable FCI if necessary + (when (and eos/fci-disabled + (eq fci-mode nil) + (> (window-width) (or fci-rule-column fill-column))) + (fci-mode 1) + (setq-local eos/fci-disabled nil))) + + (defun eos/add-fci-disabling-hook () + (interactive) + (add-hook 'window-configuration-change-hook + #'eos/maybe-disable-fci)) + + (add-hook 'prog-mode-hook #'eos/add-fci-disabling-hook)) + +; (require 'haskell-prettify) + +;; (add-hook 'haskell-mode-hook #'haskell-prettify-enable) diff --git a/packages.el b/packages.el new file mode 100644 index 0000000000..0ef4289c85 --- /dev/null +++ b/packages.el @@ -0,0 +1,58 @@ +;; -*- no-byte-compile: t; -*- +;;; private/grfn/packages.el + +;; Editor +(package! solarized-theme) +(package! fill-column-indicator) +(package! flx) +(package! general + :recipe (general + :fetcher github + :repo "noctuid/general.el")) +(package! org-clubhouse + :recipe (org-clubhouse + :fetcher file + :path "~/code/urb/org-clubhouse")) +(package! fill-column-indicator) +(package! writeroom-mode) +(package! dash) + +;; Slack etc +(package! slack) +(package! alert) + +;; Git +(package! evil-magit) +(package! magithub) +(package! magit-gh-pulls) +(package! marshal) +; (package! auth-password-store) + +;; Elisp +(package! dash) +(package! dash-functional) +(package! s) +(package! request) + +;; Haskell +(package! lsp-mode) +(package! lsp-ui :recipe (:fetcher github :repo "emacs-lsp/lsp-ui")) +(package! lsp-haskell) +(package! company-lsp) + +;; Rust +(package! cargo) + +;; Elixir +(package! flycheck-credo) +(package! flycheck-mix) +(package! flycheck-dialyxir) + +;; Lisp +(package! paxedit) + +;; Javascript +(package! flow-minor-mode) +(package! flycheck-flow) +(package! company-flow) +(package! prettier-js) diff --git a/slack-snippets.el b/slack-snippets.el new file mode 100644 index 0000000000..0c51751921 --- /dev/null +++ b/slack-snippets.el @@ -0,0 +1,216 @@ +;;; private/grfn/slack-snippets.el -*- lexical-binding: t; -*- + +(require 'dash) +(require 'dash-functional) +(require 'request) + +;;; +;;; Configuration +;;; + +(defvar slack/token nil + "Legacy (https://api.slack.com/custom-integrations/legacy-tokens) access token") + +(defvar slack/include-public-channels 't + "Whether or not to inclue public channels in the list of conversations") + +(defvar slack/include-private-channels 't + "Whether or not to inclue public channels in the list of conversations") + +(defvar slack/include-im 't + "Whether or not to inclue IMs (private messages) in the list of conversations") + +(defvar slack/include-mpim nil + "Whether or not to inclue multi-person IMs (multi-person private messages) in + the list of conversations") + +;;; +;;; Utilities +;;; + +(defmacro comment (&rest _body) + "Comment out one or more s-expressions" + nil) + +(defun ->list (vec) (append vec nil)) + +(defun json-truthy? (x) (and x (not (equal :json-false x)))) + +;;; +;;; Generic API integration +;;; + +(defvar slack/base-url "https://slack.com/api") + +(defun slack/get (path params &optional callback) + "params is an alist of query parameters" + (let* ((params-callback (if (functionp params) `(() . ,params) (cons params callback))) + (params (car params-callback)) (callback (cdr params-callback)) + (params (append `(("token" . ,slack/token)) params)) + (url (concat (file-name-as-directory slack/base-url) path))) + (request url + :type "GET" + :params params + :parser 'json-read + :success (cl-function + (lambda (&key data &allow-other-keys) + (funcall callback data)))))) + +(defun slack/post (path params &optional callback) + (let* ((params-callback (if (functionp params) `(() . ,params) (cons params callback))) + (params (car params-callback)) (callback (cdr params-callback)) + (url (concat (file-name-as-directory slack/base-url) path))) + (request url + :type "POST" + :data (json-encode params) + :headers `(("Content-Type" . "application/json") + ("Authorization" . ,(format "Bearer %s" slack/token))) + :success (cl-function + (lambda (&key data &allow-other-keys) + (funcall callback data)))))) + + +;;; +;;; Specific API endpoints +;;; + +;; Users + +(defun slack/users (cb) + "Returns users as (id . name) pairs" + (slack/get + "users.list" + (lambda (data) + (->> data + (assoc-default 'members) + ->list + (-map (lambda (user) + (cons (assoc-default 'id user) + (assoc-default 'real_name user)))) + (-filter #'cdr) + (funcall cb))))) + +(comment + (slack/get + "users.list" + (lambda (data) (setq response-data data))) + + (slack/users (lambda (data) (setq --users data))) + + ) + +;; Conversations + +(defun slack/conversation-types () + (->> + (list (when slack/include-public-channels "public_channel") + (when slack/include-private-channels "private_channel") + (when slack/include-im "im") + (when slack/include-mpim "mpim")) + (-filter #'identity) + (s-join ","))) + +(defun channel-label (chan users-alist) + (cond + ((json-truthy? (assoc-default 'is_channel chan)) + (format "#%s" (assoc-default 'name chan))) + ((json-truthy? (assoc-default 'is_im chan)) + (let ((user-id (assoc-default 'user chan))) + (format "Private message with %s" (assoc-default user-id users-alist)))) + ((json-truthy? (assoc-default 'is_mpim chan)) + (->> chan + (assoc-default 'purpose) + (assoc-default 'value))))) + +(defun slack/conversations (cb) + "Calls `cb' with (id . '((label . \"label\") '(topic . \"topic\") '(purpose . \"purpose\"))) pairs" + (slack/get + "conversations.list" + `(("types" . ,(slack/conversation-types)) + ("exclude-archived" . "true")) + (lambda (data) + (setq --data data) + (slack/users + (lambda (users) + (->> data + (assoc-default 'channels) + ->list + (-map + (lambda (chan) + (cons (assoc-default 'id chan) + `((label . ,(channel-label chan users)) + (topic . ,(->> chan + (assoc-default 'topic) + (assoc-default 'value))) + (purpose . ,(->> chan + (assoc-default 'purpose) + (assoc-default 'value))))))) + (funcall cb))))))) + +(comment + (slack/get + "conversations.list" + '(("types" . "public_channel,private_channel,im,mpim")) + (lambda (data) (setq response-data data))) + + (slack/get + "conversations.list" + '(("types" . "im")) + (lambda (data) (setq response-data data))) + + (slack/conversations + (lambda (convos) (setq --conversations convos))) + + ) + +;; Messages + +(cl-defun slack/post-message + (&key text channel-id (on-success #'identity)) + (slack/post "chat.postMessage" + `((text . ,text) + (channel . ,channel-id) + (as_user . t)) + on-success)) + +(comment + + (slack/post-message + :text "hi slackbot" + :channel-id slackbot-channel-id + :on-success (lambda (data) (setq resp data))) + + ) + +;;; +;;; Posting code snippets to slack +;;; + +(defun prompt-for-channel (cb) + (slack/conversations + (lambda (conversations) + (ivy-read + "Select channel: " + ;; TODO want to potentially use purpose / topic stuff here + (-map (lambda (chan) (let ((label (assoc-default 'label (cdr chan))) + (id (car chan))) + (propertize label 'channel-id id))) + conversations) + :history 'slack/channel-history + :action (lambda (selected) + (let ((channel-id (get-text-property 0 'channel-id selected))) + (funcall cb channel-id) + (message "Sent message to %s" selected)))))) + nil) + +(defun slack-send-code-snippet (&optional snippet-text) + (interactive) + (when-let ((snippet-text (or snippet-text + (buffer-substring-no-properties (mark) (point))))) + (prompt-for-channel + (lambda (channel-id) + (slack/post-message + :text (format "```\n%s```" snippet-text) + :channel-id channel-id))))) + +(provide 'slack-snippets) diff --git a/snippets/haskell-mode/benchmark-module b/snippets/haskell-mode/benchmark-module new file mode 100644 index 0000000000..cbb1646e41 --- /dev/null +++ b/snippets/haskell-mode/benchmark-module @@ -0,0 +1,26 @@ +# key: bench +# name: benchmark-module +# expand-env: ((yas-indent-line (quote fixed))) +# -- +-------------------------------------------------------------------------------- +module ${1:`(if (not buffer-file-name) "Module" + (let ((name (file-name-sans-extension (buffer-file-name))) + (case-fold-search nil)) + (if (cl-search "bench/" name) + (replace-regexp-in-string "/" "." + (replace-regexp-in-string "^\/[^A-Z]*" "" + (car (last (split-string name "src"))))) + (file-name-nondirectory name))))`} ( benchmark, main ) where +-------------------------------------------------------------------------------- +import Bench.Prelude +-------------------------------------------------------------------------------- +import ${1:$(s-chop-suffix "Bench" yas-text)} +-------------------------------------------------------------------------------- + +main :: IO () +main = defaultMain [benchmark] + +-------------------------------------------------------------------------------- + +benchmark :: Benchmark +benchmark = bgroup "${1:$(->> yas-text (s-chop-suffix "Bench") (s-split ".") -last-item)}" [bench "something dumb" $ nf (1 +) (1 :: Int)] diff --git a/snippets/haskell-mode/header b/snippets/haskell-mode/header new file mode 100644 index 0000000000..4d665905f6 --- /dev/null +++ b/snippets/haskell-mode/header @@ -0,0 +1,6 @@ +# key: hh +# name: header +# expand-env: ((yas-indent-line 'fixed)) +# -- +---------------------------------------------------------------------- +$2 \ No newline at end of file diff --git a/snippets/haskell-mode/hedgehog-generator b/snippets/haskell-mode/hedgehog-generator new file mode 100644 index 0000000000..68863f7054 --- /dev/null +++ b/snippets/haskell-mode/hedgehog-generator @@ -0,0 +1,8 @@ +# key: gen +# name: Hedgehog Generator +# expand-env: ((yas-indent-line (quote fixed))) +# -- +gen${1:Foo} :: Gen $1 +gen$1 = do + $2 + pure $1{..} \ No newline at end of file diff --git a/snippets/haskell-mode/hedgehog-property b/snippets/haskell-mode/hedgehog-property new file mode 100644 index 0000000000..bf39a2a3ee --- /dev/null +++ b/snippets/haskell-mode/hedgehog-property @@ -0,0 +1,9 @@ +# -*- mode: snippet -*- +# name: Hedgehog Property +# key: hprop +# expand-env: ((yas-indent-line 'fixed)) +# -- +hprop_${1:somethingIsAlwaysTrue} :: Property +hprop_$1 = property $ do + ${2:x} <- forAll ${3:Gen.int $ Range.linear 1 100} + ${4:x === x} \ No newline at end of file diff --git a/snippets/haskell-mode/lens.field b/snippets/haskell-mode/lens.field new file mode 100644 index 0000000000..b22ea3d2e8 --- /dev/null +++ b/snippets/haskell-mode/lens.field @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: lens.field +# key: lens +# expand-env: ((yas-indent-line 'fixed)) +# -- +${1:field} :: Lens' ${2:Source} ${3:Target} +$1 = lens _${4:sourceField} $ \\${2:$(-> yas-text s-word-initials s-downcase)} ${4:$(-> yas-text s-word-initials s-downcase)} -> ${2:$(-> yas-text s-word-initials s-downcase)} { _$4 = ${4:$(-> yas-text s-word-initials s-downcase)} } \ No newline at end of file diff --git a/snippets/haskell-mode/module b/snippets/haskell-mode/module new file mode 100644 index 0000000000..ce7ebcb213 --- /dev/null +++ b/snippets/haskell-mode/module @@ -0,0 +1,32 @@ +# -*- mode: snippet -*- +# key: module +# name: module +# condition: (= (length "module") (current-column)) +# expand-env: ((yas-indent-line 'fixed)) +# contributor: Luke Hoersten +# -- +---------------------------------------------------------------------- +-- | +-- Module : $1 +-- Description : $2 +-- Maintainer : Griffin Smith +-- Maturity : ${3:Draft, Usable, Maintained, OR MatureAF} +-- +-- $4 +---------------------------------------------------------------------- +module ${1:`(if (not buffer-file-name) "Module" + (let ((name (file-name-sans-extension (buffer-file-name))) + (case-fold-search nil)) + (if (or (cl-search "src/" name) + (cl-search "test/" name)) + (replace-regexp-in-string "/" "." + (replace-regexp-in-string "^\/[^A-Z]*" "" + (car (last (split-string name "src"))))) + (file-name-nondirectory name))))`} + ( + ) where +---------------------------------------------------------------------- +import Prelude +---------------------------------------------------------------------- + +$0 diff --git a/snippets/haskell-mode/test-module b/snippets/haskell-mode/test-module new file mode 100644 index 0000000000..3183fdc72a --- /dev/null +++ b/snippets/haskell-mode/test-module @@ -0,0 +1,21 @@ +# -*- mode: snippet -*- +# name: test-module +# key: test +# -- +{-# LANGUAGE ApplicativeDo #-} +-------------------------------------------------------------------------------- +module ${1:`(if (not buffer-file-name) "Module" + (let ((name (file-name-sans-extension (buffer-file-name))) + (case-fold-search nil)) + (if (cl-search "test/" name) + (replace-regexp-in-string "/" "." + (replace-regexp-in-string "^\/[^A-Z]*" "" + (car (last (split-string name "src"))))) + (file-name-nondirectory name))))`} where +-------------------------------------------------------------------------------- +import Test.Prelude +import qualified Hedgehog.Gen as Gen +import qualified Hedgehog.Range as Range +-------------------------------------------------------------------------------- +import ${1:$(s-chop-suffix "Test" yas-text)} +-------------------------------------------------------------------------------- diff --git a/snippets/haskell-mode/undefined b/snippets/haskell-mode/undefined new file mode 100644 index 0000000000..7bcd99b571 --- /dev/null +++ b/snippets/haskell-mode/undefined @@ -0,0 +1,6 @@ +# -*- mode: snippet -*- +# name: undefined +# key: u +# expand-env: ((yas-indent-line 'fixed) (yas-wrap-around-region 'nil)) +# -- +undefined$1 \ No newline at end of file diff --git a/snippets/org-mode/date b/snippets/org-mode/date new file mode 100644 index 0000000000..297529cdac --- /dev/null +++ b/snippets/org-mode/date @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# key: date +# name: date.org +# -- +[`(format-time-string "%Y-%m-%d")`]$0 diff --git a/snippets/org-mode/date-time b/snippets/org-mode/date-time new file mode 100644 index 0000000000..fde469276c --- /dev/null +++ b/snippets/org-mode/date-time @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: date-time +# key: dt +# -- +[`(format-time-string "%Y-%m-%d %H:%m:%S")`] \ No newline at end of file diff --git a/snippets/org-mode/nologdone b/snippets/org-mode/nologdone new file mode 100644 index 0000000000..e5be85d6b3 --- /dev/null +++ b/snippets/org-mode/nologdone @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: nologdone +# key: nologdone +# -- +#+STARTUP: nologdone$0 \ No newline at end of file diff --git a/snippets/org-mode/source-block b/snippets/org-mode/source-block new file mode 100644 index 0000000000..3b7694557e --- /dev/null +++ b/snippets/org-mode/source-block @@ -0,0 +1,8 @@ +# -*- mode: snippet -*- +# name: source-block +# key: src +# expand-env: ((yas-indent-line 'fixed)) +# -- +#+BEGIN_SRC ${1:elisp} +$2 +#+END_SRC \ No newline at end of file diff --git a/snippets/snippet-mode/indent b/snippets/snippet-mode/indent new file mode 100644 index 0000000000..d38ffceafb --- /dev/null +++ b/snippets/snippet-mode/indent @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: indent +# key: indent +# -- +# expand-env: ((yas-indent-line 'fixed)) \ No newline at end of file diff --git a/snippets/text-mode/date b/snippets/text-mode/date new file mode 100644 index 0000000000..7b94311470 --- /dev/null +++ b/snippets/text-mode/date @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# name: date +# key: date +# -- +`(format-time-string "%Y-%m-%d")`$0 \ No newline at end of file diff --git a/splitjoin.el b/splitjoin.el new file mode 100644 index 0000000000..166672816b --- /dev/null +++ b/splitjoin.el @@ -0,0 +1,192 @@ +;;; private/grfn/splitjoin.el -*- lexical-binding: t; -*- + +(require 'dash) +(load! utils) + +;;; +;;; Vars +;;; + +(defvar +splitjoin/split-callbacks '() + "Alist mapping major mode symbol names to lists of split callbacks") + +(defvar +splitjoin/join-callbacks '() + "Alist mapping major mode symbol names to lists of join callbacks") + + + +;;; +;;; Definition macros +;;; + +(defmacro +splitjoin/defsplit (mode name &rest body) + `(setf + (alist-get ',name (alist-get ,mode +splitjoin/split-callbacks)) + (λ! () ,@body))) + +(defmacro +splitjoin/defjoin (mode name &rest body) + `(setf + (alist-get ',name (alist-get ,mode +splitjoin/join-callbacks)) + (λ! () ,@body))) + +;;; +;;; Commands +;;; + +(defun +splitjoin/split () + (interactive) + (when-let (callbacks (->> +splitjoin/split-callbacks + (alist-get major-mode) + (-map #'cdr))) + (find-if #'funcall callbacks))) + +(defun +splitjoin/join () + (interactive) + (when-let (callbacks (->> +splitjoin/join-callbacks + (alist-get major-mode) + (-map #'cdr))) + (find-if #'funcall callbacks))) + + +;;; +;;; Splits and joins +;;; TODO: this should probably go in a file-per-language +;;; + +(+splitjoin/defjoin + 'elixir-mode + join-do + (let* ((function-pattern (rx (and (zero-or-more whitespace) + "do" + (zero-or-more whitespace) + (optional (and "#" (zero-or-more anything))) + eol))) + (end-pattern (rx bol + (zero-or-more whitespace) + "end" + (zero-or-more whitespace) + eol)) + (else-pattern (rx bol + (zero-or-more whitespace) + "else" + (zero-or-more whitespace) + eol)) + (lineno (line-number-at-pos)) + (line (thing-at-point 'line t))) + (when-let ((do-start-pos (string-match function-pattern line))) + (cond + ((string-match-p end-pattern (get-line (inc lineno))) + (modify-then-indent + (goto-line-char do-start-pos) + (insert ",") + (goto-char (line-end-position)) + (insert ": nil") + (line-move 1) + (delete-line)) + t) + + ((string-match-p end-pattern (get-line (+ 2 lineno))) + (modify-then-indent + (goto-line-char do-start-pos) + (insert ",") + (goto-char (line-end-position)) + (insert ":") + (join-line t) + (line-move 1) + (delete-line)) + t) + + ((and (string-match-p else-pattern (get-line (+ 2 lineno))) + (string-match-p end-pattern (get-line (+ 4 lineno)))) + (modify-then-indent + (goto-line-char do-start-pos) + (insert ",") + (goto-char (line-end-position)) + (insert ":") + (join-line t) + (goto-eol) + (insert ",") + (join-line t) + (goto-eol) + (insert ":") + (join-line t) + (line-move 1) + (delete-line)) + t))))) + +(comment + (string-match (rx (and bol + "if " + (one-or-more anything) + "," + (zero-or-more whitespace) + "do:" + (one-or-more anything) + "," + (zero-or-more whitespace) + "else:" + (one-or-more anything))) + "if 1, do: nil, else: nil") + + ) + +(+splitjoin/defsplit + 'elixir-mode + split-do-with-optional-else + (let* ((if-with-else-pattern (rx (and bol + (one-or-more anything) + "," + (zero-or-more whitespace) + "do:" + (one-or-more anything) + (optional + "," + (zero-or-more whitespace) + "else:" + (one-or-more anything))))) + (current-line (get-line))) + (when (string-match if-with-else-pattern current-line) + (modify-then-indent + (assert (goto-regex-on-line ",[[:space:]]*do:")) + (delete-char 1) + (assert (goto-regex-on-line ":")) + (delete-char 1) + (insert "\n") + (when (goto-regex-on-line-r ",[[:space:]]*else:") + (delete-char 1) + (insert "\n") + (assert (goto-regex-on-line ":")) + (delete-char 1) + (insert "\n")) + (goto-eol) + (insert "\nend")) + t))) + +(comment + (+splitjoin/defsplit 'elixir-mode split-def + (let ((function-pattern (rx (and "," + (zero-or-more whitespace) + "do:"))) + (line (thing-at-point 'line t))) + (when-let (idx (string-match function-pattern line)) + (let ((beg (line-beginning-position)) + (orig-line-char (- (point) (line-beginning-position)))) + (save-mark-and-excursion + (goto-line-char idx) + (delete-char 1) + (goto-line-char (string-match ":" (thing-at-point 'line t))) + (delete-char 1) + (insert "\n") + (goto-eol) + (insert "\n") + (insert "end") + (evil-indent beg (+ (line-end-position) 1)))) + (goto-line-char orig-line-char) + t)))) + +(+splitjoin/defjoin + 'elixir-mode + join-if-with-else + (let* ((current-line (thing-at-point 'line))))) + +(provide 'splitjoin) diff --git a/tests/splitjoin_test.el b/tests/splitjoin_test.el new file mode 100644 index 0000000000..6495a1a595 --- /dev/null +++ b/tests/splitjoin_test.el @@ -0,0 +1,68 @@ +;;; private/grfn/tests/splitjoin_test.el -*- lexical-binding: t; -*- + +(require 'ert) +;; (load! 'splitjoin) +;; (load! 'utils) +; (require 'splitjoin) + +;;; Helpers + +(defvar *test-buffer* nil) +(make-variable-buffer-local '*test-buffer*) + +(defun test-buffer () + (when (not *test-buffer*) + (setq *test-buffer* (get-buffer-create "test-buffer"))) + *test-buffer*) + +(defmacro with-test-buffer (&rest body) + `(with-current-buffer (test-buffer) + ,@body)) + +(defun set-test-buffer-mode (mode) + (let ((mode (if (functionp mode) mode + (-> mode symbol-name (concat "-mode") intern)))) + (assert (functionp mode)) + (with-test-buffer (funcall mode)))) + +(defmacro set-test-buffer-contents (contents) + (with-test-buffer + (erase-buffer) + (insert contents))) + +(defun test-buffer-contents () + (with-test-buffer (substring-no-properties (buffer-string)))) + +(defmacro assert-test-buffer-contents (expected-contents) + `(should (equal (string-trim (test-buffer-contents)) + (string-trim ,expected-contents)))) + +(defmacro should-join-to (mode original-contents expected-contents) + `(progn + (set-test-buffer-mode ,mode) + (set-test-buffer-contents ,original-contents) + (with-test-buffer (+splitjoin/join)) + (assert-test-buffer-contents ,expected-contents))) + +(defmacro should-split-to (mode original-contents expected-contents) + `(progn + (set-test-buffer-mode ,mode) + (set-test-buffer-contents ,original-contents) + (with-test-buffer (+splitjoin/split)) + (assert-test-buffer-contents ,expected-contents))) + +(defmacro should-splitjoin (mode joined-contents split-contents) + `(progn + (should-split-to ,mode ,joined-contents ,split-contents) + (should-join-to ,mode ,split-contents ,joined-contents))) + +;;; Tests + +;; Elixir +(ert-deftest elixir-if-splitjoin-test () + (should-splitjoin 'elixir + "if predicate?(), do: result" + "if predicate?() do + result +end")) + diff --git a/themes/grfn-solarized-light-theme.el b/themes/grfn-solarized-light-theme.el new file mode 100644 index 0000000000..338cfabfcc --- /dev/null +++ b/themes/grfn-solarized-light-theme.el @@ -0,0 +1,85 @@ +(require 'solarized) + +;; (defun grfn-solarized-theme () +;; (custom-theme-set-faces +;; theme-name +;; `(font-lock-doc-face ((,class (:foreground ,s-base1)))) +;; `(font-lock-preprocessor-face ((,class (:foreground ,red)))) +;; `(font-lock-keyword-face ((,class (:foreground ,green)))) + +;; `(elixir-attribute-face ((,class (:foreground ,blue)))) +;; `(elixir-atom-face ((,class (:foreground ,cyan)))))) + +(setq +solarized-s-base03 "#002b36" + +solarized-s-base02 "#073642" + ;; emphasized content + +solarized-s-base01 "#586e75" + ;; primary content + +solarized-s-base00 "#657b83" + +solarized-s-base0 "#839496" + ;; comments + +solarized-s-base1 "#93a1a1" + ;; background highlight light + +solarized-s-base2 "#eee8d5" + ;; background light + +solarized-s-base3 "#fdf6e3" + + ;; Solarized accented colors + +solarized-yellow "#b58900" + +solarized-orange "#cb4b16" + +solarized-red "#dc322f" + +solarized-magenta "#d33682" + +solarized-violet "#6c71c4" + +solarized-blue "#268bd2" + +solarized-cyan "#2aa198" + +solarized-green "#859900" + + ;; Darker and lighter accented colors + ;; Only use these in exceptional circumstances! + +solarized-yellow-d "#7B6000" + +solarized-yellow-l "#DEB542" + +solarized-orange-d "#8B2C02" + +solarized-orange-l "#F2804F" + +solarized-red-d "#990A1B" + +solarized-red-l "#FF6E64" + +solarized-magenta-d "#93115C" + +solarized-magenta-l "#F771AC" + +solarized-violet-d "#3F4D91" + +solarized-violet-l "#9EA0E5" + +solarized-blue-d "#00629D" + +solarized-blue-l "#69B7F0" + +solarized-cyan-d "#00736F" + +solarized-cyan-l "#69CABF" + +solarized-green-d "#546E00" + +solarized-green-l "#B4C342") + + +(deftheme grfn-solarized-light "The light variant of Griffin's solarized theme") + +(create-solarized-theme + 'light 'grfn-solarized-light + (lambda () + (custom-theme-set-faces + 'grfn-solarized-light + `(font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) + `(font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) + `(font-lock-keyword-face ((t (:foreground ,+solarized-green)))) + + `(elixir-attribute-face ((t (:foreground ,+solarized-blue)))) + `(elixir-atom-face ((t (:foreground ,+solarized-cyan)))) + ) + + )) + +(custom-theme-set-faces + 'grfn-solarized-light + `(font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) + `(font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) + `(font-lock-keyword-face ((t (:foreground ,+solarized-green)))) + + `(elixir-attribute-face ((t (:foreground ,+solarized-blue)))) + `(elixir-atom-face ((t (:foreground ,+solarized-cyan)))) + ) + +(provide-theme 'grfn-solarized-light) + diff --git a/utils.el b/utils.el new file mode 100644 index 0000000000..d6d1d5722b --- /dev/null +++ b/utils.el @@ -0,0 +1,92 @@ +;;; private/grfn/utils.el -*- lexical-binding: t; -*- + + +;; Elisp Extras + +(defmacro comment (&rest _body) + "Comment out one or more s-expressions" + nil) + +(defun inc (x) "Returns x + 1" (+ 1 x)) +(defun dec (x) "Returns x - 1" (- x 1)) + + +;; +;; Text editing utils +;; + +;; Reading strings + +(defun get-char (&optional point) + "Get the character at the given `point' (defaulting to the current point), +without properties" + (let ((point (or point (point)))) + (buffer-substring-no-properties point (+ 1 point)))) + +(defun get-line (&optional lineno) + "Read the line number `lineno', or the current line if `lineno' is nil, and +return it as a string stripped of all text properties" + (let ((current-line (line-number-at-pos))) + (if (or (not lineno) + (= current-line lineno)) + (thing-at-point 'line t) + (save-mark-and-excursion + (line-move (- lineno (line-number-at-pos))) + (thing-at-point 'line t))))) + +(defun get-line-point () + "Get the position in the current line of the point" + (- (point) (line-beginning-position))) + +;; Moving in the file + +(defun goto-line-char (pt) + "Moves the point to the given position expressed as an offset from the start +of the line" + (goto-char (+ (line-beginning-position) pt))) + +(defun goto-eol () + "Moves to the end of the current line" + (goto-char (line-end-position))) + +(defun goto-regex-on-line (regex) + "Moves the point to the first occurrence of `regex' on the current line. +Returns nil if the regex did not match, non-nil otherwise" + (when-let ((current-line (get-line)) + (line-char (string-match regex current-line))) + (goto-line-char line-char))) + +(defun goto-regex-on-line-r (regex) + "Moves the point to the *last* occurrence of `regex' on the current line. +Returns nil if the regex did not match, non-nil otherwise" + (when-let ((current-line (get-line)) + (modified-regex (concat ".*\\(" regex "\\)")) + (_ (string-match modified-regex current-line)) + (match-start (match-beginning 1))) + (goto-line-char match-start))) + +(comment + (progn + (string-match (rx (and (zero-or-more anything) + (group "foo" "foo"))) + "foofoofoo") + (match-beginning 1))) + +;; Changing file contents + +(defun delete-line () + "Remove the line at the current point" + (delete-region (line-beginning-position) + (inc (line-end-position)))) + +(defmacro modify-then-indent (&rest body) + "Modify text in the buffer according to body, then re-indent from where the + cursor started to where the cursor ended up, then return the cursor to where + it started." + `(let ((beg (line-beginning-position)) + (orig-line-char (- (point) (line-beginning-position)))) + (atomic-change-group + (save-mark-and-excursion + ,@body + (evil-indent beg (+ (line-end-position) 1)))) + (goto-line-char orig-line-char))) -- cgit 1.4.1 From f95d025d1fdddc6b781662786d5d52e20d3f1d7e Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Fri, 4 May 2018 17:01:37 -0400 Subject: fix cW for commit-wip --- config.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.el b/config.el index 595faa6d33..c30b8f2bc2 100644 --- a/config.el +++ b/config.el @@ -350,10 +350,10 @@ (defun magit-commit-wip () (interactive) - (magit-commit "-m wip")) + (magit-commit '("-m" "wip"))) -;; (magit-define-popup-action 'magit-commit-popup -;; ?w "WIP" 'magit-commit-wip) +(magit-define-popup-action 'magit-commit-popup + ?W "WIP" 'magit-commit-wip) ;; (defun grfn/split-window-more-sensibly (&optional window) ;; (let ((window (or window (selected-window)))) -- cgit 1.4.1 From 8ba14144a32ee053d7fa27b836c632eed48b6f54 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Fri, 31 Aug 2018 13:31:14 -0400 Subject: Update to latest doom, agda stuff, misc --- +bindings.el | 44 ++++-- config.el | 297 ++++++++++++++++++++++++++++---------- init.el | 214 +++++++++++++++++++-------- packages.el | 17 +++ snippets/haskell-mode/header | 3 +- snippets/haskell-mode/module | 8 +- snippets/haskell-mode/test-module | 5 +- snippets/org-mode/source-block | 8 - splitjoin.el | 2 +- 9 files changed, 436 insertions(+), 162 deletions(-) delete mode 100644 snippets/org-mode/source-block diff --git a/+bindings.el b/+bindings.el index 6609c9010c..bfb40424b3 100644 --- a/+bindings.el +++ b/+bindings.el @@ -1,6 +1,6 @@ ;; private/grfn/+bindings.el -*- lexical-binding: t; -*- -(load! utils) +(load! "utils") (require 'f) (defmacro find-file-in! (path &optional project-p) @@ -63,7 +63,7 @@ (forward-sexp) (insert " ")) -(load! splitjoin) +(load! "splitjoin") (defun +hlissner/install-snippets () "Install my snippets from https://github.com/hlissner/emacs-snippets into @@ -89,7 +89,7 @@ private/hlissner/snippets." projectile-require-project-root projectile-cached-buffer-file-name projectile-cached-project-root) - (call-interactively (command-remapping #'projectile-find-file)))) + (call-interactively #'projectile-find-file))) (defun ,(intern (format "+hlissner/browse-%s" name)) () (interactive) (let ((default-directory ,dir)) @@ -346,7 +346,8 @@ private/hlissner/snippets." :desc "Slack IM" :n "i" #'slack-im-select :desc "Slack Channel" :n "c" #'slack-channel-select - :desc "Slack Unreads" :n "u" #'slack-channel-select + :desc "Slack Group" :n "g" #'slack-group-select + :desc "Slack Unreads" :n "u" #'slack-select-unread-rooms ;; applications :desc "APP: elfeed" :n "E" #'=rss @@ -1015,12 +1016,35 @@ private/hlissner/snippets." (get-buffer-process (current-buffer)) "main"))) +(defun grfn/run-sputnik-test-for-file () + (interactive) + (haskell-interactive-mode-)) + (map! (:map haskell-mode-map - :n "K" 'intero-info - :n "g d" 'intero-goto-definition - :n "g SPC" 'intero-repl-load - :n "g \\" 'intero-repl - :n "g y" 'intero-type-at - :n "gET" 'grfn/intero-run-main)) + :n "K" 'lsp-info-under-point + :n "g d" 'lsp-ui-peek-find-definitions + :n "g r" 'lsp-ui-peek-find-references + ;; :n "g SPC" 'intero-repl-load + :n "g \\" '+haskell/repl + ;; :n "g y" 'intero-type-at + ;; :n "g RET" 'grfn/run-sputnik-test-for-file + + (:localleader + :desc "Apply action" :n "a" 'lsp-execute-code-action + :desc "Rename symbol" :n "r" 'lsp-rename)) + + (:after agda2-mode + (:map agda2-mode-map + :n "g SPC" 'agda2-load + :n "g d" 'agda2-goto-definition-keyboard + :n "] g" 'agda2-next-goal + :n "[ g" 'agda2-previous-goal + + (:localleader + :desc "Give" :n "SPC" 'agda2-give + :desc "Refine" :n "r" 'agda2-refine + :desc "Auto" :n "a" 'agda2-auto + :desc "Goal type and context" :n "t" 'agda2-goal-and-context + :desc "Goal type and context and inferred" :n ";" 'agda2-goal-and-context-and-inferred)))) diff --git a/config.el b/config.el index c30b8f2bc2..1646314ab7 100644 --- a/config.el +++ b/config.el @@ -1,14 +1,15 @@ ;;; private/grfn/config.el -*- lexical-binding: t; -*- + (defvar +grfn-dir (file-name-directory load-file-name)) (defvar +grfn-snippets-dir (expand-file-name "snippets/" +grfn-dir)) ;; (when (featurep! :feature evil) - (load! +bindings) - (load! +commands)) + (load! "+bindings") + (load! "+commands")) -(load! +private) +(load! "+private") (require 'dash) @@ -52,11 +53,6 @@ (append (list '+grfn-snippets-dir) (delq 'yas-installed-snippets-dir yas-snippet-dirs)))) -;; completion/helm -(after! helm - ;; Hide header lines in helm. I don't like them - (set-face-attribute 'helm-source-header nil :height 0.1)) - (after! company (setq company-idle-delay 0.2 company-minimum-prefix-length 1)) @@ -96,6 +92,51 @@ ;; Should really figure out which of these is correct, eventually +(setq +solarized-s-base03 "#002b36" + +solarized-s-base02 "#073642" + ;; emphasized content + +solarized-s-base01 "#586e75" + ;; primary content + +solarized-s-base00 "#657b83" + +solarized-s-base0 "#839496" + ;; comments + +solarized-s-base1 "#93a1a1" + ;; background highlight light + +solarized-s-base2 "#eee8d5" + ;; background light + +solarized-s-base3 "#fdf6e3" + + ;; Solarized accented colors + +solarized-yellow "#b58900" + +solarized-orange "#cb4b16" + +solarized-red "#dc322f" + +solarized-magenta "#d33682" + +solarized-violet "#6c71c4" + +solarized-blue "#268bd2" + +solarized-cyan "#2aa198" + +solarized-green "#859900" + + ;; Darker and lighter accented colors + ;; Only use these in exceptional circumstances! + +solarized-yellow-d "#7B6000" + +solarized-yellow-l "#DEB542" + +solarized-orange-d "#8B2C02" + +solarized-orange-l "#F2804F" + +solarized-red-d "#990A1B" + +solarized-red-l "#FF6E64" + +solarized-magenta-d "#93115C" + +solarized-magenta-l "#F771AC" + +solarized-violet-d "#3F4D91" + +solarized-violet-l "#9EA0E5" + +solarized-blue-d "#00629D" + +solarized-blue-l "#69B7F0" + +solarized-cyan-d "#00736F" + +solarized-cyan-l "#69CABF" + +solarized-green-d "#546E00" + +solarized-green-l "#B4C342") + +(set-cursor-color +solarized-s-base02) + (after! doom-theme (set-face-foreground 'font-lock-doc-face +solarized-s-base1) (set-face-foreground 'org-block +solarized-s-base00) @@ -149,7 +190,7 @@ org-tags-column -130 org-ellipsis "⤵" org-capture-templates - '(("t" "Todo" entry + `(("t" "Todo" entry (file+headline +org-default-todo-file "Inbox") "* TODO %?\n%i" :prepend t :kill-buffer t) @@ -157,13 +198,17 @@ (file+headline +org-default-notes-file "Inbox") "* %u %?\n%i" :prepend t :kill-buffer t)) org-deadline-warning-days 1 - org-agenda-skip-scheduled-if-deadline-is-shown 't) + org-agenda-skip-scheduled-if-deadline-is-shown 'todo + org-agenda-custom-commands + '(("p" "Sprint Tasks" tags-todo "sprint") + ("i" "Inbox" tags "inbox"))) (set-face-foreground 'org-block +solarized-s-base00) (add-hook! org-mode (add-hook! evil-normal-state-entry-hook #'org-align-all-tags)) (setf (alist-get 'file org-link-frame-setup) 'find-file-other-window) - (set-face-foreground 'org-block +solarized-s-base00)) + (set-face-foreground 'org-block +solarized-s-base00) + ) (after! magit (setq git-commit-summary-max-length 50) @@ -194,27 +239,31 @@ (let ((m-symbols '(("`mappend`" . "⊕") - ("<>" . "⊕")))) + ("<>" . "⊕") + ("`elem`" . "∈") + ("`notElem`" . "∉")))) (dolist (item m-symbols) (add-to-list 'haskell-font-lock-symbols-alist item))) (setq haskell-font-lock-symbols t) (add-hook! haskell-mode - (intero-mode) - (flycheck-add-next-checker - 'intero - 'haskell-hlint) - (set-fill-column 100)) + ;; (intero-mode) + (lsp-mode) + ;; (flycheck-add-next-checker + ;; 'intero + ;; 'haskell-hlint) + (set-fill-column 80) + (setq evil-shift-width 2)) ;; (load! org-clubhouse) (add-hook! org-mode #'org-clubhouse-mode) -(load! slack-snippets) +(load! "slack-snippets") (after! magit (require 'evil-magit) - (require 'magithub) + ;; (require 'magithub) ) ; (require 'auth-password-store) @@ -244,38 +293,40 @@ ;; https://github.com/alpaker/Fill-Column-Indicator/issues/67#issuecomment-195611974 -(add-hook 'prog-mode-hook #'fci-mode) -(after! fill-column-indicator - (add-hook 'prog-mode-hook #'fci-mode) - (defvar eos/fci-disabled nil) - (make-variable-buffer-local 'eos/fci-disabled) - - ;; Add a hook that disables fci if enabled when the window changes and it - ;; isn't wide enough to display it. - (defun eos/maybe-disable-fci () - (interactive) - ;; Disable FCI if necessary - (when (and fci-mode - (< (window-width) (or fci-rule-column fill-column))) - (fci-mode -1) - (setq-local eos/fci-disabled t)) - ;; Enable FCI if necessary - (when (and eos/fci-disabled - (eq fci-mode nil) - (> (window-width) (or fci-rule-column fill-column))) - (fci-mode 1) - (setq-local eos/fci-disabled nil))) - - (defun eos/add-fci-disabling-hook () - (interactive) - (add-hook 'window-configuration-change-hook - #'eos/maybe-disable-fci)) - - (add-hook 'prog-mode-hook #'eos/add-fci-disabling-hook)) +;; (add-hook 'prog-mode-hook #'fci-mode) +;; (after! fill-column-indicator +;; (add-hook 'prog-mode-hook #'fci-mode) +;; (defvar eos/fci-disabled nil) +;; (make-variable-buffer-local 'eos/fci-disabled) + +;; ;; Add a hook that disables fci if enabled when the window changes and it +;; ;; isn't wide enough to display it. +;; (defun eos/maybe-disable-fci () +;; (interactive) +;; ;; Disable FCI if necessary +;; (when (and fci-mode +;; (< (window-width) (or fci-rule-column fill-column))) +;; (fci-mode -1) +;; (setq-local eos/fci-disabled t)) +;; ;; Enable FCI if necessary +;; (when (and eos/fci-disabled +;; (eq fci-mode nil) +;; (> (window-width) (or fci-rule-column fill-column))) +;; (fci-mode 1) +;; (setq-local eos/fci-disabled nil))) + +;; (defun eos/add-fci-disabling-hook () +;; (interactive) +;; (add-hook 'window-configuration-change-hook +;; #'eos/maybe-disable-fci)) + +;; (add-hook 'prog-mode-hook #'eos/add-fci-disabling-hook)) ;;; Javascript +(require 'smartparens) + (setq js-indent-level 2) (require 'prettier-js) @@ -292,8 +343,32 @@ (flycheck-add-mode 'javascript-eslint 'flow-minor-mode) (flycheck-add-next-checker 'javascript-flow 'javascript-eslint)) + (require 'flow-minor-mode) +(remove-hook 'js2-mode-hook 'tide-setup t) + +(require 'company-flow) +(eval-after-load 'company + (lambda () (add-to-list 'company-backends 'company-flow))) +(defun flow/set-flow-executable () + (interactive) + (let* ((os (pcase system-type + ('darwin "osx") + ('gnu/linux "linux64") + (_ nil))) + (root (locate-dominating-file buffer-file-name "node_modules/flow-bin")) + (executable (car (file-expand-wildcards + (concat root "node_modules/flow-bin/*" os "*/flow"))))) + (setq-local company-flow-executable executable) + ;; These are not necessary for this package, but a good idea if you use + ;; these other packages + (setq-local flow-minor-default-binary executable) + (setq-local flycheck-javascript-flow-executable executable))) + +;; Set this to the mode you use, I use rjsx-mode +(add-hook 'rjsx-mode-hook #'flow/set-flow-executable t) + ;; Auto-format Haskell on save, with a combination of hindent + brittany @@ -352,8 +427,9 @@ (interactive) (magit-commit '("-m" "wip"))) -(magit-define-popup-action 'magit-commit-popup - ?W "WIP" 'magit-commit-wip) +(after! magit + (magit-define-popup-action 'magit-commit-popup + ?W "WIP" 'magit-commit-wip)) ;; (defun grfn/split-window-more-sensibly (&optional window) ;; (let ((window (or window (selected-window)))) @@ -375,35 +451,104 @@ ;; (with-selected-window window ;; (split-window-below)))))))) -;; (def-package! lsp-mode -;; :after (:any haskell-mode) -;; :config -;; (lsp-mode)) - -;; (def-package! lsp-ui -;; :after lsp-mode -;; :config -;; (setq lsp-ui-flycheck-enable t) -;; (setq imenu-auto-rescan t) -;; (set-face-background 'lsp-ui-doc-background +solarized-s-base2) -;; (set-face-background 'lsp-face-highlight-read +solarized-s-base2) -;; (set-face-background 'lsp-face-highlight-orite +solarized-s-base2) -;; :hook -;; (lsp-mode . lsp-ui-mode) -;; (lsp-ui-mode . flycheck-mode)) - -;; (def-package! company-lsp -;; :after (lsp-mode lsp-ui) -;; :config -;; (setq company-backends '(company-lsp)) -;; (setq company-lsp-async t)) - -;; (def-package! lsp-haskell -;; :after (lsp-mode lsp-ui haskell-mode) -;; :hook -;; (haskell-mode . lsp-haskell-enable)) +(def-package! lsp-mode + :after (:any haskell-mode) + :config + (lsp-mode) + (setq lsp-project-whitelist '("^/home/griffin/code/urb/grid/$") + lsp-response-timeout 60) + :hook + (haskell-mode . lsp-mode)) + +(def-package! lsp-ui + :after lsp-mode + :config + (setq lsp-ui-flycheck-enable t) + (setq imenu-auto-rescan t) + (set-face-background 'lsp-ui-doc-background +solarized-s-base2) + (set-face-background 'lsp-face-highlight-read +solarized-s-base2) + (set-face-background 'lsp-face-highlight-write +solarized-s-base2) + :hook + (lsp-mode . lsp-ui-mode) + (lsp-ui-mode . flycheck-mode)) + +(def-package! company-lsp + :after (lsp-mode lsp-ui) + :config + (setq company-backends '(company-lsp)) + (setq company-lsp-async t)) + +(def-package! lsp-haskell + :after (lsp-mode lsp-ui haskell-mode) + :hook + (haskell-mode . lsp-haskell-enable) + :config + (setq lsp-haskell-process-path-hie "/home/griffin/.local/bin/hie-wrapper")) + +(def-package! lsp-imenu + :after (lsp-mode lsp-ui) + :hook + (lsp-after-open . lsp-enable-imenu)) (def-package! evil-magit :after (magit)) (def-package! writeroom-mode) + +(def-package! graphql-mode) + +(require 'whitespace) +(setq whitespace-style '(face lines-tail)) +(global-whitespace-mode t) +(add-hook! 'org-mode-hook (lambda () (whitespace-mode -1))) + +(set-face-foreground 'whitespace-line +solarized-red) +(set-face-attribute 'whitespace-line nil :underline 't) + +;; (set-face-background 'ivy-posframe +solarized-s-base3) +;; (set-face-foreground 'ivy-posframe +solarized-s-base01) + +(let ((base03 "#002b36") + (base02 "#073642") + (base01 "#586e75") + (base00 "#657b83") + (base0 "#839496") + (base1 "#93a1a1") + (base2 "#eee8d5") + (base3 "#fdf6e3") + (yellow "#b58900") + (orange "#cb4b16") + (red "#dc322f") + (magenta "#d33682") + (violet "#6c71c4") + (blue "#268bd2") + (cyan "#2aa198") + (green "#859900")) + (custom-set-faces + `(agda2-highlight-keyword-face ((t (:foreground ,green)))) + `(agda2-highlight-string-face ((t (:foreground ,cyan)))) + `(agda2-highlight-number-face ((t (:foreground ,violet)))) + `(agda2-highlight-symbol-face ((((background ,base3)) (:foreground ,base01)))) + `(agda2-highlight-primitive-type-face ((t (:foreground ,blue)))) + `(agda2-highlight-bound-variable-face ((t nil))) + `(agda2-highlight-inductive-constructor-face ((t (:foreground ,green)))) + `(agda2-highlight-coinductive-constructor-face ((t (:foreground ,yellow)))) + `(agda2-highlight-datatype-face ((t (:foreground ,blue)))) + `(agda2-highlight-field-face ((t (:foreground ,red)))) + `(agda2-highlight-function-face ((t (:foreground ,blue)))) + `(agda2-highlight-module-face ((t (:foreground ,yellow)))) + `(agda2-highlight-postulate-face ((t (:foreground ,blue)))) + `(agda2-highlight-primitive-face ((t (:foreground ,blue)))) + `(agda2-highlight-record-face ((t (:foreground ,blue)))) + `(agda2-highlight-dotted-face ((t nil))) + `(agda2-highlight-operator-face ((t nil))) + `(agda2-highlight-error-face ((t (:foreground ,red :underline t)))) + `(agda2-highlight-unsolved-meta-face ((t (:background ,base2)))) + `(agda2-highlight-unsolved-constraint-face ((t (:background ,base2)))) + `(agda2-highlight-termination-problem-face ((t (:background ,orange :foreground ,base03)))) + `(agda2-highlight-incomplete-pattern-face ((t (:background ,orange :foreground ,base03)))) + `(agda2-highlight-typechecks-face ((t (:background ,cyan :foreground ,base03)))))) + +;; (with-eval-after-load 'intero +;; (setq intero-package-version "0.1.31")) + diff --git a/init.el b/init.el index c07ce23ffe..2948da3333 100644 --- a/init.el +++ b/init.el @@ -1,8 +1,157 @@ ;;; private/grfn/init.el -*- lexical-binding: t; -*- -;; An extra measure to prevent the flash of unstyled mode-line while Emacs is -;; booting up (when Doom is byte-compiled). -(setq-default mode-line-format nil) + +(doom! :feature + ;debugger ; FIXME stepping through code, to help you add bugs + eval ; run code, run (also, repls) + (evil +everywhere); come to the dark side, we have cookies + file-templates ; auto-snippets for empty files + (lookup ; helps you navigate your code and documentation + +devdocs ; ...on devdocs.io online + +docsets) ; ...or in Dash docsets locally + snippets ; my elves. They type so I don't have to + spellcheck ; tasing you for misspelling mispelling + (syntax-checker ; tasing you for every semicolon you forget + +childframe) ; use childframes for error popups (Emacs 26+ only) + workspaces ; tab emulation, persistence & separate workspaces + + :completion + (company ; the ultimate code completion backend + +auto) ; as-you-type code completion + ;(helm ; the *other* search engine for love and life + ; +fuzzy) ; enable fuzzy search backend for helm + ;ido ; the other *other* search engine... + (ivy ; a search engine for love and life + +fuzzy) ; enable fuzzy search backend for ivy + + :ui + doom ; what makes DOOM look the way it does + doom-dashboard ; a nifty splash screen for Emacs + doom-modeline ; a snazzy Atom-inspired mode-line + doom-quit ; DOOM quit-message prompts when you quit Emacs + evil-goggles ; display visual hints when editing in evil + ;fci ; a `fill-column' indicator + hl-todo ; highlight TODO/FIXME/NOTE tags + ;modeline ; snazzy, Atom-inspired modeline, plus API + nav-flash ; blink the current line after jumping + ;neotree ; a project drawer, like NERDTree for vim + ;treemacs ; a project drawer, like neotree but cooler + (popup ; tame sudden yet inevitable temporary windows + +all ; catch all popups that start with an asterix + +defaults) ; default popup rules + pretty-code ; replace bits of code with pretty symbols + ;tabbar ; FIXME an (incomplete) tab bar for Emacs + unicode ; extended unicode support for various languages + vc-gutter ; vcs diff in the fringe + vi-tilde-fringe ; fringe tildes to mark beyond EOB + window-select ; visually switch windows + + :editor + ;(format +onsave) ; automated prettiness + ;multiple-cursors ; editing in many places at once + ;parinfer ; turn lisp into python, sort of + rotate-text ; cycle region at point between text candidates + + :emacs + dired ; making dired pretty [functional] + ediff ; comparing files in Emacs + electric ; smarter, keyword-based electric-indent + ;eshell ; a consistent, cross-platform shell (WIP) + hideshow ; basic code-folding support + imenu ; an imenu sidebar and searchable code index + ;term ; terminals in Emacs + vc ; version-control and Emacs, sitting in a tree + + :tools + editorconfig ; let someone else argue about tabs vs spaces + ;ein ; tame Jupyter notebooks with emacs + gist ; interacting with github gists + ;macos ; MacOS-specific commands + make ; run make tasks from Emacs + magit ; + password-store ; password manager for nerds + pdf ; pdf enhancements + ;prodigy ; FIXME managing external services & code builders + ;rgb ; creating color strings + ;tmux ; an API for interacting with tmux + ;upload ; map local to remote projects via ssh/ftp + ;wakatime + + :lang + ;assembly ; assembly for fun or debugging + ;(cc +irony +rtags); C/C++/Obj-C madness + clojure ; java with a lisp + ;common-lisp ; if you've seen one lisp, you've seen them all + ;crystal ; ruby at the speed of c + ;csharp ; unity, .NET, and mono shenanigans + data ; config/data formats + erlang ; an elegant language for a more civilized age + elixir ; erlang done right + ;elm ; care for a cup of TEA? + emacs-lisp ; drown in parentheses + ;ess ; emacs speaks statistics + ;go ; the hipster dialect + ;(haskell +intero) ; a language that's lazier than I am + haskell ; a language that's lazier than I am + ;hy ; readability of scheme w/ speed of python + ;(java +meghanada) ; the poster child for carpal tunnel syndrome + javascript ; all(hope(abandon(ye(who(enter(here)))))) + ;julia ; a better, faster MATLAB + latex ; writing papers in Emacs has never been so fun + ;ledger ; an accounting system in Emacs + ;lua ; one-based indices? one-based indices + markdown ; writing docs for people to ignore + ;nim ; python + lisp at the speed of c + nix ; I hereby declare "nix geht mehr!" + ;ocaml ; an objective camel + (org ; organize your plain life in plain text + +attach ; custom attachment system + +babel ; running code in org + +capture ; org-capture in and outside of Emacs + +export ; Exporting org to whatever you want + +present) ; Emacs for presentations + ;perl ; write code no one else can comprehend + ;php ; perl's insecure younger brother + ;plantuml ; diagrams for confusing people more + ;purescript ; javascript, but functional + ;python ; beautiful is better than ugly + ;qt ; the 'cutest' gui framework ever + ;racket ; a DSL for DSLs + ;rest ; Emacs as a REST client + ruby ; 1.step do {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"} + ;rust ; Fe2O3.unwrap().unwrap().unwrap().unwrap() + ;scala ; java, but good + (sh +fish) ; she sells (ba|z)sh shells on the C xor + ;solidity ; do you need a blockchain? No. + ;swift ; who asked for emoji variables? + web ; the tubes + + ;; Applications are complex and opinionated modules that transform Emacs + ;; toward a specific purpose. They may have additional dependencies and + ;; should be loaded late. + :app + ;(email +gmail) ; emacs as an email client + irc ; how neckbeards socialize + ;(rss +org) ; emacs as an RSS reader + ;twitter ; twitter client https://twitter.com/vnought + ;(write ; emacs as a word processor (latex + org + markdown) + ; +wordnut ; wordnet (wn) search + ; +langtool) ; a proofreader (grammar/style check) for Emacs + + :collab + ;floobits ; peer programming for a price + ;impatient-mode ; show off code over HTTP + + :config + ;; For literate config users. This will tangle+compile a config.org + ;; literate config in your `doom-private-dir' whenever it changes. + ;literate + + ;; The default module set reasonable defaults for Emacs. It also provides + ;; a Spacemacs-inspired keybinding scheme, a custom yasnippet library, + ;; and additional ex commands for evil-mode. Use it as a reference for + ;; your own modules. + (default +bindings +snippets +evil-commands)) ;; I've swapped these keys on my keyboard @@ -12,9 +161,6 @@ (setq user-mail-address "root@gws.fyi" user-full-name "Griffin Smith") -(add-hook! doom-big-font-mode - (setq +doom-modeline-height (if doom-big-font-mode 37 29))) - ; (def-package-hook! doom-themes :disable) (after! rust @@ -192,56 +338,6 @@ ;; 'haskell-mode ;; `((,(rx "-- |") . 'haskell-keyword-face))) -;;; * Column Marker -(defun sanityinc/fci-enabled-p () (symbol-value 'fci-mode)) - -(defvar sanityinc/fci-mode-suppressed nil) -(make-variable-buffer-local 'sanityinc/fci-mode-suppressed) - -(defadvice popup-create (before suppress-fci-mode activate) - "Suspend fci-mode while popups are visible" - (let ((fci-enabled (sanityinc/fci-enabled-p))) - (when fci-enabled - (setq sanityinc/fci-mode-suppressed fci-enabled) - (turn-off-fci-mode)))) - -(defadvice popup-delete (after restore-fci-mode activate) - "Restore fci-mode when all popups have closed" - (when (and sanityinc/fci-mode-suppressed - (null popup-instances)) - (setq sanityinc/fci-mode-suppressed nil) - (turn-on-fci-mode))) - - -;; https://github.com/alpaker/Fill-Column-Indicator/issues/67#issuecomment-195611974 -(after! fill-column-indicator - (add-hook 'prog-mode-hook #'fci-mode) - (defvar eos/fci-disabled nil) - (make-variable-buffer-local 'eos/fci-disabled) - - ;; Add a hook that disables fci if enabled when the window changes and it - ;; isn't wide enough to display it. - (defun eos/maybe-disable-fci () - (interactive) - ;; Disable FCI if necessary - (when (and fci-mode - (< (window-width) (or fci-rule-column fill-column))) - (fci-mode -1) - (setq-local eos/fci-disabled t)) - ;; Enable FCI if necessary - (when (and eos/fci-disabled - (eq fci-mode nil) - (> (window-width) (or fci-rule-column fill-column))) - (fci-mode 1) - (setq-local eos/fci-disabled nil))) - - (defun eos/add-fci-disabling-hook () - (interactive) - (add-hook 'window-configuration-change-hook - #'eos/maybe-disable-fci)) - - (add-hook 'prog-mode-hook #'eos/add-fci-disabling-hook)) - -; (require 'haskell-prettify) - -;; (add-hook 'haskell-mode-hook #'haskell-prettify-enable) + +(load-file (let ((coding-system-for-read 'utf-8)) + (shell-command-to-string "agda-mode locate"))) diff --git a/packages.el b/packages.el index 0ef4289c85..2264afa9c9 100644 --- a/packages.el +++ b/packages.el @@ -1,6 +1,8 @@ ;; -*- no-byte-compile: t; -*- ;;; private/grfn/packages.el +;; (package! 'tide :disable t) + ;; Editor (package! solarized-theme) (package! fill-column-indicator) @@ -17,6 +19,11 @@ (package! writeroom-mode) (package! dash) +;; Presentation +(package! epresent) +(package! org-tree-slide) +(package! ox-reveal) + ;; Slack etc (package! slack) (package! alert) @@ -56,3 +63,13 @@ (package! flycheck-flow) (package! company-flow) (package! prettier-js) + +;; GraphQL +(package! graphql-mode) + +;; Haskell +(package! lsp-mode) +(package! lsp-ui) +(package! lsp-haskell) +(package! company-lsp) +(package! lsp-imenu) diff --git a/snippets/haskell-mode/header b/snippets/haskell-mode/header index 4d665905f6..fdd8250d86 100644 --- a/snippets/haskell-mode/header +++ b/snippets/haskell-mode/header @@ -2,5 +2,4 @@ # name: header # expand-env: ((yas-indent-line 'fixed)) # -- ----------------------------------------------------------------------- -$2 \ No newline at end of file +--------------------------------------------------------------------------------$2 \ No newline at end of file diff --git a/snippets/haskell-mode/module b/snippets/haskell-mode/module index ce7ebcb213..4554d33f9b 100644 --- a/snippets/haskell-mode/module +++ b/snippets/haskell-mode/module @@ -5,7 +5,7 @@ # expand-env: ((yas-indent-line 'fixed)) # contributor: Luke Hoersten # -- ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- -- | -- Module : $1 -- Description : $2 @@ -13,7 +13,7 @@ -- Maturity : ${3:Draft, Usable, Maintained, OR MatureAF} -- -- $4 ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- module ${1:`(if (not buffer-file-name) "Module" (let ((name (file-name-sans-extension (buffer-file-name))) (case-fold-search nil)) @@ -25,8 +25,8 @@ module ${1:`(if (not buffer-file-name) "Module" (file-name-nondirectory name))))`} ( ) where ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- import Prelude ----------------------------------------------------------------------- +-------------------------------------------------------------------------------- $0 diff --git a/snippets/haskell-mode/test-module b/snippets/haskell-mode/test-module index 3183fdc72a..82224b36a4 100644 --- a/snippets/haskell-mode/test-module +++ b/snippets/haskell-mode/test-module @@ -1,6 +1,7 @@ # -*- mode: snippet -*- # name: test-module # key: test +# expand-env: ((yas-indent-line 'fixed)) # -- {-# LANGUAGE ApplicativeDo #-} -------------------------------------------------------------------------------- @@ -13,9 +14,9 @@ module ${1:`(if (not buffer-file-name) "Module" (car (last (split-string name "src"))))) (file-name-nondirectory name))))`} where -------------------------------------------------------------------------------- -import Test.Prelude +import Test.Prelude import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range -------------------------------------------------------------------------------- -import ${1:$(s-chop-suffix "Test" yas-text)} +import ${1:$(s-chop-suffix "Test" yas-text)} -------------------------------------------------------------------------------- diff --git a/snippets/org-mode/source-block b/snippets/org-mode/source-block deleted file mode 100644 index 3b7694557e..0000000000 --- a/snippets/org-mode/source-block +++ /dev/null @@ -1,8 +0,0 @@ -# -*- mode: snippet -*- -# name: source-block -# key: src -# expand-env: ((yas-indent-line 'fixed)) -# -- -#+BEGIN_SRC ${1:elisp} -$2 -#+END_SRC \ No newline at end of file diff --git a/splitjoin.el b/splitjoin.el index 166672816b..ea4dcfc393 100644 --- a/splitjoin.el +++ b/splitjoin.el @@ -1,7 +1,7 @@ ;;; private/grfn/splitjoin.el -*- lexical-binding: t; -*- (require 'dash) -(load! utils) +(load! "utils") ;;; ;;; Vars -- cgit 1.4.1 From 29c7632fd278e6d4228290956534a1195c488fad Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Tue, 18 Sep 2018 10:18:20 -0400 Subject: Misc haskell stuff, snippets, etc --- +bindings.el | 19 ++- config.el | 286 ++++++++++++++++++++++++++++------ init.el | 193 +---------------------- packages.el | 10 +- snippets/haskell-mode/annotation | 5 + snippets/haskell-mode/import-i | 4 + snippets/haskell-mode/inl | 6 + snippets/haskell-mode/inline | 5 + snippets/haskell-mode/language pragma | 6 + snippets/haskell-mode/shut up, hlint | 6 + snippets/js2-mode/action-type | 4 + snippets/js2-mode/describe | 6 + snippets/js2-mode/expect | 5 + snippets/js2-mode/header | 6 + snippets/js2-mode/it | 7 + snippets/js2-mode/it-pending | 5 + snippets/js2-mode/module | 12 ++ snippets/js2-mode/record | 7 + snippets/js2-mode/test | 7 + 19 files changed, 345 insertions(+), 254 deletions(-) create mode 100644 snippets/haskell-mode/annotation create mode 100644 snippets/haskell-mode/import-i create mode 100644 snippets/haskell-mode/inl create mode 100644 snippets/haskell-mode/inline create mode 100644 snippets/haskell-mode/language pragma create mode 100644 snippets/haskell-mode/shut up, hlint create mode 100644 snippets/js2-mode/action-type create mode 100644 snippets/js2-mode/describe create mode 100644 snippets/js2-mode/expect create mode 100644 snippets/js2-mode/header create mode 100644 snippets/js2-mode/it create mode 100644 snippets/js2-mode/it-pending create mode 100644 snippets/js2-mode/module create mode 100644 snippets/js2-mode/record create mode 100644 snippets/js2-mode/test diff --git a/+bindings.el b/+bindings.el index bfb40424b3..eb7b14365b 100644 --- a/+bindings.el +++ b/+bindings.el @@ -1022,17 +1022,20 @@ private/hlissner/snippets." (map! (:map haskell-mode-map - :n "K" 'lsp-info-under-point - :n "g d" 'lsp-ui-peek-find-definitions - :n "g r" 'lsp-ui-peek-find-references - ;; :n "g SPC" 'intero-repl-load - :n "g \\" '+haskell/repl - ;; :n "g y" 'intero-type-at + ;; :n "K" 'lsp-info-under-point + ;; :n "g d" 'lsp-ui-peek-find-definitions + ;; :n "g r" 'lsp-ui-peek-find-references + ;; :n "g \\" '+haskell/repl + :n "K" 'intero-info + :n "g d" 'intero-goto-definition + :n "g SPC" 'intero-repl-load + :n "g \\" 'intero-repl + :n "g y" 'intero-type-at ;; :n "g RET" 'grfn/run-sputnik-test-for-file (:localleader - :desc "Apply action" :n "a" 'lsp-execute-code-action - :desc "Rename symbol" :n "r" 'lsp-rename)) + :desc "Apply action" :n "e" 'intero-repl-eval-region + :desc "Rename symbol" :n "r" 'intero-apply-suggestions)) (:after agda2-mode (:map agda2-mode-map diff --git a/config.el b/config.el index 1646314ab7..ec91438d39 100644 --- a/config.el +++ b/config.el @@ -1,5 +1,195 @@ ;;; private/grfn/config.el -*- lexical-binding: t; -*- +;; I've swapped these keys on my keyboard +(setq x-super-keysym 'alt + x-alt-keysym 'meta) + +(setq user-mail-address "root@gws.fyi" + user-full-name "Griffin Smith") + +; (def-package-hook! doom-themes :disable) + +(after! rust + (setq rust-format-on-save t)) + +; (defconst rust-src-path +; (-> "/Users/griffin/.cargo/bin/rustc --print sysroot" +; shell-command-to-string +; string-trim +; (concat "/lib/rustlib/src/rust/src"))) +; +; (setenv "RUST_SRC_PATH" rust-src-path) +; +; (after! racer +; (setq racer-rust-src-path rust-src-path)) +; +(add-hook! rust-mode + (flycheck-rust-setup) + (flycheck-mode) + (racer-mode) + (cargo-minor-mode)) + +(add-hook! elixir-mode + (require 'flycheck-credo) + (setq flycheck-elixir-credo-strict t) + (flycheck-credo-setup) + + (require 'flycheck-mix) (flycheck-mix-setup) + + (require 'flycheck-dialyxir) (flycheck-dialyxir-setup) + + (flycheck-mode)) + +(setq exec-path (append exec-path '("/Users/griffin/.cargo/bin"))) + +(after! cargo + (setq cargo-process--custom-path-to-bin "/Users/griffin/.cargo/bin/cargo")) + +(setq +solarized-s-base03 "#002b36" + +solarized-s-base02 "#073642" + ;; emphasized content + +solarized-s-base01 "#586e75" + ;; primary content + +solarized-s-base00 "#657b83" + +solarized-s-base0 "#839496" + ;; comments + +solarized-s-base1 "#93a1a1" + ;; background highlight light + +solarized-s-base2 "#eee8d5" + ;; background light + +solarized-s-base3 "#fdf6e3" + + ;; Solarized accented colors + +solarized-yellow "#b58900" + +solarized-orange "#cb4b16" + +solarized-red "#dc322f" + +solarized-magenta "#d33682" + +solarized-violet "#6c71c4" + +solarized-blue "#268bd2" + +solarized-cyan "#2aa198" + +solarized-green "#859900" + + ;; Darker and lighter accented colors + ;; Only use these in exceptional circumstances! + +solarized-yellow-d "#7B6000" + +solarized-yellow-l "#DEB542" + +solarized-orange-d "#8B2C02" + +solarized-orange-l "#F2804F" + +solarized-red-d "#990A1B" + +solarized-red-l "#FF6E64" + +solarized-magenta-d "#93115C" + +solarized-magenta-l "#F771AC" + +solarized-violet-d "#3F4D91" + +solarized-violet-l "#9EA0E5" + +solarized-blue-d "#00629D" + +solarized-blue-l "#69B7F0" + +solarized-cyan-d "#00736F" + +solarized-cyan-l "#69CABF" + +solarized-green-d "#546E00" + +solarized-green-l "#B4C342") + +(defadvice load-theme (after theme-set-overrides activate) + (dolist (theme-settings theme-overrides) + (let ((theme (car theme-settings)) + (faces (cadr theme-settings))) + (if (member theme custom-enabled-themes) + (dolist (face faces) + (custom-theme-set-faces theme face)))))) + +(defcustom theme-overrides nil + "Association list of override faces to set for different custom themes.") + +(defun alist-set (alist-symbol key value) + "Set VALUE of a KEY in ALIST-SYMBOL." + (set alist-symbol (cons (list key value) (assq-delete-all key (eval alist-symbol))))) + +(alist-set 'theme-overrides 'grfn-solarized-light + `((font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) + (font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) + (font-lock-keyword-face ((t (:foreground ,+solarized-green)))) + + (elixir-attribute-face ((t (:foreground ,+solarized-blue)))) + (elixir-atom-face ((t (:foreground ,+solarized-cyan)))) + (linum ((t (:background ,+solarized-s-base2 :foreground ,+solarized-s-base1)))) + (line-number ((t (:background ,+solarized-s-base2 :foreground ,+solarized-s-base1)))) + + (haskell-operator-face ((t (:foreground ,+solarized-green)))) + (haskell-keyword-face ((t (:foreground ,+solarized-cyan)))))) + +(setq solarized-use-variable-pitch nil + solarized-scale-org-headlines nil) + +(add-to-list 'custom-theme-load-path "~/.doom.d/themes") +(load-theme 'grfn-solarized-light t) + +(defface haskell-import-face `((t (:foreground ,+solarized-magenta))) "") + +(setq doom-theme 'grfn-solarized-light) +; (setq doom-theme 'doom-solarized-light) + +(add-hook! doom-post-init + (set-face-attribute 'bold nil :weight 'ultra-light) + (set-face-bold-p 'bold nil)) + +(defun rx-words (&rest words) + (rx-to-string + `(and symbol-start (group (or ,@words)) symbol-end))) + +(font-lock-add-keywords + 'elixir-mode + `((,(rx-words "def" + "defp" + "test" + "describe" + "property" + "defrecord" + "defmodule" + "defstruct" + "defdelegate" + "defprotocol" + "defimpl" + "use" + "import" + "alias" + "require" + "assert" + "refute" + "assert_raise") + . + 'font-lock-preprocessor-face))) + +(font-lock-add-keywords + 'elixir-mode + `((,(rx-words "def" + "defp" + "test" + "describe" + "property" + "defrecord" + "defmodule" + "defstruct" + "defdelegate" + "use" + "import" + "alias" + "require" + "assert" + "refute" + "assert_raise") + . + 'font-lock-preprocessor-face))) + +(font-lock-add-keywords + 'haskell-mode + `((,(rx-words "import") . 'haskell-import-face))) + +;; (font-lock-add-keywords +;; 'haskell-mode +;; `((,(rx "-- |") . 'haskell-keyword-face))) + + +(load-file (let ((coding-system-for-read 'utf-8)) + (shell-command-to-string "agda-mode locate"))) (defvar +grfn-dir (file-name-directory load-file-name)) (defvar +grfn-snippets-dir (expand-file-name "snippets/" +grfn-dir)) @@ -85,9 +275,6 @@ (def-package! org-clubhouse) -(setq solarized-use-variable-pitch nil - solarized-scale-org-headlines nil) - ; (require 'doom-themes) ;; Should really figure out which of these is correct, eventually @@ -248,11 +435,11 @@ (add-hook! haskell-mode - ;; (intero-mode) - (lsp-mode) - ;; (flycheck-add-next-checker - ;; 'intero - ;; 'haskell-hlint) + (intero-mode) + ;; (lsp-mode) + (flycheck-add-next-checker + 'intero + 'haskell-hlint) (set-fill-column 80) (setq evil-shift-width 2)) @@ -451,44 +638,47 @@ ;; (with-selected-window window ;; (split-window-below)))))))) -(def-package! lsp-mode - :after (:any haskell-mode) - :config - (lsp-mode) - (setq lsp-project-whitelist '("^/home/griffin/code/urb/grid/$") - lsp-response-timeout 60) - :hook - (haskell-mode . lsp-mode)) - -(def-package! lsp-ui - :after lsp-mode - :config - (setq lsp-ui-flycheck-enable t) - (setq imenu-auto-rescan t) - (set-face-background 'lsp-ui-doc-background +solarized-s-base2) - (set-face-background 'lsp-face-highlight-read +solarized-s-base2) - (set-face-background 'lsp-face-highlight-write +solarized-s-base2) - :hook - (lsp-mode . lsp-ui-mode) - (lsp-ui-mode . flycheck-mode)) - -(def-package! company-lsp - :after (lsp-mode lsp-ui) - :config - (setq company-backends '(company-lsp)) - (setq company-lsp-async t)) - -(def-package! lsp-haskell - :after (lsp-mode lsp-ui haskell-mode) - :hook - (haskell-mode . lsp-haskell-enable) - :config - (setq lsp-haskell-process-path-hie "/home/griffin/.local/bin/hie-wrapper")) - -(def-package! lsp-imenu - :after (lsp-mode lsp-ui) - :hook - (lsp-after-open . lsp-enable-imenu)) +;; (def-package! lsp-mode +;; :after (:any haskell-mode) +;; :config +;; (lsp-mode) +;; (setq lsp-project-whitelist '("^/home/griffin/code/urb/grid/$") +;; lsp-response-timeout 60) +;; :hook +;; (haskell-mode . lsp-mode)) + +;; (def-package! lsp-ui +;; :after lsp-mode +;; :config +;; (setq lsp-ui-flycheck-enable t) +;; (setq imenu-auto-rescan t) +;; (set-face-background 'lsp-ui-doc-background +solarized-s-base2) +;; (set-face-background 'lsp-face-highlight-read +solarized-s-base2) +;; (set-face-background 'lsp-face-highlight-write +solarized-s-base2) +;; :hook +;; (lsp-mode . lsp-ui-mode) +;; (lsp-ui-mode . flycheck-mode)) + +;; (def-package! company-lsp +;; :after (lsp-mode lsp-ui) +;; :config +;; (setq company-backends '(company-lsp)) +;; (setq company-lsp-async t)) + +;; (def-package! lsp-haskell +;; :after (lsp-mode lsp-ui haskell-mode) +;; :hook +;; (haskell-mode . lsp-haskell-enable) +;; :config +;; (setq lsp-haskell-process-path-hie "/home/griffin/.local/bin/hie-wrapper" +;; lsp-haskell-process-args-hie +;; '("-d" "-l" "/tmp/hie.log" "+RTS" "-M4G" "-H1G" "-K4G" "-A16M" "-RTS" +;; "--lsp"))) + +;; (def-package! lsp-imenu +;; :after (lsp-mode lsp-ui) +;; :hook +;; (lsp-after-open . lsp-enable-imenu)) (def-package! evil-magit :after (magit)) @@ -548,7 +738,3 @@ `(agda2-highlight-termination-problem-face ((t (:background ,orange :foreground ,base03)))) `(agda2-highlight-incomplete-pattern-face ((t (:background ,orange :foreground ,base03)))) `(agda2-highlight-typechecks-face ((t (:background ,cyan :foreground ,base03)))))) - -;; (with-eval-after-load 'intero -;; (setq intero-package-version "0.1.31")) - diff --git a/init.el b/init.el index 2948da3333..e984b50ef4 100644 --- a/init.el +++ b/init.el @@ -91,8 +91,8 @@ emacs-lisp ; drown in parentheses ;ess ; emacs speaks statistics ;go ; the hipster dialect - ;(haskell +intero) ; a language that's lazier than I am - haskell ; a language that's lazier than I am + (haskell +intero) ; a language that's lazier than I am + ;; haskell ; a language that's lazier than I am ;hy ; readability of scheme w/ speed of python ;(java +meghanada) ; the poster child for carpal tunnel syndrome javascript ; all(hope(abandon(ye(who(enter(here)))))) @@ -152,192 +152,3 @@ ;; and additional ex commands for evil-mode. Use it as a reference for ;; your own modules. (default +bindings +snippets +evil-commands)) - - -;; I've swapped these keys on my keyboard -(setq x-super-keysym 'alt - x-alt-keysym 'meta) - -(setq user-mail-address "root@gws.fyi" - user-full-name "Griffin Smith") - -; (def-package-hook! doom-themes :disable) - -(after! rust - (setq rust-format-on-save t)) - -; (defconst rust-src-path -; (-> "/Users/griffin/.cargo/bin/rustc --print sysroot" -; shell-command-to-string -; string-trim -; (concat "/lib/rustlib/src/rust/src"))) -; -; (setenv "RUST_SRC_PATH" rust-src-path) -; -; (after! racer -; (setq racer-rust-src-path rust-src-path)) -; -(add-hook! rust-mode - (flycheck-rust-setup) - (flycheck-mode) - (racer-mode) - (cargo-minor-mode)) - -(add-hook! elixir-mode - (require 'flycheck-credo) - (setq flycheck-elixir-credo-strict t) - (flycheck-credo-setup) - - (require 'flycheck-mix) (flycheck-mix-setup) - - (require 'flycheck-dialyxir) (flycheck-dialyxir-setup) - - (flycheck-mode)) - -(setq exec-path (append exec-path '("/Users/griffin/.cargo/bin"))) - -(after! cargo - (setq cargo-process--custom-path-to-bin "/Users/griffin/.cargo/bin/cargo")) - -(setq +solarized-s-base03 "#002b36" - +solarized-s-base02 "#073642" - ;; emphasized content - +solarized-s-base01 "#586e75" - ;; primary content - +solarized-s-base00 "#657b83" - +solarized-s-base0 "#839496" - ;; comments - +solarized-s-base1 "#93a1a1" - ;; background highlight light - +solarized-s-base2 "#eee8d5" - ;; background light - +solarized-s-base3 "#fdf6e3" - - ;; Solarized accented colors - +solarized-yellow "#b58900" - +solarized-orange "#cb4b16" - +solarized-red "#dc322f" - +solarized-magenta "#d33682" - +solarized-violet "#6c71c4" - +solarized-blue "#268bd2" - +solarized-cyan "#2aa198" - +solarized-green "#859900" - - ;; Darker and lighter accented colors - ;; Only use these in exceptional circumstances! - +solarized-yellow-d "#7B6000" - +solarized-yellow-l "#DEB542" - +solarized-orange-d "#8B2C02" - +solarized-orange-l "#F2804F" - +solarized-red-d "#990A1B" - +solarized-red-l "#FF6E64" - +solarized-magenta-d "#93115C" - +solarized-magenta-l "#F771AC" - +solarized-violet-d "#3F4D91" - +solarized-violet-l "#9EA0E5" - +solarized-blue-d "#00629D" - +solarized-blue-l "#69B7F0" - +solarized-cyan-d "#00736F" - +solarized-cyan-l "#69CABF" - +solarized-green-d "#546E00" - +solarized-green-l "#B4C342") - -(defadvice load-theme (after theme-set-overrides activate) - (dolist (theme-settings theme-overrides) - (let ((theme (car theme-settings)) - (faces (cadr theme-settings))) - (if (member theme custom-enabled-themes) - (dolist (face faces) - (custom-theme-set-faces theme face)))))) - -(defcustom theme-overrides nil - "Association list of override faces to set for different custom themes.") - -(defun alist-set (alist-symbol key value) - "Set VALUE of a KEY in ALIST-SYMBOL." - (set alist-symbol (cons (list key value) (assq-delete-all key (eval alist-symbol))))) - -(alist-set 'theme-overrides 'grfn-solarized-light - `((font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) - (font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) - (font-lock-keyword-face ((t (:foreground ,+solarized-green)))) - - (elixir-attribute-face ((t (:foreground ,+solarized-blue)))) - (elixir-atom-face ((t (:foreground ,+solarized-cyan)))) - (linum ((t (:background ,+solarized-s-base2 :foreground ,+solarized-s-base1)))) - (line-number ((t (:background ,+solarized-s-base2 :foreground ,+solarized-s-base1)))) - - (haskell-operator-face ((t (:foreground ,+solarized-green)))) - (haskell-keyword-face ((t (:foreground ,+solarized-cyan)))))) - -(add-to-list 'custom-theme-load-path "~/.doom.d/themes") -(load-theme 'grfn-solarized-light t) - -(defface haskell-import-face `((t (:foreground ,+solarized-magenta))) "") - -(setq doom-theme 'grfn-solarized-light) -; (setq doom-theme 'doom-solarized-light) - -(add-hook! doom-post-init - (set-face-attribute 'bold nil :weight 'ultra-light) - (set-face-bold-p 'bold nil)) - -(defun rx-words (&rest words) - (rx-to-string - `(and symbol-start (group (or ,@words)) symbol-end))) - -(font-lock-add-keywords - 'elixir-mode - `((,(rx-words "def" - "defp" - "test" - "describe" - "property" - "defrecord" - "defmodule" - "defstruct" - "defdelegate" - "defprotocol" - "defimpl" - "use" - "import" - "alias" - "require" - "assert" - "refute" - "assert_raise") - . - 'font-lock-preprocessor-face))) - -(font-lock-add-keywords - 'elixir-mode - `((,(rx-words "def" - "defp" - "test" - "describe" - "property" - "defrecord" - "defmodule" - "defstruct" - "defdelegate" - "use" - "import" - "alias" - "require" - "assert" - "refute" - "assert_raise") - . - 'font-lock-preprocessor-face))) - -(font-lock-add-keywords - 'haskell-mode - `((,(rx-words "import") . 'haskell-import-face))) - -;; (font-lock-add-keywords -;; 'haskell-mode -;; `((,(rx "-- |") . 'haskell-keyword-face))) - - -(load-file (let ((coding-system-for-read 'utf-8)) - (shell-command-to-string "agda-mode locate"))) diff --git a/packages.el b/packages.el index 2264afa9c9..75d28d6850 100644 --- a/packages.el +++ b/packages.el @@ -68,8 +68,8 @@ (package! graphql-mode) ;; Haskell -(package! lsp-mode) -(package! lsp-ui) -(package! lsp-haskell) -(package! company-lsp) -(package! lsp-imenu) +;; (package! lsp-mode) +;; (package! lsp-ui) +;; (package! lsp-haskell) +;; (package! company-lsp) +;; (package! lsp-imenu) diff --git a/snippets/haskell-mode/annotation b/snippets/haskell-mode/annotation new file mode 100644 index 0000000000..8a2854d759 --- /dev/null +++ b/snippets/haskell-mode/annotation @@ -0,0 +1,5 @@ +# key: ann +# name: annotation +# expand-env: ((yas-indent-line 'fixed)) +# -- +{-# ANN ${1:module} ("${2:HLint: ignore ${3:Reduce duplication}}" :: String) #-} \ No newline at end of file diff --git a/snippets/haskell-mode/import-i b/snippets/haskell-mode/import-i new file mode 100644 index 0000000000..4a7fca2c2f --- /dev/null +++ b/snippets/haskell-mode/import-i @@ -0,0 +1,4 @@ +# key: i +# name: import-i +# -- +import ${1:Prelude} \ No newline at end of file diff --git a/snippets/haskell-mode/inl b/snippets/haskell-mode/inl new file mode 100644 index 0000000000..6e17b83d71 --- /dev/null +++ b/snippets/haskell-mode/inl @@ -0,0 +1,6 @@ +# -*- mode: snippet -*- +# name: inl +# key: inl +# expand-env: ((yas-indent-line 'fixed)) +# -- +{-# INLINE $1 #-} \ No newline at end of file diff --git a/snippets/haskell-mode/inline b/snippets/haskell-mode/inline new file mode 100644 index 0000000000..1beafbe50b --- /dev/null +++ b/snippets/haskell-mode/inline @@ -0,0 +1,5 @@ +# key: inline +# name: inline +# expand-env: ((yas-indent-line 'fixed)) +# -- +{-# INLINE $1 #-} \ No newline at end of file diff --git a/snippets/haskell-mode/language pragma b/snippets/haskell-mode/language pragma new file mode 100644 index 0000000000..6f84720f45 --- /dev/null +++ b/snippets/haskell-mode/language pragma @@ -0,0 +1,6 @@ +# -*- mode: snippet -*- +# name: language pragma +# key: lang +# expand-env: ((yas-indent-line 'fixed)) +# -- +{-# LANGUAGE $1 #-} \ No newline at end of file diff --git a/snippets/haskell-mode/shut up, hlint b/snippets/haskell-mode/shut up, hlint new file mode 100644 index 0000000000..fccff1d66f --- /dev/null +++ b/snippets/haskell-mode/shut up, hlint @@ -0,0 +1,6 @@ +# -*- mode: snippet -*- +# name: shut up, hlint +# key: dupl +# expand-env: ((yas-indent-line 'fixed)) +# -- +{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-} \ No newline at end of file diff --git a/snippets/js2-mode/action-type b/snippets/js2-mode/action-type new file mode 100644 index 0000000000..ef8d1a3863 --- /dev/null +++ b/snippets/js2-mode/action-type @@ -0,0 +1,4 @@ +# key: at +# name: action-type +# -- +export const ${1:FOO_BAR$(->> yas-text s-upcase (s-replace-all '(("-" . "_") (" " . "_"))))}: '${3:ns}/${1:$(-> yas-text s-dashed-words)}' = '$3/${1:$(-> yas-text s-dashed-words)}'$5 \ No newline at end of file diff --git a/snippets/js2-mode/describe b/snippets/js2-mode/describe new file mode 100644 index 0000000000..bd0198181d --- /dev/null +++ b/snippets/js2-mode/describe @@ -0,0 +1,6 @@ +# key: desc +# name: describe +# -- +describe('$1', () => { + $2 +}) \ No newline at end of file diff --git a/snippets/js2-mode/expect b/snippets/js2-mode/expect new file mode 100644 index 0000000000..eba41ef330 --- /dev/null +++ b/snippets/js2-mode/expect @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: expect +# key: ex +# -- +expect($1).$2 \ No newline at end of file diff --git a/snippets/js2-mode/header b/snippets/js2-mode/header new file mode 100644 index 0000000000..3e303764cb --- /dev/null +++ b/snippets/js2-mode/header @@ -0,0 +1,6 @@ +# -*- mode: snippet -*- +# name: header +# key: hh +# expand-env: ((yas-indent-line 'fixed)) +# -- +//////////////////////////////////////////////////////////////////////////////// diff --git a/snippets/js2-mode/it b/snippets/js2-mode/it new file mode 100644 index 0000000000..a451cfc08a --- /dev/null +++ b/snippets/js2-mode/it @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: it +# key: it +# -- +it('$1', () => { + $2 +}) \ No newline at end of file diff --git a/snippets/js2-mode/it-pending b/snippets/js2-mode/it-pending new file mode 100644 index 0000000000..00da312e10 --- /dev/null +++ b/snippets/js2-mode/it-pending @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: it-pending +# key: xi +# -- +it('$1')$0 \ No newline at end of file diff --git a/snippets/js2-mode/module b/snippets/js2-mode/module new file mode 100644 index 0000000000..dc79819d89 --- /dev/null +++ b/snippets/js2-mode/module @@ -0,0 +1,12 @@ +# key: module +# name: module +# expand-env: ((yas-indent-line (quote fixed))) +# condition: (= (length "module") (current-column)) +# -- +/** + * @fileOverview $1 + * @name ${2:`(file-name-nondirectory (buffer-file-name))`} + * @author Griffin Smith + * @license Proprietary + */ +$3 \ No newline at end of file diff --git a/snippets/js2-mode/record b/snippets/js2-mode/record new file mode 100644 index 0000000000..0bb0f02436 --- /dev/null +++ b/snippets/js2-mode/record @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: record +# key: rec +# -- +export default class $1 extends Record({ + $2 +}) {} \ No newline at end of file diff --git a/snippets/js2-mode/test b/snippets/js2-mode/test new file mode 100644 index 0000000000..938d490a74 --- /dev/null +++ b/snippets/js2-mode/test @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: test +# key: test +# -- +test('$1', () => { + $2 +}) \ No newline at end of file -- cgit 1.4.1 From 0edecaf151346351a4bfd255c789f08b696fe1a1 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Wed, 21 Nov 2018 12:45:05 -0500 Subject: clojure stuff, org stuff --- +bindings.el | 59 ++++++++++++++++++++++++------ +commands.el | 2 + config.el | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- init.el | 6 +-- packages.el | 6 +++ 5 files changed, 174 insertions(+), 16 deletions(-) diff --git a/+bindings.el b/+bindings.el index eb7b14365b..f92346262a 100644 --- a/+bindings.el +++ b/+bindings.el @@ -1,4 +1,4 @@ -;; private/grfn/+bindings.el -*- lexical-binding: t; -*- +;; /+bindings.el -*- lexical-binding: t; -*- (load! "utils") (require 'f) @@ -333,7 +333,8 @@ private/hlissner/snippets." :desc "Browse mode notes" :n "m" #'+org/browse-notes-for-major-mode :desc "Browse project notes" :n "p" #'+org/browse-notes-for-project :desc "Create clubhouse story" :n "c" #'org-clubhouse-create-story - :desc "Archive subtree" :n "k" #'org-archive-subtree) + :desc "Archive subtree" :n "k" #'org-archive-subtree + :desc "Goto clocked-in note" :n "g" #'org-clock-goto) (:desc "open" :prefix "o" :desc "Default browser" :n "b" #'browse-url-of-file @@ -413,11 +414,17 @@ private/hlissner/snippets." ;; --- vim-sexp-mappings-for-regular-people (:after paxedit (:map paxedit-mode-map + :i ";" #'paxedit-insert-semicolon + :i "(" #'paxedit-open-round + :i "[" #'paxedit-open-bracket + :i "{" #'paxedit-open-curly :n [remap evil-yank-line] #'paxedit-copy - :n [remap evil-delete-line] #'paxedit-delete - :n "go" #'paxedit-sexp-raise + :n [remap evil-delete-line] #'paxedit-kill + :n "g o" #'paxedit-sexp-raise :n [remap evil-join-whitespace] #'paxedit-compress - :n "gS" #'paxedit-format-1)) + :n "g S" #'paxedit-format-1 + :n "g k" #'paxedit-backward-up + :n "g j" #'paxedit-backward-end)) ;; --- vim-splitjoin :n [remap evil-join-whitespace] #'+splitjoin/join @@ -981,7 +988,6 @@ private/hlissner/snippets." ;; ") ; slurp forward +;; <) ; barf forward +;; <( ; slurp backward +;; >( ; slurp backward + +;; (require 'doom-themes) (defun grfn/haskell-test-file-p () (string-match-p (rx (and "Spec.hs" eol)) (buffer-file-name))) +(require 'haskell) + (defun grfn/intero-run-main () (interactive) (intero-repl-load) @@ -1016,9 +1032,11 @@ private/hlissner/snippets." (get-buffer-process (current-buffer)) "main"))) -(defun grfn/run-sputnik-test-for-file () +(defun grfn/run-clj-or-cljs-test () (interactive) - (haskell-interactive-mode-)) + (cl-case (cider-repl-type-for-buffer) + ("cljs" (cider-interactive-eval "(with-out-string (cljs.test/run-tests))")) + ("clj" (cider-test-run-ns-tests)))) (map! (:map haskell-mode-map @@ -1049,5 +1067,24 @@ private/hlissner/snippets." :desc "Refine" :n "r" 'agda2-refine :desc "Auto" :n "a" 'agda2-auto :desc "Goal type and context" :n "t" 'agda2-goal-and-context - :desc "Goal type and context and inferred" :n ";" 'agda2-goal-and-context-and-inferred)))) + :desc "Goal type and context and inferred" :n ";" 'agda2-goal-and-context-and-inferred))) + + (:after cider-mode + (:map cider-mode-map + :n "g SPC" 'cider-eval-buffer + :n "g \\" 'cider-switch-to-repl-buffer + :n "K" 'cider-doc + :n "g K" 'cider-grimoire + :n "g d" 'cider-find-dwim + :n "C-w ]" 'cider-find-dwim-other-window + :n "g RET" 'cider-test-run-ns-tests + "C-c C-r r" 'cljr-add-require-to-ns + + (:localleader + ;; :desc "Inspect last result" :n "i" 'cider-inspect-last-result + ;; :desc "Search for documentation" :n "h s" 'cider-apropos-doc + :desc "Add require to ns" :n "n r" 'cljr-add-require-to-ns)) + (:map cider-repl-mode-map + :n "g \\" 'cider-switch-to-last-clojure-buffer)) + ) diff --git a/+commands.el b/+commands.el index 87123ed3c8..9b4a685e1c 100644 --- a/+commands.el +++ b/+commands.el @@ -110,6 +110,8 @@ (ex! "tabs" #'+workspace/display) (ex! "tabsave" #'+workspace:save) +(ex! "scr[atch]" #'cider-scratch) + ;; Org-mode (ex! "cap" #'+org-capture/dwim) diff --git a/config.el b/config.el index ec91438d39..6fd5ac59cf 100644 --- a/config.el +++ b/config.el @@ -379,11 +379,28 @@ org-capture-templates `(("t" "Todo" entry (file+headline +org-default-todo-file "Inbox") - "* TODO %?\n%i" :prepend t :kill-buffer t) + "* TODO %?\n%i" + :prepend t + :kill-buffer t) ("n" "Notes" entry (file+headline +org-default-notes-file "Inbox") - "* %u %?\n%i" :prepend t :kill-buffer t)) + "* %u %?\n%i" + :prepend t + :kill-buffer t) + + ("c" "Task note" entry + (clock) + "* %u %?\n%i[[%l][Context]]\n" + :kill-buffer t + :unnarrowed t) + + ("d" "Tech debt" entry + (file+headline ,(concat org-directory "/work.org") + "Inbox") + "* TODO %? :debt:\nContext: %a\nIn task: %K" + :prepend t + :kill-buffer t)) org-deadline-warning-days 1 org-agenda-skip-scheduled-if-deadline-is-shown 'todo org-agenda-custom-commands @@ -738,3 +755,99 @@ `(agda2-highlight-termination-problem-face ((t (:background ,orange :foreground ,base03)))) `(agda2-highlight-incomplete-pattern-face ((t (:background ,orange :foreground ,base03)))) `(agda2-highlight-typechecks-face ((t (:background ,cyan :foreground ,base03)))))) + + +(after! cider + (setq cider-prompt-for-symbol nil + cider-font-lock-dynamically 't + cider-save-file-on-load 't) + ) + +(defun +org-clocked-in-element () + (when-let ((item (car org-clock-history))) + (save-mark-and-excursion + (with-current-buffer (marker-buffer item) + (goto-char (marker-position item)) + (org-element-at-point))))) + +(comment + (setq elt (+org-clocked-in-item)) + + (eq 'headline (car elt)) + (plist-get (cadr elt) :raw-value) + ) + +(defun +org-headline-title (headline) + (when (eq 'headline (car elt)) + (plist-get (cadr elt) :raw-value))) + +(setq +pretty-code-symbols + (append +pretty-code-symbols + '(:equal "≡" + :not-equal "≠" + :is "≣" + :isnt "≢" + :lte "≤" + :gte "≥" + :subseteq "⊆" + ))) + +(after! python + (set-pretty-symbols! 'python-mode :merge t + :equal "==" + :not-equal "!=" + :lte "<=" + :gte ">=" + :is "is" + :isnt "is not" + :subseteq "issubset" + + ;; doom builtins + + ;; Functional + :def "def" + :lambda "lambda" + ;; Types + :null "None" + :true "True" :false "False" + :int "int" :str "str" + :float "float" + :bool "bool" + :tuple "tuple" + ;; Flow + :not "not" + :in "in" :not-in "not in" + :and "and" :or "or" + :for "for" + :return "return" :yield "yield")) + +(after! clojure-mode + (define-clojure-indent + (PUT 2) + (POST 2) + (GET 2) + (PATCH 2) + (DELETE 2) + (context 2) + (checking 3))) + +(def-package! flycheck-clojure + :disabled t + :after flycheck + :config + (flycheck-clojure-setup)) + +(after! clj-refactor + (setq cljr-magic-requires :prompt + cljr-clojure-test-declaration "[clojure.test :refer :all]" + cljr-cljc-clojure-test-declaration"#?(:clj [clojure.test :refer :all] +:cljs [cljs.test :refer-macros [deftest is testing])" + ) + (add-to-list + 'cljr-magic-require-namespaces + '("s" . "clojure.spec.alpha"))) + +(def-package! sqlup-mode + :hook + (sql-mode-hook . sqlup-mode) + (sql-interactive-mode-hook . sqlup-mode)) diff --git a/init.el b/init.el index e984b50ef4..af5ae02370 100644 --- a/init.el +++ b/init.el @@ -1,6 +1,5 @@ ;;; private/grfn/init.el -*- lexical-binding: t; -*- - (doom! :feature ;debugger ; FIXME stepping through code, to help you add bugs eval ; run code, run (also, repls) @@ -30,7 +29,7 @@ doom-modeline ; a snazzy Atom-inspired mode-line doom-quit ; DOOM quit-message prompts when you quit Emacs evil-goggles ; display visual hints when editing in evil - ;fci ; a `fill-column' indicator + fci ; a `fill-column' indicator hl-todo ; highlight TODO/FIXME/NOTE tags ;modeline ; snazzy, Atom-inspired modeline, plus API nav-flash ; blink the current line after jumping @@ -63,6 +62,7 @@ vc ; version-control and Emacs, sitting in a tree :tools + docker editorconfig ; let someone else argue about tabs vs spaces ;ein ; tame Jupyter notebooks with emacs gist ; interacting with github gists @@ -114,7 +114,7 @@ ;php ; perl's insecure younger brother ;plantuml ; diagrams for confusing people more ;purescript ; javascript, but functional - ;python ; beautiful is better than ugly + python ; beautiful is better than ugly ;qt ; the 'cutest' gui framework ever ;racket ; a DSL for DSLs ;rest ; Emacs as a REST client diff --git a/packages.el b/packages.el index 75d28d6850..f0563d3d41 100644 --- a/packages.el +++ b/packages.el @@ -73,3 +73,9 @@ ;; (package! lsp-haskell) ;; (package! company-lsp) ;; (package! lsp-imenu) + +;; Clojure +(package! flycheck-clojure) + +;; SQL +(package! sqlup-mode) -- cgit 1.4.1 From 4bebee0cc69f20d20dfdc81f14c854e846f235cc Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Sat, 5 Jan 2019 14:15:48 -0500 Subject: bunch of org, clojure stuff, fix lots of bugs --- +bindings.el | 26 ++++++++++++++------------ config.el | 39 +++++++++++++++++++++++++++++++++------ packages.el | 14 +++++++++++--- 3 files changed, 58 insertions(+), 21 deletions(-) diff --git a/+bindings.el b/+bindings.el index f92346262a..023e7cb793 100644 --- a/+bindings.el +++ b/+bindings.el @@ -174,7 +174,7 @@ private/hlissner/snippets." :desc "M-x" :nv ":" #'execute-extended-command :desc "Pop up scratch buffer" :nv "x" #'doom/open-scratch-buffer :desc "Org Capture" :nv "X" #'org-capture - :desc "Org Capture" :nv "a" #'+org-capture/open + :desc "Org Capture" :nv "a" #'org-capture ;; Most commonly used :desc "Find file in project" :n "SPC" #'projectile-find-file @@ -886,13 +886,6 @@ private/hlissner/snippets." :i "C-e" #'doom/forward-to-last-non-comment-or-eol :i "C-u" #'doom/backward-kill-to-bol-and-indent - ;; textmate-esque newline insertion - :i [M-return] #'evil-open-below - :i [S-M-return] #'evil-open-above - ;; textmate-esque deletion - [M-backspace] #'doom/backward-kill-to-bol-and-indent - :i [backspace] #'delete-backward-char - :i [M-backspace] #'doom/backward-kill-to-bol-and-indent ;; Emacsien motions for insert mode :i "C-b" #'backward-word :i "C-f" #'forward-word @@ -908,8 +901,7 @@ private/hlissner/snippets." (:after org (:map org-mode-map :i [remap doom/inflate-space-maybe] #'org-self-insert-command - :i "C-e" #'org-end-of-line - :i "C-a" #'org-beginning-of-line)) + )) ;; Restore common editing keys (and ESC) in minibuffer (:map (minibuffer-local-map @@ -920,7 +912,7 @@ private/hlissner/snippets." evil-ex-completion-map evil-ex-search-keymap read-expression-map) - [escape] #'abort-recursive-edit + ;; [escape] #'abort-recursive-edit "C-r" #'evil-paste-from-register "C-a" #'move-beginning-of-line "C-w" #'doom/minibuffer-kill-word @@ -1087,4 +1079,14 @@ private/hlissner/snippets." :desc "Add require to ns" :n "n r" 'cljr-add-require-to-ns)) (:map cider-repl-mode-map :n "g \\" 'cider-switch-to-last-clojure-buffer)) - ) + + (:after w3m + (:map w3m-mode-map + "/" 'evil-search-forward + "?" 'evil-search-backward)) + + (:after org + (:map org-mode-map + [remap counsel-imenu] #'counsel-org-goto + (:localleader + :n "g" #'counsel-org-goto)))) diff --git a/config.el b/config.el index 6fd5ac59cf..5463d83196 100644 --- a/config.el +++ b/config.el @@ -356,7 +356,9 @@ org-default-notes-file (concat org-directory "/inbox.org") +org-default-todo-file (concat org-directory "/inbox.org") org-agenda-files (list (expand-file-name "~/notes")) - org-refile-targets '((org-agenda-files :maxlevel . 1)) + org-refile-targets '((org-agenda-files :maxlevel . 3)) + org-outline-path-complete-in-steps nil + org-refile-use-outline-path t org-file-apps `((auto-mode . emacs) (,(rx (or (and "." (optional "x") (optional "htm") (optional "l") buffer-end) (and buffer-start "http" (optional "s") "://"))) @@ -376,6 +378,7 @@ org-hidden-keywords '(title) org-tags-column -130 org-ellipsis "⤵" + org-imenu-depth 9 org-capture-templates `(("t" "Todo" entry (file+headline +org-default-todo-file "Inbox") @@ -385,13 +388,13 @@ ("n" "Notes" entry (file+headline +org-default-notes-file "Inbox") - "* %u %?\n%i" + "* %U %?\n%i" :prepend t :kill-buffer t) ("c" "Task note" entry (clock) - "* %u %?\n%i[[%l][Context]]\n" + "* %U %?\n%i[[%l][Context]]\n" :kill-buffer t :unnarrowed t) @@ -405,7 +408,9 @@ org-agenda-skip-scheduled-if-deadline-is-shown 'todo org-agenda-custom-commands '(("p" "Sprint Tasks" tags-todo "sprint") - ("i" "Inbox" tags "inbox"))) + ("i" "Inbox" tags "inbox") + ("r" "Running jobs" todo "RUNNING"))) + (set-face-foreground 'org-block +solarized-s-base00) (add-hook! org-mode (add-hook! evil-normal-state-entry-hook @@ -627,6 +632,8 @@ ('npm ".test") (otherwise (projectile-test-suffix project-type))))) +(setq projectile-create-missing-test-files 't) + (defun magit-commit-wip () (interactive) (magit-commit '("-m" "wip"))) @@ -707,7 +714,7 @@ (require 'whitespace) (setq whitespace-style '(face lines-tail)) (global-whitespace-mode t) -(add-hook! 'org-mode-hook (lambda () (whitespace-mode -1))) +(add-hook 'org-mode-hook (lambda () (whitespace-mode -1)) t) (set-face-foreground 'whitespace-line +solarized-red) (set-face-attribute 'whitespace-line nil :underline 't) @@ -829,7 +836,9 @@ (PATCH 2) (DELETE 2) (context 2) - (checking 3))) + (checking 3) + (match 1) + (domonad 0))) (def-package! flycheck-clojure :disabled t @@ -851,3 +860,21 @@ :hook (sql-mode-hook . sqlup-mode) (sql-interactive-mode-hook . sqlup-mode)) + +(def-package! yapfify + :hook + (python-mode-hook . yapf-mode)) + +(def-package! w3m + :hook + (setq browse-url-browser-function 'w3m-browse-url)) + +(def-package! ob-http + :config + (add-to-list 'org-babel-load-languages '(http . t))) + +(def-package! ob-ipython + :config + (add-to-list 'org-babel-load-languages '(ipython . t)) + (setq ob-ipython-command + "/home/griffin/code/urb/ciml-video-classifier/bin/jupyter")) diff --git a/packages.el b/packages.el index f0563d3d41..acf776dab1 100644 --- a/packages.el +++ b/packages.el @@ -11,13 +11,18 @@ :recipe (general :fetcher github :repo "noctuid/general.el")) +(package! fill-column-indicator) +(package! writeroom-mode) +(package! dash) +(package! w3m) + +;;; Org (package! org-clubhouse :recipe (org-clubhouse :fetcher file :path "~/code/urb/org-clubhouse")) -(package! fill-column-indicator) -(package! writeroom-mode) -(package! dash) +(package! ob-http) +(package! ob-ipython) ;; Presentation (package! epresent) @@ -79,3 +84,6 @@ ;; SQL (package! sqlup-mode) + +;;; Python +(package! yapfify) -- cgit 1.4.1 From 5ce12fd2948c52be050329bd592ce36c2cfe25d6 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Sat, 26 Jan 2019 09:55:16 -0500 Subject: fireplace-esque cider bindings --- +bindings.el | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/+bindings.el b/+bindings.el index 023e7cb793..bcd49e0511 100644 --- a/+bindings.el +++ b/+bindings.el @@ -340,8 +340,6 @@ private/hlissner/snippets." :desc "Default browser" :n "b" #'browse-url-of-file :desc "Debugger" :n "d" #'+debug/open :desc "REPL" :n "r" #'+eval/open-repl - :v "r" #'+eval:repl - :desc "Neotree" :n "n" #'+neotree/toggle :desc "Terminal" :n "t" #'+term/open-popup :desc "Terminal in project" :n "T" #'+term/open-popup-in-project @@ -999,9 +997,75 @@ private/hlissner/snippets." "I" 'grfn/insert-at-sexp-start "a" 'grfn/insert-at-form-start)) -;; (nmap :keymaps 'cider-mode-map -;; "c" (general-key-dispatch 'evil-change -;; "p" 'cider-eval-sexp-at-point-in-context)) +(evil-define-operator fireplace-eval (beg end) + (cider-interactive-eval nil nil (list beg end))) + +(defun cider-insert-current-sexp-in-repl (&optional arg) + "Insert the expression at point in the REPL buffer. +If invoked with a prefix ARG eval the expression after inserting it" + (interactive "P") + (cider-insert-in-repl (cider-sexp-at-point) arg)) + +(evil-define-operator fireplace-send (beg end) + (cider-insert-current-sexp-in-repl nil nil (list beg end))) + +(defun +clojure-pprint-expr (form) + (format "(with-out-str (clojure.pprint/pprint %s))" + form)) + +(defun cider-eval-read-and-print-handler (&optional buffer) + "Make a handler for evaluating and reading then printing result in BUFFER." + (nrepl-make-response-handler + (or buffer (current-buffer)) + (lambda (buffer value) + (let ((value* (read value))) + (with-current-buffer buffer + (insert + (if (derived-mode-p 'cider-clojure-interaction-mode) + (format "\n%s\n" value*) + value*))))) + (lambda (_buffer out) (cider-emit-interactive-eval-output out)) + (lambda (_buffer err) (cider-emit-interactive-eval-err-output err)) + '())) + +(defun cider-eval-and-replace (beg end) + "Evaluate the expression in region and replace it with its result" + (interactive "r") + (let ((form (buffer-substring beg end))) + (cider-nrepl-sync-request:eval form) + (kill-region beg end) + (cider-interactive-eval + (+clojure-pprint-expr form) + (cider-eval-read-and-print-handler)))) + +(defun cider-eval-current-sexp-and-replace () + "Evaluate the expression at point and replace it with its result" + (interactive) + (apply #'cider-eval-and-replace (cider-sexp-at-point 'bounds))) + +(evil-define-operator fireplace-replace (beg end) + (cider-eval-and-replace beg end)) + +(evil-define-operator fireplace-eval-context (beg end) + (cider--eval-in-context (buffer-substring beg end))) + +;;; fireplace-esque eval binding +(nmap :keymaps 'cider-mode-map + "c" (general-key-dispatch 'evil-change + "p" (general-key-dispatch 'fireplace-eval + "p" 'cider-eval-sexp-at-point + "c" 'cider-eval-last-sexp + "d" 'cider-eval-defun-at-point + "r" 'cider-test-run-test) + "q" (general-key-dispatch 'fireplace-send + "q" 'cider-insert-current-sexp-in-repl + "c" 'cider-insert-last-sexp-in-repl) + "x" (general-key-dispatch 'fireplace-eval-context + "x" 'cider-eval-sexp-at-point-in-context + "c" 'cider-eval-last-sexp-in-context) + "!" (general-key-dispatch 'fireplace-replace + "!" 'cider-eval-current-sexp-and-replace + "c" 'cider-eval-last-sexp-and-replace))) ;; >) ; slurp forward @@ -1061,6 +1125,11 @@ private/hlissner/snippets." :desc "Goal type and context" :n "t" 'agda2-goal-and-context :desc "Goal type and context and inferred" :n ";" 'agda2-goal-and-context-and-inferred))) + (:after clojure-mode + (:map clojure-mode-map + :n "] f" 'forward-sexp + :n "[ f" 'backward-sexp)) + (:after cider-mode (:map cider-mode-map :n "g SPC" 'cider-eval-buffer @@ -1072,11 +1141,13 @@ private/hlissner/snippets." :n "g RET" 'cider-test-run-ns-tests "C-c C-r r" 'cljr-add-require-to-ns + "C-c C-r i" 'cljr-add-import-to-ns (:localleader ;; :desc "Inspect last result" :n "i" 'cider-inspect-last-result ;; :desc "Search for documentation" :n "h s" 'cider-apropos-doc - :desc "Add require to ns" :n "n r" 'cljr-add-require-to-ns)) + :desc "Add require to ns" :n "n r" 'cljr-add-require-to-ns + :desc "Add import to ns" :n "n i" 'cljr-add-import-to-ns)) (:map cider-repl-mode-map :n "g \\" 'cider-switch-to-last-clojure-buffer)) -- cgit 1.4.1 From b342415667464aeb8586ddbdaa2a124bc97fb3d9 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Wed, 27 Feb 2019 14:08:47 -0500 Subject: Lots of org stuff, spotify client, misc. dependency updates --- +bindings.el | 165 ++++++++++++++++++++++++++++++++++------------------------- config.el | 88 ++++++++++++++++++++++--------- init.el | 106 ++++++++++++++++++++------------------ packages.el | 12 +++-- 4 files changed, 223 insertions(+), 148 deletions(-) diff --git a/+bindings.el b/+bindings.el index bcd49e0511..a0c4467319 100644 --- a/+bindings.el +++ b/+bindings.el @@ -330,11 +330,10 @@ private/hlissner/snippets." :desc "Store link" :n "l" #'org-store-link :desc "Browse notes" :n "N" #'+hlissner/browse-notes :desc "Org capture" :n "x" #'+org-capture/open - :desc "Browse mode notes" :n "m" #'+org/browse-notes-for-major-mode - :desc "Browse project notes" :n "p" #'+org/browse-notes-for-project :desc "Create clubhouse story" :n "c" #'org-clubhouse-create-story :desc "Archive subtree" :n "k" #'org-archive-subtree - :desc "Goto clocked-in note" :n "g" #'org-clock-goto) + :desc "Goto clocked-in note" :n "g" #'org-clock-goto + :desc "Clock Out" :n "o" #'org-clock-out) (:desc "open" :prefix "o" :desc "Default browser" :n "b" #'browse-url-of-file @@ -354,6 +353,11 @@ private/hlissner/snippets." :desc "APP: twitter" :n "T" #'=twitter :desc "APP: regex" :n "X" #'=regex + (:desc "spotify" :prefix "s" + :desc "Search track" :n "t" #'counsel-spotify-search-track + :desc "Search album" :n "a" #'counsel-spotify-search-album + :desc "Search artist" :n "A" #'counsel-spotify-search-artist) + ;; macos (:when IS-MAC :desc "Reveal in Finder" :n "o" #'+macos/reveal-in-finder @@ -534,9 +538,6 @@ private/hlissner/snippets." ;; evil-exchange :n "gx" #'evil-exchange - ;; evil-matchit - :nv [tab] #'+evil/matchit-or-toggle-fold - ;; evil-magit (:after evil-magit :map (magit-status-mode-map magit-revision-mode-map) @@ -1065,7 +1066,8 @@ If invoked with a prefix ARG eval the expression after inserting it" "c" 'cider-eval-last-sexp-in-context) "!" (general-key-dispatch 'fireplace-replace "!" 'cider-eval-current-sexp-and-replace - "c" 'cider-eval-last-sexp-and-replace))) + "c" 'cider-eval-last-sexp-and-replace) + "y" 'cider-copy-last-result)) ;; >) ; slurp forward @@ -1094,70 +1096,91 @@ If invoked with a prefix ARG eval the expression after inserting it" ("cljs" (cider-interactive-eval "(with-out-string (cljs.test/run-tests))")) ("clj" (cider-test-run-ns-tests)))) +(defun cider-copy-last-result () + (interactive) + (cider-interactive-eval + "*1" + (nrepl-make-response-handler + (current-buffer) + (lambda (_ value) + (kill-new value) + (message "Copied last result (%s) to clipboard" + (if (= (length value) 1) "1 char" + (format "%d chars" (length value))))) + nil nil nil))) + + (map! - (:map haskell-mode-map - ;; :n "K" 'lsp-info-under-point - ;; :n "g d" 'lsp-ui-peek-find-definitions - ;; :n "g r" 'lsp-ui-peek-find-references - ;; :n "g \\" '+haskell/repl - :n "K" 'intero-info - :n "g d" 'intero-goto-definition - :n "g SPC" 'intero-repl-load - :n "g \\" 'intero-repl - :n "g y" 'intero-type-at - ;; :n "g RET" 'grfn/run-sputnik-test-for-file + (:map magit-mode-map + :n "#" 'forge-dispatch) + + (:map haskell-mode-map + ;; :n "K" 'lsp-info-under-point + ;; :n "g d" 'lsp-ui-peek-find-definitions + ;; :n "g r" 'lsp-ui-peek-find-references + ;; :n "g \\" '+haskell/repl + :n "K" 'intero-info + :n "g d" 'intero-goto-definition + :n "g SPC" 'intero-repl-load + :n "g \\" 'intero-repl + :n "g y" 'intero-type-at + ;; :n "g RET" 'grfn/run-sputnik-test-for-file + + (:localleader + :desc "Apply action" :n "e" 'intero-repl-eval-region + :desc "Rename symbol" :n "r" 'intero-apply-suggestions)) + + (:after agda2-mode + (:map agda2-mode-map + :n "g SPC" 'agda2-load + :n "g d" 'agda2-goto-definition-keyboard + :n "] g" 'agda2-next-goal + :n "[ g" 'agda2-previous-goal + + (:localleader + :desc "Give" :n "SPC" 'agda2-give + :desc "Refine" :n "r" 'agda2-refine + :desc "Auto" :n "a" 'agda2-auto + :desc "Goal type and context" :n "t" 'agda2-goal-and-context + :desc "Goal type and context and inferred" :n ";" 'agda2-goal-and-context-and-inferred))) + + (:after clojure-mode + (:map clojure-mode-map + :n "] f" 'forward-sexp + :n "[ f" 'backward-sexp)) + + (:after cider-mode + (:map cider-mode-map + :n "g SPC" 'cider-eval-buffer + :n "g \\" 'cider-switch-to-repl-buffer + :n "K" 'cider-doc + :n "g K" 'cider-grimoire + :n "g d" 'cider-find-dwim + :n "C-w ]" 'cider-find-dwim-other-window + :n "g RET" 'cider-test-run-ns-tests + + "C-c C-r r" 'cljr-add-require-to-ns + "C-c C-r i" 'cljr-add-import-to-ns + + (:localleader + ;; :desc "Inspect last result" :n "i" 'cider-inspect-last-result + ;; :desc "Search for documentation" :n "h s" 'cider-apropos-doc + :desc "Add require to ns" :n "n r" 'cljr-add-require-to-ns + :desc "Add import to ns" :n "n i" 'cljr-add-import-to-ns)) + (:map cider-repl-mode-map + :n "g \\" 'cider-switch-to-last-clojure-buffer)) + + (:after w3m + (:map w3m-mode-map + "/" 'evil-search-forward + "?" 'evil-search-backward)) + + (:after org + :n "C-c C-x C-o" #'org-clock-out + (:map org-mode-map + [remap counsel-imenu] #'counsel-org-goto + "M-k" #'org-move-subtree-up + "M-j" #'org-move-subtree-down (:localleader - :desc "Apply action" :n "e" 'intero-repl-eval-region - :desc "Rename symbol" :n "r" 'intero-apply-suggestions)) - - (:after agda2-mode - (:map agda2-mode-map - :n "g SPC" 'agda2-load - :n "g d" 'agda2-goto-definition-keyboard - :n "] g" 'agda2-next-goal - :n "[ g" 'agda2-previous-goal - - (:localleader - :desc "Give" :n "SPC" 'agda2-give - :desc "Refine" :n "r" 'agda2-refine - :desc "Auto" :n "a" 'agda2-auto - :desc "Goal type and context" :n "t" 'agda2-goal-and-context - :desc "Goal type and context and inferred" :n ";" 'agda2-goal-and-context-and-inferred))) - - (:after clojure-mode - (:map clojure-mode-map - :n "] f" 'forward-sexp - :n "[ f" 'backward-sexp)) - - (:after cider-mode - (:map cider-mode-map - :n "g SPC" 'cider-eval-buffer - :n "g \\" 'cider-switch-to-repl-buffer - :n "K" 'cider-doc - :n "g K" 'cider-grimoire - :n "g d" 'cider-find-dwim - :n "C-w ]" 'cider-find-dwim-other-window - :n "g RET" 'cider-test-run-ns-tests - - "C-c C-r r" 'cljr-add-require-to-ns - "C-c C-r i" 'cljr-add-import-to-ns - - (:localleader - ;; :desc "Inspect last result" :n "i" 'cider-inspect-last-result - ;; :desc "Search for documentation" :n "h s" 'cider-apropos-doc - :desc "Add require to ns" :n "n r" 'cljr-add-require-to-ns - :desc "Add import to ns" :n "n i" 'cljr-add-import-to-ns)) - (:map cider-repl-mode-map - :n "g \\" 'cider-switch-to-last-clojure-buffer)) - - (:after w3m - (:map w3m-mode-map - "/" 'evil-search-forward - "?" 'evil-search-backward)) - - (:after org - (:map org-mode-map - [remap counsel-imenu] #'counsel-org-goto - (:localleader - :n "g" #'counsel-org-goto)))) + :n "g" #'counsel-org-goto)))) diff --git a/config.el b/config.el index 5463d83196..ffc25fa517 100644 --- a/config.el +++ b/config.el @@ -12,6 +12,8 @@ (after! rust (setq rust-format-on-save t)) +(load! "utils") + ; (defconst rust-src-path ; (-> "/Users/griffin/.cargo/bin/rustc --print sysroot" ; shell-command-to-string @@ -106,7 +108,9 @@ (alist-set 'theme-overrides 'grfn-solarized-light `((font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) (font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) - (font-lock-keyword-face ((t (:foreground ,+solarized-green)))) + (font-lock-keyword-face ((t (:foreground ,+solarized-green :bold nil)))) + (font-lock-builtin-face ((t (:foreground ,+solarized-s-base01 + :bold t)))) (elixir-attribute-face ((t (:foreground ,+solarized-blue)))) (elixir-atom-face ((t (:foreground ,+solarized-cyan)))) @@ -117,7 +121,8 @@ (haskell-keyword-face ((t (:foreground ,+solarized-cyan)))))) (setq solarized-use-variable-pitch nil - solarized-scale-org-headlines nil) + solarized-scale-org-headlines nil + solarized-use-less-bold t) (add-to-list 'custom-theme-load-path "~/.doom.d/themes") (load-theme 'grfn-solarized-light t) @@ -129,7 +134,8 @@ (add-hook! doom-post-init (set-face-attribute 'bold nil :weight 'ultra-light) - (set-face-bold-p 'bold nil)) + (set-face-bold 'bold nil) + (enable-theme 'grfn-solarized-light)) (defun rx-words (&rest words) (rx-to-string @@ -273,7 +279,16 @@ ;; (hook-name) ;; (symbol-name mode))))) -(def-package! org-clubhouse) +(def-package! org-clubhouse + :config + (setq org-clubhouse-state-alist + '(("PROPOSED" . "Proposed") + ("BACKLOG" . "Backlog") + ("TODO" . "Scheduled") + ("ACTIVE" . "In Progress") + ("PR" . "In Review") + ("TESTING" . "In Testing") + ("DONE" . "Completed")))) ; (require 'doom-themes) @@ -409,7 +424,8 @@ org-agenda-custom-commands '(("p" "Sprint Tasks" tags-todo "sprint") ("i" "Inbox" tags "inbox") - ("r" "Running jobs" todo "RUNNING"))) + ("r" "Running jobs" todo "RUNNING") + ("w" "@Work" tags-todo "@work"))) (set-face-foreground 'org-block +solarized-s-base00) (add-hook! org-mode @@ -420,9 +436,10 @@ ) (after! magit - (setq git-commit-summary-max-length 50) - (require 'magit-gh-pulls) - (add-hook 'magit-mode-hook 'turn-on-magit-gh-pulls)) + (setq git-commit-summary-max-length 50)) + +;; (def-package! forge +;; :after magit) (comment @@ -471,7 +488,7 @@ (load! "slack-snippets") (after! magit - (require 'evil-magit) + ;; (require 'evil-magit) ;; (require 'magithub) ) @@ -581,12 +598,12 @@ ;; Auto-format Haskell on save, with a combination of hindent + brittany -(define-minor-mode brittany-haskell-mode - :init-value nil - :group 'haskell - :lighter "Brittany-Haskell" - :keymap '() - ) +; (define-minor-mode brittany-haskell-mode +; :init-value nil +; :group 'haskell +; :lighter "Brittany-Haskell" +; :keymap '() +; ) (defun urbint/format-haskell-source () @@ -620,6 +637,7 @@ (require 'slack) (setq slack-buffer-emojify 't slack-prefer-current-team 't) + (require 'alert) (setq alert-default-style 'libnotify) @@ -634,13 +652,15 @@ (setq projectile-create-missing-test-files 't) -(defun magit-commit-wip () - (interactive) - (magit-commit '("-m" "wip"))) - (after! magit - (magit-define-popup-action 'magit-commit-popup - ?W "WIP" 'magit-commit-wip)) + (define-suffix-command magit-commit-wip () + (interactive) + (magit-commit-create '("-m" "wip"))) + + (transient-append-suffix + #'magit-commit + ["c"] + (list "W" "Commit WIP" #'magit-commit-wip))) ;; (defun grfn/split-window-more-sensibly (&optional window) ;; (let ((window (or window (selected-window)))) @@ -838,11 +858,14 @@ (context 2) (checking 3) (match 1) - (domonad 0))) + (domonad 0) + (describe 1) + (before 1) + (it 2))) (def-package! flycheck-clojure - :disabled t - :after flycheck + ;; :disabled t + :after (flycheck cider) :config (flycheck-clojure-setup)) @@ -878,3 +901,20 @@ (add-to-list 'org-babel-load-languages '(ipython . t)) (setq ob-ipython-command "/home/griffin/code/urb/ciml-video-classifier/bin/jupyter")) + +(def-package! counsel-spotify) + +(def-package! evil-snipe :disabled t) +(evil-snipe-mode -1) + +(def-package! rainbow-mode) + +(def-package! org-alert + :config + (org-alert-enable) + (setq alert-default-style 'libnotify + org-alert-headline-title "org")) + +(def-package! ob-async) + +(enable-theme 'grfn-solarized-light) diff --git a/init.el b/init.el index af5ae02370..ca4a89069e 100644 --- a/init.el +++ b/init.el @@ -6,12 +6,10 @@ (evil +everywhere); come to the dark side, we have cookies file-templates ; auto-snippets for empty files (lookup ; helps you navigate your code and documentation - +devdocs ; ...on devdocs.io online +docsets) ; ...or in Dash docsets locally snippets ; my elves. They type so I don't have to spellcheck ; tasing you for misspelling mispelling - (syntax-checker ; tasing you for every semicolon you forget - +childframe) ; use childframes for error popups (Emacs 26+ only) + syntax-checker ; tasing you for every semicolon you forget workspaces ; tab emulation, persistence & separate workspaces :completion @@ -26,12 +24,11 @@ :ui doom ; what makes DOOM look the way it does doom-dashboard ; a nifty splash screen for Emacs - doom-modeline ; a snazzy Atom-inspired mode-line doom-quit ; DOOM quit-message prompts when you quit Emacs evil-goggles ; display visual hints when editing in evil fci ; a `fill-column' indicator hl-todo ; highlight TODO/FIXME/NOTE tags - ;modeline ; snazzy, Atom-inspired modeline, plus API + modeline ; snazzy, Atom-inspired modeline, plus API nav-flash ; blink the current line after jumping ;neotree ; a project drawer, like NERDTree for vim ;treemacs ; a project drawer, like neotree but cooler @@ -46,26 +43,32 @@ window-select ; visually switch windows :editor - ;(format +onsave) ; automated prettiness - ;multiple-cursors ; editing in many places at once - ;parinfer ; turn lisp into python, sort of + fold + ;; (format +onsave) ; automated prettiness + ;;lispy ; vim for lisp, for people who dont like vim + ;;multiple-cursors ; editing in many places at once + ;;parinfer ; turn lisp into python, sort of rotate-text ; cycle region at point between text candidates :emacs - dired ; making dired pretty [functional] - ediff ; comparing files in Emacs + (dired ; making dired pretty [functional] + ;;+ranger ; bringing the goodness of ranger to dired + ;;+icons ; colorful icons for dired-mode + ) electric ; smarter, keyword-based electric-indent - ;eshell ; a consistent, cross-platform shell (WIP) - hideshow ; basic code-folding support + ;;eshell ; a consistent, cross-platform shell (WIP) imenu ; an imenu sidebar and searchable code index - ;term ; terminals in Emacs + ;;term ; terminals in Emacs vc ; version-control and Emacs, sitting in a tree :tools docker editorconfig ; let someone else argue about tabs vs spaces - ;ein ; tame Jupyter notebooks with emacs + ein ; tame Jupyter notebooks with emacs + flycheck ; tasing you for every semicolon you forget + flyspell ; tasing you for misspelling mispelling gist ; interacting with github gists + lsp ;macos ; MacOS-specific commands make ; run make tasks from Emacs magit ; @@ -73,58 +76,61 @@ pdf ; pdf enhancements ;prodigy ; FIXME managing external services & code builders ;rgb ; creating color strings - ;tmux ; an API for interacting with tmux - ;upload ; map local to remote projects via ssh/ftp - ;wakatime + ;;terraform ; infrastructure as code + ;;tmux ; an API for interacting with tmux + ;;upload ; map local to remote projects via ssh/ftp + ;;wakatime :lang - ;assembly ; assembly for fun or debugging - ;(cc +irony +rtags); C/C++/Obj-C madness + ;;assembly ; assembly for fun or debugging + ;;(cc +irony +rtags); C/C++/Obj-C madness clojure ; java with a lisp - ;common-lisp ; if you've seen one lisp, you've seen them all - ;crystal ; ruby at the speed of c - ;csharp ; unity, .NET, and mono shenanigans + ;;common-lisp ; if you've seen one lisp, you've seen them all + coq ; proofs-as-programs + ;;crystal ; ruby at the speed of c + ;;csharp ; unity, .NET, and mono shenanigans data ; config/data formats erlang ; an elegant language for a more civilized age elixir ; erlang done right - ;elm ; care for a cup of TEA? + ;;elm ; care for a cup of TEA? emacs-lisp ; drown in parentheses - ;ess ; emacs speaks statistics - ;go ; the hipster dialect - (haskell +intero) ; a language that's lazier than I am - ;; haskell ; a language that's lazier than I am - ;hy ; readability of scheme w/ speed of python - ;(java +meghanada) ; the poster child for carpal tunnel syndrome + ;;ess ; emacs speaks statistics + ;;go ; the hipster dialect + (haskell +intero) ; a language that's lazier than I am + ;;hy ; readability of scheme w/ speed of python + idris ; + (java +meghanada) ; the poster child for carpal tunnel syndrome javascript ; all(hope(abandon(ye(who(enter(here)))))) - ;julia ; a better, faster MATLAB - latex ; writing papers in Emacs has never been so fun - ;ledger ; an accounting system in Emacs - ;lua ; one-based indices? one-based indices + julia ; a better, faster MATLAB + ;;latex ; writing papers in Emacs has never been so fun + ;;ledger ; an accounting system in Emacs + ;;lua ; one-based indices? one-based indices markdown ; writing docs for people to ignore - ;nim ; python + lisp at the speed of c - nix ; I hereby declare "nix geht mehr!" - ;ocaml ; an objective camel + ;;nim ; python + lisp at the speed of c + ;;nix ; I hereby declare "nix geht mehr!" + ocaml ; an objective camel (org ; organize your plain life in plain text +attach ; custom attachment system +babel ; running code in org +capture ; org-capture in and outside of Emacs +export ; Exporting org to whatever you want +present) ; Emacs for presentations - ;perl ; write code no one else can comprehend - ;php ; perl's insecure younger brother - ;plantuml ; diagrams for confusing people more - ;purescript ; javascript, but functional + ;;perl ; write code no one else can comprehend + ;;php ; perl's insecure younger brother + ;;plantuml ; diagrams for confusing people more + purescript ; javascript, but functional python ; beautiful is better than ugly - ;qt ; the 'cutest' gui framework ever - ;racket ; a DSL for DSLs - ;rest ; Emacs as a REST client - ruby ; 1.step do {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"} - ;rust ; Fe2O3.unwrap().unwrap().unwrap().unwrap() - ;scala ; java, but good - (sh +fish) ; she sells (ba|z)sh shells on the C xor - ;solidity ; do you need a blockchain? No. - ;swift ; who asked for emoji variables? - web ; the tubes + ;;qt ; the 'cutest' gui framework ever + racket ; a DSL for DSLs + rest ; Emacs as a REST client + ;;ruby ; 1.step do {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"} + rust ; Fe2O3.unwrap().unwrap().unwrap().unwrap() + ;;scala ; java, but good + (sh +fish) ; she sells (ba|z|fi)sh shells on the C xor + ;;solidity ; do you need a blockchain? No. + ;;swift ; who asked for emoji variables? + ;;web ; the tubes + ;;vala ; GObjective-C ;; Applications are complex and opinionated modules that transform Emacs ;; toward a specific purpose. They may have additional dependencies and diff --git a/packages.el b/packages.el index acf776dab1..e57037e831 100644 --- a/packages.el +++ b/packages.el @@ -3,6 +3,8 @@ ;; (package! 'tide :disable t) +(package! moody) + ;; Editor (package! solarized-theme) (package! fill-column-indicator) @@ -15,14 +17,17 @@ (package! writeroom-mode) (package! dash) (package! w3m) +(package! rainbow-mode) ;;; Org (package! org-clubhouse :recipe (org-clubhouse :fetcher file :path "~/code/urb/org-clubhouse")) +(package! org-alert) (package! ob-http) (package! ob-ipython) +(package! ob-async) ;; Presentation (package! epresent) @@ -35,10 +40,8 @@ ;; Git (package! evil-magit) -(package! magithub) -(package! magit-gh-pulls) (package! marshal) -; (package! auth-password-store) +(package! forge) ;; Elisp (package! dash) @@ -87,3 +90,6 @@ ;;; Python (package! yapfify) + +;;; Desktop interaction +(package! counsel-spotify) -- cgit 1.4.1 From 6adfc92a2c4c8770897ad7223905868a8efa05df Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Sun, 10 Mar 2019 22:23:45 -0400 Subject: Start work on company-sql --- company-sql.el | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ config.el | 6 ++ packages.el | 2 + 3 files changed, 251 insertions(+) create mode 100644 company-sql.el diff --git a/company-sql.el b/company-sql.el new file mode 100644 index 0000000000..c19182f917 --- /dev/null +++ b/company-sql.el @@ -0,0 +1,243 @@ +;;; ~/.doom.d/company-sql.el + +;;; Commentary: +;;; TODO + +;;; Code: + +(require 'emacsql) +(require 'emacsql-psql) +(require 'dash) +(require 's) +(require 'cl-lib) + +;;; Config + +(defvar-local company-sql-db-host "localhost" + "Host of the postgresql database to query for autocomplete information") + +(defvar-local company-sql-db-port 5432 + "Port of the postgresql database to query for autocomplete information") + +(defvar-local company-sql-db-user "postgres" + "Username of the postgresql database to query for autocomplete information") + +(defvar-local company-sql-db-name nil + "PostgreSQL database name to query for autocomplete information") + +;;; DB Connection + +(defvar-local company-sql/connection nil) + +(defun company-sql/connect () + (unless company-sql/connection + (setq-local company-sql/connection + (emacsql-psql company-sql-db-name + :hostname company-sql-db-host + :username company-sql-db-user + :port (number-to-string company-sql-db-port)))) + company-sql/connection) + +(defun company-sql/query (&rest args) + (apply 'emacsql (cons (company-sql/connect) args))) + +;;; Utils + +(defmacro comment (&rest _)) + +(defun ->string (x) + (cond + ((stringp x) x) + ((symbolp x) (symbol-name x)))) + +;;; Listing relations + +(defun company-sql/list-tables () + (-map (-compose 'symbol-name 'car) + (company-sql/query + [:select [tablename] + :from pg_catalog:pg_tables + :where (and (!= schemaname '"information_schema") + (!= schemaname '"pg_catalog"))]))) + +(defun company-sql/list-columns () + (-map + (lambda (row) + (propertize (symbol-name (nth 0 row)) + 'table-name (nth 1 row) + 'data-type (nth 2 row))) + (company-sql/query + [:select [column_name + table_name + data_type] + :from information_schema:columns]))) + +;;; Keywords + +(defvar company-postgresql/keywords + (list +"a" "abort" "abs" "absent" "absolute" "access" "according" "action" "ada" "add" +"admin" "after" "aggregate" "all" "allocate" "also" "alter" "always" "analyse" +"analyze" "and" "any" "are" "array" "array_agg" "array_max_cardinality" "as" +"asc" "asensitive" "assertion" "assignment" "asymmetric" "at" "atomic" "attach" +"attribute" "attributes" "authorization" "avg" "backward" "base64" "before" +"begin" "begin_frame" "begin_partition" "bernoulli" "between" "bigint" "binary" +"bit" "bit_length" "blob" "blocked" "bom" "boolean" "both" "breadth" "by" "c" +"cache" "call" "called" "cardinality" "cascade" "cascaded" "case" "cast" +"catalog" "catalog_name" "ceil" "ceiling" "chain" "char" "character" +"characteristics" "characters" "character_length" "character_set_catalog" +"character_set_name" "character_set_schema" "char_length" "check" "checkpoint" +"class" "class_origin" "clob" "close" "cluster" "coalesce" "cobol" "collate" +"collation" "collation_catalog" "collation_name" "collation_schema" "collect" +"column" "columns" "column_name" "command_function" "command_function_code" +"comment" "comments" "commit" "committed" "concurrently" "condition" +"condition_number" "configuration" "conflict" "connect" "connection" +"connection_name" "constraint" "constraints" "constraint_catalog" +"constraint_name" "constraint_schema" "constructor" "contains" "content" +"continue" "control" "conversion" "convert" "copy" "corr" "corresponding" "cost" +"count" "covar_pop" "covar_samp" "create" "cross" "csv" "cube" "cume_dist" +"current" "current_catalog" "current_date" "current_default_transform_group" +"current_path" "current_role" "current_row" "current_schema" "current_time" +"current_timestamp" "current_transform_group_for_type" "current_user" "cursor" +"cursor_name" "cycle" "data" "database" "datalink" "date" +"datetime_interval_code" "datetime_interval_precision" "day" "db" "deallocate" +"dec" "decimal" "declare" "default" "defaults" "deferrable" "deferred" "defined" +"definer" "degree" "delete" "delimiter" "delimiters" "dense_rank" "depends" +"depth" "deref" "derived" "desc" "describe" "descriptor" "detach" +"deterministic" "diagnostics" "dictionary" "disable" "discard" "disconnect" +"dispatch" "distinct" "dlnewcopy" "dlpreviouscopy" "dlurlcomplete" +"dlurlcompleteonly" "dlurlcompletewrite" "dlurlpath" "dlurlpathonly" +"dlurlpathwrite" "dlurlscheme" "dlurlserver" "dlvalue" "do" "document" "domain" +"double" "drop" "dynamic" "dynamic_function" "dynamic_function_code" "each" +"element" "else" "empty" "enable" "encoding" "encrypted" "end" "end-exec" +"end_frame" "end_partition" "enforced" "enum" "equals" "escape" "event" "every" +"except" "exception" "exclude" "excluding" "exclusive" "exec" "execute" "exists" +"exp" "explain" "expression" "extension" "external" "extract" "false" "family" +"fetch" "file" "filter" "final" "first" "first_value" "flag" "float" "floor" +"following" "for" "force" "foreign" "fortran" "forward" "found" "frame_row" +"free" "freeze" "from" "fs" "full" "function" "functions" "fusion" "g" "general" +"generated" "get" "global" "go" "goto" "grant" "granted" "greatest" "group" +"grouping" "groups" "handler" "having" "header" "hex" "hierarchy" "hold" "hour" +"id" "identity" "if" "ignore" "ilike" "immediate" "immediately" "immutable" +"implementation" "implicit" "import" "in" "include" "including" "increment" +"indent" "index" "indexes" "indicator" "inherit" "inherits" "initially" "inline" +"inner" "inout" "input" "insensitive" "insert" "instance" "instantiable" +"instead" "int" "integer" "integrity" "intersect" "intersection" "interval" +"into" "invoker" "is" "isnull" "isolation" "join" "k" "key" "key_member" +"key_type" "label" "lag" "language" "large" "last" "last_value" "lateral" "lead" +"leading" "leakproof" "least" "left" "length" "level" "library" "like" +"like_regex" "limit" "link" "listen" "ln" "load" "local" "localtime" +"localtimestamp" "location" "locator" "lock" "locked" "logged" "lower" "m" "map" +"mapping" "match" "matched" "materialized" "max" "maxvalue" "max_cardinality" +"member" "merge" "message_length" "message_octet_length" "message_text" "method" +"min" "minute" "minvalue" "mod" "mode" "modifies" "module" "month" "more" "move" +"multiset" "mumps" "name" "names" "namespace" "national" "natural" "nchar" +"nclob" "nesting" "new" "next" "nfc" "nfd" "nfkc" "nfkd" "nil" "no" "none" +"normalize" "normalized" "not" "nothing" "notify" "notnull" "nowait" "nth_value" +"ntile" "null" "nullable" "nullif" "nulls" "number" "numeric" "object" +"occurrences_regex" "octets" "octet_length" "of" "off" "offset" "oids" "old" +"on" "only" "open" "operator" "option" "options" "or" "order" "ordering" +"ordinality" "others" "out" "outer" "output" "over" "overlaps" "overlay" +"overriding" "owned" "owner" "p" "pad" "parallel" "parameter" "parameter_mode" +"parameter_name" "parameter_ordinal_position" "parameter_specific_catalog" +"parameter_specific_name" "parameter_specific_schema" "parser" "partial" +"partition" "pascal" "passing" "passthrough" "password" "path" "percent" +"percentile_cont" "percentile_disc" "percent_rank" "period" "permission" +"placing" "plans" "pli" "policy" "portion" "position" "position_regex" "power" +"precedes" "preceding" "precision" "prepare" "prepared" "preserve" "primary" +"prior" "privileges" "procedural" "procedure" "procedures" "program" "public" +"publication" "quote" "range" "rank" "read" "reads" "real" "reassign" "recheck" +"recovery" "recursive" "ref" "references" "referencing" "refresh" "regr_avgx" +"regr_avgy" "regr_count" "regr_intercept" "regr_r2" "regr_slope" "regr_sxx" +"regr_sxy" "regr_syy" "reindex" "relative" "release" "rename" "repeatable" +"replace" "replica" "requiring" "reset" "respect" "restart" "restore" "restrict" +"result" "return" "returned_cardinality" "returned_length" +"returned_octet_length" "returned_sqlstate" "returning" "returns" "revoke" +"right" "role" "rollback" "rollup" "routine" "routines" "routine_catalog" +"routine_name" "routine_schema" "row" "rows" "row_count" "row_number" "rule" +"savepoint" "scale" "schema" "schemas" "schema_name" "scope" "scope_catalog" +"scope_name" "scope_schema" "scroll" "search" "second" "section" "security" +"select" "selective" "self" "sensitive" "sequence" "sequences" "serializable" +"server" "server_name" "session" "session_user" "set" "setof" "sets" "share" +"show" "similar" "simple" "size" "skip" "smallint" "snapshot" "some" "source" +"space" "specific" "specifictype" "specific_name" "sql" "sqlcode" "sqlerror" +"sqlexception" "sqlstate" "sqlwarning" "sqrt" "stable" "standalone" "start" +"state" "statement" "static" "statistics" "stddev_pop" "stddev_samp" "stdin" +"stdout" "storage" "strict" "strip" "structure" "style" "subclass_origin" +"submultiset" "subscription" "substring" "substring_regex" "succeeds" "sum" +"symmetric" "sysid" "system" "system_time" "system_user" "t" "table" "tables" +"tablesample" "tablespace" "table_name" "temp" "template" "temporary" "text" +"then" "ties" "time" "timestamp" "timezone_hour" "timezone_minute" "to" "token" +"top_level_count" "trailing" "transaction" "transactions_committed" +"transactions_rolled_back" "transaction_active" "transform" "transforms" +"translate" "translate_regex" "translation" "treat" "trigger" "trigger_catalog" +"trigger_name" "trigger_schema" "trim" "trim_array" "true" "truncate" "trusted" +"type" "types" "uescape" "unbounded" "uncommitted" "under" "unencrypted" "union" +"unique" "unknown" "unlink" "unlisten" "unlogged" "unnamed" "unnest" "until" +"untyped" "update" "upper" "uri" "usage" "user" "user_defined_type_catalog" +"user_defined_type_code" "user_defined_type_name" "user_defined_type_schema" +"using" "vacuum" "valid" "validate" "validator" "value" "values" "value_of" +"varbinary" "varchar" "variadic" "varying" "var_pop" "var_samp" "verbose" +"version" "versioning" "view" "views" "volatile" "when" "whenever" "where" +"whitespace" "width_bucket" "window" "with" "within" "without" "work" "wrapper" +"write" "xml" "xmlagg" "xmlattributes" "xmlbinary" "xmlcast" "xmlcomment" +"xmlconcat" "xmldeclaration" "xmldocument" "xmlelement" "xmlexists" "xmlforest" +"xmliterate" "xmlnamespaces" "xmlparse" "xmlpi" "xmlquery" "xmlroot" "xmlschema" +"xmlserialize" "xmltable" "xmltext" "xmlvalidate" "year" "yes" "zone")) + +;;; Company backend + +(defun company-postgresql/candidates (prefix) + (-filter + (apply-partially #'s-starts-with? prefix) + (append (-map (lambda (s) + (propertize s 'company-postgresql-annotation "table")) + (company-sql/list-tables)) + (-map (lambda (s) + (propertize s 'company-postgresql-annotation + (format "%s.%s %s" + (get-text-property 0 'table-name s) + s + (-> + (get-text-property 0 'data-type s) + (->string) + (upcase))))) + (company-sql/list-columns)) + (-map (lambda (s) + (propertize s 'company-postgresql-annotation "keyword")) + company-postgresql/keywords)))) + +(defun company-postgresql (command &optional arg &rest _) + (interactive (list 'interactive)) + (cl-case command + (interactive (company-begin-backend 'company-postgresql)) + (init (company-sql/connect)) + (prefix (if (bound-and-true-p org-mode) + (when (company-sql/in-sql-source-block-p) + (company-grab-symbol)) + (company-grab-symbol))) + (annotation + (get-text-property 0 'company-postgresql-annotation arg)) + (candidates (company-postgresql/candidates arg)) + (duplicates t) + (ignore-case t))) + +;;; org-babel company sql + +(defvar-local org-company-sql/connections) + +(defun company-sql/in-sql-source-block-p () + (let ((org-elt (org-element-at-point))) + (and (eq 'src-block (car org-elt)) + (equal "sql" (plist-get (cadr org-elt) + :language))))) + +(defun company-ob-postgresql (command &optional arg &rest _) + (interactive (list 'interactive)) + (cl-case command + (interactive (company-begin-backend 'company-ob-postgresql)) + (init (company-sql/connect)))) + +;;; + +(provide 'company-sql) diff --git a/config.el b/config.el index ffc25fa517..04f1ea704e 100644 --- a/config.el +++ b/config.el @@ -14,6 +14,8 @@ (load! "utils") +(load! "company-sql") + ; (defconst rust-src-path ; (-> "/Users/griffin/.cargo/bin/rustc --print sysroot" ; shell-command-to-string @@ -884,6 +886,10 @@ (sql-mode-hook . sqlup-mode) (sql-interactive-mode-hook . sqlup-mode)) +(def-package! emacsql) +(def-package! emacsql-psql + :after (emacsql)) + (def-package! yapfify :hook (python-mode-hook . yapf-mode)) diff --git a/packages.el b/packages.el index e57037e831..86146eb6df 100644 --- a/packages.el +++ b/packages.el @@ -87,6 +87,8 @@ ;; SQL (package! sqlup-mode) +(package! emacsql) +(package! emacsql-psql) ;;; Python (package! yapfify) -- cgit 1.4.1 From fe879c97f3b8b9c04f800ebadc055790abc7cb32 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 11 Mar 2019 11:56:35 -0400 Subject: Support for org source blocks in company-sqlcode wooooooo --- company-sql.el | 93 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 18 deletions(-) diff --git a/company-sql.el b/company-sql.el index c19182f917..58c57dde80 100644 --- a/company-sql.el +++ b/company-sql.el @@ -38,9 +38,6 @@ :port (number-to-string company-sql-db-port)))) company-sql/connection) -(defun company-sql/query (&rest args) - (apply 'emacsql (cons (company-sql/connect) args))) - ;;; Utils (defmacro comment (&rest _)) @@ -50,23 +47,29 @@ ((stringp x) x) ((symbolp x) (symbol-name x)))) +(defun alist-get-equal (key alist) + "Like `alist-get', but uses `equal' instead of `eq' for comparing keys" + (->> alist + (-find (lambda (pair) (equal key (car pair)))) + (cdr))) + ;;; Listing relations -(defun company-sql/list-tables () +(cl-defun company-sql/list-tables (conn) (-map (-compose 'symbol-name 'car) - (company-sql/query + (emacsql conn [:select [tablename] :from pg_catalog:pg_tables :where (and (!= schemaname '"information_schema") (!= schemaname '"pg_catalog"))]))) -(defun company-sql/list-columns () +(cl-defun company-sql/list-columns (conn) (-map (lambda (row) (propertize (symbol-name (nth 0 row)) 'table-name (nth 1 row) 'data-type (nth 2 row))) - (company-sql/query + (emacsql conn [:select [column_name table_name data_type] @@ -187,12 +190,12 @@ ;;; Company backend -(defun company-postgresql/candidates (prefix) +(cl-defun company-postgresql/candidates (prefix conn) (-filter (apply-partially #'s-starts-with? prefix) (append (-map (lambda (s) (propertize s 'company-postgresql-annotation "table")) - (company-sql/list-tables)) + (company-sql/list-tables conn)) (-map (lambda (s) (propertize s 'company-postgresql-annotation (format "%s.%s %s" @@ -202,7 +205,7 @@ (get-text-property 0 'data-type s) (->string) (upcase))))) - (company-sql/list-columns)) + (company-sql/list-columns conn)) (-map (lambda (s) (propertize s 'company-postgresql-annotation "keyword")) company-postgresql/keywords)))) @@ -212,31 +215,85 @@ (cl-case command (interactive (company-begin-backend 'company-postgresql)) (init (company-sql/connect)) - (prefix (if (bound-and-true-p org-mode) - (when (company-sql/in-sql-source-block-p) - (company-grab-symbol)) - (company-grab-symbol))) + (prefix (company-grab-symbol)) (annotation (get-text-property 0 'company-postgresql-annotation arg)) - (candidates (company-postgresql/candidates arg)) + (candidates (company-postgresql/candidates + arg + (company-sql/connect))) (duplicates t) (ignore-case t))) ;;; org-babel company sql -(defvar-local org-company-sql/connections) +(defvar-local org-company-sql/connections + ()) + +(defun org-company-sql/connect (conn-params) + (car ; ??? + (or (alist-get-equal conn-params org-company-sql/connections) + (let ((conn (apply 'emacsql-psql conn-params))) + (add-to-list 'org-company-sql/connections (cons conn-params conn)) + conn)))) -(defun company-sql/in-sql-source-block-p () +(defun org-company-sql/in-sql-source-block-p () (let ((org-elt (org-element-at-point))) (and (eq 'src-block (car org-elt)) (equal "sql" (plist-get (cadr org-elt) :language))))) +(defun org-company-sql/parse-cmdline (cmdline) + (let* ((lexed (s-split (rx (one-or-more blank)) cmdline)) + (go (lambda (state tokens) + (if (null tokens) () + (let ((token (car tokens)) + (tokens (cdr tokens))) + (if (null state) + (if (s-starts-with? "-" token) + (funcall go token tokens) + (cons token (funcall go state tokens))) + (cons (cons state token) ; ("-h" . "localhost") + (funcall go nil tokens))))))) + (opts (funcall go nil lexed))) + opts)) + +(defun org-company-sql/source-block-conn-params () + (let* ((block-info (org-babel-get-src-block-info)) + (params (caddr block-info)) + (cmdline (alist-get :cmdline params)) + (parsed (org-company-sql/parse-cmdline cmdline)) + (opts (-filter #'listp parsed)) + (positional (-filter #'stringp parsed)) + (host (alist-get-equal "-h" opts)) + (port (or (alist-get-equal "-p" opts) + "5432")) + (dbname (or (alist-get-equal "-d" opts) + (car positional))) + (username (or (alist-get-equal "-U" opts) + (cadr positional)))) + (list dbname + :hostname host + :username username + :port port))) + +(defun org-company-sql/connection-for-source-block () + (org-company-sql/connect + (org-company-sql/source-block-conn-params))) + + (defun company-ob-postgresql (command &optional arg &rest _) (interactive (list 'interactive)) (cl-case command (interactive (company-begin-backend 'company-ob-postgresql)) - (init (company-sql/connect)))) + (prefix (and (org-company-sql/in-sql-source-block-p) + (company-grab-symbol))) + (annotation (get-text-property 0 'company-postgresql-annotation arg)) + (candidates + (company-postgresql/candidates + arg + (org-company-sql/connection-for-source-block))) + (duplicates t) + (ignore-case t))) ;;; -- cgit 1.4.1 From 857bb51980457e0d34aea80f9095b3b03e70b874 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Wed, 13 Mar 2019 12:33:05 -0400 Subject: binding to insert new source blocks --- +bindings.el | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/+bindings.el b/+bindings.el index a0c4467319..c3acadf295 100644 --- a/+bindings.el +++ b/+bindings.el @@ -1110,6 +1110,37 @@ If invoked with a prefix ARG eval the expression after inserting it" nil nil nil))) +(defun grfn/insert-new-src-block () + (interactive) + (let* ((current-src-block (org-element-at-point)) + (src-block-head (save-excursion + (goto-char (org-element-property + :begin current-src-block)) + (thing-at-point 'line t))) + (point-to-insert + (if-let (results-loc (org-babel-where-is-src-block-result)) + (save-excursion + (goto-char results-loc) + (org-element-property + :end + (org-element-at-point))) + (org-element-property :end (org-element-at-point))))) + (goto-char point-to-insert) + (insert "\n") + (insert src-block-head) + (let ((contents (point-marker))) + (insert "\n#+END_SRC\n") + (goto-char contents)))) + +(defun grfn/+org-insert-item (orig direction) + (interactive) + (if (and (org-in-src-block-p) + (equal direction 'below)) + (grfn/insert-new-src-block) + (funcall orig direction))) + +(advice-add #'+org/insert-item :around #'grfn/+org-insert-item) + (map! (:map magit-mode-map -- cgit 1.4.1 From c3cc2313513992f9e225d1bd39b7c858a5e3d463 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Sun, 24 Mar 2019 20:52:35 -0400 Subject: Command to make a new alembic migration --- +commands.el | 8 ++++++++ config.el | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/+commands.el b/+commands.el index 9b4a685e1c..4025a9504a 100644 --- a/+commands.el +++ b/+commands.el @@ -115,6 +115,14 @@ ;; Org-mode (ex! "cap" #'+org-capture/dwim) +(ex! "arev" #'generate-alembic-migration) + +(evil-define-command evil-alembic-upgrade (&optional revision) + (interactive "") + (alembic-upgrade revision)) + +(ex! "aup" #'evil-alembic-upgrade) + ;; Elixir (add-hook! elixir-mode (ex! "AV" #'alchemist-project-toggle-file-and-tests-other-window) diff --git a/config.el b/config.el index 04f1ea704e..20df1d0ebf 100644 --- a/config.el +++ b/config.el @@ -923,4 +923,63 @@ (def-package! ob-async) +(def-package! org-recent-headings + :after (org) + :config + (map! :n "SPC n r" #'org-recent-headings-ivy)) + +(def-package! org-sticky-header + :after (org) + :hook (org-mode-hook . org-sticky-header-mode) + :config + (setq-default org-sticky-header-heading-star "●")) + (enable-theme 'grfn-solarized-light) + +;;; word-char +(add-hook! prog-mode + (modify-syntax-entry ?_ "w")) + +(add-hook! lisp-mode + (modify-syntax-entry ?- "w")) + +(after! flycheck + (put 'flycheck-python-pylint-executable 'safe-local-variable (lambda (_) t))) + +(defvar alembic-command "alembic" + "Command to execute when running alembic") + +(defvar alembic-dir-fun (lambda () default-directory) + "Reference to a function whose return value will be used as the directory to + run Alembic in") + +(comment + (+grfn/extract-alembic-migration-name + "Generating +/home/griffin/code/urb/grid/backend/src/grid/migrations/versions/15fb1b518507_test.py +... done")) + +(defun +grfn/extract-alembic-migration-name (output) + (string-match (rx (0+ anything) "Generating " + (group (one-or-more (not (syntax whitespace)))) + " ... done" + (0+ anything)) + output) + (match-string-no-properties 1 output)) + +(defun generate-alembic-migration (msg) + (interactive "sMessage: ") + (let* ((default-directory (funcall alembic-dir-fun)) + (out (shell-command-to-string + (format "%s revision -m \"%s\"" + alembic-command + msg))) + (migration-name (+grfn/extract-alembic-migration-name out))) + (find-file-other-window migration-name))) + +(defun alembic-upgrade (&optional revision) + (let ((default-directory (funcall alembic-dir-fun))) + (message + (shell-command-to-string (format "%s upgrade %s" + alembic-command + (or revision "head")))))) -- cgit 1.4.1 From a3eb6846b3eeb739bce26a7b92b6a634688e57af Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Fri, 29 Mar 2019 12:10:48 -0400 Subject: Start making fireplace eval commands work in elisp --- +bindings.el | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- config.el | 4 ++- packages.el | 4 +++ 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/+bindings.el b/+bindings.el index c3acadf295..af54d84086 100644 --- a/+bindings.el +++ b/+bindings.el @@ -2,6 +2,7 @@ (load! "utils") (require 'f) +(require 'predd) (defmacro find-file-in! (path &optional project-p) "Returns an interactive function for searching files." @@ -101,6 +102,14 @@ private/hlissner/snippets." (+hlissner-def-finder! doomd (expand-file-name ".doom.d" "~")) (+hlissner-def-finder! notes +org-dir) +(defun +grfn/paxedit-kill (&optional n) + (interactive "p") + (or (paxedit-comment-kill) + (when (paxedit-symbol-cursor-within?) + (paxedit-symbol-kill)) + (paxedit-implicit-sexp-kill n) + (paxedit-sexp-kill n) + (message paxedit-message-kill))) ;;; (map! @@ -421,7 +430,7 @@ private/hlissner/snippets." :i "[" #'paxedit-open-bracket :i "{" #'paxedit-open-curly :n [remap evil-yank-line] #'paxedit-copy - :n [remap evil-delete-line] #'paxedit-kill + :n [remap evil-delete-line] #'+grfn/paxedit-kill :n "g o" #'paxedit-sexp-raise :n [remap evil-join-whitespace] #'paxedit-compress :n "g S" #'paxedit-format-1 @@ -998,9 +1007,56 @@ private/hlissner/snippets." "I" 'grfn/insert-at-sexp-start "a" 'grfn/insert-at-form-start)) -(evil-define-operator fireplace-eval (beg end) +(predd-defmulti eval-sexp (lambda (form) major-mode)) + +(predd-defmethod eval-sexp 'clojure-mode (form) + (cider-interactive-eval form)) + +(predd-defmethod eval-sexp 'emacs-lisp-mode (form) + (pp-eval-expression form)) + +(predd-defmulti eval-sexp-region (lambda (_beg _end) major-mode)) + +(predd-defmethod eval-sexp-region 'clojure-mode (beg end) (cider-interactive-eval nil nil (list beg end))) +(predd-defmethod eval-sexp-region 'emacs-lisp-mode (beg end) + (pp-eval-expression (read (buffer-substring beg end)))) + +(predd-defmulti eval-sexp-region-context (lambda (_beg _end _context) major-mode)) + +(predd-defmethod eval-sexp-region-context 'clojure-mode (beg end context) + (cider--eval-in-context (buffer-substring beg end))) + +(defun pp-eval-context-region (beg end context) + (interactive "r\nxContext: ") + (let* ((inner-expr (read (buffer-substring beg end))) + (full-expr (list 'let* context inner-expr))) + (pp-eval-expression full-expr))) + +(predd-defmethod eval-sexp-region-context 'emacs-lisp-mode (beg end context) + (pp-eval-context-region beg end context)) + +(predd-defmulti preceding-sexp (lambda () major-mode)) + +(predd-defmethod preceding-sexp 'clojure-mode () + (cider-last-sexp)) + +(predd-defmethod preceding-sexp 'emacs-lisp-mode () + (elisp--preceding-sexp)) + +(defun eval-sexp-at-point () + (interactive) + (let ((bounds (bounds-of-thing-at-point 'sexp))) + (eval-sexp-region (car bounds) + (cdr bounds)))) + +(defun eval-last-sexp () + (interactive) + (eval-sexp (preceding-sexp))) + +;;; + (defun cider-insert-current-sexp-in-repl (&optional arg) "Insert the expression at point in the REPL buffer. If invoked with a prefix ARG eval the expression after inserting it" @@ -1044,11 +1100,16 @@ If invoked with a prefix ARG eval the expression after inserting it" (interactive) (apply #'cider-eval-and-replace (cider-sexp-at-point 'bounds))) +;;; + +(evil-define-operator fireplace-eval (beg end) + (eval-sexp-region beg end)) + (evil-define-operator fireplace-replace (beg end) (cider-eval-and-replace beg end)) (evil-define-operator fireplace-eval-context (beg end) - (cider--eval-in-context (buffer-substring beg end))) + (eval-sexp-region-context beg end)) ;;; fireplace-esque eval binding (nmap :keymaps 'cider-mode-map @@ -1069,6 +1130,23 @@ If invoked with a prefix ARG eval the expression after inserting it" "c" 'cider-eval-last-sexp-and-replace) "y" 'cider-copy-last-result)) +;;; + +(nmap :keymaps 'emacs-lisp-mode-map + "c" (general-key-dispatch 'evil-change + "p" (general-key-dispatch 'fireplace-eval + "p" 'eval-sexp-at-point + "c" 'eval-last-sexp + "d" 'cider-eval-defun-at-point + "r" 'cider-test-run-test) + "x" (general-key-dispatch 'fireplace-eval-context + "x" 'cider-eval-sexp-at-point-in-context + "c" 'cider-eval-last-sexp-in-context) + "!" (general-key-dispatch 'fireplace-replace + "!" 'cider-eval-current-sexp-and-replace + "c" 'cider-eval-last-sexp-and-replace) + "y" 'cider-copy-last-result)) + ;; >) ; slurp forward ;; <) ; barf forward @@ -1207,6 +1285,10 @@ If invoked with a prefix ARG eval the expression after inserting it" "/" 'evil-search-forward "?" 'evil-search-backward)) + (:after slack + (:map slack-message-buffer-mode-map + :i "" #'slack-message-edit)) + (:after org :n "C-c C-x C-o" #'org-clock-out (:map org-mode-map diff --git a/config.el b/config.el index 20df1d0ebf..b928937623 100644 --- a/config.el +++ b/config.el @@ -211,12 +211,14 @@ (require 'dash) +(def-package! predd) + ;; ;; Global config ;; -(setq +doom-modeline-buffer-file-name-style 'relative-to-project) +(setq doom-modeline-buffer-file-name-style 'relative-to-project) ;; ;; Modules diff --git a/packages.el b/packages.el index 86146eb6df..799bcbe92a 100644 --- a/packages.el +++ b/packages.el @@ -48,6 +48,10 @@ (package! dash-functional) (package! s) (package! request) +(package! predd + :recipe (predd + :fetcher github + :repo "skeeto/predd")) ;; Haskell (package! lsp-mode) -- cgit 1.4.1 From 23b179ad1d3d2e07c114741dffc50a8343f0a7a6 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Tue, 9 Jul 2019 17:50:51 -0400 Subject: A bunch of new snippets --- snippets/js2-mode/before | 7 +++++++ snippets/js2-mode/context | 7 +++++++ snippets/js2-mode/function | 6 ++++++ snippets/org-mode/SQL source block | 6 ++++++ snippets/org-mode/description | 7 +++++++ snippets/org-mode/python source block | 6 ++++++ snippets/org-mode/transaction | 7 +++++++ snippets/python-mode/add_column | 5 +++++ snippets/python-mode/op.get_bind.execute | 6 ++++++ snippets/rust-mode/#[macro_use] | 5 +++++ snippets/rust-mode/tests | 9 +++++++++ snippets/sql-mode/count(*) group by | 5 +++++ 12 files changed, 76 insertions(+) create mode 100644 snippets/js2-mode/before create mode 100644 snippets/js2-mode/context create mode 100644 snippets/js2-mode/function create mode 100644 snippets/org-mode/SQL source block create mode 100644 snippets/org-mode/description create mode 100644 snippets/org-mode/python source block create mode 100644 snippets/org-mode/transaction create mode 100644 snippets/python-mode/add_column create mode 100644 snippets/python-mode/op.get_bind.execute create mode 100644 snippets/rust-mode/#[macro_use] create mode 100644 snippets/rust-mode/tests create mode 100644 snippets/sql-mode/count(*) group by diff --git a/snippets/js2-mode/before b/snippets/js2-mode/before new file mode 100644 index 0000000000..4569b65831 --- /dev/null +++ b/snippets/js2-mode/before @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: before +# key: bef +# -- +before(function() { + $1 +}) diff --git a/snippets/js2-mode/context b/snippets/js2-mode/context new file mode 100644 index 0000000000..d83809f3c3 --- /dev/null +++ b/snippets/js2-mode/context @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: context +# key: context +# -- +context('$1', function() { + $2 +}) diff --git a/snippets/js2-mode/function b/snippets/js2-mode/function new file mode 100644 index 0000000000..b423044b44 --- /dev/null +++ b/snippets/js2-mode/function @@ -0,0 +1,6 @@ +# key: f +# name: function +# -- +function $1($2) { + $3 +} \ No newline at end of file diff --git a/snippets/org-mode/SQL source block b/snippets/org-mode/SQL source block new file mode 100644 index 0000000000..b5d43fd6bc --- /dev/null +++ b/snippets/org-mode/SQL source block @@ -0,0 +1,6 @@ +# key: sql +# name: SQL source block +# -- +#+BEGIN_SRC sql ${1::async} +$2 +#+END_SRC diff --git a/snippets/org-mode/description b/snippets/org-mode/description new file mode 100644 index 0000000000..a43bc95cc3 --- /dev/null +++ b/snippets/org-mode/description @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: description +# key: desc +# -- +:DESCRIPTION: +$1 +:END: diff --git a/snippets/org-mode/python source block b/snippets/org-mode/python source block new file mode 100644 index 0000000000..247ae51b0b --- /dev/null +++ b/snippets/org-mode/python source block @@ -0,0 +1,6 @@ +# key: py +# name: Python source block +# -- +#+BEGIN_SRC python +$0 +#+END_SRC \ No newline at end of file diff --git a/snippets/org-mode/transaction b/snippets/org-mode/transaction new file mode 100644 index 0000000000..37f2dd31ca --- /dev/null +++ b/snippets/org-mode/transaction @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: transaction +# key: begin +# -- +BEGIN; +$0 +ROLLBACK; \ No newline at end of file diff --git a/snippets/python-mode/add_column b/snippets/python-mode/add_column new file mode 100644 index 0000000000..47e83850d5 --- /dev/null +++ b/snippets/python-mode/add_column @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: add_column +# key: op.add_column +# -- +op.add_column('${1:table}', sa.Column('${2:name}', sa.${3:String()}))$0 diff --git a/snippets/python-mode/op.get_bind.execute b/snippets/python-mode/op.get_bind.execute new file mode 100644 index 0000000000..5f46464ac9 --- /dev/null +++ b/snippets/python-mode/op.get_bind.execute @@ -0,0 +1,6 @@ +# key: exec +# name: op.get_bind.execute +# -- +op.get_bind().execute(""" + `(progn (sqlup-mode) "")`$1 +""") diff --git a/snippets/rust-mode/#[macro_use] b/snippets/rust-mode/#[macro_use] new file mode 100644 index 0000000000..fea942a337 --- /dev/null +++ b/snippets/rust-mode/#[macro_use] @@ -0,0 +1,5 @@ +# key: macro_use +# name: #[macro_use] +# -- +#[macro_use] +${1:extern crate} ${2:something};$0 diff --git a/snippets/rust-mode/tests b/snippets/rust-mode/tests new file mode 100644 index 0000000000..0a476ab586 --- /dev/null +++ b/snippets/rust-mode/tests @@ -0,0 +1,9 @@ +# key: tests +# name: test module +# -- +#[cfg(test)] +mod ${1:tests} { + use super::*; + + $0 +} diff --git a/snippets/sql-mode/count(*) group by b/snippets/sql-mode/count(*) group by new file mode 100644 index 0000000000..6acc46ff39 --- /dev/null +++ b/snippets/sql-mode/count(*) group by @@ -0,0 +1,5 @@ +# -*- mode: snippet -*- +# name: count(*) group by +# key: countby +# -- +SELECT count(*), ${1:column} FROM ${2:table} GROUP BY $1; -- cgit 1.4.1 From 35c76e7098111ed0d84aef1bd09f7025ce728b87 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Thu, 26 Mar 2020 15:03:25 -0400 Subject: Many updates, too many to count commit messages are for code, not config I guess --- +bindings.el | 151 ++++++-- +commands.el | 28 +- clocked-in-elt.el | 18 + company-sql.el | 47 +-- config.el | 732 +++++++++++++++++++++++------------ init.el | 185 ++++++--- nix-yapf-mode.el | 21 + org-alerts.el | 188 +++++++++ org-config.el | 91 +++++ org-query.el | 96 +++++ packages.el | 73 +++- show-matching-paren.el | 61 +++ slack-snippets.el | 35 +- snippets/haskell-mode/hlint | 8 + snippets/nix-mode/fetchFromGitHub | 12 + snippets/nix-mode/pythonPackage | 16 + snippets/nix-mode/sha256 | 7 + snippets/org-mode/combat | 13 + snippets/org-mode/reveal | 6 + snippets/python-mode/decorate | 15 + snippets/python-mode/name | 7 + snippets/python-mode/pdb | 7 + sql-strings.el | 75 ++++ themes/grfn-solarized-light-theme.el | 72 +++- 24 files changed, 1535 insertions(+), 429 deletions(-) create mode 100644 clocked-in-elt.el create mode 100644 nix-yapf-mode.el create mode 100644 org-alerts.el create mode 100644 org-config.el create mode 100644 org-query.el create mode 100644 show-matching-paren.el create mode 100644 snippets/haskell-mode/hlint create mode 100644 snippets/nix-mode/fetchFromGitHub create mode 100644 snippets/nix-mode/pythonPackage create mode 100644 snippets/nix-mode/sha256 create mode 100644 snippets/org-mode/combat create mode 100644 snippets/org-mode/reveal create mode 100644 snippets/python-mode/decorate create mode 100644 snippets/python-mode/name create mode 100644 snippets/python-mode/pdb create mode 100644 sql-strings.el diff --git a/+bindings.el b/+bindings.el index af54d84086..875d298d42 100644 --- a/+bindings.el +++ b/+bindings.el @@ -304,7 +304,11 @@ private/hlissner/snippets." :desc "Git grep" :n "g" #'counsel-git-grep :desc "Checkout Branch" :n "c" #'counsel-git-checkout :desc "Next hunk" :nv "]" #'git-gutter:next-hunk - :desc "Previous hunk" :nv "[" #'git-gutter:previous-hunk) + :desc "Previous hunk" :nv "[" #'git-gutter:previous-hunk + + (:desc "smerge" :prefix "m" + :desc "Keep Current" :n "SPC" #'smerge-keep-current + :desc "Keep All" :n "a" #'smerge-keep-all)) (:desc "help" :prefix "h" :n "h" help-map @@ -344,6 +348,7 @@ private/hlissner/snippets." :desc "Goto clocked-in note" :n "g" #'org-clock-goto :desc "Clock Out" :n "o" #'org-clock-out) + (:desc "open" :prefix "o" :desc "Default browser" :n "b" #'browse-url-of-file :desc "Debugger" :n "d" #'+debug/open @@ -356,9 +361,10 @@ private/hlissner/snippets." :desc "Slack Group" :n "g" #'slack-group-select :desc "Slack Unreads" :n "u" #'slack-select-unread-rooms + :desc "Email" :n "m" #'mu4e + ;; applications :desc "APP: elfeed" :n "E" #'=rss - :desc "APP: email" :n "M" #'=email :desc "APP: twitter" :n "T" #'=twitter :desc "APP: regex" :n "X" #'=regex @@ -376,6 +382,12 @@ private/hlissner/snippets." :desc "Send to Launchbar" :n "l" #'+macos/send-to-launchbar :desc "Send project to Launchbar" :n "L" #'+macos/send-project-to-launchbar)) + (:desc "Email" :prefix "M" + :desc "Compose" :n "m" #'mu4e-compose-new + :desc "Update" :n "u" #'mu4e-update-mail-and-index + :desc "Sync" :n "s" #'mu4e-update-mail-and-index + :desc "Open" :n "o" #'mu4e) + (:desc "project" :prefix "p" :desc "Browse project" :n "." (find-file-in! (doom-project-root)) :desc "Find file in project" :n "/" #'projectile-find-file @@ -422,6 +434,9 @@ private/hlissner/snippets." (:map dired-mode-map "-" #'grfn/dired-minus)) + (:map smartparens-mode-map + :n "g o" #'sp-raise-sexp) + ;; --- vim-sexp-mappings-for-regular-people (:after paxedit (:map paxedit-mode-map @@ -535,14 +550,13 @@ private/hlissner/snippets." [escape] #'company-search-abort)) ;; counsel - (:after counsel - (:map counsel-ag-map - [backtab] #'+ivy/wgrep-occur ; search/replace on results - "C-SPC" #'ivy-call-and-recenter ; preview - "M-RET" (+ivy-do-action! #'+ivy-git-grep-other-window-action))) +; (:after counsel +; (:map counsel-ag-map +; [backtab] #'+ivy/wgrep-occur ; search/replace on results +; "C-SPC" #'ivy-call-and-recenter ; preview)) ;; evil-commentary - :n "gc" #'evil-commentary + ;; :n "gc" #'evil-commentary ;; evil-exchange :n "gx" #'evil-exchange @@ -795,10 +809,13 @@ private/hlissner/snippets." ;; Haskell (:after haskell-mode (:map haskell-mode-map - :n "K" #'intero-info + ;; :n "K" #'intero-info + :n "K" #'lsp-describe-thing-at-point + ;; :n "g d" #'lsp-ui-peek-find-definitions :n "g d" #'lsp-ui-peek-find-definitions - :n "g SPC" #'intero-repl-load - :n "g y" #'intero-type-at)) + ;; :n "g SPC" #'intero-repl-load + ;; :n "g y" #'lsp-ui- + )) ;; Javascript ;; (:after rjsx-mode @@ -813,7 +830,8 @@ private/hlissner/snippets." ;; Elisp (:map emacs-lisp-mode-map - :n "g SPC" #'eval-buffer) + :n "g SPC" #'eval-buffer + :n "g RET" (λ! () (ert t))) ;; --- Custom evil text-objects --------------------- @@ -991,21 +1009,41 @@ private/hlissner/snippets." (require 'general) (general-evil-setup t) -(nmap :keymaps 'paxedit-mode-map - ">" (general-key-dispatch 'evil-shift-right - "e" 'paxedit-transpose-forward - ")" 'sp-forward-slurp-sexp - "(" 'sp-backward-barf-sexp - "I" 'grfn/insert-at-sexp-end - "a" 'grfn/insert-at-form-end)) - -(nmap :keymaps 'paxedit-mode-map - "<" (general-key-dispatch 'evil-shift-left - "e" 'paxedit-transpose-backward - ")" 'sp-forward-barf-sexp - "(" 'sp-backward-slurp-sexp - "I" 'grfn/insert-at-sexp-start - "a" 'grfn/insert-at-form-start)) +(nmap + ">" (general-key-dispatch 'evil-shift-right + "e" 'paxedit-transpose-forward + ")" 'sp-forward-slurp-sexp + "(" 'sp-backward-barf-sexp + "I" 'grfn/insert-at-sexp-end + ;; "a" 'grfn/insert-at-form-end + )) + +(nmap + "<" (general-key-dispatch 'evil-shift-left + "e" 'paxedit-transpose-backward + ")" 'sp-forward-barf-sexp + "(" 'sp-backward-slurp-sexp + "I" 'grfn/insert-at-sexp-start + ;; "a" 'grfn/insert-at-form-start + )) + + +(defmacro saving-excursion (&rest body) + `(λ! () (save-excursion ,@body))) + +(nmap "c" (general-key-dispatch 'evil-change + "r c" (saving-excursion (string-inflection-lower-camelcase)) + "r C" (saving-excursion (string-inflection-camelcase)) + "r m" (saving-excursion (string-inflection-camelcase)) + "r s" (saving-excursion (string-inflection-underscore)) + "r u" (saving-excursion (string-inflection-upcase)) + "r -" (saving-excursion (string-inflection-kebab-case)) + "r k" (saving-excursion (string-inflection-kebab-case)) + ;; "r ." (saving-excursion (string-inflection-dot-case)) + ;; "r ." (saving-excursion (string-inflection-space-case)) + ;; "r ." (saving-excursion (string-inflection-title-case)) + )) + (predd-defmulti eval-sexp (lambda (form) major-mode)) @@ -1137,7 +1175,7 @@ If invoked with a prefix ARG eval the expression after inserting it" "p" (general-key-dispatch 'fireplace-eval "p" 'eval-sexp-at-point "c" 'eval-last-sexp - "d" 'cider-eval-defun-at-point + "d" 'eval-defun "r" 'cider-test-run-test) "x" (general-key-dispatch 'fireplace-eval-context "x" 'cider-eval-sexp-at-point-in-context @@ -1214,10 +1252,21 @@ If invoked with a prefix ARG eval the expression after inserting it" (interactive) (if (and (org-in-src-block-p) (equal direction 'below)) - (grfn/insert-new-src-block) + (grfn/insert-new-src-block) (funcall orig direction))) -(advice-add #'+org/insert-item :around #'grfn/+org-insert-item) +(advice-add #'+org--insert-item :around #'grfn/+org-insert-item) +;; (advice-add #'+org/insert-item-below :around +;; (lambda (orig) (grfn/+org-insert-item orig 'below))) + +(defun set-pdb-trace () + (interactive) + (end-of-line) + (insert (format "\n%simport pdb;pdb.set_trace()" + (make-string (python-indent-calculate-indentation) + ?\s))) + (evil-indent (line-beginning-position) + (line-end-position))) (map! @@ -1225,21 +1274,28 @@ If invoked with a prefix ARG eval the expression after inserting it" :n "#" 'forge-dispatch) (:map haskell-mode-map - ;; :n "K" 'lsp-info-under-point - ;; :n "g d" 'lsp-ui-peek-find-definitions - ;; :n "g r" 'lsp-ui-peek-find-references - ;; :n "g \\" '+haskell/repl - :n "K" 'intero-info - :n "g d" 'intero-goto-definition - :n "g SPC" 'intero-repl-load - :n "g \\" 'intero-repl - :n "g y" 'intero-type-at + :n "K" 'lsp-info-under-point + :n "g d" 'lsp-ui-peek-find-definitions + :n "g r" 'lsp-ui-peek-find-references + :n "g \\" '+haskell/repl + ;; :n "K" 'intero-info + ;; :n "g d" 'intero-goto-definition + ;; :n "g SPC" 'intero-repl-load + ;; :n "g \\" 'intero-repl + ;; :n "g y" 'intero-type-at ;; :n "g RET" 'grfn/run-sputnik-test-for-file (:localleader :desc "Apply action" :n "e" 'intero-repl-eval-region :desc "Rename symbol" :n "r" 'intero-apply-suggestions)) + (:map python-mode-map + :n "K" #'anaconda-mode-show-doc + :n "g SPC" #'+eval/buffer + :n "g RET" #'python-pytest-file + :n "g \\" #'+python/open-ipython-repl + [remap evil-commentary-yank] #'set-pdb-trace) + (:after agda2-mode (:map agda2-mode-map :n "g SPC" 'agda2-load @@ -1249,8 +1305,10 @@ If invoked with a prefix ARG eval the expression after inserting it" (:localleader :desc "Give" :n "SPC" 'agda2-give + :desc "Case Split" :n "c" 'agda2-make-case + :desc "Make Helper" :n "h" 'agda2-helper-function-type :desc "Refine" :n "r" 'agda2-refine - :desc "Auto" :n "a" 'agda2-auto + :desc "Auto" :n "a" 'agda2-auto-maybe-all :desc "Goal type and context" :n "t" 'agda2-goal-and-context :desc "Goal type and context and inferred" :n ";" 'agda2-goal-and-context-and-inferred))) @@ -1296,4 +1354,15 @@ If invoked with a prefix ARG eval the expression after inserting it" "M-k" #'org-move-subtree-up "M-j" #'org-move-subtree-down (:localleader - :n "g" #'counsel-org-goto)))) + :n "g" #'counsel-org-goto)) + + (:map org-capture-mode-map + :n "g RET" #'org-capture-finalize + :n "g \\" #'org-captue-refile)) + + (:after lsp + (:map lsp-mode-map + :n "K" #'lsp-describe-thing-at-point + :n "g r" #'lsp-rename + (:localleader + :n "a" #'lsp-execute-code-action)))) diff --git a/+commands.el b/+commands.el index 4025a9504a..a5753c8e99 100644 --- a/+commands.el +++ b/+commands.el @@ -1,4 +1,4 @@ -;;; private/grfn/+commands.el -*- lexical-binding: t; -*- + (defalias 'ex! 'evil-ex-define-cmd) @@ -29,6 +29,8 @@ (ex! "na[rrow]" #'+evil:narrow-buffer) (ex! "retab" #'+evil:retab) +(ex! "glog" #'magit-log-buffer-file) + ;; External resources ;; TODO (ex! "db" #'doom:db) ;; TODO (ex! "dbu[se]" #'doom:db-select) @@ -115,13 +117,31 @@ ;; Org-mode (ex! "cap" #'+org-capture/dwim) -(ex! "arev" #'generate-alembic-migration) +(evil-define-command evil-alembic-revision (args) + (interactive "") + (apply + #'generate-alembic-migration + (read-string "Message: ") + (s-split "\\s+" (or args "")))) +(ex! "arev[ision]" #'evil-alembic-revision) (evil-define-command evil-alembic-upgrade (&optional revision) (interactive "") - (alembic-upgrade revision)) + (alembic-upgrade (or revision "head"))) + +(ex! "aup[grade]" #'evil-alembic-upgrade) + +(evil-define-command evil-alembic-downgrade (&optional revision) + (interactive "") + (alembic-downgrade revision)) + +(ex! "adown[grade]" #'evil-alembic-downgrade) + +(evil-define-command evil-alembic (args) + (interactive "") + (run-alembic args)) -(ex! "aup" #'evil-alembic-upgrade) +(ex! "alemb[ic]" #'evil-alembic) ;; Elixir (add-hook! elixir-mode diff --git a/clocked-in-elt.el b/clocked-in-elt.el new file mode 100644 index 0000000000..00fda047e4 --- /dev/null +++ b/clocked-in-elt.el @@ -0,0 +1,18 @@ +;;; ~/.doom.d/clocked-in-elt.el -*- lexical-binding: t; -*- +;;; +(load (expand-file-name "init" (or (getenv "EMACSDIR") + (expand-file-name + "../.emacs.d" + (file-name-directory (file-truename load-file-name)))))) + +(require 'org-clock) +(require 'org-element) + +(let ((item (or org-clock-marker + (car org-clock-history)))) + (when item + (with-current-buffer (marker-buffer item) + (goto-char (marker-position item)) + (let ((element (org-element-at-point))) + (when (eq 'headline (car element)) + (message "%s" (plist-get (cadr element) :raw-value))))))) diff --git a/company-sql.el b/company-sql.el index 58c57dde80..2408347cef 100644 --- a/company-sql.el +++ b/company-sql.el @@ -56,24 +56,26 @@ ;;; Listing relations (cl-defun company-sql/list-tables (conn) - (-map (-compose 'symbol-name 'car) - (emacsql conn - [:select [tablename] - :from pg_catalog:pg_tables - :where (and (!= schemaname '"information_schema") - (!= schemaname '"pg_catalog"))]))) + (with-timeout (3) + (-map (-compose 'symbol-name 'car) + (emacsql conn + [:select [tablename] + :from pg_catalog:pg_tables + :where (and (!= schemaname '"information_schema") + (!= schemaname '"pg_catalog"))])))) (cl-defun company-sql/list-columns (conn) - (-map - (lambda (row) - (propertize (symbol-name (nth 0 row)) - 'table-name (nth 1 row) - 'data-type (nth 2 row))) - (emacsql conn - [:select [column_name - table_name - data_type] - :from information_schema:columns]))) + (with-timeout (3) + (-map + (lambda (row) + (propertize (symbol-name (nth 0 row)) + 'table-name (nth 1 row) + 'data-type (nth 2 row))) + (emacsql conn + [:select [column_name + table_name + data_type] + :from information_schema:columns])))) ;;; Keywords @@ -195,7 +197,7 @@ (apply-partially #'s-starts-with? prefix) (append (-map (lambda (s) (propertize s 'company-postgresql-annotation "table")) - (company-sql/list-tables conn)) + (-map (lambda (s) (propertize s 'company-postgresql-annotation (format "%s.%s %s" @@ -208,7 +210,7 @@ (company-sql/list-columns conn)) (-map (lambda (s) (propertize s 'company-postgresql-annotation "keyword")) - company-postgresql/keywords)))) + company-postgresql/keywords))))) (defun company-postgresql (command &optional arg &rest _) (interactive (list 'interactive)) @@ -230,11 +232,10 @@ ()) (defun org-company-sql/connect (conn-params) - (car ; ??? - (or (alist-get-equal conn-params org-company-sql/connections) - (let ((conn (apply 'emacsql-psql conn-params))) - (add-to-list 'org-company-sql/connections (cons conn-params conn)) - conn)))) + (or (alist-get-equal conn-params org-company-sql/connections) + (let ((conn (apply 'emacsql-psql conn-params))) + (add-to-list 'org-company-sql/connections (cons conn-params conn)) + conn))) (defun org-company-sql/in-sql-source-block-p () (let ((org-elt (org-element-at-point))) diff --git a/config.el b/config.el index b928937623..287d097893 100644 --- a/config.el +++ b/config.el @@ -4,17 +4,26 @@ (setq x-super-keysym 'alt x-alt-keysym 'meta) -(setq user-mail-address "root@gws.fyi" +(setq user-mail-address "griffin@urbint.com" user-full-name "Griffin Smith") -; (def-package-hook! doom-themes :disable) +(setq doom-font (font-spec :family "Meslo LGSDZ Nerd Font" :size 14) + doom-big-font (font-spec :family "Meslo LGSDZ Nerd Font" :size 19) + doom-big-font-increment 5 + doom-variable-pitch-font (font-spec :family "DejaVu Sans") + doom-unicode-font (font-spec :family "Meslo LG S DZ")) (after! rust - (setq rust-format-on-save t)) + ;; (require 'ein) + (setq rust-format-on-save t) + (add-hook! :after rust-mode-hook #'lsp) + (add-hook! :after rust-mode-hook #'rust-enable-format-on-save)) (load! "utils") - (load! "company-sql") +(load! "org-query") +(load! "nix-yapf-mode") +(load! "show-matching-paren") ; (defconst rust-src-path ; (-> "/Users/griffin/.cargo/bin/rustc --print sysroot" @@ -30,8 +39,11 @@ (add-hook! rust-mode (flycheck-rust-setup) (flycheck-mode) - (racer-mode) - (cargo-minor-mode)) + (cargo-minor-mode) + (lsp) + (rust-enable-format-on-save) + (map! :map rust-mode-map + "C-c C-f" #'rust-format-buffer)) (add-hook! elixir-mode (require 'flycheck-credo) @@ -97,8 +109,9 @@ (let ((theme (car theme-settings)) (faces (cadr theme-settings))) (if (member theme custom-enabled-themes) - (dolist (face faces) - (custom-theme-set-faces theme face)))))) + (progn + (dolist (face faces) + (custom-theme-set-faces theme face))))))) (defcustom theme-overrides nil "Association list of override faces to set for different custom themes.") @@ -107,12 +120,23 @@ "Set VALUE of a KEY in ALIST-SYMBOL." (set alist-symbol (cons (list key value) (assq-delete-all key (eval alist-symbol))))) +(comment + (custom-theme-set-faces 'grfn-solarized-light + `(font-lock-doc-face + ((t (:foreground ,+solarized-s-base1))))) + ++solarized-s-base1 +(custom-theme-) + (custom-face-get-current-spec 'font-lock-doc-face) + + ) + (alist-set 'theme-overrides 'grfn-solarized-light `((font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) (font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) (font-lock-keyword-face ((t (:foreground ,+solarized-green :bold nil)))) (font-lock-builtin-face ((t (:foreground ,+solarized-s-base01 - :bold t)))) + :bold t)))) (elixir-attribute-face ((t (:foreground ,+solarized-blue)))) (elixir-atom-face ((t (:foreground ,+solarized-cyan)))) @@ -120,7 +144,10 @@ (line-number ((t (:background ,+solarized-s-base2 :foreground ,+solarized-s-base1)))) (haskell-operator-face ((t (:foreground ,+solarized-green)))) - (haskell-keyword-face ((t (:foreground ,+solarized-cyan)))))) + (haskell-keyword-face ((t (:foreground ,+solarized-cyan)))) + + (org-drawer ((t (:foreground ,+solarized-s-base1 + :bold t)))))) (setq solarized-use-variable-pitch nil solarized-scale-org-headlines nil @@ -203,15 +230,14 @@ (defvar +grfn-snippets-dir (expand-file-name "snippets/" +grfn-dir)) ;; -(when (featurep! :feature evil) - (load! "+bindings") - (load! "+commands")) +(load! "+bindings") +(load! "+commands") (load! "+private") (require 'dash) -(def-package! predd) +(use-package! predd) ;; @@ -238,14 +264,6 @@ (sp-pair "[" nil :post-handlers '(("| " " ")) :unless '(sp-point-before-word-p sp-point-before-same-p))) -;; feature/evil -(after! evil-mc - ;; Make evil-mc resume its cursors when I switch to insert mode - (add-hook! 'evil-mc-before-cursors-created - (add-hook 'evil-insert-state-entry-hook #'evil-mc-resume-cursors nil t)) - (add-hook! 'evil-mc-after-cursors-deleted - (remove-hook 'evil-insert-state-entry-hook #'evil-mc-resume-cursors t))) - ;; feature/snippets (after! yasnippet ;; Don't use default snippets, use mine. @@ -257,44 +275,36 @@ (setq company-idle-delay 0.2 company-minimum-prefix-length 1)) -(setq +doom-modeline-height 10) - -;; lang/org -;; (after! org-bullets -;; ;; The standard unicode characters are usually misaligned depending on the -;; ;; font. This bugs me. Personally, markdown #-marks for headlines are more -;; ;; elegant, so we use those. -;; (setq org-bullets-bullet-list '("#"))) - -;; (defmacro faces! (mode &rest forms) -;; (let ((hook-name (-> mode symbol-name (concat "-hook")))) -;; (if-let ((hook-sym (intern-soft hook-name))) -;; `(add-hook! ,hook-sym -;; (message "HELLO I AM MACRO TIME") -;; ,@(-> -;; forms -;; (seq-partition 2) -;; (->> (seq-map -;; (lambda (pair) -;; (let ((face (car pair)) -;; (color (cadr pair))) -;; `(set-face-foreground ,face ,color))))))) -;; (warn "Hook name %s (for mode %s) does not exist as symbol!" -;; (hook-name) -;; (symbol-name mode))))) - -(def-package! org-clubhouse +(setq doom-modeline-height 12) + +(load "/home/griffin/code/org-clubhouse/org-clubhouse.el") +(use-package! org-clubhouse :config (setq org-clubhouse-state-alist '(("PROPOSED" . "Proposed") ("BACKLOG" . "Backlog") ("TODO" . "Scheduled") ("ACTIVE" . "In Progress") - ("PR" . "In Review") - ("TESTING" . "In Testing") - ("DONE" . "Completed")))) + ("PR" . "Peer Review") + ("TESTING" . "Stakeholder Review") + ("DONE" . "Completed")) + org-clubhouse-username "griffin" + org-clubhouse-claim-story-on-status-update + '("ACTIVE" "PR" "TESTING" "DONE") + org-clubhouse-create-stories-with-labels 'existing + org-clubhouse-workflow-name "Urbint") + + (defun grfn/sprint-tasks () + (interactive) + (find-file "/home/griffin/notes/work.org") + (goto-char 1) + (search-forward "* Sprint Tasks") + (goto-eol) (insert-char ?\n) + (org-clubhouse-headlines-from-query + 2 + "owner:griffin state:Scheduled"))) + -; (require 'doom-themes) ;; Should really figure out which of these is correct, eventually @@ -369,96 +379,31 @@ (setq evil-shift-width 2)) (after! org - (setq - org-directory (expand-file-name "~/notes") - +org-dir (expand-file-name "~/notes") - org-default-notes-file (concat org-directory "/inbox.org") - +org-default-todo-file (concat org-directory "/inbox.org") - org-agenda-files (list (expand-file-name "~/notes")) - org-refile-targets '((org-agenda-files :maxlevel . 3)) - org-outline-path-complete-in-steps nil - org-refile-use-outline-path t - org-file-apps `((auto-mode . emacs) - (,(rx (or (and "." (optional "x") (optional "htm") (optional "l") buffer-end) - (and buffer-start "http" (optional "s") "://"))) - . "firefox %s") - (,(rx ".pdf" buffer-end) . "apvlv %s") - (,(rx "." (or "png" - "jpg" - "jpeg" - "gif" - "tif" - "tiff") - buffer-end) - . "feh %s")) - org-log-done 'time - org-archive-location "~/notes/trash::* From %s" - org-cycle-separator-lines 2 - org-hidden-keywords '(title) - org-tags-column -130 - org-ellipsis "⤵" - org-imenu-depth 9 - org-capture-templates - `(("t" "Todo" entry - (file+headline +org-default-todo-file "Inbox") - "* TODO %?\n%i" - :prepend t - :kill-buffer t) - - ("n" "Notes" entry - (file+headline +org-default-notes-file "Inbox") - "* %U %?\n%i" - :prepend t - :kill-buffer t) - - ("c" "Task note" entry - (clock) - "* %U %?\n%i[[%l][Context]]\n" - :kill-buffer t - :unnarrowed t) - - ("d" "Tech debt" entry - (file+headline ,(concat org-directory "/work.org") - "Inbox") - "* TODO %? :debt:\nContext: %a\nIn task: %K" - :prepend t - :kill-buffer t)) - org-deadline-warning-days 1 - org-agenda-skip-scheduled-if-deadline-is-shown 'todo - org-agenda-custom-commands - '(("p" "Sprint Tasks" tags-todo "sprint") - ("i" "Inbox" tags "inbox") - ("r" "Running jobs" todo "RUNNING") - ("w" "@Work" tags-todo "@work"))) + (load! "org-config") (set-face-foreground 'org-block +solarized-s-base00) (add-hook! org-mode (add-hook! evil-normal-state-entry-hook #'org-align-all-tags)) + (add-hook 'org-mode-hook (lambda () (display-line-numbers-mode -1))) + (setq whitespace-global-modes '(not org-mode magit-mode)) (setf (alist-get 'file org-link-frame-setup) 'find-file-other-window) (set-face-foreground 'org-block +solarized-s-base00) - ) + + (add-hook! org-mode + (set-company-backend! 'org-mode + '(:separate company-ob-postgresql + company-dabbrev + company-yasnippet + company-ispell)))) (after! magit (setq git-commit-summary-max-length 50)) -;; (def-package! forge -;; :after magit) - -(comment - - (string-match-p "(?!foo).*" "bar") - ) - (after! ivy (setq ivy-re-builders-alist '((t . ivy--regex-fuzzy)))) -(setq doom-font (font-spec :family "Meslo LGSDZ Nerd Font" :size 14) - doom-big-font (font-spec :family "Meslo LGSDZ Nerd Font" :size 19) - doom-variable-pitch-font (font-spec :family "DejaVu Sans") - doom-unicode-font (font-spec :family "Meslo LG S DZ")) - (add-hook 'before-save-hook 'delete-trailing-whitespace) (after! paxedit @@ -478,11 +423,11 @@ (add-hook! haskell-mode - (intero-mode) - ;; (lsp-mode) - (flycheck-add-next-checker - 'intero - 'haskell-hlint) + ;; (intero-mode) + (lsp-mode) + ;; (flycheck-add-next-checker + ;; 'intero + ;; 'haskell-hlint) (set-fill-column 80) (setq evil-shift-width 2)) @@ -491,13 +436,6 @@ (load! "slack-snippets") -(after! magit - ;; (require 'evil-magit) - ;; (require 'magithub) - ) - -; (require 'auth-password-store) -; (auth-pass-enable) (auth-source-pass-enable) (require 'fill-column-indicator) @@ -522,37 +460,6 @@ (turn-on-fci-mode))) -;; https://github.com/alpaker/Fill-Column-Indicator/issues/67#issuecomment-195611974 -;; (add-hook 'prog-mode-hook #'fci-mode) -;; (after! fill-column-indicator -;; (add-hook 'prog-mode-hook #'fci-mode) -;; (defvar eos/fci-disabled nil) -;; (make-variable-buffer-local 'eos/fci-disabled) - -;; ;; Add a hook that disables fci if enabled when the window changes and it -;; ;; isn't wide enough to display it. -;; (defun eos/maybe-disable-fci () -;; (interactive) -;; ;; Disable FCI if necessary -;; (when (and fci-mode -;; (< (window-width) (or fci-rule-column fill-column))) -;; (fci-mode -1) -;; (setq-local eos/fci-disabled t)) -;; ;; Enable FCI if necessary -;; (when (and eos/fci-disabled -;; (eq fci-mode nil) -;; (> (window-width) (or fci-rule-column fill-column))) -;; (fci-mode 1) -;; (setq-local eos/fci-disabled nil))) - -;; (defun eos/add-fci-disabling-hook () -;; (interactive) -;; (add-hook 'window-configuration-change-hook -;; #'eos/maybe-disable-fci)) - -;; (add-hook 'prog-mode-hook #'eos/add-fci-disabling-hook)) - - ;;; Javascript (require 'smartparens) @@ -657,6 +564,11 @@ (setq projectile-create-missing-test-files 't) (after! magit + (map! :map magit-mode-map + ;; :n "] ]" #'magit-section-forward + ;; :n "[ [" #'magit-section-backward + ) + (define-suffix-command magit-commit-wip () (interactive) (magit-commit-create '("-m" "wip"))) @@ -664,7 +576,50 @@ (transient-append-suffix #'magit-commit ["c"] - (list "W" "Commit WIP" #'magit-commit-wip))) + (list "W" "Commit WIP" #'magit-commit-wip)) + + (define-suffix-command magit-reset-head-back () + (interactive) + (magit-reset-mixed "HEAD~")) + + (define-suffix-command magit-reset-head-previous () + (interactive) + (magit-reset-mixed "HEAD@{1}")) + + (transient-append-suffix + #'magit-reset + ["f"] + (list "b" "Reset HEAD~" #'magit-reset-head-back)) + (transient-append-suffix + #'magit-reset + ["f"] + (list "o" "Reset HEAD@{1}" #'magit-reset-head-previous)) + + (defun magit-read-org-clubhouse-branch-args () + (if-let ((story-id (org-clubhouse-clocked-in-story-id))) + (let ((start-point (magit-read-starting-point + "Create and checkout branch for Clubhouse story" + nil + "origin/master"))) + (if (magit-rev-verify start-point) + (let ((desc (magit-read-string-ns + (format "Story description (to go after gs/ch%d/)" + story-id)))) + (list + (format "gs/ch%d/%s" story-id desc) + start-point)) + (user-error "Not a valid starting point: %s" choice))) + (user-error "No currently clocked-in clubhouse story"))) + + (define-suffix-command magit-checkout-org-clubhouse-branch (branch start-point) + (interactive (magit-read-org-clubhouse-branch-args)) + (magit-branch-and-checkout branch start-point)) + + (transient-append-suffix + #'magit-branch + ["c"] + (list "C" "Checkout Clubhouse branch" #'magit-checkout-org-clubhouse-branch)) + ) ;; (defun grfn/split-window-more-sensibly (&optional window) ;; (let ((window (or window (selected-window)))) @@ -686,54 +641,104 @@ ;; (with-selected-window window ;; (split-window-below)))))))) -;; (def-package! lsp-mode -;; :after (:any haskell-mode) -;; :config -;; (lsp-mode) -;; (setq lsp-project-whitelist '("^/home/griffin/code/urb/grid/$") -;; lsp-response-timeout 60) -;; :hook -;; (haskell-mode . lsp-mode)) - -;; (def-package! lsp-ui -;; :after lsp-mode -;; :config -;; (setq lsp-ui-flycheck-enable t) -;; (setq imenu-auto-rescan t) -;; (set-face-background 'lsp-ui-doc-background +solarized-s-base2) -;; (set-face-background 'lsp-face-highlight-read +solarized-s-base2) -;; (set-face-background 'lsp-face-highlight-write +solarized-s-base2) -;; :hook -;; (lsp-mode . lsp-ui-mode) -;; (lsp-ui-mode . flycheck-mode)) - -;; (def-package! company-lsp -;; :after (lsp-mode lsp-ui) -;; :config -;; (setq company-backends '(company-lsp)) -;; (setq company-lsp-async t)) +(use-package! lsp-mode + :after (:any haskell-mode) + :config + (lsp-mode) + (setq lsp-response-timeout 60) + :hook + (haskell-mode . lsp-mode)) -;; (def-package! lsp-haskell -;; :after (lsp-mode lsp-ui haskell-mode) -;; :hook -;; (haskell-mode . lsp-haskell-enable) -;; :config -;; (setq lsp-haskell-process-path-hie "/home/griffin/.local/bin/hie-wrapper" -;; lsp-haskell-process-args-hie -;; '("-d" "-l" "/tmp/hie.log" "+RTS" "-M4G" "-H1G" "-K4G" "-A16M" "-RTS" -;; "--lsp"))) +(use-package! lsp-ui + :after lsp-mode + :config + (defun +grfn/lsp-ui-doc-frame-hook (frame window) + (set-frame-font (if doom-big-font-mode doom-big-font doom-font) + nil (list frame))) + (setq lsp-ui-flycheck-enable t + lsp-ui-doc-header nil + lsp-ui-doc-position 'top + lsp-ui-doc-alignment 'window + lsp-ui-doc-frame-hook '+grfn/lsp-ui-doc-frame-hook) + (setq imenu-auto-rescan t) + (set-face-background 'lsp-ui-doc-background +solarized-s-base2) + (set-face-background 'lsp-face-highlight-read +solarized-s-base2) + (set-face-background 'lsp-face-highlight-write +solarized-s-base2) + :hook + (lsp-mode . lsp-ui-mode) + (lsp-ui-mode . flycheck-mode)) + +(use-package! company-lsp + :after (lsp-mode lsp-ui) + :config + ;; (setq company-backends '(company-lsp)) + (setq company-lsp-async t)) + +(use-package! lsp-treemacs + :config + (map! :map lsp-mode-map + (:leader + "c X" #'lsp-treemacs-errors-list))) + +(use-package! dap-mode) + +(defun +grfn/haskell-mode-setup () + (interactive) + (flymake-mode -1) + ;; If there’s a 'hie.sh' defined locally by a project + ;; (e.g. to run HIE in a nix-shell), use it… + (let ((hie-directory (locate-dominating-file default-directory "hie.sh"))) + (when hie-directory + (setq-local lsp-haskell-process-path-hie (expand-file-name "hie.sh" hie-directory)) + (setq-local + haskell-hoogle-command + (s-trim + (shell-command-to-string + (concat + "nix-shell " (expand-file-name "shell.nix" hie-directory) + " --run \"which hoogle\" 2>/dev/null")))))) + ;; … and only then setup the LSP. + (lsp)) + +(defun never-flymake-mode (orig &rest args) + (when (and (bound-and-true-p flymake-mode)) + (funcall orig 0) + (message "disabled flymake-mode"))) +(advice-add #'flymake-mode :around #'never-flymake-mode) + +(use-package! lsp-haskell + :after (lsp-mode lsp-ui haskell-mode) + ;; :hook + ;; (haskell-mode . lsp-haskell-enable) + :config + (add-hook 'haskell-mode-hook #'+grfn/haskell-mode-setup 't) + (setq lsp-haskell-process-path-hie "/home/griffin/.nix-profile/bin/hie-8.6.5" + lsp-haskell-process-args-hie + '("-d" "-l" "/tmp/hie.log" "+RTS" "-M4G" "-H1G" "-K4G" "-A16M" "-RTS"))) -;; (def-package! lsp-imenu -;; :after (lsp-mode lsp-ui) -;; :hook -;; (lsp-after-open . lsp-enable-imenu)) +(use-package! lsp-imenu + :after (lsp-mode lsp-ui) + :hook + (lsp-after-open . lsp-enable-imenu)) + +;; (use-package! counsel-etags +;; :ensure t +;; :init +;; (add-hook 'haskell-mode-hook +;; (lambda () +;; (add-hook 'after-save-hook +;; 'counsel-etags-virtual-update-tags 'append 'local))) +;; :config +;; (setq counsel-etags-update-interval 60) +;; ;; (push "build" counsel-etags-ignore-directories) +;; ) -(def-package! evil-magit +(use-package! evil-magit :after (magit)) -(def-package! writeroom-mode) +(use-package! writeroom-mode) -(def-package! graphql-mode) +(use-package! graphql-mode) (require 'whitespace) (setq whitespace-style '(face lines-tail)) @@ -867,7 +872,7 @@ (before 1) (it 2))) -(def-package! flycheck-clojure +(use-package! flycheck-clojure ;; :disabled t :after (flycheck cider) :config @@ -883,54 +888,67 @@ 'cljr-magic-require-namespaces '("s" . "clojure.spec.alpha"))) -(def-package! sqlup-mode +(use-package! sqlup-mode :hook (sql-mode-hook . sqlup-mode) (sql-interactive-mode-hook . sqlup-mode)) -(def-package! emacsql) -(def-package! emacsql-psql +(use-package! emacsql) +(use-package! emacsql-psql :after (emacsql)) -(def-package! yapfify - :hook - (python-mode-hook . yapf-mode)) +(use-package! pyimport + :after (python)) -(def-package! w3m - :hook - (setq browse-url-browser-function 'w3m-browse-url)) +(use-package! yapfify + :after (python) + :init + (add-hook! python-mode #'yapf-mode)) -(def-package! ob-http +(use-package! w3m + :config + (setq browse-url-browser-function + `(("^https://app.clubhouse.io.*" . browse-url-firefox) + ("^https://github.com.*" . browse-url-firefox) + (".*" . browse-url-firefox)))) + +(use-package! ob-http :config (add-to-list 'org-babel-load-languages '(http . t))) -(def-package! ob-ipython +(use-package! ob-ipython + :after (pyimport) :config (add-to-list 'org-babel-load-languages '(ipython . t)) (setq ob-ipython-command "/home/griffin/code/urb/ciml-video-classifier/bin/jupyter")) -(def-package! counsel-spotify) +(use-package! counsel-spotify) + +(after! counsel + (map! [remap counsel-org-capture] #'org-capture + [remap org-capture] #'org-capture)) -(def-package! evil-snipe :disabled t) +(use-package! evil-snipe :disabled t) (evil-snipe-mode -1) -(def-package! rainbow-mode) +(use-package! rainbow-mode) -(def-package! org-alert +(use-package! org-alert + :disabled t :config (org-alert-enable) (setq alert-default-style 'libnotify org-alert-headline-title "org")) -(def-package! ob-async) +(use-package! ob-async) -(def-package! org-recent-headings +(use-package! org-recent-headings :after (org) :config (map! :n "SPC n r" #'org-recent-headings-ivy)) -(def-package! org-sticky-header +(use-package! org-sticky-header :after (org) :hook (org-mode-hook . org-sticky-header-mode) :config @@ -955,11 +973,13 @@ "Reference to a function whose return value will be used as the directory to run Alembic in") -(comment - (+grfn/extract-alembic-migration-name - "Generating -/home/griffin/code/urb/grid/backend/src/grid/migrations/versions/15fb1b518507_test.py -... done")) +(put 'alembic-command 'safe-local-variable (lambda (_) t)) +(put 'alembic-dir-fun 'safe-local-variable (lambda (_) t)) + +(defun make-alembic-command (args) + (if (functionp alembic-command) + (funcall alembic-command args) + (concat alembic-command " " args))) (defun +grfn/extract-alembic-migration-name (output) (string-match (rx (0+ anything) "Generating " @@ -969,19 +989,227 @@ output) (match-string-no-properties 1 output)) -(defun generate-alembic-migration (msg) - (interactive "sMessage: ") +(defun -run-alembic (args) (let* ((default-directory (funcall alembic-dir-fun)) - (out (shell-command-to-string - (format "%s revision -m \"%s\"" - alembic-command - msg))) - (migration-name (+grfn/extract-alembic-migration-name out))) - (find-file-other-window migration-name))) - -(defun alembic-upgrade (&optional revision) + (command (make-alembic-command args)) + ;; (format "nix-shell --run 'alembic %s'" args) + ;; (format "%s %s" alembic-command args) + (res + (with-temp-buffer + (cons + (shell-command command t) + (s-replace-regexp + "^.*Nix search path entry.*$" "" + (buffer-string))))) + (exit-code (car res)) + (out (cdr res))) + ;; (if (= 0 exit-code) + ;; out + ;; (error "Error running %s: %s" command out)) + out + )) + +(comment + --exit-code + --bs + ) + +(defun run-alembic (args) + (interactive "sAlembic command: ") + (message "%s" (-run-alembic args))) + +(defun generate-alembic-migration (msg &rest args) + (interactive "sMessage: ") + (-> + (format "revision %s -m \"%s\"" + (s-join " " args) + msg) + (-run-alembic) + (+grfn/extract-alembic-migration-name) + (find-file-other-window))) + +(cl-defun alembic-upgrade (&optional revision &key namespace) + (interactive "sRevision: ") (let ((default-directory (funcall alembic-dir-fun))) - (message - (shell-command-to-string (format "%s upgrade %s" - alembic-command - (or revision "head")))))) + (run-alembic (format "%s upgrade %s" + (if namespace (concat "-n " namespace) "") + (or revision "head"))))) + +(defun alembic-downgrade (revision) + (interactive "sRevision: ") + (let ((default-directory (funcall alembic-dir-fun))) + (run-alembic (format "downgrade %s" (or revision "head"))))) + +(use-package! gnuplot) +(use-package! gnuplot-mode :after gnuplot) +(use-package! string-inflection) + +(after! anaconda-mode + (set-company-backend! 'anaconda-mode #'company-yasnippet)) + +;; (add-hook! python-mode +;; (capf)) + +(cl-defstruct pull-request url number title author repository) + +(defun grfn/alist->plist (alist) + (->> alist + (-mapcat (lambda (pair) + (list (intern (concat ":" (symbol-name (car pair)))) + (cdr pair)))))) + +(defun grfn/review-requests () + (let ((resp (ghub-graphql "query reviewRequests { + reviewRequests: search( + type:ISSUE, + query: \"is:open is:pr review-requested:glittershark archived:false\", + first: 100 + ) { + issueCount + nodes { + ... on PullRequest { + url + number + title + author { + login + ... on User { name } + } + repository { + name + owner { login } + } + } + } + } + }"))) + (->> resp + (alist-get 'data) + (alist-get 'reviewRequests) + (alist-get 'nodes) + (-map + (lambda (pr) + (apply + #'make-pull-request + (grfn/alist->plist pr))))))) + +(defun grfn/pr->org-headline (level pr) + (check-type level integer) + (check-type pr pull-request) + (format "%s TODO Review %s's PR on %s/%s: %s :pr: +SCHEDULED: <%s>" + (make-string level ?*) + (->> pr (pull-request-author) (alist-get 'name)) + (->> pr (pull-request-repository) + (alist-get 'owner) + (alist-get 'login)) + (->> pr (pull-request-repository) (alist-get 'name)) + (org-make-link-string + (pull-request-url pr) + (pull-request-title pr)) + (format-time-string "%Y-%m-%d %a"))) + +(require 'ghub) +(defun grfn/org-headlines-from-review-requests (level) + "Create org-mode headlines at LEVEL from all review-requested PRs on Github" + (interactive "*nLevel: ") + (let* ((prs (grfn/review-requests)) + (text (mapconcat (apply-partially #'grfn/pr->org-headline level) prs "\n"))) + (save-mark-and-excursion + (insert text)) + (org-align-tags 't))) + +(comment + (require 'ghub) + + (intern (substring (symbol-name :foo) 1)) + + ((data (reviewRequests + (issueCount . 2) + (nodes ((url . "https://github.com/urbint/grid/pull/819") + (number . 819) + (title . "Hector.blanco/ch11498/take storagebucket out of crossbores schema") + (repository (name . "grid") + (owner (login . "urbint")))) + ((url . "https://github.com/urbint/ml/pull/32") + (number . 32) + (title . "Quality scoring") + (repository (name . "ml") + (owner (login . "urbint")))))))) + ) + +(defun grfn/num-inbox-items () + (length (org-elements-agenda-match "inbox" t))) + +(use-package! dhall-mode + :mode "\\.dhall\\'") + +(use-package! github-review + :after forge) + +(after! mu4e + (setq sendmail-program "/usr/bin/msmtp" + send-mail-function #'smtpmail-send-it + message-sendmail-f-is-evil t + message-sendmail-extra-arguments '("--read-envelope-from") + message-send-mail-function #'message-send-mail-with-sendmail)) + +(defun grfn/org-add-db-connection-params () + (interactive) + (ivy-read + "DB to connect to: " + (-map (lambda (opts) + (propertize (symbol-name (car opts)) + 'header-args (cdr opts))) + db-connection-param-options) + :require-match t + :action + (lambda (opt) + (let ((header-args (get-text-property 0 'header-args opt))) + (org-set-property "header-args" header-args))))) + +(use-package! kubernetes + :commands (kubernetes-overview)) + +(use-package! k8s-mode + :hook (k8s-mode . yas-minor-mode)) + +(use-package! sx) + +;; (use-package! nix-update +;; :config +;; (map! (:map nix-mode-map +;; (:leader +;; :desc "Update fetcher" :nv #'nix-update-fetch)))) + + +(after! lsp-haskell + (lsp-register-client + (make-lsp--client + :new-connection (lsp-stdio-connection (lambda () (lsp-haskell--hie-command))) + :major-modes '(haskell-mode) + :server-id 'hie + ;; :multi-root t + ;; :initialization-options 'lsp-haskell--make-init-options + ) + ) + ) + +(after! mu4e + (setq mu4e-contexts + `(,(make-mu4e-context + :name "work" + :vars + '()) + ,(make-mu4e-context + :name "personal" + :vars + '())))) + +(solaire-global-mode -1) + +(use-package! wsd-mode) + +(use-package! metal-mercury-mode) +(use-package! flycheck-mercury + :after (metal-mercury-mode flycheck-mercury)) diff --git a/init.el b/init.el index ca4a89069e..1dd0180f87 100644 --- a/init.el +++ b/init.el @@ -1,54 +1,45 @@ ;;; private/grfn/init.el -*- lexical-binding: t; -*- -(doom! :feature - ;debugger ; FIXME stepping through code, to help you add bugs - eval ; run code, run (also, repls) - (evil +everywhere); come to the dark side, we have cookies - file-templates ; auto-snippets for empty files - (lookup ; helps you navigate your code and documentation - +docsets) ; ...or in Dash docsets locally - snippets ; my elves. They type so I don't have to - spellcheck ; tasing you for misspelling mispelling - syntax-checker ; tasing you for every semicolon you forget - workspaces ; tab emulation, persistence & separate workspaces - - :completion - (company ; the ultimate code completion backend - +auto) ; as-you-type code completion - ;(helm ; the *other* search engine for love and life - ; +fuzzy) ; enable fuzzy search backend for helm - ;ido ; the other *other* search engine... - (ivy ; a search engine for love and life - +fuzzy) ; enable fuzzy search backend for ivy +(doom! :completion + company ; the ultimate code completion backend + ;;helm ; the *other* search engine for love and life + ;;ido ; the other *other* search engine... + ivy ; a search engine for love and life :ui + ;;deft ; notational velocity for Emacs doom ; what makes DOOM look the way it does - doom-dashboard ; a nifty splash screen for Emacs + ;doom-dashboard ; a nifty splash screen for Emacs doom-quit ; DOOM quit-message prompts when you quit Emacs - evil-goggles ; display visual hints when editing in evil - fci ; a `fill-column' indicator + ;fill-column ; a `fill-column' indicator hl-todo ; highlight TODO/FIXME/NOTE tags + ;;indent-guides ; highlighted indent columns modeline ; snazzy, Atom-inspired modeline, plus API nav-flash ; blink the current line after jumping - ;neotree ; a project drawer, like NERDTree for vim - ;treemacs ; a project drawer, like neotree but cooler + ;;neotree ; a project drawer, like NERDTree for vim + ophints ; highlight the region an operation acts on (popup ; tame sudden yet inevitable temporary windows +all ; catch all popups that start with an asterix +defaults) ; default popup rules pretty-code ; replace bits of code with pretty symbols - ;tabbar ; FIXME an (incomplete) tab bar for Emacs + ;;tabbar ; FIXME an (incomplete) tab bar for Emacs + ;;treemacs ; a project drawer, like neotree but cooler unicode ; extended unicode support for various languages vc-gutter ; vcs diff in the fringe vi-tilde-fringe ; fringe tildes to mark beyond EOB window-select ; visually switch windows + workspaces ; tab emulation, persistence & separate workspaces :editor - fold - ;; (format +onsave) ; automated prettiness + (evil +everywhere); come to the dark side, we have cookies + file-templates ; auto-snippets for empty files + fold ; (nigh) universal code folding + ;;(format +onsave) ; automated prettiness ;;lispy ; vim for lisp, for people who dont like vim - ;;multiple-cursors ; editing in many places at once + multiple-cursors ; editing in many places at once ;;parinfer ; turn lisp into python, sort of rotate-text ; cycle region at point between text candidates + snippets ; my elves. They type so I don't have to :emacs (dired ; making dired pretty [functional] @@ -57,33 +48,40 @@ ) electric ; smarter, keyword-based electric-indent ;;eshell ; a consistent, cross-platform shell (WIP) - imenu ; an imenu sidebar and searchable code index ;;term ; terminals in Emacs vc ; version-control and Emacs, sitting in a tree :tools + ;;ansible + ;;debugger ; FIXME stepping through code, to help you add bugs + ;;direnv docker - editorconfig ; let someone else argue about tabs vs spaces - ein ; tame Jupyter notebooks with emacs + ;;editorconfig ; let someone else argue about tabs vs spaces + ;; ein ; tame Jupyter notebooks with emacs + eval ; run code, run (also, repls) flycheck ; tasing you for every semicolon you forget flyspell ; tasing you for misspelling mispelling gist ; interacting with github gists - lsp - ;macos ; MacOS-specific commands + (lookup ; helps you navigate your code and documentation + +docsets) ; ...or in Dash docsets locally + ;;lsp + ;;macos ; MacOS-specific commands + magit ; a git porcelain for Emacs make ; run make tasks from Emacs - magit ; - password-store ; password manager for nerds + pass ; password manager for nerds pdf ; pdf enhancements - ;prodigy ; FIXME managing external services & code builders - ;rgb ; creating color strings + ;;prodigy ; FIXME managing external services & code builders + ;;rgb ; creating color strings ;;terraform ; infrastructure as code ;;tmux ; an API for interacting with tmux ;;upload ; map local to remote projects via ssh/ftp ;;wakatime + ;;vterm ; another terminals in Emacs :lang + agda ; types of types of types of types... ;;assembly ; assembly for fun or debugging - ;;(cc +irony +rtags); C/C++/Obj-C madness + cc ; C/C++/Obj-C madness clojure ; java with a lisp ;;common-lisp ; if you've seen one lisp, you've seen them all coq ; proofs-as-programs @@ -96,25 +94,29 @@ emacs-lisp ; drown in parentheses ;;ess ; emacs speaks statistics ;;go ; the hipster dialect - (haskell +intero) ; a language that's lazier than I am + ;; (haskell +intero) ; a language that's lazier than I am + haskell ; a language that's lazier than I am ;;hy ; readability of scheme w/ speed of python idris ; - (java +meghanada) ; the poster child for carpal tunnel syndrome + ;;(java +meghanada) ; the poster child for carpal tunnel syndrome javascript ; all(hope(abandon(ye(who(enter(here)))))) julia ; a better, faster MATLAB - ;;latex ; writing papers in Emacs has never been so fun + ;;kotlin ; a better, slicker Java(Script) + latex ; writing papers in Emacs has never been so fun ;;ledger ; an accounting system in Emacs ;;lua ; one-based indices? one-based indices markdown ; writing docs for people to ignore ;;nim ; python + lisp at the speed of c - ;;nix ; I hereby declare "nix geht mehr!" - ocaml ; an objective camel + nix ; I hereby declare "nix geht mehr!" + ;;ocaml ; an objective camel (org ; organize your plain life in plain text +attach ; custom attachment system +babel ; running code in org +capture ; org-capture in and outside of Emacs +export ; Exporting org to whatever you want - +present) ; Emacs for presentations + +habit ; Keep track of your habits + +present ; Emacs for presentations + +protocol) ; Support for org-protocol:// links ;;perl ; write code no one else can comprehend ;;php ; perl's insecure younger brother ;;plantuml ; diagrams for confusing people more @@ -129,6 +131,7 @@ (sh +fish) ; she sells (ba|z|fi)sh shells on the C xor ;;solidity ; do you need a blockchain? No. ;;swift ; who asked for emoji variables? + ;;terra ; Earth and Moon in alignment for performance. ;;web ; the tubes ;;vala ; GObjective-C @@ -136,25 +139,89 @@ ;; toward a specific purpose. They may have additional dependencies and ;; should be loaded late. :app - ;(email +gmail) ; emacs as an email client + ;;(email +gmail) ; emacs as an email client irc ; how neckbeards socialize - ;(rss +org) ; emacs as an RSS reader - ;twitter ; twitter client https://twitter.com/vnought - ;(write ; emacs as a word processor (latex + org + markdown) - ; +wordnut ; wordnet (wn) search - ; +langtool) ; a proofreader (grammar/style check) for Emacs + ;;(rss +org) ; emacs as an RSS reader + twitter ; twitter client https://twitter.com/vnought + ;;(write ; emacs as a word processor (latex + org + markdown) + ;; +wordnut ; wordnet (wn) search + ;; +langtool) ; a proofreader (grammar/style check) for Emacs + + :email + (mu4e +gmail) + notmuch :collab - ;floobits ; peer programming for a price - ;impatient-mode ; show off code over HTTP + ;;floobits ; peer programming for a price + ;;impatient-mode ; show off code over HTTP :config ;; For literate config users. This will tangle+compile a config.org ;; literate config in your `doom-private-dir' whenever it changes. - ;literate + ;;literate - ;; The default module set reasonable defaults for Emacs. It also provides - ;; a Spacemacs-inspired keybinding scheme, a custom yasnippet library, - ;; and additional ex commands for evil-mode. Use it as a reference for - ;; your own modules. - (default +bindings +snippets +evil-commands)) + ;; The default module sets reasonable defaults for Emacs. It also + ;; provides a Spacemacs-inspired keybinding scheme and a smartparens + ;; config. Use it as a reference for your own modules. + (default +bindings +smartparens)) +(custom-set-variables + ;; custom-set-variables was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(doom-big-font-mode nil) + '(flycheck-javascript-flow-args nil) + '(org-agenda-files + '("/home/griffin/notes/personal.org" "/home/griffin/notes/2020-01-27-data-pipeline-deploy-mismatch.org" "/home/griffin/notes/architecture.org" "/home/griffin/notes/cooking.org" "/home/griffin/notes/culture-survey.org" "/home/griffin/notes/dir-structure.org" "/home/griffin/notes/dnd.org" "/home/griffin/notes/inbox.org" "/home/griffin/notes/misc-todo.org" "/home/griffin/notes/nix-talk.org" "/home/griffin/notes/notes.org" "/home/griffin/notes/one-on-one.org" "/home/griffin/notes/work.org" "/home/griffin/notes/xanthous.org" "/home/griffin/notes/xgboost.org")) + '(safe-local-variable-values + '((intero-stack-yaml . "/home/griffin/code/mlem/stack.yaml") + (elisp-lint-indent-specs + (if-let* . 2) + (when-let* . 1) + (let* . defun) + (nrepl-dbind-response . 2) + (cider-save-marker . 1) + (cider-propertize-region . 1) + (cider-map-repls . 1) + (cider--jack-in . 1) + (cider--make-result-overlay . 1) + (insert-label . defun) + (insert-align-label . defun) + (insert-rect . defun) + (cl-defun . 2) + (with-parsed-tramp-file-name . 2) + (thread-first . 1) + (thread-last . 1)) + (checkdoc-package-keywords-flag) + (cider-jack-in-default . "shadow-cljs") + (projectile-project-root . "/home/griffin/code/urb/grid/backend/src") + (python-pytest-executable . "/home/griffin/code/urb/grid/backend/src/.venv/bin/pytest")))) +(custom-set-faces + ;; custom-set-faces was added by Custom. + ;; If you edit it by hand, you could mess it up, so be careful. + ;; Your init file should contain only one such instance. + ;; If there is more than one, they won't work right. + '(default ((((class color) (min-colors 89)) (:foreground "#657b83" :background "#fdf6e3")))) + '(agda2-highlight-bound-variable-face ((t nil))) + '(agda2-highlight-coinductive-constructor-face ((t (:foreground "#b58900")))) + '(agda2-highlight-datatype-face ((t (:foreground "#268bd2")))) + '(agda2-highlight-dotted-face ((t nil))) + '(agda2-highlight-error-face ((t (:foreground "#dc322f" :underline t)))) + '(agda2-highlight-field-face ((t (:foreground "#dc322f")))) + '(agda2-highlight-function-face ((t (:foreground "#268bd2")))) + '(agda2-highlight-incomplete-pattern-face ((t (:background "#cb4b16" :foreground "#002b36")))) + '(agda2-highlight-inductive-constructor-face ((t (:foreground "#859900")))) + '(agda2-highlight-keyword-face ((t (:foreground "#859900")))) + '(agda2-highlight-module-face ((t (:foreground "#b58900")))) + '(agda2-highlight-number-face ((t (:foreground "#6c71c4")))) + '(agda2-highlight-operator-face ((t nil))) + '(agda2-highlight-postulate-face ((t (:foreground "#268bd2")))) + '(agda2-highlight-primitive-face ((t (:foreground "#268bd2")))) + '(agda2-highlight-primitive-type-face ((t (:foreground "#268bd2")))) + '(agda2-highlight-record-face ((t (:foreground "#268bd2")))) + '(agda2-highlight-string-face ((t (:foreground "#2aa198")))) + '(agda2-highlight-symbol-face ((((background "#fdf6e3")) (:foreground "#586e75")))) + '(agda2-highlight-termination-problem-face ((t (:background "#cb4b16" :foreground "#002b36")))) + '(agda2-highlight-typechecks-face ((t (:background "#2aa198" :foreground "#002b36")))) + '(agda2-highlight-unsolved-constraint-face ((t (:background "#eee8d5")))) + '(agda2-highlight-unsolved-meta-face ((t (:background "#eee8d5"))))) diff --git a/nix-yapf-mode.el b/nix-yapf-mode.el new file mode 100644 index 0000000000..9dba47bd36 --- /dev/null +++ b/nix-yapf-mode.el @@ -0,0 +1,21 @@ +;;; ~/.doom.d/nix-yapf-mode.el -*- lexical-binding: t; -*- + + +(defun +grfn/yapfify-call-bin (input-buffer output-buffer start-line end-line) + (with-current-buffer input-buffer + (call-process-region + (point-min) + (point-max) + "nix-shell" + nil + (list output-buffer nil) + nil + "/home/griffin/code/urb/grid/yapf.nix" + "--run" + (concat + "yapf -l " + (number-to-string start-line) + "-" + (number-to-string end-line))))) + +(advice-add #'yapfify-call-bin :override #'+grfn/yapfify-call-bin) diff --git a/org-alerts.el b/org-alerts.el new file mode 100644 index 0000000000..993791f367 --- /dev/null +++ b/org-alerts.el @@ -0,0 +1,188 @@ +;;; ~/.doom.d/org-alerts.el -*- lexical-binding: t; -*- + +;;; Commentary: + +;;; Code: + +(require 's) +(require 'dash) +(require 'alert) +(require 'org-agenda) + + +(defvar grfn/org-alert-interval 300 + "Interval in seconds to recheck and display deadlines.") + + +(defvar grfn/org-alert-notification-title "*org*" + "Title to be sent with notify-send.") + +(defvar grfn/org-alert-headline-regexp "\\(Sched.+:.+\\|Deadline:.+\\)" + "Regexp for headlines to search in agenda buffer.") + +(defun grfn/org-alert--strip-prefix (headline) + "Remove the scheduled/deadline prefix from HEADLINE." + (replace-regexp-in-string ".*:\s+" "" headline)) + + +(defun grfn/org-alert--unique-headlines (regexp agenda) + "Return unique headlines from the results of REGEXP in AGENDA." + (let ((matches (-distinct (-flatten (s-match-strings-all regexp agenda))))) + (--map (grfn/org-alert--strip-prefix it) matches))) + + +(defun grfn/org-alert--get-headlines () + "Return the current org agenda as text only." + (with-temp-buffer + (let ((org-agenda-sticky nil) + (org-agenda-buffer-tmp-name (buffer-name))) + (ignore-errors (org-agenda-list nil "TODAY" 1)) + (grfn/org-alert--unique-headlines + grfn/org-alert-headline-regexp + (buffer-substring-no-properties (point-min) (point-max)))))) + +(defun grfn/parse-range-string (str) + (when + (string-match (rx (group (repeat 2 (any digit)) + ":" + (repeat 2 (any digit))) + (optional + (and + "-" + (group (repeat 2 (any digit)) + ":" + (repeat 2 (any digit)))))) + str) + (list + (org-read-date nil t + (match-string 1 str)) + (when-let ((et (match-string 2 str))) (org-read-date nil t et))))) + +(defun grfn/start-time-from-range-string (str) + (pcase-let ((`(,start-time . _) (grfn/parse-range-string str))) + start-time)) + +(comment + (org-agenda-list nil "TODAY" 1) + + (grfn/org-alert--get-headlines) + (setq --src + (with-temp-buffer + (let ((org-agenda-sticky nil) + (org-agenda-buffer-tmp-name (buffer-name))) + (ignore-errors (org-agenda-list nil "TODAY" 1)) + (buffer-substring-no-properties (point-min) (point-max))))) + + (setq --entries + (with-temp-buffer + (let ((inhibit-redisplay t) + (org-agenda-sticky nil) + (org-agenda-buffer-tmp-name (buffer-name)) + (org-agenda-buffer-name (buffer-name)) + (org-agenda-buffer (current-buffer))) + (org-agenda-get-day-entries + (cadr (org-agenda-files nil 'ifmode)) + (calendar-gregorian-from-absolute + (time-to-days (org-read-date nil t "TODAY"))))))) + + (loop for k in (text-properties-at 0 (car --entries)) + by #'cddr + collect k) + + (--map (substring-no-properties (get-text-property 0 'txt it)) --entries) + (--map (get-text-property 0 'time it) --entries) + (current-time) + + (format-time-string "%R" (org-read-date nil t "10:00-11:00")) + + (grfn/start-time-from-range-string "10:00") + + (current-time-string (org-read-date nil t "10:00-11:00")) + + (todo-state + org-habit-p + priority + warntime + ts-date + date + type + org-hd-marker + org-marker + face + undone-face + help-echo + mouse-face + done-face + org-complex-heading-regexp + org-todo-regexp + org-not-done-regexp + dotime + format + extra + time + level + txt + breadcrumbs + duration + time-of-day + org-lowest-priority + org-highest-priority + tags + org-category) + + (propertize) + + --src + ) + + +(defun grfn/org-alert--headline-complete? (headline) + "Return whether HEADLINE has been completed." + (--any? (s-starts-with? it headline) org-done-keywords-for-agenda)) + + +(defun grfn/org-alert--filter-active (deadlines) + "Remove any completed headings from the provided DEADLINES." + (-remove 'grfn/org-alert--headline-complete? deadlines)) + + +(defun grfn/org-alert--strip-states (deadlines) + "Remove the todo states from DEADLINES." + (--map (s-trim (s-chop-prefixes org-todo-keywords-for-agenda it)) deadlines)) + + +(defun grfn/org-alert-check () + "Check for active, due deadlines and initiate notifications." + (interactive) + ;; avoid interrupting current command. + (unless (minibufferp) + (save-window-excursion + (save-excursion + (save-restriction + (let ((active (grfn/org-alert--filter-active (grfn/org-alert--get-headlines)))) + (dolist (dl (grfn/org-alert--strip-states active)) + (alert dl :title grfn/org-alert-notification-title)))))) + (when (get-buffer org-agenda-buffer-name) + (ignore-errors + (with-current-buffer org-agenda-buffer-name + (org-agenda-redo t)))))) + + +(defun grfn/org-alert-enable () + "Enable the notification timer. Cancels existing timer if running." + (interactive) + (grfn/org-alert-disable) + (run-at-time 0 grfn/org-alert-interval 'grfn/org-alert-check)) + + +(defun grfn/org-alert-disable () + "Cancel the running notification timer." + (interactive) + (dolist (timer timer-list) + (if (eq (elt timer 5) 'grfn/org-alert-check) + (cancel-timer timer)))) + + + +(provide 'grfn/org-alert) +;;; grfn/org-alert.el ends here diff --git a/org-config.el b/org-config.el new file mode 100644 index 0000000000..faf2a1bf42 --- /dev/null +++ b/org-config.el @@ -0,0 +1,91 @@ +;;; ~/.doom.d/org-config.el -*- lexical-binding: t; -*- +;;; + +(defun notes-file (f) + (concat org-directory (if (string-prefix-p "/" f) "" "/") f)) + +(require 'org-mu4e) + +(setq + org-directory (expand-file-name "~/notes") + +org-dir (expand-file-name "~/notes") + org-default-notes-file (concat org-directory "/inbox.org") + +org-default-todo-file (concat org-directory "/inbox.org") + org-agenda-files (list org-directory) + org-refile-targets '((org-agenda-files :maxlevel . 3)) + org-outline-path-complete-in-steps nil + org-refile-use-outline-path t + org-file-apps `((auto-mode . emacs) + (,(rx (or (and "." (optional "x") (optional "htm") (optional "l") buffer-end) + (and buffer-start "http" (optional "s") "://"))) + . "firefox %s") + (,(rx ".pdf" buffer-end) . "apvlv %s") + (,(rx "." (or "png" + "jpg" + "jpeg" + "gif" + "tif" + "tiff") + buffer-end) + . "feh %s")) + org-log-done 'time + org-archive-location "~/notes/trash::* From %s" + org-cycle-separator-lines 2 + org-hidden-keywords '(title) + org-tags-column -130 + org-ellipsis "⤵" + org-imenu-depth 9 + org-capture-templates + `(("t" "Todo" entry + (file +org-default-todo-file) + "* TODO %?\n%i" + :kill-buffer t) + + ("n" "Notes" entry + (file +org-default-todo-file) + "* %U %?\n%i" + :prepend t + :kill-buffer t) + + ("c" "Task note" entry + (clock) + "* %U %?\n%i[[%l][Context]]\n" + :kill-buffer t + :unnarrowed t) + + ;; ("d" "Tech debt" entry + ;; (file+headline ,(concat org-directory "/work.org") + ;; "Inbox") + ;; "* TODO %? :debt:\nContext: %a\nIn task: %K" + ;; :prepend t + ;; :kill-buffer t) + + ("p" "Projects") + ("px" "Xanthous" entry + (file+headline ,(notes-file "xanthous.org") "Backlog") + "* TODO %?\nContext %a\nIn task: %K") + + ("d" "Data recording") + ;; ("dr" "Reflux data" table-line + ;; (file+olp ,(notes-file "personal.org") + ;; "Data" "Reflux") + ;; "| %U | %^{reflux|0|1|2|3|4|5} | %^{ate 1hr before bed?|Y|N} | %^{ate spicy food yesterday?|Y|N} |" + ;; :unnarrowed t + ;; :immediate-finish t + ;; ) + ) + + org-capture-templates-contexts + `(("px" ((in-file . "/home/griffin/code/xanthous/.*")))) + + org-deadline-warning-days 1 + org-agenda-skip-scheduled-if-deadline-is-shown 'todo + org-todo-keywords '((sequence "TODO(t)" "ACTIVE(a)" "|" "DONE(d)" "RUNNING(r)") + (sequence "NEXT(n)" "WAITING(w)" "LATER(l)" "|" "CANCELLED(c)")) + org-agenda-custom-commands + '(("p" "Sprint Tasks" tags-todo "sprint") + ("i" "Inbox" tags "inbox") + ("r" "Running jobs" todo "RUNNING") + ("w" "@Work" tags-todo "@work") + ("n" . "Next...") + ("np" "Next Sprint" tags-todo "next_sprint|sprint_planning"))) diff --git a/org-query.el b/org-query.el new file mode 100644 index 0000000000..3ed4b086af --- /dev/null +++ b/org-query.el @@ -0,0 +1,96 @@ +;;; ~/.doom.d/org-query.el -*- lexical-binding: t; -*- + +(require 'org) +(require 'org-agenda) +(require 'inflections) + +(defun grfn/org-agenda-entry->element (agenda-entry) + ;; ??? + ()) + +(defun org-elements-agenda-match (match &optional todo-only) + (setq match + (propertize match 'inherited t)) + (with-temp-buffer + (let ((inhibit-redisplay (not debug-on-error)) + (org-agenda-sticky nil) + (org-agenda-buffer-tmp-name (buffer-name)) + (org-agenda-buffer-name (buffer-name)) + (org-agenda-buffer (current-buffer)) + (matcher (org-make-tags-matcher match)) + result) + (org-agenda-prepare (concat "TAGS " match)) + (setq match (car matcher) + matcher (cdr matcher)) + (dolist (file (org-agenda-files nil 'ifmode) + result) + (catch 'nextfile + (org-check-agenda-file file) + (when-let ((buffer (if (file-exists-p file) + (org-get-agenda-file-buffer file) + (error "No such file %s" file)))) + (with-current-buffer buffer + (unless (derived-mode-p 'org-mode) + (error "Agenda file %s is not in Org mode" file)) + (save-excursion + (save-restriction + (if (eq buffer org-agenda-restrict) + (narrow-to-region org-agenda-restrict-begin + org-agenda-restrict-end) + (widen)) + (setq result + (append result (org-scan-tags + 'agenda + matcher + todo-only)))))))))))) + +(defun grfn/num-inbox-items () + (length (org-elements-agenda-match "inbox" t))) + +(defun grfn/num-inbox-items-message () + (let ((n (grfn/num-inbox-items))) + (unless (zerop n) + (format "%d %s" + n + (if (= 1 n) "item" "items"))))) + +(defmacro grfn/at-org-clocked-in-item (&rest body) + `(when (org-clocking-p) + (let ((m org-clock-marker)) + (with-current-buffer (marker-buffer m) + (save-mark-and-excursion + (goto-char m) + (org-back-to-heading t) + ,@body))))) + +(defun grfn/org-element-clocked-in-task () + (grfn/at-org-clocked-in-item + (org-element-at-point))) + +(comment + (grfn/org-element-clocked-in-task) + (org-element-property :title (grfn/org-element-clocked-in-task)) + ) + +(defun grfn/minutes->hours:minutes (minutes) + (format "%d:%02d" + (floor (/ minutes 60)) + (mod minutes 60))) + +(comment + (grfn/minutes->hours:minutes 1) ; => "0:01" + (grfn/minutes->hours:minutes 15) ; => "0:15" + (grfn/minutes->hours:minutes 130) ; => "2:10" + ) + +(defun grfn/org-current-clocked-in-task-message () + (if (org-clocking-p) + (format "(%s) [%s]" + (org-element-property :title (grfn/org-element-clocked-in-task)) + (grfn/minutes->hours:minutes + (org-clock-get-clocked-time))) + "")) + +(comment + (grfn/org-current-clocked-in-task-message) + ) diff --git a/packages.el b/packages.el index 799bcbe92a..41e8e14904 100644 --- a/packages.el +++ b/packages.el @@ -1,8 +1,6 @@ ;; -*- no-byte-compile: t; -*- ;;; private/grfn/packages.el -;; (package! 'tide :disable t) - (package! moody) ;; Editor @@ -10,24 +8,26 @@ (package! fill-column-indicator) (package! flx) (package! general - :recipe (general - :fetcher github - :repo "noctuid/general.el")) + :recipe (:host github :repo "noctuid/general.el")) (package! fill-column-indicator) (package! writeroom-mode) (package! dash) (package! w3m) (package! rainbow-mode) +(package! string-inflection) ;;; Org (package! org-clubhouse - :recipe (org-clubhouse - :fetcher file - :path "~/code/urb/org-clubhouse")) + :recipe (:host file + :local-repo "~/code/org-clubhouse")) (package! org-alert) (package! ob-http) (package! ob-ipython) (package! ob-async) +(package! org-recent-headings) +(package! org-sticky-header) +(package! gnuplot) +(package! gnuplot-mode) ;; Presentation (package! epresent) @@ -42,6 +42,12 @@ (package! evil-magit) (package! marshal) (package! forge) +(package! + github-review + :recipe + (:host github + :repo "charignon/github-review" + :files ("github-review.el"))) ;; Elisp (package! dash) @@ -49,17 +55,22 @@ (package! s) (package! request) (package! predd - :recipe (predd - :fetcher github - :repo "skeeto/predd")) + :recipe (:host github :repo "skeeto/predd")) ;; Haskell -(package! lsp-mode) -(package! lsp-ui :recipe (:fetcher github :repo "emacs-lsp/lsp-ui")) (package! lsp-haskell) +(package! counsel-etags) + +;;; LSP +(package! lsp-mode) +(package! lsp-ui :recipe (:host github :repo "emacs-lsp/lsp-ui")) (package! company-lsp) +(package! lsp-treemacs) +(package! dap-mode) ;; Rust +(package! rustic :disable t) +(package! racer :disable t) (package! cargo) ;; Elixir @@ -80,10 +91,10 @@ (package! graphql-mode) ;; Haskell -;; (package! lsp-mode) -;; (package! lsp-ui) -;; (package! lsp-haskell) -;; (package! company-lsp) +(package! lsp-mode) +(package! lsp-ui) +(package! lsp-haskell) +(package! company-lsp) ;; (package! lsp-imenu) ;; Clojure @@ -95,7 +106,35 @@ (package! emacsql-psql) ;;; Python +(package! pyimport) (package! yapfify) ;;; Desktop interaction (package! counsel-spotify) + +;;; Dhall +(package! dhall-mode) + +;;; Kubernetes +(package! kubernetes) +(package! kubernetes-evil) +(package! k8s-mode) + +;;; Stack Exchange +(package! sx) + +;;; Nix +(package! nix-update + :recipe (:host github + :repo "glittershark/nix-update-el")) + +;;; Sequence diagrams +(package! wsd-mode + :recipe (:host github + :repo "josteink/wsd-mode")) + +;;; logic? +(package! metal-mercury-mode + :recipe (:host github + :repo "ahungry/metal-mercury-mode")) +(package! flycheck-mercury) diff --git a/show-matching-paren.el b/show-matching-paren.el new file mode 100644 index 0000000000..d10751a63f --- /dev/null +++ b/show-matching-paren.el @@ -0,0 +1,61 @@ +;;; ~/.doom.d/show-matching-paren.el -*- lexical-binding: t; -*- + +;;; https://with-emacs.com/posts/ui-hacks/show-matching-lines-when-parentheses-go-off-screen/ + +;; we will call `blink-matching-open` ourselves... +(remove-hook 'post-self-insert-hook + #'blink-paren-post-self-insert-function) +;; this still needs to be set for `blink-matching-open` to work +(setq blink-matching-paren 'show) + +(let ((ov nil)) ; keep track of the overlay + (advice-add + #'show-paren-function + :after + (defun show-paren--off-screen+ (&rest _args) + "Display matching line for off-screen paren." + (when (overlayp ov) + (delete-overlay ov)) + ;; check if it's appropriate to show match info, + ;; see `blink-paren-post-self-insert-function' + (when (and (overlay-buffer show-paren--overlay) + (not (or cursor-in-echo-area + executing-kbd-macro + noninteractive + (minibufferp) + this-command)) + (and (not (bobp)) + (memq (char-syntax (char-before)) '(?\) ?\$))) + (= 1 (logand 1 (- (point) + (save-excursion + (forward-char -1) + (skip-syntax-backward "/\\") + (point)))))) + ;; rebind `minibuffer-message' called by + ;; `blink-matching-open' to handle the overlay display + (cl-letf (((symbol-function #'minibuffer-message) + (lambda (msg &rest args) + (let ((msg (apply #'format-message msg args))) + (setq ov (display-line-overlay+ + (window-start) msg )))))) + (blink-matching-open)))))) + +(defun display-line-overlay+ (pos str &optional face) + "Display line at POS as STR with FACE. + +FACE defaults to inheriting from default and highlight." + (let ((ol (save-excursion + (goto-char pos) + (make-overlay (line-beginning-position) + (line-end-position))))) + (overlay-put ol 'display str) + (overlay-put ol 'face + (or face '(:inherit default :inherit highlight))) + ol)) + +(setq show-paren-style 'paren + show-paren-delay 0.03 + show-paren-highlight-openparen t + show-paren-when-point-inside-paren nil + show-paren-when-point-in-periphery t) +(show-paren-mode 1) diff --git a/slack-snippets.el b/slack-snippets.el index 0c51751921..9e05382ee6 100644 --- a/slack-snippets.el +++ b/slack-snippets.el @@ -192,10 +192,11 @@ (ivy-read "Select channel: " ;; TODO want to potentially use purpose / topic stuff here - (-map (lambda (chan) (let ((label (assoc-default 'label (cdr chan))) - (id (car chan))) - (propertize label 'channel-id id))) - conversations) + (->> conversations + (-filter (lambda (c) (assoc-default 'label (cdr c)))) + (-map (lambda (chan) (let ((label (assoc-default 'label (cdr chan))) + (id (car chan))) + (propertize label 'channel-id id))))) :history 'slack/channel-history :action (lambda (selected) (let ((channel-id (get-text-property 0 'channel-id selected))) @@ -203,14 +204,24 @@ (message "Sent message to %s" selected)))))) nil) +(comment + (prompt-for-channel #'message) + (->> --convos + (-filter (lambda (c) (assoc-default 'label (cdr c)))) + (-map (lambda (chan) (let ((label (assoc-default 'label (cdr chan))) + (id (car chan))) + (propertize label 'channel-id id))))) + + (->> --convos (car) (cdr) (assoc-default 'label)) + ) + (defun slack-send-code-snippet (&optional snippet-text) - (interactive) - (when-let ((snippet-text (or snippet-text - (buffer-substring-no-properties (mark) (point))))) - (prompt-for-channel - (lambda (channel-id) - (slack/post-message - :text (format "```\n%s```" snippet-text) - :channel-id channel-id))))) + (interactive + (list (buffer-substring-no-properties (mark) (point)))) + (prompt-for-channel + (lambda (channel-id) + (slack/post-message + :text (format "```\n%s```" snippet-text) + :channel-id channel-id)))) (provide 'slack-snippets) diff --git a/snippets/haskell-mode/hlint b/snippets/haskell-mode/hlint new file mode 100644 index 0000000000..74b63dc672 --- /dev/null +++ b/snippets/haskell-mode/hlint @@ -0,0 +1,8 @@ +# -*- mode: snippet -*- +# name: hlint +# uuid: +# expand-env: ((yas-indent-line 'fixed)) +# key: hlint +# condition: t +# -- +{-# ANN module ("Hlint: ignore $1" :: String) #- } \ No newline at end of file diff --git a/snippets/nix-mode/fetchFromGitHub b/snippets/nix-mode/fetchFromGitHub new file mode 100644 index 0000000000..9b93735730 --- /dev/null +++ b/snippets/nix-mode/fetchFromGitHub @@ -0,0 +1,12 @@ +# -*- mode: snippet -*- +# name: fetchFromGitHub +# uuid: +# key: fetchFromGitHub +# condition: t +# -- +fetchFromGitHub { + owner = "$1"; + repo = "$2"; + rev = "$3"; + sha256 = "0000000000000000000000000000000000000000000000000000"; +} \ No newline at end of file diff --git a/snippets/nix-mode/pythonPackage b/snippets/nix-mode/pythonPackage new file mode 100644 index 0000000000..0a74c21e18 --- /dev/null +++ b/snippets/nix-mode/pythonPackage @@ -0,0 +1,16 @@ +# key: pypkg +# name: pythonPackage +# condition: t +# -- +${1:pname} = buildPythonPackage rec { + name = "\${pname}-\${version}"; + pname = "$1"; + version = "${2:1.0.0}"; + src = fetchPypi { + inherit pname version; + sha256 = "0000000000000000000000000000000000000000000000000000"; + }; + propagatedBuildInputs = with pythonSelf; [ + $3 + ]; +}; \ No newline at end of file diff --git a/snippets/nix-mode/sha256 b/snippets/nix-mode/sha256 new file mode 100644 index 0000000000..e3d52e1c02 --- /dev/null +++ b/snippets/nix-mode/sha256 @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: sha256 +# uuid: +# key: sha256 +# condition: t +# -- +sha256 = "0000000000000000000000000000000000000000000000000000"; \ No newline at end of file diff --git a/snippets/org-mode/combat b/snippets/org-mode/combat new file mode 100644 index 0000000000..ef46062d09 --- /dev/null +++ b/snippets/org-mode/combat @@ -0,0 +1,13 @@ +# -*- mode: snippet -*- +# name: combat +# uuid: +# key: combat +# condition: t +# -- +| | initiative | max hp | current hp | status | | +|-------------+------------+--------+------------+--------+------| +| Barty Barty | | | | | <--- | +| Hectoroth | | | | | | +| Xanadu | | | | | | +| Aurora | | | | | | +| EFB | | | | | | \ No newline at end of file diff --git a/snippets/org-mode/reveal b/snippets/org-mode/reveal new file mode 100644 index 0000000000..1bdbdfa5dc --- /dev/null +++ b/snippets/org-mode/reveal @@ -0,0 +1,6 @@ +# key: reveal +# name: reveal +# condition: t +# -- +#+ATTR_REVEAL: :frag ${1:roll-in} +$0 \ No newline at end of file diff --git a/snippets/python-mode/decorate b/snippets/python-mode/decorate new file mode 100644 index 0000000000..9448b45c96 --- /dev/null +++ b/snippets/python-mode/decorate @@ -0,0 +1,15 @@ +# -*- mode: snippet -*- +# name: decorate +# uuid: +# key: decorate +# condition: t +# -- +def wrap(inner): + @wraps(inner) + def wrapped(*args, **kwargs): + ret = inner(*args, **kwargs) + return ret + + return wrapped + +return wrap \ No newline at end of file diff --git a/snippets/python-mode/name b/snippets/python-mode/name new file mode 100644 index 0000000000..eca6d60b48 --- /dev/null +++ b/snippets/python-mode/name @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: name +# uuid: +# key: name +# condition: t +# -- +__name__ \ No newline at end of file diff --git a/snippets/python-mode/pdb b/snippets/python-mode/pdb new file mode 100644 index 0000000000..6b5c0bbc0a --- /dev/null +++ b/snippets/python-mode/pdb @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: pdb +# uuid: +# key: pdb +# condition: t +# -- +import pdb; pdb.set_trace() \ No newline at end of file diff --git a/sql-strings.el b/sql-strings.el new file mode 100644 index 0000000000..37e22af421 --- /dev/null +++ b/sql-strings.el @@ -0,0 +1,75 @@ +;;; ~/.doom.d/sql-strings.el -*- lexical-binding: t; -*- + +;;; https://www.emacswiki.org/emacs/StringAtPoint +(defun ourcomments-string-or-comment-bounds-1 (what) + (save-restriction + (widen) + (let* ((here (point)) + ;; Fix-me: when on end-point, how to handle that and which should be last hit point? + (state (parse-partial-sexp (point-min) (1+ here))) + (type (if (nth 3 state) + 'string + (if (nth 4 state) + 'comment))) + (start (when type (nth 8 state))) + end) + (unless start + (setq state (parse-partial-sexp (point-min) here)) + (setq type (if (nth 3 state) + 'string + (if (nth 4 state) + 'comment))) + (setq start (when type (nth 8 state)))) + (unless (or (not what) + (eq what type)) + (setq start nil)) + (if (not start) + (progn + (goto-char here) + nil) + (setq state (parse-partial-sexp (1+ start) (point-max) + nil nil state 'syntax-table)) + (setq end (point)) + (goto-char here) + (cons start end))))) + +(defun ourcomments-bounds-of-string-at-point () + "Return bounds of string at point if any." + (ourcomments-string-or-comment-bounds-1 'string)) + +(put 'string 'bounds-of-thing-at-point 'ourcomments-bounds-of-string-at-point) + +(defun -sanitize-sql-string (str) + (->> str + (downcase) + (s-trim) + (replace-regexp-in-string + (rx (or (and string-start (or "\"\"\"" + "\"")) + (and (or "\"\"\"" + "\"") + string-end))) + "") + (s-trim))) + +(defun sql-string-p (str) + "Returns 't if STR looks like a string literal for a SQL statement" + (setq str (-sanitize-sql-string str)) + (or (s-starts-with? "select" str))) + +;;; tests + +(require 'ert) + +(ert-deftest sanitize-sql-string-test () + (should (string-equal "select * from foo;" + (-sanitize-sql-string + "\"\"\"SELECT * FROM foo;\n\n\"\"\"")))) + +(ert-deftest test-sql-string-p () + (dolist (str '("SELECT * FROM foo;" + "select * from foo;")) + (should (sql-string-p str))) + + (dolist (str '("not a QUERY")) + (should-not (sql-string-p str)))) diff --git a/themes/grfn-solarized-light-theme.el b/themes/grfn-solarized-light-theme.el index 338cfabfcc..ae00b6b5fc 100644 --- a/themes/grfn-solarized-light-theme.el +++ b/themes/grfn-solarized-light-theme.el @@ -1,4 +1,6 @@ (require 'solarized) +(eval-when-compile + (require 'solarized-palettes)) ;; (defun grfn-solarized-theme () ;; (custom-theme-set-faces @@ -56,30 +58,58 @@ (deftheme grfn-solarized-light "The light variant of Griffin's solarized theme") -(create-solarized-theme - 'light 'grfn-solarized-light - (lambda () - (custom-theme-set-faces - 'grfn-solarized-light - `(font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) - `(font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) - `(font-lock-keyword-face ((t (:foreground ,+solarized-green)))) +(setq grfn-solarized-faces + '("Griffin's solarized theme customization" + (custom-theme-set-faces + theme-name + `(font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) + `(font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) + `(font-lock-keyword-face ((t (:foreground ,+solarized-green)))) - `(elixir-attribute-face ((t (:foreground ,+solarized-blue)))) - `(elixir-atom-face ((t (:foreground ,+solarized-cyan)))) - ) + `(elixir-attribute-face ((t (:foreground ,+solarized-blue)))) + `(elixir-atom-face ((t (:foreground ,+solarized-cyan)))) + `(agda2-highlight-keyword-face ((t (:foreground ,green)))) + `(agda2-highlight-string-face ((t (:foreground ,cyan)))) + `(agda2-highlight-number-face ((t (:foreground ,violet)))) + `(agda2-highlight-symbol-face ((((background ,base3)) (:foreground ,base01)))) + `(agda2-highlight-primitive-type-face ((t (:foreground ,blue)))) + `(agda2-highlight-bound-variable-face ((t nil))) + `(agda2-highlight-inductive-constructor-face ((t (:foreground ,green)))) + `(agda2-highlight-coinductive-constructor-face ((t (:foreground ,yellow)))) + `(agda2-highlight-datatype-face ((t (:foreground ,blue)))) + `(agda2-highlight-field-face ((t (:foreground ,red)))) + `(agda2-highlight-function-face ((t (:foreground ,blue)))) + `(agda2-highlight-module-face ((t (:foreground ,yellow)))) + `(agda2-highlight-postulate-face ((t (:foreground ,blue)))) + `(agda2-highlight-primitive-face ((t (:foreground ,blue)))) + `(agda2-highlight-record-face ((t (:foreground ,blue)))) + `(agda2-highlight-dotted-face ((t nil))) + `(agda2-highlight-operator-face ((t nil))) + `(agda2-highlight-error-face ((t (:foreground ,red :underline t)))) + `(agda2-highlight-unsolved-meta-face ((t (:background ,base2)))) + `(agda2-highlight-unsolved-constraint-face ((t (:background ,base2)))) + `(agda2-highlight-termination-problem-face ((t (:background ,orange :foreground ,base03)))) + `(agda2-highlight-incomplete-pattern-face ((t (:background ,orange :foreground ,base03)))) + `(agda2-highlight-typechecks-face ((t (:background ,cyan :foreground ,base03)))) - )) + `(font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) + `(font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) + `(font-lock-keyword-face ((t (:foreground ,+solarized-green :bold nil)))) + `(font-lock-builtin-face ((t (:foreground ,+solarized-s-base01 + :bold t)))) -(custom-theme-set-faces - 'grfn-solarized-light - `(font-lock-doc-face ((t (:foreground ,+solarized-s-base1)))) - `(font-lock-preprocessor-face ((t (:foreground ,+solarized-red)))) - `(font-lock-keyword-face ((t (:foreground ,+solarized-green)))) + `(elixir-attribute-face ((t (:foreground ,+solarized-blue)))) + `(elixir-atom-face ((t (:foreground ,+solarized-cyan)))) + `(linum ((t (:background ,+solarized-s-base2 :foreground ,+solarized-s-base1)))) + `(line-number ((t (:background ,+solarized-s-base2 :foreground ,+solarized-s-base1)))) - `(elixir-attribute-face ((t (:foreground ,+solarized-blue)))) - `(elixir-atom-face ((t (:foreground ,+solarized-cyan)))) - ) + `(haskell-operator-face ((t (:foreground ,+solarized-green)))) + `(haskell-keyword-face ((t (:foreground ,+solarized-cyan)))) -(provide-theme 'grfn-solarized-light) + `(org-drawer ((t (:foreground ,+solarized-s-base1 + :bold t))))))) + +(solarized-with-color-variables + 'light 'grfn-solarized-light solarized-light-color-palette-alist) +(provide-theme 'grfn-solarized-light) -- cgit 1.4.1 From 9a5c75e431809b147d4dab53d7440af1214a7b62 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:31:11 -0400 Subject: __snippet__ --- snippets/python-mode/dunder | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 snippets/python-mode/dunder diff --git a/snippets/python-mode/dunder b/snippets/python-mode/dunder new file mode 100644 index 0000000000..c49ec40a15 --- /dev/null +++ b/snippets/python-mode/dunder @@ -0,0 +1,7 @@ +# -*- mode: snippet -*- +# name: dunder +# uuid: +# key: du +# condition: t +# -- +__$1__$0 \ No newline at end of file -- cgit 1.4.1 From c9f970ded4daf1cc3c8dd9e1ee81f2ccf5dca090 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:31:30 -0400 Subject: attempt at rework of finder --- +bindings.el | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/+bindings.el b/+bindings.el index 875d298d42..475a3c7861 100644 --- a/+bindings.el +++ b/+bindings.el @@ -80,10 +80,10 @@ private/hlissner/snippets." (message (kill-new (abbreviate-file-name filename))) (error "Couldn't find filename in current buffer"))) -(defmacro +hlissner-def-finder! (name dir) +(defmacro +def-finder! (name dir) "Define a pair of find-file and browse functions." `(progn - (defun ,(intern (format "+hlissner/find-in-%s" name)) () + (defun ,(intern (format "+find-in-%s" name)) () (interactive) (let ((default-directory ,dir) projectile-project-name @@ -96,11 +96,13 @@ private/hlissner/snippets." (let ((default-directory ,dir)) (call-interactively (command-remapping #'find-file)))))) -(+hlissner-def-finder! templates +file-templates-dir) -(+hlissner-def-finder! snippets +grfn-snippets-dir) -(+hlissner-def-finder! dotfiles (expand-file-name ".dotfiles" "~")) -(+hlissner-def-finder! doomd (expand-file-name ".doom.d" "~")) -(+hlissner-def-finder! notes +org-dir) +(+def-finder! templates +file-templates-dir) +(+def-finder! snippets +grfn-snippets-dir) +(+def-finder! dotfiles (expand-file-name ".dotfiles" "~")) +(+def-finder! doomd (expand-file-name ".doom.d" "~")) +(+def-finder! notes +org-dir) +(+def-finder! home-config (expand-file-name "code/system/home" "~")) +(+def-finder! system-config (expand-file-name "code/system/system" "~")) (defun +grfn/paxedit-kill (&optional n) (interactive "p") @@ -279,19 +281,21 @@ private/hlissner/snippets." :v "r" #'+eval:repl) (:desc "file" :prefix "f" - :desc "Find file" :n "." #'find-file - :desc "Sudo find file" :n ">" #'doom/sudo-find-file - :desc "Find file in project" :n "/" #'projectile-find-file - :desc "Find file from here" :n "?" #'counsel-file-jump - :desc "Find other file" :n "a" #'projectile-find-other-file - :desc "Open project editorconfig" :n "c" #'editorconfig-find-current-editorconfig - :desc "Find file in dotfiles" :n "d" #'+hlissner/find-in-dotfiles - :desc "Browse dotfiles" :n "D" #'+hlissner/browse-dotfiles - :desc "Find file in emacs.d" :n "e" #'+hlissner/find-in-doomd - :desc "Browse emacs.d" :n "E" #'+hlissner/browse-doomd - :desc "Recent files" :n "r" #'recentf-open-files - :desc "Recent project files" :n "R" #'projectile-recentf - :desc "Yank filename" :n "y" #'+hlissner/yank-buffer-filename) + :desc "Find file" :n "." #'find-file + :desc "Sudo find file" :n ">" #'doom/sudo-find-file + :desc "Find file in project" :n "/" #'projectile-find-file + :desc "Find file from here" :n "?" #'counsel-file-jump + :desc "Find other file" :n "a" #'projectile-find-other-file + :desc "Open project editorconfig" :n "c" #'editorconfig-find-current-editorconfig + :desc "Find file in dotfiles" :n "d" #'+find-in-dotfiles + :desc "Find file in system config" :n "s" #'+find-in-system-config + :desc "Find file in home config" :n "h" #'+find-in-home-config + :desc "Browse dotfiles" :n "D" #'+hlissner/browse-dotfiles + :desc "Find file in emacs.d" :n "e" #'+find-in-doomd + :desc "Browse emacs.d" :n "E" #'+hlissner/browse-doomd + :desc "Recent files" :n "r" #'recentf-open-files + :desc "Recent project files" :n "R" #'projectile-recentf + :desc "Yank filename" :n "y" #'+hlissner/yank-buffer-filename) (:desc "git" :prefix "g" :desc "Git status" :n "S" #'magit-status -- cgit 1.4.1 From cb85df13c8b14945c88c334de7198fdb553c1d8f Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:31:42 -0400 Subject: font changes for nixos --- config.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.el b/config.el index 287d097893..9e862ae687 100644 --- a/config.el +++ b/config.el @@ -8,10 +8,10 @@ user-full-name "Griffin Smith") (setq doom-font (font-spec :family "Meslo LGSDZ Nerd Font" :size 14) - doom-big-font (font-spec :family "Meslo LGSDZ Nerd Font" :size 19) + doom-big-font (font-spec :family "Meslo LGSDZ Nerd Font" :size 24) doom-big-font-increment 5 doom-variable-pitch-font (font-spec :family "DejaVu Sans") - doom-unicode-font (font-spec :family "Meslo LG S DZ")) + doom-unicode-font (font-spec :family "Meslo LGSDZ Nerd Font")) (after! rust ;; (require 'ein) -- cgit 1.4.1 From bd4bfbfacf1f2c4965c09372995f05997937d573 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:31:55 -0400 Subject: update to init for doom --- init.el | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/init.el b/init.el index 1dd0180f87..59e34b0bf8 100644 --- a/init.el +++ b/init.el @@ -59,8 +59,6 @@ ;;editorconfig ; let someone else argue about tabs vs spaces ;; ein ; tame Jupyter notebooks with emacs eval ; run code, run (also, repls) - flycheck ; tasing you for every semicolon you forget - flyspell ; tasing you for misspelling mispelling gist ; interacting with github gists (lookup ; helps you navigate your code and documentation +docsets) ; ...or in Dash docsets locally @@ -78,13 +76,17 @@ ;;wakatime ;;vterm ; another terminals in Emacs + :checkers + syntax ; tasing you for every semicolon you forget + spell ; tasing you for misspelling mispelling + :lang agda ; types of types of types of types... ;;assembly ; assembly for fun or debugging cc ; C/C++/Obj-C madness clojure ; java with a lisp ;;common-lisp ; if you've seen one lisp, you've seen them all - coq ; proofs-as-programs + ; coq ; proofs-as-programs ;;crystal ; ruby at the speed of c ;;csharp ; unity, .NET, and mono shenanigans data ; config/data formats @@ -110,11 +112,12 @@ nix ; I hereby declare "nix geht mehr!" ;;ocaml ; an objective camel (org ; organize your plain life in plain text + +dragndrop ; drag & drop files/images into org buffers +attach ; custom attachment system +babel ; running code in org +capture ; org-capture in and outside of Emacs +export ; Exporting org to whatever you want - +habit ; Keep track of your habits + ;; +habit ; Keep track of your habits +present ; Emacs for presentations +protocol) ; Support for org-protocol:// links ;;perl ; write code no one else can comprehend -- cgit 1.4.1 From dcff9be5aaf83990fc80ab23d532b1ead61170f9 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:32:07 -0400 Subject: org-babel-clojure --- org-config.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/org-config.el b/org-config.el index faf2a1bf42..4ffe7dbf33 100644 --- a/org-config.el +++ b/org-config.el @@ -4,8 +4,6 @@ (defun notes-file (f) (concat org-directory (if (string-prefix-p "/" f) "" "/") f)) -(require 'org-mu4e) - (setq org-directory (expand-file-name "~/notes") +org-dir (expand-file-name "~/notes") @@ -88,4 +86,6 @@ ("r" "Running jobs" todo "RUNNING") ("w" "@Work" tags-todo "@work") ("n" . "Next...") - ("np" "Next Sprint" tags-todo "next_sprint|sprint_planning"))) + ("np" "Next Sprint" tags-todo "next_sprint|sprint_planning")) + + org-babel-clojure-backend 'cider) -- cgit 1.4.1 From 2bc8919a241e0d65c547e5671e3909e1c85b347f Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:32:51 -0400 Subject: misc packages --- config.el | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++----------- packages.el | 16 +++++++++++- 2 files changed, 83 insertions(+), 16 deletions(-) diff --git a/config.el b/config.el index 9e862ae687..0c70b44204 100644 --- a/config.el +++ b/config.el @@ -900,28 +900,43 @@ (use-package! pyimport :after (python)) -(use-package! yapfify +(use-package! blacken :after (python) :init - (add-hook! python-mode #'yapf-mode)) - -(use-package! w3m + (add-hook #'python-mode-hook #'blacken-mode) :config - (setq browse-url-browser-function - `(("^https://app.clubhouse.io.*" . browse-url-firefox) - ("^https://github.com.*" . browse-url-firefox) - (".*" . browse-url-firefox)))) + (setq blacken-only-if-project-is-blackened t + blacken-allow-py36 t + blacken-line-length 100)) + +(after! python + (defun +python-setup () + (setq-local fill-column 100 + whitespace-line-column 100 + flycheck-disabled-checkers '(python-flake8) + flycheck-checker 'python-pylint)) + + (add-hook #'python-mode-hook #'+python-setup) + (add-hook #'python-mode-hook #'lsp) + (remove-hook #'python-mode-hook #'pipenv-mode)) + +; (use-package! w3m +; :config +; (setq browse-url-browser-function +; `(("^https://app.clubhouse.io.*" . browse-url-firefox) +; ("^https://github.com.*" . browse-url-firefox) +; (".*" . browse-url-firefox)))) (use-package! ob-http :config (add-to-list 'org-babel-load-languages '(http . t))) -(use-package! ob-ipython - :after (pyimport) - :config - (add-to-list 'org-babel-load-languages '(ipython . t)) - (setq ob-ipython-command - "/home/griffin/code/urb/ciml-video-classifier/bin/jupyter")) +;; (use-package! ob-ipython +;; :after (pyimport) +;; :config +;; (add-to-list 'org-babel-load-languages '(ipython . t)) +;; (setq ob-ipython-command + ;; "/home/griffin/code/urb/ciml-video-classifier/bin/jupyter")) (use-package! counsel-spotify) @@ -1045,7 +1060,8 @@ (use-package! string-inflection) (after! anaconda-mode - (set-company-backend! 'anaconda-mode #'company-yasnippet)) + ;; (set-company-backend! 'anaconda-mode #'company-yasnippet) + ) ;; (add-hook! python-mode ;; (capf)) @@ -1213,3 +1229,40 @@ SCHEDULED: <%s>" (use-package! metal-mercury-mode) (use-package! flycheck-mercury :after (metal-mercury-mode flycheck-mercury)) + +(use-package! direnv + :config (direnv-mode)) + +(after! notmuch + (setq notmuch-saved-searches + '((:name "inbox" :query "tag:inbox tag:important not tag:trash" :key "i") + (:name "flagged" :query "tag:flagged" :key "f") + (:name "sent" :query "tag:sent" :key "s") + (:name "drafts" :query "tag:draft" :key "d") + + (:name "work" :query "tag:inbox and tag:important and path:work/**" + :key "w") + (:name "personal" :query "tag:inbox and tag:important and path:personal/**" + :key "p")) + message-send-mail-function 'message-send-mail-with-sendmail) + + (add-hook! notmuch-message-mode-hook + #'notmuch-company-setup)) + +(after! erc + ;; (setq erc-autojoin-channels-alist '(("freenode.net" "#nixos" "#haskell" "##tvl"))) + ) + +(defun evil-disable-insert-state-bindings () + evil-disable-insert-state-bindings) + +;; (use-package! terraform-mode) +;; (use-package! company-terraform +;; :after terraform-mode +;; :config (company-terraform-init)) + +(use-package! znc + :config + (setq znc-servers + '(("znc.gws.fyi" 5000 t + ((freenode "glittershark" "Ompquy")))))) diff --git a/packages.el b/packages.el index 41e8e14904..5a29c60ae9 100644 --- a/packages.el +++ b/packages.el @@ -107,7 +107,9 @@ ;;; Python (package! pyimport) -(package! yapfify) +;; (package! yapfify) +(package! blacken) + ;;; Desktop interaction (package! counsel-spotify) @@ -127,6 +129,10 @@ (package! nix-update :recipe (:host github :repo "glittershark/nix-update-el")) +(package! direnv) + +;;; Email +(package! mu4e) ;;; Sequence diagrams (package! wsd-mode @@ -138,3 +144,11 @@ :recipe (:host github :repo "ahungry/metal-mercury-mode")) (package! flycheck-mercury) + +(package! terraform-mode) +(package! company-terraform) + +;;; +(package! znc + :recipe (:host github + :repo "sshirokov/ZNC.el")) -- cgit 1.4.1 From 67d95c58c09b67457a51ad780f9c7b5499036862 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:33:04 -0400 Subject: no more mu --- config.el | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/config.el b/config.el index 0c70b44204..12eca00ae7 100644 --- a/config.el +++ b/config.el @@ -1163,13 +1163,6 @@ SCHEDULED: <%s>" (use-package! github-review :after forge) -(after! mu4e - (setq sendmail-program "/usr/bin/msmtp" - send-mail-function #'smtpmail-send-it - message-sendmail-f-is-evil t - message-sendmail-extra-arguments '("--read-envelope-from") - message-send-mail-function #'message-send-mail-with-sendmail)) - (defun grfn/org-add-db-connection-params () (interactive) (ivy-read @@ -1211,16 +1204,38 @@ SCHEDULED: <%s>" ) ) -(after! mu4e - (setq mu4e-contexts - `(,(make-mu4e-context - :name "work" - :vars - '()) - ,(make-mu4e-context - :name "personal" - :vars - '())))) +;; (use-package! mu4e +;; :config +;; (setq mu4e-contexts +;; `(,(make-mu4e-context +;; :name "work" +;; :match-func +;; (lambda (msg) +;; (when msg +;; (string-match-p "^/work" +;; (mu4e-message-field msg :maildir)))) +;; :vars +;; '((user-mail-address . "griffin@urbint.com"))) +;; ,(make-mu4e-context +;; :name "personal" +;; :match-func +;; (lambda (msg) +;; (when msg +;; (string-match-p "^/personal" +;; (mu4e-message-field msg :maildir)))) +;; :vars +;; '((user-mail-address . "root@gws.fyi")))) +;; mu4e-maildir (expand-file-name "mail" "~") +;; sendmail-program "msmtp" +;; send-mail-function #'smtpmail-send-it +;; message-sendmail-f-is-evil t +;; message-sendmail-extra-arguments '("--read-envelope-from") +;; message-send-mail-function #'message-send-mail-with-sendmail) + +;; (set-email-account! +;; "work" +;; '((user-mail-address . "griffin@urbint.com") +;; (smtmpmail-smtp-user . "griffin@urbint.com")))) (solaire-global-mode -1) -- cgit 1.4.1 From 599af30849761e5dc532d13015f75a7d80fdc39b Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:33:12 -0400 Subject: drop comment --- config.el | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/config.el b/config.el index 12eca00ae7..3fab956818 100644 --- a/config.el +++ b/config.el @@ -1135,25 +1135,6 @@ SCHEDULED: <%s>" (insert text)) (org-align-tags 't))) -(comment - (require 'ghub) - - (intern (substring (symbol-name :foo) 1)) - - ((data (reviewRequests - (issueCount . 2) - (nodes ((url . "https://github.com/urbint/grid/pull/819") - (number . 819) - (title . "Hector.blanco/ch11498/take storagebucket out of crossbores schema") - (repository (name . "grid") - (owner (login . "urbint")))) - ((url . "https://github.com/urbint/ml/pull/32") - (number . 32) - (title . "Quality scoring") - (repository (name . "ml") - (owner (login . "urbint")))))))) - ) - (defun grfn/num-inbox-items () (length (org-elements-agenda-match "inbox" t))) -- cgit 1.4.1 From 5ff3dad0e53bd5cf17752b420ca37b8ba09431f2 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:33:27 -0400 Subject: company-lsp --- config.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.el b/config.el index 3fab956818..14ea16faf2 100644 --- a/config.el +++ b/config.el @@ -671,7 +671,7 @@ (use-package! company-lsp :after (lsp-mode lsp-ui) :config - ;; (setq company-backends '(company-lsp)) + (add-to-list #'company-backends #'company-lsp) (setq company-lsp-async t)) (use-package! lsp-treemacs -- cgit 1.4.1 From 27f32372798d3727c277c6487a8789e72e929100 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:33:34 -0400 Subject: fix alembic migration extraction --- config.el | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/config.el b/config.el index 14ea16faf2..d5a2f2545f 100644 --- a/config.el +++ b/config.el @@ -997,11 +997,12 @@ (concat alembic-command " " args))) (defun +grfn/extract-alembic-migration-name (output) - (string-match (rx (0+ anything) "Generating " - (group (one-or-more (not (syntax whitespace)))) - " ... done" - (0+ anything)) - output) + (unless (string-match (rx (0+ anything) "Generating " + (group (one-or-more (not (syntax whitespace)))) + " ..." (one-or-more (syntax whitespace)) "done" + (0+ anything)) + output) + (user-error "Error: %s" output)) (match-string-no-properties 1 output)) (defun -run-alembic (args) -- cgit 1.4.1 From 12597283407dda0b641a475ff5326e13c64a80dc Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:33:41 -0400 Subject: don't enable lsp-mode everywhere --- config.el | 1 - 1 file changed, 1 deletion(-) diff --git a/config.el b/config.el index d5a2f2545f..503f8d10ba 100644 --- a/config.el +++ b/config.el @@ -644,7 +644,6 @@ (use-package! lsp-mode :after (:any haskell-mode) :config - (lsp-mode) (setq lsp-response-timeout 60) :hook (haskell-mode . lsp-mode)) -- cgit 1.4.1 From 7374d02180b0f05bbc6e7bb81da4bfeb37db6a23 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:33:50 -0400 Subject: no flow --- config.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.el b/config.el index 503f8d10ba..e9b2eb046e 100644 --- a/config.el +++ b/config.el @@ -485,9 +485,9 @@ (remove-hook 'js2-mode-hook 'tide-setup t) -(require 'company-flow) -(eval-after-load 'company - (lambda () (add-to-list 'company-backends 'company-flow))) +;; (require 'company-flow) +;; (eval-after-load 'company +;; (lambda () (add-to-list 'company-backends 'company-flow))) (defun flow/set-flow-executable () (interactive) (let* ((os (pcase system-type -- cgit 1.4.1 From 06eaf0ad9693d187466287809552f5fe0e4aba8c Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:33:57 -0400 Subject: vowels are for dweebs --- config.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.el b/config.el index e9b2eb046e..343db6d349 100644 --- a/config.el +++ b/config.el @@ -56,10 +56,10 @@ (flycheck-mode)) -(setq exec-path (append exec-path '("/Users/griffin/.cargo/bin"))) +(setq exec-path (append exec-path '("/home/grfn/.cargo/bin"))) (after! cargo - (setq cargo-process--custom-path-to-bin "/Users/griffin/.cargo/bin/cargo")) + (setq cargo-process--custom-path-to-bin "/home/grfn/.cargo/bin/cargo")) (setq +solarized-s-base03 "#002b36" +solarized-s-base02 "#073642" @@ -277,7 +277,7 @@ (setq doom-modeline-height 12) -(load "/home/griffin/code/org-clubhouse/org-clubhouse.el") +(load "/home/grfn/code/org-clubhouse/org-clubhouse.el") (use-package! org-clubhouse :config (setq org-clubhouse-state-alist -- cgit 1.4.1 From a6078d2e33dd6cbad21d22c30bff8e9ba43eb82d Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:34:08 -0400 Subject: Doom modeline config those icons are gross --- config.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config.el b/config.el index 343db6d349..f30e07a105 100644 --- a/config.el +++ b/config.el @@ -244,7 +244,9 @@ ;; Global config ;; -(setq doom-modeline-buffer-file-name-style 'relative-to-project) +(setq doom-modeline-buffer-file-name-style 'relative-to-project + doom-modeline-modal-icon nil + doom-modeline-github t) ;; ;; Modules -- cgit 1.4.1 From 0e3204bd22373dd74e5d65c5247b5d534a8560f7 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:34:24 -0400 Subject: fix variable warning definition order! --- config.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.el b/config.el index f30e07a105..a2f63d3627 100644 --- a/config.el +++ b/config.el @@ -104,6 +104,9 @@ +solarized-green-d "#546E00" +solarized-green-l "#B4C342") +(defcustom theme-overrides nil + "Association list of override faces to set for different custom themes.") + (defadvice load-theme (after theme-set-overrides activate) (dolist (theme-settings theme-overrides) (let ((theme (car theme-settings)) @@ -113,9 +116,6 @@ (dolist (face faces) (custom-theme-set-faces theme face))))))) -(defcustom theme-overrides nil - "Association list of override faces to set for different custom themes.") - (defun alist-set (alist-symbol key value) "Set VALUE of a KEY in ALIST-SYMBOL." (set alist-symbol (cons (list key value) (assq-delete-all key (eval alist-symbol))))) -- cgit 1.4.1 From 2b9235bd59e42b508cf881795044ee5d59022689 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:34:43 -0400 Subject: some irc --- config.el | 12 ++++++- irc.el | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 irc.el diff --git a/config.el b/config.el index a2f63d3627..734ea7f996 100644 --- a/config.el +++ b/config.el @@ -22,8 +22,18 @@ (load! "utils") (load! "company-sql") (load! "org-query") -(load! "nix-yapf-mode") +;; (load! "nix-yapf-mode") (load! "show-matching-paren") +(load! "irc") + +(require 's) + +;; (add-to-list 'load-path +;; (concat +;; (s-trim +;; (shell-command-to-string +;; "nix-build --no-link '' -A mu")) +;; "/share/emacs/site-lisp/mu4e")) ; (defconst rust-src-path ; (-> "/Users/griffin/.cargo/bin/rustc --print sysroot" diff --git a/irc.el b/irc.el new file mode 100644 index 0000000000..1d56d787c4 --- /dev/null +++ b/irc.el @@ -0,0 +1,113 @@ +;;; ~/.doom.d/irc.el + +(require 'erc) +(require 'alert) + +(defun irc-connect () + (interactive) + (let ((pw (let* ((irc-pw (first + (auth-source-search :host "znc.gws.fyi" + :max 1))) + (secret (plist-get irc-pw :secret))) + (if (functionp secret) (funcall secret)))) + (gnutls-verify-error nil)) + (erc-tls :server "znc.gws.fyi" + :port 5000 + :nick "glittershark" + :password (concat "glittershark/freenode:" pw)))) + + +(defgroup erc-alert nil + "Alert me using alert.el for important ERC messages" + :group 'erc) + +(defcustom erc-noise-regexp + "\\(Logging in:\\|Signing off\\|You're now away\\|Welcome back\\)" + "This regexp matches unwanted noise." + :type 'regexp + :group 'erc) + +(setq tvl-enabled? t) + +(defun erc-alert-important-p (info) + (setq last-info info) + (let ((message (plist-get info :message)) + (erc-message (-> info (plist-get :data) (plist-get :message))) + (erc-channel (-> info (plist-get :data) (plist-get :channel)))) + (and erc-message + (not (or (string-match "^\\** *Users on #" message) + (string-match erc-noise-regexp + message))) + (or (and tvl-enabled? + (string-equal erc-channel "##tvl")) + (string-match "glittershark" message))))) + +(comment + last-info + erc-noise-regexp + (setq tvl-enabled? nil) + ) + +(defun my-erc-hook (&optional match-type nick message) + "Shows a notification, when user's nick was mentioned. +If the buffer is currently not visible, makes it sticky." + (setq last-message message) + (if (or (null match-type) (not (eq match-type 'fool))) + (let (alert-log-messages) + (alert (or message (buffer-string)) + :severity (if (string-match "glittershark" (or message "")) + 'high 'low) + :title (or nick (buffer-name)) + :data `(:message ,(or message (buffer-string)) + :channel ,(or nick (buffer-name))))))) + +(add-hook 'erc-text-matched-hook 'my-erc-hook) +(add-hook 'erc-insert-modify-hook 'my-erc-hook) + +(defun my-erc-define-alerts (&rest ignore) + ;; Unless the user has recently typed in the ERC buffer, highlight the fringe + (alert-add-rule + :status '(buried visible idle) + :severity '(moderate high urgent) + :mode 'erc-mode + :predicate + #'(lambda (info) + (and (not (eq (current-buffer) (plist-get info :buffer))) + (string-match "glittershark:" (plist-get info :message)))) + :persistent + #'(lambda (info) + ;; If the buffer is buried, or the user has been idle for + ;; `alert-reveal-idle-time' seconds, make this alert + ;; persistent. Normally, alerts become persistent after + ;; `alert-persist-idle-time' seconds. + (memq (plist-get info :status) '(buried idle))) + :style 'message + :continue t) + + (alert-add-rule + :status 'buried + :mode 'erc-mode + :predicate #'erc-alert-important-p + :style 'libnotify + :append t) + + (alert-add-rule + :status 'buried + :mode 'erc-mode + :predicate #'erc-alert-important-p + :style 'message + :append t) + + (alert-add-rule + :mode 'erc-mode + :predicate #'erc-alert-important-p + :style 'log + :append t) + + (alert-add-rule :mode 'erc-mode :style 'ignore :append t)) + +(add-hook 'erc-connect-pre-hook 'my-erc-define-alerts) + +(comment + (my-erc-define-alerts) + ) -- cgit 1.4.1 From 91e19984b3a8ab5eb35a5f7612cc058d7c8af470 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 18 May 2020 11:35:21 -0400 Subject: misc bindings --- +bindings.el | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/+bindings.el b/+bindings.el index 475a3c7861..db1c5e6c7a 100644 --- a/+bindings.el +++ b/+bindings.el @@ -343,7 +343,7 @@ private/hlissner/snippets." (:desc "notes" :prefix "n" :desc "Agenda" :n "a" #'org-agenda - :desc "Find file in notes" :n "n" #'+hlissner/find-in-notes + :desc "Find file in notes" :n "n" #'+find-in-notes :desc "Store link" :n "l" #'org-store-link :desc "Browse notes" :n "N" #'+hlissner/browse-notes :desc "Org capture" :n "x" #'+org-capture/open @@ -365,12 +365,14 @@ private/hlissner/snippets." :desc "Slack Group" :n "g" #'slack-group-select :desc "Slack Unreads" :n "u" #'slack-select-unread-rooms - :desc "Email" :n "m" #'mu4e + :desc "Email" :n "m" #'notmuch-jump-search + + (:desc "ERC" :prefix "e" + :desc "Channel" :n "c" #'erc-switch-to-buffer) ;; applications :desc "APP: elfeed" :n "E" #'=rss :desc "APP: twitter" :n "T" #'=twitter - :desc "APP: regex" :n "X" #'=regex (:desc "spotify" :prefix "s" :desc "Search track" :n "t" #'counsel-spotify-search-track @@ -418,7 +420,7 @@ private/hlissner/snippets." :desc "New snippet" :n "n" #'yas-new-snippet :desc "Insert snippet" :nv "i" #'yas-insert-snippet :desc "Find snippet for mode" :n "s" #'yas-visit-snippet-file - :desc "Find snippet" :n "S" #'+hlissner/find-in-snippets) + :desc "Find snippet" :n "S" #'+find-in-snippets) (:desc "toggle" :prefix "t" :desc "Flyspell" :n "s" #'flyspell-mode @@ -1212,9 +1214,21 @@ If invoked with a prefix ARG eval the expression after inserting it" (defun grfn/run-clj-or-cljs-test () (interactive) + (message "Running tests...") (cl-case (cider-repl-type-for-buffer) - ("cljs" (cider-interactive-eval "(with-out-string (cljs.test/run-tests))")) - ("clj" (cider-test-run-ns-tests)))) + ('cljs + (cider-interactive-eval + "(with-out-str (cljs.test/run-tests))" + (nrepl-make-response-handler + (current-buffer) + (lambda (_ value) + (with-output-to-temp-buffer "*cljs-test-results*" + (print + (->> value + (s-replace "\"" "") + (s-replace "\\n" "\n"))))) + nil nil nil))) + ('clj (cider-test-run-ns-tests)))) (defun cider-copy-last-result () (interactive) @@ -1329,7 +1343,8 @@ If invoked with a prefix ARG eval the expression after inserting it" :n "g K" 'cider-grimoire :n "g d" 'cider-find-dwim :n "C-w ]" 'cider-find-dwim-other-window - :n "g RET" 'cider-test-run-ns-tests + ;; :n "g RET" 'cider-test-run-ns-tests + :n "g RET" 'grfn/run-clj-or-cljs-test "C-c C-r r" 'cljr-add-require-to-ns "C-c C-r i" 'cljr-add-import-to-ns @@ -1364,9 +1379,8 @@ If invoked with a prefix ARG eval the expression after inserting it" :n "g RET" #'org-capture-finalize :n "g \\" #'org-captue-refile)) - (:after lsp - (:map lsp-mode-map - :n "K" #'lsp-describe-thing-at-point - :n "g r" #'lsp-rename - (:localleader - :n "a" #'lsp-execute-code-action)))) + (:map lsp-mode-map + :n "K" #'lsp-describe-thing-at-point + :n "g r" #'lsp-rename + (:localleader + :n "a" #'lsp-execute-code-action))) -- cgit 1.4.1 From 712f997de1378b23466dd33302f8e82a2b901e97 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Tue, 26 May 2020 10:22:37 -0400 Subject: Binding to make org hls for requested changes --- config.el | 68 +---------------------------------------- github-org.el | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 67 deletions(-) create mode 100644 github-org.el diff --git a/config.el b/config.el index 734ea7f996..1ba55b2ad3 100644 --- a/config.el +++ b/config.el @@ -25,6 +25,7 @@ ;; (load! "nix-yapf-mode") (load! "show-matching-paren") (load! "irc") +(load! "github-org") (require 's) @@ -1080,73 +1081,6 @@ (cl-defstruct pull-request url number title author repository) -(defun grfn/alist->plist (alist) - (->> alist - (-mapcat (lambda (pair) - (list (intern (concat ":" (symbol-name (car pair)))) - (cdr pair)))))) - -(defun grfn/review-requests () - (let ((resp (ghub-graphql "query reviewRequests { - reviewRequests: search( - type:ISSUE, - query: \"is:open is:pr review-requested:glittershark archived:false\", - first: 100 - ) { - issueCount - nodes { - ... on PullRequest { - url - number - title - author { - login - ... on User { name } - } - repository { - name - owner { login } - } - } - } - } - }"))) - (->> resp - (alist-get 'data) - (alist-get 'reviewRequests) - (alist-get 'nodes) - (-map - (lambda (pr) - (apply - #'make-pull-request - (grfn/alist->plist pr))))))) - -(defun grfn/pr->org-headline (level pr) - (check-type level integer) - (check-type pr pull-request) - (format "%s TODO Review %s's PR on %s/%s: %s :pr: -SCHEDULED: <%s>" - (make-string level ?*) - (->> pr (pull-request-author) (alist-get 'name)) - (->> pr (pull-request-repository) - (alist-get 'owner) - (alist-get 'login)) - (->> pr (pull-request-repository) (alist-get 'name)) - (org-make-link-string - (pull-request-url pr) - (pull-request-title pr)) - (format-time-string "%Y-%m-%d %a"))) - -(require 'ghub) -(defun grfn/org-headlines-from-review-requests (level) - "Create org-mode headlines at LEVEL from all review-requested PRs on Github" - (interactive "*nLevel: ") - (let* ((prs (grfn/review-requests)) - (text (mapconcat (apply-partially #'grfn/pr->org-headline level) prs "\n"))) - (save-mark-and-excursion - (insert text)) - (org-align-tags 't))) - (defun grfn/num-inbox-items () (length (org-elements-agenda-match "inbox" t))) diff --git a/github-org.el b/github-org.el new file mode 100644 index 0000000000..942ed2d629 --- /dev/null +++ b/github-org.el @@ -0,0 +1,98 @@ +;;; ~/.doom.d/github-org.el -*- lexical-binding: t; -*- + +(require 'ghub) + +(defun grfn/alist->plist (alist) + (->> alist + (-mapcat (lambda (pair) + (list (intern (concat ":" (symbol-name (car pair)))) + (cdr pair)))))) + +;;; + +(cl-defstruct pull-request url number title author repository) + +(defun grfn/query-pulls (query) + (let ((resp (ghub-graphql "query reviewRequests($query: String!) { + reviewRequests: search( + type:ISSUE, + query: $query, + first: 100 + ) { + issueCount + nodes { + ... on PullRequest { + url + number + title + author { + login + ... on User { name } + } + repository { + name + owner { login } + } + } + } + } + }" `((query . ,query))))) + (->> resp + (alist-get 'data) + (alist-get 'reviewRequests) + (alist-get 'nodes) + (-map + (lambda (pr) + (apply + #'make-pull-request + (grfn/alist->plist pr))))))) + +(defun grfn/requested-changes ()) + +(defun grfn/pull-request->org-headline (format-string level pr) + (check-type format-string string) + (check-type level integer) + (check-type pr pull-request) + (s-format (concat (make-string level ?*) " " format-string) + #'aget + `((author . ,(->> pr (pull-request-author) (alist-get 'name))) + (owner . ,(->> pr (pull-request-repository) + (alist-get 'owner) + (alist-get 'login))) + (repo . ,(->> pr (pull-request-repository) (alist-get 'name))) + (pr-link . ,(org-make-link-string + (pull-request-url pr) + (pull-request-title pr))) + (today . ,(format-time-string "%Y-%m-%d %a"))))) + +(defun grfn/org-headlines-from-review-requests (level) + "Create org-mode headlines at LEVEL from all review-requested PRs on Github" + (interactive "*nLevel: ") + (let* ((prs (grfn/query-pulls + "is:open is:pr review-requested:glittershark archived:false")) + (text (mapconcat + (apply-partially + #'grfn/pull-request->org-headline + "TODO Review ${author}'s PR on ${owner}/${repo}: ${pr-link} :pr: +SCHEDULED: <${today}>" + level) prs "\n"))) + (save-mark-and-excursion + (insert text)) + (org-align-tags 't))) + +(defun grfn/org-headlines-from-requested-changes (level) + "Create org-mode headlines at LEVEL from all PRs with changes requested + on Github" + (interactive "*nLevel: ") + (let* ((prs (grfn/query-pulls + (concat "is:pr is:open author:glittershark archived:false " + "sort:updated-desc review:changes-requested"))) + (text (mapconcat + (apply-partially + #'grfn/pull-request->org-headline + "TODO Address review comments on ${pr-link} :pr: +SCHEDULED: <${today}>" + level) prs "\n"))) + (save-mark-and-excursion + (insert text)) + (org-align-tags 't))) -- cgit 1.4.1 From 723ff591ee952fb94fd50997160b90b5219e4b74 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Tue, 26 May 2020 10:28:16 -0400 Subject: Pre-format exec snippet --- snippets/python-mode/op.get_bind.execute | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/snippets/python-mode/op.get_bind.execute b/snippets/python-mode/op.get_bind.execute index 5f46464ac9..aba801c6ba 100644 --- a/snippets/python-mode/op.get_bind.execute +++ b/snippets/python-mode/op.get_bind.execute @@ -1,6 +1,7 @@ # key: exec # name: op.get_bind.execute # -- -op.get_bind().execute(""" +op.get_bind().execute( + """ `(progn (sqlup-mode) "")`$1 -""") + """) -- cgit 1.4.1 From 77f6ed22065e026be826f978905097742dbb3fc4 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Tue, 26 May 2020 10:28:24 -0400 Subject: Fix run-tests snippet cider-test-run-ns-tests needs to be called interactively --- +bindings.el | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/+bindings.el b/+bindings.el index db1c5e6c7a..9596d485f2 100644 --- a/+bindings.el +++ b/+bindings.el @@ -1228,7 +1228,10 @@ If invoked with a prefix ARG eval the expression after inserting it" (s-replace "\"" "") (s-replace "\\n" "\n"))))) nil nil nil))) - ('clj (cider-test-run-ns-tests)))) + ('clj + (funcall-interactively + #'cider-test-run-ns-tests + nil)))) (defun cider-copy-last-result () (interactive) -- cgit 1.4.1 From 699da9cebdeefc2fdba47dbe98fa95752d6472c1 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Tue, 26 May 2020 10:29:02 -0400 Subject: Drop nix-yapf-mode we're using black now --- config.el | 1 - nix-yapf-mode.el | 21 --------------------- 2 files changed, 22 deletions(-) delete mode 100644 nix-yapf-mode.el diff --git a/config.el b/config.el index 1ba55b2ad3..5dfcbb5cd8 100644 --- a/config.el +++ b/config.el @@ -22,7 +22,6 @@ (load! "utils") (load! "company-sql") (load! "org-query") -;; (load! "nix-yapf-mode") (load! "show-matching-paren") (load! "irc") (load! "github-org") diff --git a/nix-yapf-mode.el b/nix-yapf-mode.el deleted file mode 100644 index 9dba47bd36..0000000000 --- a/nix-yapf-mode.el +++ /dev/null @@ -1,21 +0,0 @@ -;;; ~/.doom.d/nix-yapf-mode.el -*- lexical-binding: t; -*- - - -(defun +grfn/yapfify-call-bin (input-buffer output-buffer start-line end-line) - (with-current-buffer input-buffer - (call-process-region - (point-min) - (point-max) - "nix-shell" - nil - (list output-buffer nil) - nil - "/home/griffin/code/urb/grid/yapf.nix" - "--run" - (concat - "yapf -l " - (number-to-string start-line) - "-" - (number-to-string end-line))))) - -(advice-add #'yapfify-call-bin :override #'+grfn/yapfify-call-bin) -- cgit 1.4.1 From 9a430d5844c5ad3799322dc13380c90ab3f84462 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Wed, 27 May 2020 10:17:14 -0400 Subject: make insert-src-block handle #+NAME:d blocks the name of a src block is part of the org-element, so need to go down a line if it's present --- +bindings.el | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/+bindings.el b/+bindings.el index 9596d485f2..e2dec2a3ad 100644 --- a/+bindings.el +++ b/+bindings.el @@ -1253,7 +1253,11 @@ If invoked with a prefix ARG eval the expression after inserting it" (src-block-head (save-excursion (goto-char (org-element-property :begin current-src-block)) - (thing-at-point 'line t))) + (let ((line (thing-at-point 'line t))) + (if (not (s-starts-with? "#+NAME:" (s-trim line))) + line + (forward-line) + (thing-at-point 'line t))))) (point-to-insert (if-let (results-loc (org-babel-where-is-src-block-result)) (save-excursion -- cgit 1.4.1 From b9a6e4b2b275f7346515f4a9fbee8eff03cf4339 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Wed, 3 Jun 2020 16:29:50 -0400 Subject: don't do task blocking get out my way, org --- org-config.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/org-config.el b/org-config.el index 4ffe7dbf33..2624cf4aad 100644 --- a/org-config.el +++ b/org-config.el @@ -88,4 +88,7 @@ ("n" . "Next...") ("np" "Next Sprint" tags-todo "next_sprint|sprint_planning")) + org-agenda-dim-blocked-tasks nil + org-enforce-todo-dependencies nil + org-babel-clojure-backend 'cider) -- cgit 1.4.1 From fa149d1164e36a0d576fafb8e6d245ec5b76cfc2 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 15 Jun 2020 11:56:12 -0400 Subject: sync gcal events -> org-mode file --- config.el | 1 + org-gcal.el | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ packages.el | 1 + 3 files changed, 174 insertions(+) create mode 100644 org-gcal.el diff --git a/config.el b/config.el index 5dfcbb5cd8..f01a8f9f0c 100644 --- a/config.el +++ b/config.el @@ -25,6 +25,7 @@ (load! "show-matching-paren") (load! "irc") (load! "github-org") +(load! "org-gcal") (require 's) diff --git a/org-gcal.el b/org-gcal.el new file mode 100644 index 0000000000..d31e705269 --- /dev/null +++ b/org-gcal.el @@ -0,0 +1,172 @@ +;;; ~/.doom.d/org-gcal.el -*- lexical-binding: t; -*- + +(require 'aio) +(require 'parse-time) + +(setq-local lexical-binding t) +(setq plstore-cache-passphrase-for-symmetric-encryption t) + +(defvar gcal-client-id) +(defvar gcal-client-secret) + +(defvar google-calendar-readonly-scope + "https://www.googleapis.com/auth/calendar.readonly") + +(defvar events-file "/home/grfn/notes/events.org") + +(defun google--get-token (scope client-id client-secret) + (oauth2-auth-and-store + "https://accounts.google.com/o/oauth2/v2/auth" + "https://oauth2.googleapis.com/token" + scope + client-id + client-secret)) + +(cl-defun google--request (url &key method params scope) + (let ((p (aio-promise)) + (auth-token (google--get-token scope gcal-client-id gcal-client-secret))) + (oauth2-url-retrieve + auth-token + url + (lambda (&rest _) + (goto-char (point-min)) + (re-search-forward "^$") + (let ((resp (json-parse-buffer :object-type 'alist))) + (aio-resolve p (lambda () resp)))) + nil + (or method "GET") + params) + p)) + +(cl-defun list-events (&key min-time max-time) + (google--request + (concat + "https://www.googleapis.com/calendar/v3/calendars/griffin@urbint.com/events" + "?timeMin=" (format-time-string "%Y-%m-%dT%T%z" min-time) + "&timeMax=" (format-time-string "%Y-%m-%dT%T%z" max-time)) + :scope google-calendar-readonly-scope)) + + +(defun last-week-events () + (list-events :min-time (time-subtract + (current-time) + (seconds-to-time + (* 60 60 24 7))) + :max-time (current-time))) + +(defun next-week-events () + (list-events :min-time (current-time) + :max-time (time-add + (current-time) + (seconds-to-time + (* 60 60 24 7))))) + +(defun attending-event? (event) + (let* ((attendees (append (alist-get 'attendees event) nil)) + (self (--find (alist-get 'self it) attendees))) + (equal "accepted" (alist-get 'responseStatus self)))) + +(defun event->org-headline (event level) + (cl-flet ((make-time + (key) + (when-let ((raw-time (->> event (alist-get key) (alist-get 'dateTime)))) + (format-time-string + (org-time-stamp-format t) + (parse-iso8601-time-string raw-time))))) + (if-let ((start-time (make-time 'start)) + (end-time (make-time 'end))) + (s-format + "${headline} [[${htmlLink}][${summary}]] :event: +${startTime}--${endTime} +:PROPERTIES: +:LOCATION: ${location} +:EVENT: ${htmlLink} +:END: + +${description}" + (function + (lambda (k m) + (or (alist-get (intern k) m) + (format "key not found: %s" k)))) + (append + event + `((headline . ,(make-string level ?*)) + (startTime . ,start-time) + (endTime . ,end-time)))) + ""))) + +(defun write-events (events) + (with-current-buffer (find-file-noselect events-file) + (save-mark-and-excursion + (save-restriction + (widen) + (erase-buffer) + (goto-char (point-min)) + (insert "#+TITLE: Events") + (newline) (newline) + (prog1 + (loop for event in (append events nil) + when (attending-event? event) + do + (insert (event->org-headline event 1)) + (newline) + sum 1) + (org-align-tags t)))))) + +(defun +grfn/sync-events () + (interactive) + (let* ((events (alist-get 'items (aio-wait-for (next-week-events)))) + (num-written (write-events events))) + (message "Successfully wrote %d events" num-written))) + +(comment + ((kind . "calendar#event") + (etag . "\"3174776941020000\"") + (id . "SNIP") + (status . "confirmed") + (htmlLink . "https://www.google.com/calendar/event?eid=SNIP") + (created . "2020-04-01T13:30:09.000Z") + (updated . "2020-04-20T13:14:30.510Z") + (summary . "SNIP") + (description . "SNIP") + (location . "SNIP") + (creator + (email . "griffin@urbint.com") + (self . t)) + (organizer + (email . "griffin@urbint.com") + (self . t)) + (start + (dateTime . "2020-04-01T12:00:00-04:00") + (timeZone . "America/New_York")) + (end + (dateTime . "2020-04-01T12:30:00-04:00") + (timeZone . "America/New_York")) + (recurrence . + ["RRULE:FREQ=WEEKLY;UNTIL=20200408T035959Z;BYDAY=WE"]) + (iCalUID . "SNIP") + (sequence . 0) + (attendees . + [((email . "griffin@urbint.com") + (organizer . t) + (self . t) + (responseStatus . "accepted")) + ((email . "SNIP") + (displayName . "SNIP") + (responseStatus . "needsAction"))]) + (extendedProperties + (private + (origRecurringId . "309q48kc1dihsvbi13pnlimb5a")) + (shared + (origRecurringId . "309q48kc1dihsvbi13pnlimb5a"))) + (reminders + (useDefault . t))) + + (require 'icalendar) + + (icalendar--convert-recurring-to-diary + nil + "RRULE:FREQ=WEEKLY;UNTIL=20200408T035959Z;BYDAY=WE" + ) + + ) diff --git a/packages.el b/packages.el index 5a29c60ae9..63a753eec4 100644 --- a/packages.el +++ b/packages.el @@ -56,6 +56,7 @@ (package! request) (package! predd :recipe (:host github :repo "skeeto/predd")) +(package! aio) ;; Haskell (package! lsp-haskell) -- cgit 1.4.1 From 69ee53bffaf145eb86dd39a6cdc0ae4d9d3de45c Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 15 Jun 2020 11:56:45 -0400 Subject: projectile+grid integration --- config.el | 1 + grid.el | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 grid.el diff --git a/config.el b/config.el index f01a8f9f0c..09d80b2acc 100644 --- a/config.el +++ b/config.el @@ -26,6 +26,7 @@ (load! "irc") (load! "github-org") (load! "org-gcal") +(load! "grid") (require 's) diff --git a/grid.el b/grid.el new file mode 100644 index 0000000000..31c69097c6 --- /dev/null +++ b/grid.el @@ -0,0 +1,110 @@ +;;; ~/.doom.d/grid.el -*- lexical-binding: t; -*- + +(require 's) + +(defun grfn/all-match-groups (s) + (loop for n from 1 + for x = (match-string n s) + while x + collect x)) + +(defun projectile-grid-ff (path &optional ask) + "Call `find-file' function on PATH when it is not nil and the file exists. +If file does not exist and ASK in not nil it will ask user to proceed." + (if (or (and path (file-exists-p path)) + (and ask (yes-or-no-p + (s-lex-format + "File does not exists. Create a new buffer ${path} ?")))) + (find-file path))) + +(defun projectile-grid-goto-file (filepath &optional ask) + "Find FILEPATH after expanding root. ASK is passed straight to `projectile-grid-ff'." + (projectile-grid-ff (projectile-expand-root filepath) ask)) + +(defun projectile-grid-choices (ds) + "Uses `projectile-dir-files' function to find files in directories. +The DIRS is list of lists consisting of a directory path and regexp to filter files from that directory. +Optional third element can be present in the DS list. The third element will be a prefix to be placed before +the filename in the resulting choice. +Returns a hash table with keys being short names (choices) and values being relative paths to the files." + (loop with hash = (make-hash-table :test 'equal) + for (dir re prefix) in ds do + (loop for file in (projectile-dir-files (projectile-expand-root dir)) do + (when (string-match re file) + (puthash + (concat (or prefix "") + (s-join "/" (grfn/all-match-groups file))) + (concat dir file) + hash))) + finally return hash)) + +(defmacro projectile-grid-find-resource (prompt dirs &optional newfile-template) + "Presents files from DIRS with PROMPT to the user using `projectile-completing-read'. +If users chooses a non existant file and NEWFILE-TEMPLATE is not nil +it will use that variable to interpolate the name for the new file. +NEWFILE-TEMPLATE will be the argument for `s-lex-format'. +The bound variable is \"filename\"." + `(lexical-let ((choices (projectile-grid-choices ,dirs))) + (projectile-completing-read + ,prompt + (hash-table-keys choices) + :action + (lambda (c) + (let* ((filepath (gethash c choices)) + (filename c)) ;; so `s-lex-format' can interpolate FILENAME + (if filepath + (projectile-grid-goto-file filepath) + (when-let ((newfile-template ,newfile-template)) + (projectile-grid-goto-file + (funcall newfile-template filepath) + ;; (cond + ;; ((functionp newfile-template) (funcall newfile-template filepath)) + ;; ((stringp newfile-template) (s-lex-format newfile-template))) + t)))))))) + +(defun projectile-grid-find-model () + "Find a model." + (interactive) + (projectile-grid-find-resource + "model: " + '(("python/urbint_lib/models/" + "\\(.+\\)\\.py$") + ("python/urbint_lib/" + "\\(.+\\)/models/\\(.+\\).py$")) + (lambda (filename) + (pcase (s-split "/" filename) + (`(,model) + (s-lex-format "python/urbint_lib/models/${model}.py")) + (`(,app ,model) + (s-lex-format "python/urbint_lib/${app}/models/${model}.py")))))) + +(defun projectile-grid-find-controller () + "Find a controller." + (interactive) + (projectile-grid-find-resource + "controller: " + '(("backend/src/grid/api/controllers/" + "\\(.+\\)\\.py$") + ("backend/src/grid/api/apps/" + "\\(.+\\)/controllers/\\(.+\\).py$")) + (lambda (filename) + (pcase (s-split "/" filename) + (`(,controller) + (s-lex-format "backend/src/grid/api/controllers/${controller}.py")) + (`(,app ,controller) + (s-lex-format "backend/src/grid/api/apps/${app}/controllers/${controller}.py")))))) + +(defvar projectile-grid-mode-map + (let ((map (make-keymap))) + (map! + (:map map + (:leader + (:desc "Edit..." :prefix "e" + :desc "Model" :n "m" #'projectile-grid-find-model + :desc "Controller" :n "c" #'projectile-grid-find-controller)))))) + +(define-minor-mode projectile-grid-mode + "Minor mode for finding files in GRID" + :init-value nil + :lighter " GRID" + :keymap projectile-grid-mode-map) -- cgit 1.4.1