diff options
Diffstat (limited to '.config/emacs/modules')
| -rw-r--r-- | .config/emacs/modules/mm-abbrev.el | 8 | ||||
| -rw-r--r-- | .config/emacs/modules/mm-editing.el | 60 | ||||
| -rw-r--r-- | .config/emacs/modules/mm-humanwave.el | 141 | ||||
| -rw-r--r-- | .config/emacs/modules/mm-modeline.el | 2 | ||||
| -rw-r--r-- | .config/emacs/modules/mm-projects.el | 64 | ||||
| -rw-r--r-- | .config/emacs/modules/mm-theme.el | 16 | ||||
| -rw-r--r-- | .config/emacs/modules/mm-treesit.el | 5 |
7 files changed, 242 insertions, 54 deletions
diff --git a/.config/emacs/modules/mm-abbrev.el b/.config/emacs/modules/mm-abbrev.el index 937d558..66ca8d7 100644 --- a/.config/emacs/modules/mm-abbrev.el +++ b/.config/emacs/modules/mm-abbrev.el @@ -78,6 +78,14 @@ case-sensitive to avoid unexpected abbreviation expansions." "sme" "save-mark-and-excursion" "sr" "save-restriction") +(when mm-humanwave-p + (with-eval-after-load 'python-ts-mode + (mm-define-abbreviations python-ts-mode-abbrev-table + "empb" "with emphasize.Block():" + "empf" "@emphasize.func" + "empi" "from shared.system import emphasize" + "empt" "emphasize.this"))) + ;;; Template Configuration diff --git a/.config/emacs/modules/mm-editing.el b/.config/emacs/modules/mm-editing.el index 540bae4..6054f5a 100644 --- a/.config/emacs/modules/mm-editing.el +++ b/.config/emacs/modules/mm-editing.el @@ -56,6 +56,7 @@ (go-ts-mode . (:extras go-ts-mode-indent-offset)) (gsp-ts-mode . (:width 2 :extras gsp-ts-mode-indent-rules)) (helpful-mode . (:width 8)) ; GNU code uses 8-column tabs + (json-ts-mode . (:extras json-ts-mode-indent-offset)) (latex-mode . (:width 2)) (lisp-data-mode . (:spaces t)) (lisp-interaction-mode . (:spaces t)) @@ -66,6 +67,7 @@ (python-ts-mode . (:extras python-indent-offset)) (sgml-mode . (:extras sgml-basic-offset)) (sh-mode . (:extras sh-basic-offset)) + (sql-mode . (:extras sqlind-basic-offset)) (tex-mode . (:width 2)) (typescript-ts-mode . (:extras typescript-ts-mode-indent-offset)) (vimscript-ts-mode . (:extras vimscript-ts-mode-indent-level)) @@ -125,6 +127,11 @@ those should be listed in `mm-editing-indentation-settings'." extras)) (set (make-local-variable extra) tabsize))))) +(use-package sh-mode + :custom + (sh-indent-for-case-label 0) + (sh-indent-for-case-alt #'+)) + ;;; Code Commenting @@ -298,6 +305,18 @@ surround with spaces." (push '("`" . "'") surround-pairs)))) +;;; Insert Webpage Contents + +(defun mm-insert-from-url (url) + "Insert the contents of URL at point." + (interactive + (let ((url-at-point (thing-at-point 'url))) + (list (read-string + (format-prompt "URL" url-at-point) + nil nil url-at-point)))) + (call-process "curl" nil '(t nil) nil url)) + + ;;; Emmet Mode (defun mm-editing-emmet-dwim (arg) @@ -318,6 +337,36 @@ is as described by `emmet-expand-line'." (emmet-self-closing-tag-style "")) +;;; JQ Manipulation in JSON Mode + +(defun mm-jq-filter (query &optional beg end) + "TODO" + (interactive + (list + (read-string (format-prompt "Query" nil)) + (when (use-region-p) (region-beginning)) + (when (use-region-p) (region-end)))) + (let* ((beg (or beg (point-min))) + (end (or end (point-max))) + (temp-buffer (generate-new-buffer "* jq temp*")) + (exit-code (call-process-region beg end "jq" nil temp-buffer nil + "--tab" query)) + (output (with-current-buffer temp-buffer (buffer-string)))) + (if (zerop exit-code) + (atomic-change-group + (delete-region beg end) + (insert output) + (indent-region beg (point))) + (message "%s" output)) + (kill-buffer temp-buffer))) + +(use-package json-ts-mode + :bind ( :map json-ts-mode-map + ("C-|" . #'mm-jq-filter)) + :config + (require 'live-jq)) + + ;;; Number Formatting (use-package number-format-mode @@ -329,6 +378,7 @@ is as described by `emmet-expand-line'." ;;; Additional Major Modes (use-package awk-ts-mode :ensure t) +(use-package cmake-mode :ensure t) (use-package git-modes :ensure t) (use-package po-mode :ensure t) (use-package sed-mode :ensure t) @@ -362,6 +412,12 @@ is as described by `emmet-expand-line'." ;;; Add Missing Extensions (dolist (pattern '("\\.tmac\\'" "\\.mom\\'")) - (add-to-list 'auto-mode-alist (cons pattern 'nroff-mode))) + (add-to-list 'auto-mode-alist (cons pattern #'nroff-mode))) + + +;;; Subword Navigation + +(use-package subword + :hook prog-mode) -(provide 'mm-editing)
\ No newline at end of file +(provide 'mm-editing) diff --git a/.config/emacs/modules/mm-humanwave.el b/.config/emacs/modules/mm-humanwave.el new file mode 100644 index 0000000..3aa97b3 --- /dev/null +++ b/.config/emacs/modules/mm-humanwave.el @@ -0,0 +1,141 @@ +;;; mm-humanwave.el --- Humanwave extras -*- lexical-binding: t; -*- + + +;;; Query the Backend + +(defvar mm--humanwave-query-history nil + "History for endpoints given to `mm-humanwave-query'.") + +(defun mm-humanwave-query (endpoint &optional method) + "Query and display the result of an HTTP reqiest on ENDPOINT. +If METHOD is nil, a GET request is performed." + (interactive + (let* ((query (read-string (format-prompt "Query" nil) + (car-safe mm--humanwave-query-history) + 'mm--humanwave-query-history)) + (parts (string-split (string-trim query) " " :omit-nulls))) + (when (length> parts 2) + (user-error "Queries must be of the form `METHOD ENDPOINT' or `ENDPOINT'.")) + (nreverse parts))) + (let* ((project-root (project-root (project-current :maybe-prompt))) + (qry-path (expand-file-name "qry" project-root)) + extras) + (unless (file-executable-p qry-path) + (user-error "No `qry' executable found in the project root")) + (let ((output-buffer (get-buffer-create "*Query Response*"))) + (with-current-buffer output-buffer + (delete-region (point-min) (point-max)) + (call-process qry-path nil t nil + (string-trim endpoint) "-X" (or method "GET")) + (unless (eq major-mode 'json-ts-mode) + (json-ts-mode)) + (goto-char (point-min))) + (display-buffer output-buffer)))) + +(keymap-set project-prefix-map "q" #'mm-humanwave-query) + + +;;; IMenu Support for Handlers + +(defvar mm-humanwave-handler--regexp + (rx bol + (* blank) + (or "if" "elif") + (* blank) + (or "topic" "schedule") + (* blank) + "==" + (* blank) + (or (seq ?\' (* (not ?\')) ?\') + (seq ?\" (* (not ?\")) ?\")) + (* blank) + ?: + (* blank) + eol)) + +(defun mm-humanwave-handler-topic-imenu-index () + (let ((tree-index (when (fboundp 'treesit-simple-imenu--generic-function) + (treesit-simple-imenu--generic-function + treesit-simple-imenu-settings))) + (topic-index '())) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward mm-humanwave-handler--regexp nil :noerror) + (let ((label (match-string 0)) + (pos (match-beginning 0))) + (push (cons (format "Topic: %s" (string-trim label)) pos) topic-index)))) + (append (nreverse topic-index) tree-index))) + +(defun mm-humanwave-handler-topic-imenu-setup () + "Setup custom imenu index for `python-ts-mode'." + (when (and (string-match-p "handlers?" (or (buffer-file-name) "")) + (derived-mode-p #'python-ts-mode)) + (setq-local imenu-create-index-function + #'mm-humanwave-handler-topic-imenu-index))) + +(add-hook 'after-change-major-mode-hook + #'mm-humanwave-handler-topic-imenu-setup) + + +;;; Insert Imports in Vue + +(defun mm-humanwave-insert-vue-import-path (base-directory target-file) + "Insert an import directive at POINT. +The import directive imports TARGET-FILE relative from BASE-DIRECTORY. +When called interactively BASE-DIRECTORY is the directory of the current +open Vue file and TARGET-FILE is a file in the current project that is +queried interactively. + +When called interactively the prefix argument can be used to emulate the +behaviour of the INCLUDE-ALL-P argument to `mm-project-read-file-name'." + (interactive + (list + default-directory + (mm-humanwave-project-read-file-name current-prefix-arg))) + (let ((path (file-name-sans-extension + (file-relative-name target-file base-directory)))) + (unless (string-match-p "/" path) + (setq path (concat "./" path))) + (insert "import ") + (save-excursion + (insert (thread-last + (file-name-base path) + (mm-string-split "-") + (mapconcat #'capitalize))) + (push-mark (point)) + (insert (format " from '%s';" path))))) + +(defun mm-humanwave-project-read-file-name (&optional include-all-p) + "Prompt for a project file. +This function is similar to `project-find-file', but it returns the path +to the selected file instead of opening it. + +When called interactively the selected file is printed to the minibuffer, +otherwise it is returned. + +The prefix argument INCLUDE-ALL-P is the same as the INCLUDE-ALL argument +to the `project-find-file' command." + (interactive "P") + (let* ((project (project-current :maybe-prompt)) + (root (project-root project)) + (files (if include-all-p + (let ((vc-ignores (mapcar + (lambda (dir) (concat dir "/")) + vc-directory-exclusion-list))) + (project--files-in-directory root vc-ignores)) + (project-files project))) + (canditates (mapcar (lambda (f) (file-relative-name f root)) + files)) + (table (lambda (string predicate action) + (if (eq action 'metadata) + '(metadata (category . file)) + (complete-with-action action canditates string predicate)))) + (default-directory root) + (choice (completing-read (format-prompt "Find project file" nil) + table nil :require-match))) + (let ((path (expand-file-name choice root))) + (if (called-interactively-p 'any) + (message "%s" path) + path)))) + +(provide 'mm-humanwave) diff --git a/.config/emacs/modules/mm-modeline.el b/.config/emacs/modules/mm-modeline.el index d1ec6f0..44fc115 100644 --- a/.config/emacs/modules/mm-modeline.el +++ b/.config/emacs/modules/mm-modeline.el @@ -90,7 +90,7 @@ the text it should be mapped to.") ((derived-mode-p 'comint-mode) "$ ") ((derived-mode-p 'conf-mode) "# ") ((derived-mode-p 'prog-mode) "λ ") - ((derived-mode-p 'special-mode) "❇ ") + ((derived-mode-p 'special-mode) "★ ") ((derived-mode-p 'text-mode) "§ ") (:default "")) 'face 'mm-modeline-major-mode-symbol-face)) diff --git a/.config/emacs/modules/mm-projects.el b/.config/emacs/modules/mm-projects.el index 71006d5..02d7af4 100644 --- a/.config/emacs/modules/mm-projects.el +++ b/.config/emacs/modules/mm-projects.el @@ -19,7 +19,7 @@ This is intended to be called interactively via (project-find-file "Find File" ?f) (mm-projects-project-magit-status "Git Status" ?s))) :config - (unless mm-darwin-p + (unless mm-humanwave-p (if-let ((repo-directory (getenv "REPODIR"))) (let* ((list-dir (lambda (path) @@ -47,9 +47,10 @@ This is intended to be called interactively via (use-package magit :ensure t - :bind ( :map magit-status-mode-map - ("[" . magit-section-backward-sibling) - ("]" . magit-section-forward-sibling)) + :bind (("C-c b" . magit-blame-addition) + :map magit-status-mode-map + ("[" . magit-section-backward-sibling) + ("]" . magit-section-forward-sibling)) :custom (git-commit-style-convention-checks '(non-empty-second-line overlong-summary-line)) @@ -70,11 +71,18 @@ This is intended to be called interactively via "push" "-v" args remote (format "refs/heads/%s:refs/heads/%s" branch branch))))) (transient-append-suffix #'magit-push '(1 -1) - '("a" "all remotes" mm-projects-magit-push-current-to-all-remotes))) + '("a" "all remotes" mm-projects-magit-push-current-to-all-remotes)) + (add-to-list 'magit-blame-styles + '(margin + (show-lines . t) + (margin-format . (" %C %a" " %s%f" " ")) + (margin-width . 73) + (margin-face . magit-blame-margin) + (margin-body-face . (magit-blame-dimmed))))) (use-package magit-repos :ensure nil ; Part of ‘magit’ - :if (not mm-darwin-p) + :if (not mm-humanwave-p) :commands (magit-list-repositories) :init (if-let ((directory (getenv "REPODIR"))) @@ -100,45 +108,7 @@ This is intended to be called interactively via ;;; GitHub Pull Requests (require 'gh) -(keymap-global-set "C-c p" #'gh-create-pr) +(keymap-global-set "C-c p c" #'gh-create-pr) +(keymap-global-set "C-c p o" #'gh-open-previous-pr) -;; (defun mm-gh--get-labels () -;; (with-temp-buffer -;; (call-process "gh" nil t nil "label" "list" "--json" "name") -;; (goto-char (point-min)) -;; (let* ((data (json-parse-buffer)) -;; (labels (seq-map (lambda (x) (gethash "name" x)) data))) -;; (sort labels -;; :in-place t -;; :lessp (lambda (x y) -;; (let ((prefix-x-p (string-prefix-p "Sprint " x)) -;; (prefix-y-p (string-prefix-p "Sprint " y))) -;; (cond -;; ((and prefix-x-p prefix-y-p) (string> x y)) -;; (prefix-x-p t) -;; (prefix-y-p nil) -;; (:else (string< x y))))))))) - -;; (defun mm-gh-create-pr (title draftp labels) -;; "Create a GitHub pull request using the gh CLI. -;; If DRAFT is non-nil, the PR will be created as a draft. -;; LABELS should be a comma-separated string of GitHub labels." -;; (interactive -;; (list -;; (read-string (format-prompt "PR Title" nil)) -;; (y-or-n-p "Create as draft PR? ") -;; (completing-read-multiple (format-prompt "PR Labels" nil) -;; (mm-gh--get-labels)))) -;; (let* ((branch (car (vc-git-branches))) -;; (title (format "%s %s" branch title)) -;; (flags `("--fill-verbose" "--title" ,title "--assignee" "@me")) -;; (label-string (mapconcat #'identity labels ","))) -;; (when draftp -;; (setq flags (append flags '("--draft")))) -;; (when labels -;; (setq flags (append flags `("--label" ,label-string)))) -;; (with-temp-buffer -;; (apply #'call-process "gh" nil t nil "pr" "create" flags) -;; (message (buffer-string))))) - -(provide 'mm-projects)
\ No newline at end of file +(provide 'mm-projects) diff --git a/.config/emacs/modules/mm-theme.el b/.config/emacs/modules/mm-theme.el index 90b89ba..cde214a 100644 --- a/.config/emacs/modules/mm-theme.el +++ b/.config/emacs/modules/mm-theme.el @@ -8,7 +8,7 @@ ;;; Fonts -(defvar mm-theme-monospace-font `(,(if mm-darwin-p +(defvar mm-theme-monospace-font `(,(if mm-humanwave-p "Iosevka Custom" "Iosevka Smooth") :weight regular @@ -166,6 +166,16 @@ See also the `mm-theme-background-opacity' variable." (("C-c h l" . pulsar-highlight-dwim))) +;;; In-buffer highlighting + +(require 'hi-lock) ; For extra face definitions +(use-package highlighter + :bind (("C-c h m" . #'highlighter-mark) + ("C-c h u" . #'highlighter-unmark) + ("C-c h U" . #'highlighter-unmark-buffer)) + :commands (highlighter-mark highlighter-unmark highlighter-unmark-buffer)) + + ;;; Add Padding (use-package spacious-padding @@ -224,7 +234,7 @@ See also the `mm-theme-background-opacity' variable." ;;; Indent Guides -(when mm-darwin-p +(when mm-humanwave-p (use-package highlight-indent-guides :ensure t :hook ((jinja2-mode vue-ts-mode mhtml-mode) . highlight-indent-guides-mode) @@ -233,4 +243,4 @@ See also the `mm-theme-background-opacity' variable." (highlight-indent-guides-auto-even-face-perc 30) (highlight-indent-guides-auto-odd-face-perc 0))) -(provide 'mm-theme)
\ No newline at end of file +(provide 'mm-theme) diff --git a/.config/emacs/modules/mm-treesit.el b/.config/emacs/modules/mm-treesit.el index 1d4defa..bd146ce 100644 --- a/.config/emacs/modules/mm-treesit.el +++ b/.config/emacs/modules/mm-treesit.el @@ -35,6 +35,8 @@ "https://github.com/tree-sitter/tree-sitter-java") (javascript "https://github.com/tree-sitter/tree-sitter-javascript") + (json + "https://github.com/tree-sitter/tree-sitter-json") (markdown "https://github.com/tree-sitter-grammars/tree-sitter-markdown" "split_parser" "tree-sitter-markdown/src") @@ -116,6 +118,7 @@ The parsers are taken from `treesit-language-source-alist'." (defvar mm-treesit-language-file-name-alist '((go . "\\.go\\'") (gomod . "/go\\.mod\\'") + (json . "\\.json\\'") (tsx . "\\.tsx\\'") (typescript . "\\.ts\\'")) "Alist mapping languages to their associated file-names. @@ -219,4 +222,4 @@ back to regular `expreg-expand'." :commands (mm-expreg-expand mm-expreg-expand-dwim) :bind ("M-SPC" . mm-expreg-expand-dwim)) -(provide 'mm-treesit)
\ No newline at end of file +(provide 'mm-treesit) |