diff options
-rw-r--r-- | +bindings.el | 151 | ||||
-rw-r--r-- | +commands.el | 28 | ||||
-rw-r--r-- | clocked-in-elt.el | 18 | ||||
-rw-r--r-- | company-sql.el | 47 | ||||
-rw-r--r-- | config.el | 732 | ||||
-rw-r--r-- | init.el | 185 | ||||
-rw-r--r-- | nix-yapf-mode.el | 21 | ||||
-rw-r--r-- | org-alerts.el | 188 | ||||
-rw-r--r-- | org-config.el | 91 | ||||
-rw-r--r-- | org-query.el | 96 | ||||
-rw-r--r-- | packages.el | 73 | ||||
-rw-r--r-- | show-matching-paren.el | 61 | ||||
-rw-r--r-- | slack-snippets.el | 35 | ||||
-rw-r--r-- | snippets/haskell-mode/hlint | 8 | ||||
-rw-r--r-- | snippets/nix-mode/fetchFromGitHub | 12 | ||||
-rw-r--r-- | snippets/nix-mode/pythonPackage | 16 | ||||
-rw-r--r-- | snippets/nix-mode/sha256 | 7 | ||||
-rw-r--r-- | snippets/org-mode/combat | 13 | ||||
-rw-r--r-- | snippets/org-mode/reveal | 6 | ||||
-rw-r--r-- | snippets/python-mode/decorate | 15 | ||||
-rw-r--r-- | snippets/python-mode/name | 7 | ||||
-rw-r--r-- | snippets/python-mode/pdb | 7 | ||||
-rw-r--r-- | sql-strings.el | 75 | ||||
-rw-r--r-- | themes/grfn-solarized-light-theme.el | 72 |
24 files changed, 1535 insertions, 429 deletions
diff --git a/+bindings.el b/+bindings.el index af54d8408624..875d298d4262 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 4025a9504a42..a5753c8e995b 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 "<a>") + (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 "<a>") - (alembic-upgrade revision)) + (alembic-upgrade (or revision "head"))) + +(ex! "aup[grade]" #'evil-alembic-upgrade) + +(evil-define-command evil-alembic-downgrade (&optional revision) + (interactive "<a>") + (alembic-downgrade revision)) + +(ex! "adown[grade]" #'evil-alembic-downgrade) + +(evil-define-command evil-alembic (args) + (interactive "<a>") + (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 000000000000..00fda047e4a9 --- /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 58c57dde80e5..2408347ceffc 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 b9289376233a..287d0978936d 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 ca4a89069e84..1dd0180f87e2 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 000000000000..9dba47bd3614 --- /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 000000000000..993791f367ae --- /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 000000000000..faf2a1bf423b --- /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 000000000000..3ed4b086af0c --- /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 799bcbe92a40..41e8e1490432 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 000000000000..d10751a63f94 --- /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 0c5175192107..9e05382ee6f0 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 000000000000..74b63dc672e4 --- /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 000000000000..9b9373573048 --- /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 000000000000..0a74c21e1857 --- /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 000000000000..e3d52e1c0201 --- /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 000000000000..ef46062d09b4 --- /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 000000000000..1bdbdfa5dc36 --- /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 000000000000..9448b45c9623 --- /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 000000000000..eca6d60b481f --- /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 000000000000..6b5c0bbc0a73 --- /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 000000000000..37e22af421c6 --- /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 338cfabfcc24..ae00b6b5fc75 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) |