Skip to content

Instantly share code, notes, and snippets.

Created April 25, 2022 23:00
Show Gist options
  • Save SignSpice/84127ce981e0f5c6951a846c56f72349 to your computer and use it in GitHub Desktop.
Save SignSpice/84127ce981e0f5c6951a846c56f72349 to your computer and use it in GitHub Desktop.
;;; $DOOMDIR/config.el -*- lexical-binding: t; -*-
;; Place your private configuration here! Remember, you do not need to run 'doom
;; sync' after modifying this file!
;; Some functionality uses this to identify you, e.g. GPG configuration, email
;; clients, file templates and snippets.
;; Doom exposes five (optional) variables for controlling fonts in Doom. Here
;; are the three important ones:
;; + `doom-font'
;; + `doom-variable-pitch-font'
;; + `doom-big-font' -- used for `doom-big-font-mode'; use this for
;; presentations or streaming.
;; They all accept either a font-spec, font string ("Input Mono-12"), or xlfd
;; font string. You generally only need these two:
;; (setq doom-font (font-spec :family "monospace" :size 12 :weight 'semi-light)
;; doom-variable-pitch-font (font-spec :family "sans" :size 13))
;; There are two ways to load a theme. Both assume the theme is installed and
;; available. You can either set `doom-theme' or manually load a theme with the
;; `load-theme' function. This is the default:
(setq doom-theme 'doom-homage-white)
;; If you use `org' and don't want your org files in the default location below,
;; change `org-directory'. It must be set before org loads!
(setq org-directory "~/org/")
(setq org-roam-directory "~/org")
(setq org-agenda-files (quote ("~/org"
;; This determines the style of line numbers in effect. If set to `nil', line
;; numbers are disabled. For relative line numbers, set this to `relative'.
(setq display-line-numbers-type nil)
;; Here are some additional functions/macros that could help you configure Doom:
;; - `load!' for loading external *.el files relative to this one
;; - `use-package!' for configuring packages
;; - `after!' for running code after a package has loaded
;; - `add-load-path!' for adding directories to the `load-path', relative to
;; this file. Emacs searches the `load-path' when you load packages with
;; `require' or `use-package'.
;; - `map!' for binding new keys
;; To get information about any of these functions/macros, move the cursor over
;; the highlighted symbol at press 'K' (non-evil users must press 'C-c c k').
;; This will open documentation for it, including demos of how they are used.
;; You can also try 'gd' (or 'C-c c d') to jump to their definition and see how
;; they are implemented.
(setq locate-command "fd")
(setq mouse-autoselect-window t)
;; (add-hook 'clojure-mode-hook #'cider-hydra-mode)
(require 'flycheck-clj-kondo)
(use-package! which-key
(setq which-key-popup-type 'side-window)
(setq which-key-side-window-location 'bottom)
(setq which-key-idle-delay .3)
(after! evil
(evil-define-minor-mode-key '(normal insert) 'which-key-mode (kbd "M-s") 'which-key-show-next-page-cycle)
(evil-define-minor-mode-key '(normal insert) 'which-key-mode (kbd "M-H") 'which-key-show-previous-page-cycle)))
(map! :leader
:desc "M-x without the M" "SPC" #'execute-extended-command)
(if nil (use-package! org-roam
(map! :leader
:prefix "r"
:desc "org-roam" "l" #'org-roam
:desc "org-roam-insert" "i" #'org-roam-insert
:desc "switch-to rm-buffer" "b" #'org-roam-switch-to-buffer
:desc "org-roam-find-file" "f" #'org-roam-find-file
:desc "org-roam-graph-show" "g" #'org-roam-show-graph
:desc "org-roam-capture" "c" #'org-roam-capture
:desc "Daily -> Today" "t" #'org-roam-dailies-find-today
(:prefix ("d" . "by date")
:desc "Arbitrary date" "d" #'org-roam-dailies-date
:desc "Today" "t" #'org-roam-dailies-find-today
:desc "Tomorrow" "m" #'org-roam-dailies-find-tomorrow
:desc "Yesterday" "y" #'org-roam-dailies-find-yesterday))))
(use-package! deft
(setq deft-directory "~/org/")
(setq deft-recursive t))
(setq initial-major-mode 'lisp-interaction-mode)
(defun xah-save-all-unsaved ()
"Save all unsaved files. no ask.
Version 2019-11-05"
(save-some-buffers t))
(setq after-focus-change-function 'xah-save-all-unsaved)
(setq ulisp-term-buffer-name "/dev/ttyUSB0")
(defun ulisp-eval-last-expression-in-term ()
(let ((expr (buffer-substring-no-properties
(save-excursion (backward-sexp) (point))
(with-current-buffer ulisp-term-buffer-name
(goto-char (point-max))
(sit-for 0.3)
(insert expr)
;; (global-set-key (kbd "C-c C-c") 'ulisp-eval-last-expression-in-term)
(setq clojure-toplevel-inside-comment-form t)
(setq scroll-step 1
scroll-margin 1
hscroll-step 1
hscroll-margin 1
scroll-conservatively 101
scroll-up-aggressively 0.01
scroll-down-aggressively 0.01)
(use-package! lsp
(setq lsp-modeline-code-actions-enable nil
lsp-ui-sideline-enable nil
lsp-enable-symbol-highlighting nil
lsp-lens-enable t
lsp-ui-doc-enable t))
(setq mouse-wheel-progressive-speed nil)
(advice-add 'undo-auto--last-boundary-amalgamating-number :override #'ignore)
;; (setq evil-want-fine-undo t)
(setq evil-want-fine-undo nil)
;; (use-package! complex-undo
;; :config
;; (add-hook 'after-change-major-mode-hook 'complex-undo-mode))
(use-package! keycast
:commands keycast-mode
(define-minor-mode keycast-mode
"Show current command and its key binding in the mode line."
:global t
(if keycast-mode
(add-hook 'pre-command-hook 'keycast--update t)
(add-to-list 'global-mode-string '("" mode-line-keycast " ")))
(remove-hook 'pre-command-hook 'keycast--update)
(setq global-mode-string (remove '("" mode-line-keycast " ") global-mode-string))))
'(keycast-command :inherit doom-modeline-debug
:height 0.9)
'(keycast-key :inherit custom-modified
:height 1.1
:weight bold)))
(use-package! origami)
(use-package! symex
(setq lispy-avy-keys (nconc (number-sequence ?a ?x)
(number-sequence ?A ?Z)
(number-sequence ?1 ?9)
(setq avy-keys (nconc (number-sequence ?a ?x)
(number-sequence ?A ?Z)
(number-sequence ?1 ?9)
(setq symex--user-evil-keyspec
'(("j" . symex-go-up)
("k" . symex-go-down)
("s" . symex-go-forward)
("n" . symex-traverse-forward)
("N" . symex-traverse-forward-skip)
("C-w" . symex-wrap-square)
("M-w" . symex-wrap-curly)
("C-j" . symex-climb-branch)
("C-k" . symex-descend-branch)
("M-j" . symex-goto-highest)
("M-k" . symex-goto-lowest)
("." . symex-soar-forward)
("," . symex-soar-backward)
("r" . symex-replace)
("t" . (lambda () (interactive) (evil-set-jump) (lispy-ace-paren)))
("T" . (lambda () (interactive) (evil-set-jump) (call-interactively #'avy-goto-symbol-1)))
("C-t" . (lambda () (interactive) (signspice-with-mark 'lispy-ace-paren)))
("M-t" . (lambda () (interactive) (lispy-ace-paren 2)))
("M-T" . (lambda () (interactive) (signspice-with-mark 'lispy-ace-paren 2)))
("M-r" . cljr-raise-sexp)
("M-R" . lispy-raise-some)
("C-e" . signspice-eval-mark)
("z" . evil-scroll-line-to-top)
("C-u" . signspice-goto-previous-mark)
("<tab>" . origami-toggle-node)
("<backtab>" . evil-show-marks)
("C-d" . cider-pprint-eval-defun-at-point)
("C-p" . signspice-pprint-at-point)
("C-s-p" . portal.api/open)
("C-S-s-p" . portal-copy)
("M-p" . signspice-steal-from-ace)))
(setq evil-symex-state-cursor '("#884444" box))
(setq evil-normal-state-cursor 'hollow-rectangle))
(advice-add 'mwheel-scroll
(lambda (&rest _args)
(if (not (eq last-command 'mwheel-scroll))
(defmacro ss/save-symex (&rest body)
"work in progess, doesn't work yet."
(let ((in-symex-mode (or (equal evil-state 'emacslike)
(equal evil-state 'normallike))))
(cons 'progn body)
(when in-symex-mode
(defun ss/wrap-with-spy ()
(cider-interactive-eval "(require 'sc.api)")
(insert "sc.api/spy ")
(defun ss/rescope-last ()
(let ((ns (cider-current-ns t)))
(cider-nrepl-sync-request:eval "(require 'sc.api)" nil ns)
(cider-nrepl-sync-request:eval "(defmacro defsc*
`(sc.api/defsc ~(sc.api/last-ep-id)))" nil ns)
(cider-nrepl-sync-request:eval "(defsc*)" nil ns)))
(defun ss/run-with-args (&optional rescope)
(symex-traverse-forward 2)
(let ((fn-name (thing-at-point 'sexp t)))
(symex-go-forward 1)
(let* ((fn-args (thing-at-point 'sexp t))
(fn-args-in (read-string (concat fn-name " " fn-args ": "))))
(cider-nrepl-sync-request:eval (format "(%s %s)" fn-name fn-args-in)
(cider-current-ns t))
(when rescope (ss/re-scope-last)))))))
(defun ss/run-with-args-and-rescope ()
(ss/run-with-args t))
(defun ss/run-and-rescope-dwim* ()
;; undo hack, not sure why it doesn't work w/o this.
(insert ""))))
(defun ss/run-and-rescope-dwim ()
(defun ss/instrument-spy* ()
;; undo hack, not sure why it doesn't work w/o this.
(defun ss/instrument-spy ()
(let ((in-symex-mode (or (equal evil-state 'emacslike)
(equal evil-state 'normallike))))
(when in-symex-mode
(defun signspice-with-mark (f &rest args)
(setq signspice-last-jump (point))
(apply f args))
(defun signspice-yank-and-put-to-mark ()
(symex-yank 1)
(goto-char signspice-last-jump)
(symex-paste-after 1))
(defun signspice-steal-from-ace ()
(let ((starting-point (point)))
(lispy-ace-paren 2)
(symex-yank 1)
(goto-char starting-point)
(symex-paste-after 1)))
(defun signspice-eval-mark (char)
(interactive (list (read-char "evaluate mark:")))
(evil-goto-mark char)
(symex-evaluate 1)))
(defun portal-copy ()
(kill-new (nrepl-dict-get (cider-nrepl-sync-request:eval "@p") "value"))
(symex-paste-after 1))
(after! cider-mode
(defun cider-tap (&rest r)
(cons (concat "(let [__value "
(caar r)
"] (tap> (if (instance? clojure.lang.IObj __value)
(with-meta __value {:portal.viewer/default :portal.viewer/tree
:theme :portal.colors/solarized-light})
(cdar r)))
(advice-add 'cider-nrepl-request:eval
:filter-args #'cider-tap))
(defun jet-pretty ()
"jet --pretty --edn-reader-opts '{:default tagged-literal}'"
"*jet error buffer*"
(setq signspice-last-jump nil)
(defun signspice-goto-previous-mark ()
(when (not signspice-last-jump)
(setq signspice-last-jump (point)))
(let ((pos (point))
(last-pos signspice-last-jump))
(goto-char last-pos)
(setq signspice-last-jump pos)))
(defun signspice-pprint-at-point ()
(defun signspice-jsx->clj ()
(call-shell-region (point-min) (point-max) "node ~/projects/jsx-to-clojurescript/jsx-to-clojurescript.js --target om --ns n --kebab-tags" t t))
(defun signspice-tsx->jsx ()
(call-shell-region (point-min) (point-max) ">> /tmp/temp.tsx; npx detype /tmp/temp.tsx /tmp/temp.jsx; cat /tmp/temp.jsx; rm /tmp/temp.tsx" t t))
(use-package! anakondo
:commands anakondo-minor-mode)
(use-package! popper
:bind (("C-`" . popper-toggle-latest)
("M-`" . popper-cycle)
("C-M-`" . popper-toggle-type))
(setq popper-reference-buffers
"\\*Async Shell Command\\*"
(popper-mode +1)
(popper-echo-mode +1))
(use-package! git-timemachine)
;; (use-package! monroe
;; :config
;; (add-hook 'fennel-mode-hook 'clojure-enable-monroe))
(use-package! counsel)
(use-package! rigpa
:after (counsel evil symex)
(setq rigpa-mode t)
;; temporary workaround for
(remove-hook 'evil-symex-state-exit-hook #'symex-disable-editing-minor-mode)
;; custom config
(setq rigpa-show-menus nil)
;; navigating meta modes
(global-unset-key (kbd "s-m"))
(global-set-key (kbd "s-m s-m") 'rigpa-flashback-to-last-tower)
(global-set-key (kbd "C-<escape>")
(lambda ()
(when (eq rigpa--complex rigpa-meta-complex)
(global-set-key (kbd "M-<escape>") 'rigpa-enter-mode-mode)
(global-set-key (kbd "s-<escape>") 'rigpa-enter-mode-mode)
(global-set-key (kbd "M-<return>")
(lambda ()
(when (eq rigpa--complex rigpa-meta-complex)
(let ((ground (rigpa--get-ground-buffer)))
(switch-to-buffer ground)))))
(global-set-key (kbd "s-<return>")
(lambda ()
(when (eq rigpa--complex rigpa-meta-complex)
(let ((ground (rigpa--get-ground-buffer)))
(switch-to-buffer ground)))))
(global-set-key (kbd "C-<return>")
(lambda ()
(when (eq rigpa--complex rigpa-meta-tower-complex)
;; indexed entry to various modes
(global-set-key (kbd "s-n") 'evil-normal-state)
(global-set-key (kbd "s-y") ; symex mode
(lambda ()
(rigpa-enter-mode "symex")))
(global-set-key (kbd "s-;") (kbd "s-y"))
(global-set-key (kbd "s-w") ; window mode
(lambda ()
(rigpa-enter-mode "window")))
(global-set-key (kbd "M-s-v") ; view mode
(lambda ()
(rigpa-enter-mode "view")))
(global-set-key (kbd "s-x") ; char mode
(lambda ()
(rigpa-enter-mode "char")))
(global-set-key (kbd "s-a") ; activity mode
(lambda ()
(rigpa-enter-mode "activity")))
(global-set-key (kbd "s-z") ; text mode
(lambda ()
(rigpa-enter-mode "text")))
(global-set-key (kbd "s-g") ; history mode
(lambda ()
(rigpa-enter-mode "history")))
(global-set-key (kbd "s-i") ; system mode
(lambda ()
(rigpa-enter-mode "system")))
(global-set-key (kbd "s-b") ; buffer mode
(lambda ()
(rigpa-enter-mode "buffer")))
(global-set-key (kbd "s-f") ; file mode
(lambda ()
(rigpa-enter-mode "file")))
(global-set-key (kbd "s-t") ; tab mode
(lambda ()
(rigpa-enter-mode "tab")))
(global-set-key (kbd "s-l") ; line mode
(lambda ()
(rigpa-enter-mode "line")))
(global-set-key (kbd "s-e") ; application mode
(lambda ()
(rigpa-enter-mode "application")))
(global-set-key (kbd "s-r") ; word mode
(lambda ()
(rigpa-enter-mode "word"))))
(setq aw-keys '(?a ?o ?e ?u ?h ?t ?n ?s))
(global-set-key (kbd "M-n") #'ace-window)
;;; Cario's config :D -- with some mods ;)
;;; Personal settings and appeareance
;;(setq org-directory "~/personal/org/")
;;(setq org-roam-directory "~/personal/roam")
;;(setq doom-font (font-spec :family "iosevka" :size 20))
;; (setq doom-theme 'doom-gruvbox)
;; (setq display-line-numbers-type t)
;; (setq select-enable-clipboard t)
;;; Nixos Interop
;; Opening my nixos configuration
;; (map! :leader
;; :desc "Edit nixos configuration"
;; "f n"
;; (lambda () (interactive) (doom/sudo-find-file "/etc/nixos/configuration.nix")))
;; Prefetching urls
;; (defun nix-prefetch-url ()
;; "Gives back the hash of an url, to use in
;; nixos/configuration.nix, and puts in in the clipboard"
;; (interactive)
;; (kill-new
;; (shell-command-to-string
;; (concat "nix-prefetch-url --unpack "
;; (buffer-substring-no-properties (mark) (point))
;; " 2> /dev/null"))))
;; Packing and unpacking thunks
;; (defun nix-thunk-pack ()
;; "Packs a nix thunk"
;; (interactive)
;; (shell-command (concat "nix-thunk pack " (dired-file-name-at-point))))
;; (defun nix-thunk-unpack ()
;; "Unpacks a nix thunk"
;; (interactive)
;; (shell-command (concat "nix-thunk unpack " (dired-file-name-at-point))))
;; Default viewers in dired buffer (via !)
(setq dired-guess-shell-alist-user
'(("\\.rar$" "unrar x")
("\\.pdf$" "evince")
("\\.epub$" "foliate")
("\\.(mp4|avi|ts)$" "vlc")
("\\.(png|jpg)$" "feh")))
;; Clojure configuration
;; For evaluating clojure forms in (comment)
(after! clojure-mode (setq clojure-toplevel-inside-comment-form t))
;; I also want to not show the eval result in the minibuffer
(after! clojure-mode (setq cider-use-overlays t))
;; Suppress the warnings when I'm not in a project
(after! clojure-mode (setq cider-allow-jack-in-without-project t))
(after! clojure-mode (setq cljr-suppress-no-project-warning t))
;; (map! :mode clojure-mode :nv "SPC k" 'ghostwheel-quickcheck)
(map! :mode clojure-mode :nv "SPC l" 'cider-find-and-clear-repl-output)
(map! :mode clojure-mode :nv "SPC r" 'cider-switch-to-repl-buffer)
;; Not so useful anymore as I use portal
;; Actually, let's wait
;; (map! :mode clojure-mode :nv "SPC d" 'cider-pprint-eval-defun-at-point)
;; Indent >defn as defn
(after! clojure-mode (put-clojure-indent '>defn :defn))
(defun clerk-show ()
(let ((filename (buffer-file-name)))
(when filename
(concat "(nextjournal.clerk/show! \"" filename "\")")))))
(defun open-portal-api ()
(cider-interactive-eval "(do (require 'portal.api)
(add-tap #'portal.api/submit)
(def portella (portal.api/open {:theme :portal.colors/solarized-light :portal.viewer/default :portal.viewer/tree}))
(defun open-portal-web ()
(cider-interactive-eval "(do (require 'portal.web)
(add-tap #'portal.api/submit)
(def portella (portal.api/open {:theme :portal.colors/solarized-light :portal.viewer/default :portal.viewer/tree}))
(defun portal.api/clear ()
"(#?(:clj portal.api/clear :cljs portal.web/clear))"))
(defun portal/invoke-portal-command (command-str)
(concat "(#?(:clj portal.api/eval-str :cljs portal.web/eval-str) \"" command-str "\")")))
(defmacro define-portal-command (command-name)
(let ((emacs-command-name (intern (format "portal-ui-commands/%s" command-name)))
(clojure-invocation (format "(portal.ui.commands/%s portal.ui.state/state)" command-name)))
`(defun ,emacs-command-name ()
(portal/invoke-portal-command ,clojure-invocation))))
(define-portal-command select-root)
(define-portal-command select-next)
(define-portal-command select-prev)
(define-portal-command select-parent)
(define-portal-command select-child)
(define-portal-command history-back)
(define-portal-command toggle-expand)
(define-portal-command focus-selected)
(define-portal-command toggle-shell)
(define-portal-command toggle-shell)
(defun portal-copy ()
(insert (nrepl-dict-get (cider-nrepl-sync-request:eval "@portella") "value")))
(defun portal-ui-commands/set-viewer (viewer)
"(require '[portal.ui.state :as s])
(defn set-viewer! [viewer]
(s/get-selected-context @s/state))]
(set-viewer! :portal.viewer/" viewer ")")))
(defun portal-ui-commands/set-tree-viewer ()
(interactive) (portal-ui-commands/set-viewer "tree"))
(defun portal-ui-commands/set-pprint-viewer ()
(interactive) (portal-ui-commands/set-viewer "pprint"))
(defun portal-ui-commands/set-inspector-viewer ()
(interactive) (portal-ui-commands/set-viewer "inspector"))
(after! clojure-mode
(defhydra hydra-portal (clojure-mode-map "C-c C-c")
("r" portal-ui-commands/select-root "Select root")
("s" portal-ui-commands/select-next "Select next")
("h" portal-ui-commands/select-prev "Select prev")
("k" portal-ui-commands/select-parent "Select parent")
("j" portal-ui-commands/select-child "Select child")
("n" portal-ui-commands/select-child "Select child")
("C-h" portal-ui-commands/history-back "History back")
("-" portal-ui-commands/focus-selected "Focus selected")
("e" portal-ui-commands/toggle-expand "Toggle expand")
("i" portal-ui-commands/set-inspector-viewer "Set inspector viewer")
("t" portal-ui-commands/set-tree-viewer "Set tree viewer")
("p" portal-ui-commands/set-pprint-viewer "Set pprint viewer")
("S" portal-ui-commands/toggle-shell "Toggle shell")
("c" portal-copy "Copy")
(";" portal.api/clear "Clear")
("q" nil "Exit" :exit t)))
(defun portal-select-first ()
(map! :leader
:desc "portal"
"k" #'portal-select-first)
(after! cider-mode
(defun cider-tap (&rest r)
(cons (concat "(let [__value " (caar r) "]"
" (tap> __value)
(cdar r)))
(advice-add 'cider-nrepl-request:eval
:filter-args #'cider-tap))
;; Get versions of libraries
(defun find-clojure-dep ()
"Fuzzy search for a clojure library; needs the lambdaisland aliases"
(let ((desired-package (read-from-minibuffer "Find clojure dep for package: ")))
(concat "clojure -M:search/libraries "
" -l 50 -R :regex -F :merge 2>/dev/null"))))
;; Convenience functions for malli
(defun med/cider-eval-on-top-level-form (fn-str)
(let ((quoted-defn (concat "'" (cider-defun-at-point))))
(cider-interactive-eval (concat "(" fn-str " " quoted-defn ")"))))
(defun malli-check-this ()
"#(portal.malli.visualizer/check->portal (mi/check {:filters [(mi/-filter-var #{(resolve (second %))})]}))"))
(defun malli-check-all ()
(cider-interactive-eval "(-> (mi/check) portal.malli.visualizer/check->portal)"))
(map! :leader
(:prefix-map ("z" . "Generative testing")
"z" #'malli-check-this
"a" #'malli-check-all))
;; Format a clojure region with zprint
(defun format-clojure-zprint (start end)
"Formats inplace a region containing some JSON data"
(interactive (list (region-beginning) (region-end)))
(setq-local buffer-read-only nil)
(when (not (region-active-p))
(evil-set-range (point-min) (point-max))
(evil-visual-make-region (point-min) (point-max)))
;; beginning and end of buffer
(point-min) (point-max)
;; command and parameters
;; output buffer
;; replace?
;; name of the error buffer
"*Clojure zprint format error buffer*"
;; show error buffer?
(defun eval-clojure-command-on-region (start end)
(interactive "r")
(message (buffer-substring-no-properties start end)))
(defun show-fly-err-at-point ()
"If the cursor is sitting on a flymake error, display the
message in the minibuffer"
(let ((line-no (line-number-at-pos)))
(dolist (elem flymake-err-info)
(if (eq (car elem) line-no)
(let ((err (car (second elem))))
(message "%s" (fly-pyflake-determine-message err)))))))
(defun fly-pyflake-determine-message (err)
"pyflake is flakey if it has compile problems, this adjusts the
message to display, so there is one ;)"
(cond ((not (or (eq major-mode 'Python) (eq major-mode 'python-mode) t)))
((null (flymake-ler-file err))
;; normal message do your thing
(flymake-ler-text err))
(t ;; could not compile err
(format "compile error, problem on line %s" (flymake-ler-line err)))))
(defadvice flymake-goto-next-error (after display-message activate compile)
"Display the error in the mini-buffer rather than having to mouse over it"
(defadvice flymake-goto-prev-error (after display-message activate compile)
"Display the error in the mini-buffer rather than having to mouse over it"
(defadvice flymake-mode (before post-command-stuff activate compile)
"Add functionality to the post command hook so that if the
cursor is sitting on a flymake error the error information is
displayed in the minibuffer (rather than having to mouse over
(set (make-local-variable 'post-command-hook)
(cons 'show-fly-err-at-point post-command-hook)))
(defun comment-or-uncomment-current-line-or-region ()
"Comments or uncomments current current line or whole lines in region."
(let (min max)
(if (or (region-active-p) (eq last-command 'comment-or-uncomment-current-line-or-region))
(comment-or-uncomment-region (region-beginning) (region-end))
(goto-char (line-beginning-position))
(goto-char (line-end-position))
(comment-or-uncomment-region (region-beginning) (region-end))))))
(defun cycle-files-with-same-suffix ()
"Cycle between files between the same suffix, e.g. index.css, index.html, index.js"
(let* ((file-name-base (replace-regexp-in-string "\.[^.]*$" "" (buffer-file-name)))
(matching-files (f-entries (f-dirname file-name-base) (lambda (fn) (s-contains-p file-name-base fn)) nil))
(index (-elem-index buffer-file-name matching-files))
(next-counterpart (nth (% (1+ index) (length matching-files)) matching-files)))
(find-file next-counterpart)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment