Emacs configuration files written with the help of org-mode and org-babel
xcode-select --install
brew tap d12frosted/emacs-plus
brew install emacs-plus@30 --with-no-frame-refocus --with-xwidgets --with-native-comp --with-savchenkovaleriy-big-sur-icon
To start a bg service, run:
brew services start emacs-plus@29
brew reinstall emacs-plus@30 --with-no-frame-refocus --with-xwidgets --with-native-comp --with-savchenkovaleriy-big-sur-icon
sometimes when you update macsos you need to make sure gcc and libgccjit is updated as well
brew reinstall gcc libgccjit
Better package management
;;; -*- lexical-binding: t -*-
(message "This is tangled README.el. lexical-binding has the value %S" lexical-binding)
auto-minor-mode (link)
(use-package auto-minor-mode)
better-defaults (link)
(use-package better-defaults
:config
(ido-mode 0))
async (link)
(use-package async
:config
(dired-async-mode 1))
(use-package auth-source
:ensure nil
:no-require t
:custom
(auth-sources '("~/.authinfo.gpg")))
(add-hook 'emacs-startup-hook
(lambda ()
(message "*** Emacs loaded in %s with %d garbage collections."
(format "%.2f seconds"
(float-time
(time-subtract after-init-time before-init-time)))
gcs-done)))
(if (and (fboundp 'server-running-p)
(not (server-running-p)))
(server-start))
(when (featurep 'ns)
(defun ns-raise-emacs ()
"Raise Emacs."
(ns-do-applescript "tell application \"Emacs\" to activate"))
(defun ns-raise-emacs-with-frame (frame)
"Raise Emacs and select the provided frame."
(with-selected-frame frame
(when (display-graphic-p)
(ns-raise-emacs))))
(add-hook 'after-make-frame-functions 'ns-raise-emacs-with-frame)
(when (display-graphic-p)
(ns-raise-emacs)))
When running as a deamon emacs checks if custom.el is in safe place. Here were
setting custom.el in /tmp
dir and it will sometimes throw an
errors. Here is a dirty hack.
(defadvice server-ensure-safe-dir
(around
my-around-server-ensure-safe-dir
activate)
"Ignores any errors raised from server-ensure-safe-dir"
(ignore-errors ad-do-it))
Disable native-compile warnings when starting emacs. Warnings should not break the init of Emacs.
(setq warning-minimum-level :error)
(prefer-coding-system 'utf-8)
(use-package shell
:ensure nil
:hook
(shell-mode . ansi-color-for-comint-mode-on))
(use-package emacs
:ensure nil
:custom
(apropos-do-all t)
(auto-save-default nil)
(bidi-inhibit-bpa t)
(compilation-scroll-output nil)
(completion-ignore-case t)
(create-lockfiles nil)
(cursor-in-non-selected-windows nil)
(debugger-stack-frame-as-list t)
(dired-kill-when-opening-new-dired-buffer t)
(fast-but-imprecise-scrolling t)
(ffap-machine-p-known 'reject)
(frame-resize-pixelwise t)
(frame-title-format nil)
(global-auto-revert-non-file-buffers t)
(highlight-nonselected-windows nil)
(history-delete-duplicates t)
(indent-tabs-mode nil)
(inhibit-compacting-font-caches t)
(inhibit-startup-echo-area-message user-login-name)
(inhibit-startup-message t)
(inhibit-startup-screen t)
(make-backup-files nil)
(minibuffer-prompt-properties '(read-only t point-entered minibuffer-avoid-prompt face minibuffer-prompt))
(narrow-to-defun-include-comments t)
(ns-right-alternate-modifier nil)
(ns-use-proxy-icon nil)
(pop-up-frames nil)
(read-buffer-completion-ignore-case t)
(ring-bell-function 'ignore)
(scroll-conservatively 101)
(scroll-margin 0)
(scroll-preserve-screen-position t)
(scroll-step 1)
(show-paren-mode 1)
(show-trailing-whitespace nil)
(split-height-threshold nil)
(split-width-threshold 170)
(switch-to-buffer-in-dedicated-window nil)
(switch-to-buffer-obey-display-actions t)
(transient-mark-mode t)
(use-dialog-box nil)
(vc-handled-backends nil)
(visible-bell t)
(x-stretch-cursor t)
:config
(set-default 'truncate-lines t)
(global-hl-line-mode 0)
(set-window-margins nil 0 0)
(electric-pair-mode 0)
(line-number-mode 0)
(column-number-mode 0)
(delete-selection-mode 1)
(global-auto-revert-mode 1)
(menu-bar-mode 0)
(save-place-mode 1)
(recentf-mode 1)
(pixel-scroll-precision-mode 1)
;; Better support for files with long lines
(setq-default bidi-display-reordering 'left-to-right
bidi-paragraph-direction 'left-to-right)
(setq-default bidi-inhibit-bpa t)
(global-so-long-mode 1)
(advice-add #'tty-run-terminal-initialization :override #'ignore)
(advice-add #'display-startup-echo-area-message :override #'ignore))
(use-package prog-mode
:ensure nil
:hook (prog-mode . electric-pair-mode))
(setq remote-file-name-inhibit-cache nil)
(setq vc-ignore-dir-regexp
(format "%s\\|%s"
vc-ignore-dir-regexp
tramp-file-name-regexp))
(setq tramp-verbose 1)
(fset 'yes-or-no-p 'y-or-n-p)
;; http://mbork.pl/2021-11-13_y-or-n-p_but_with_RET_meaning_yes
(defconst y-or-n-p-ret-yes-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map y-or-n-p-map)
(define-key map [return] 'act)
map)
"A keymap for y-or-n-p with RET meaning \"yes\".")
(setq y-or-n-p-map y-or-n-p-ret-yes-map)
(global-unset-key (kbd "C-x C-c"))
(global-unset-key (kbd "s-w"))
(global-unset-key (kbd "C-x C-z"))
(global-unset-key (kbd "C-<wheel-up>"))
(global-unset-key (kbd "C-<wheel-down>"))
(global-unset-key (kbd "<mouse-2>"))
(global-unset-key (kbd "s-t"))
;; TODO: find better replacement for those bindigns
(global-set-key (kbd "<pinch>") 'ignore)
(global-set-key (kbd "<C-wheel-up>") 'ignore)
(global-set-key (kbd "<C-wheel-down>") 'ignore)
;; Make shebang (#!) file executable when saved
(add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)
;; font sizes
(global-set-key
(kbd "s-=")
(lambda ()
(interactive)
(let ((old-face-attribute (face-attribute 'default :height)))
(message (format "Changed font size to %d" (+ old-face-attribute 10)))
(set-face-attribute 'default nil :height (+ old-face-attribute 10)))))
(global-set-key
(kbd "s--")
(lambda ()
(interactive)
(let ((old-face-attribute (face-attribute 'default :height)))
(message (format "Changed font size to %d" (- old-face-attribute 10)))
(set-face-attribute 'default nil :height (- old-face-attribute 10)))))
(global-set-key "\C-l" 'goto-line)
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)
(global-set-key (kbd "M-s-<right>") 'tab-next)
(global-set-key (kbd "M-s-<left>") 'tab-previous)
(use-package comint
:ensure nil
:config
(add-to-list 'comint-output-filter-functions 'ansi-color-process-output))
(defun colorize-compilation-buffer ()
(let ((inhibit-read-only t))
(ansi-color-apply-on-region (point-min) (point-max))))
(use-package compilation-mode
:ensure nil
:hook
(compilation-filter . colorize-compilation-buffer))
(use-package auto-compile
:custom
(auto-compile-display-buffer nil)
(auto-compile-mode-line-counter t)
:config
(auto-compile-on-load-mode)
(auto-compile-on-save-mode))
(defun alerter--symbol-value (symbol)
"Stripts keyword symbol name from a colon"
(replace-regexp-in-string "^:" "" (symbol-name symbol)))
(defun alerter--option (args)
"Returns a function that will generate single argument for alerter using ARGS as a string"
(lambda (key)
(concat "-" (alerter--symbol-value key) " " (plist-get args key))))
(setq alerter-default-args
'(:title "Emacs" :sender "org.gnu.Emacs" :timeout "5"))
(defun alerter (message &rest args)
"Notify user using native macOS notifications. MESSAGE will be displayed using alerter package, with additional ARGS"
(if (executable-find "alerter")
(let* ((args (append alerter-default-args args))
(options (seq-filter (lambda (element) (keywordp element)) args))
(config (mapconcat (alerter--option args) options " "))
(cmd (concat "alerter " config " -message \"" (replace-regexp-in-string "\"" "\\\"" message t t) "\" &")))
(message cmd)
(call-process-shell-command cmd))
(error "Can't find alerter executable")))
We need to redefine xwidget-webkit-enable-plugins
variable for webkit
to work properly
(if (boundp 'xwidget-webkit-enable-plugins)
(setq xwidget-webkit-enable-plugins t)
(defvar xwidget-webkit-enable-plugins t))
(use-package framemove
:ensure (framemove :fetcher github :host github :repo "emacsmirror/framemove")
:custom
(framemove-hook-into-windmove t)
:config
(windmove-default-keybindings 'super)
(windmove-swap-states-default-keybindings (list 'super 'control))
(winner-mode 1))
(use-package osx-trash
:if (eq system-type 'darwin)
:defer 2
:custom
(osx-trash-setup)
(osx-trash-command "trash -F")
(delete-by-moving-to-trash t))
(when (eq system-type 'darwin)
(defvar ls-lisp-use-insert-directory-program)
(defvar powerline-image-apple-rgb)
(setq ns-use-srgb-colorspace t)
(setq powerline-image-apple-rgb t)
(require 'ls-lisp)
(setq ls-lisp-use-insert-directory-program nil))
Very annoying binding, lets get rid of it.
(global-unset-key (kbd "C-z"))
(use-package browse-url
:ensure nil
:custom
(browse-url-browser-function 'browse-url-default-browser))
(use-package browse-url-dwim
:defer 2
:config
(browse-url-dwim-mode 1))
(use-package epa
:ensure-system-package pinentry-mac
:ensure nil
:custom
(epa-file-encrypt-to "[email protected]")
(password-cache-expiry (* 60 15))
(epa-file-select-keys t)
(epg-pinentry-mode 'loopback))
when starting, we should prepare our gpg config
gpg --list-keys
echo "pinentry-program /opt/homebrew/bin/pinentry-mac" >> $HOME/.gnupg/gpg-agent.conf
gpg --expert --full-generate-key
https://alexschroeder.ch/wiki/2016-03-17_GPG_Agent_and_Emacs
(use-package re-builder
:ensure nil
:custom
(reb-re-syntax 'string))
(use-package popper
:ensure t ; or :straight t
:bind (("s-§" . popper-toggle-latest)
("M-§" . popper-cycle)
("s-M-§" . popper-toggle-type)
("s-<escape>" . popper-toggle-latest)
("M-<escape>" . popper-cycle)
("C-M-<escape>" . popper-toggle-type))
:custom
(popper-reference-buffers
'("\\*Messages\\*"
"Output\\*$"
"\\*Async Shell Command\\*"
compilation-mode
vterm-mode
"\\*verminal"))
(popper-mode-line '(:eval
(propertize " POP " 'face 'mode-line-emphasis)))
(popper-display-control t)
(popper-group-function nil)
:config
(popper-mode +1)
(popper-echo-mode +1))
Shackle (link)
Shackle gives you the means to put an end to popped up buffers not behaving they way you’d like them to. By setting up simple rules you can for instance make Emacs always select help buffers for you or make everything reuse your currently selected window.
(use-package shackle
:custom
(shackle-rules
'(("*eshell*" :select t :other t)
(flycheck-error-list-mode :select t :align below :size 0.25)
("*LSP Error List*" :select t :align below :size 0.25)
(compilation-mode :select nil :align below :size 0.25)
(messages-buffer-mode :select t :align below :size 0.25)
(inferior-emacs-lisp-mode :select t :align below :size 0.25)
("\\*vterminal.*" :select t :align below :size 0.25 :regexp t)
(vterm-mode :select t :align below :size 0.25)
(multi-vterm :select t :align below :size 0.25)
("*rg*" :select t :other t)
(" *Deletions*" :select t :align below :size 0.25)
(" *Marked Files*" :select t :align below :size 0.25)
("*system-packages*" :select t :align below :size 0.25)
("*Org Select*" :same t)
("*Org Note*" :select t :align below :size 0.33)
("*Org Links*" :select t :align below :size 0.2)
(" *Org todo*" :select t :align below :size 0.2)
("*Man.*" :select t :align below :size 0.5 :regexp t)
("*Org Src.*" :select t :align right :size 0.5 :regexp t)))
(shackle-default-rule
'(:select t))
:config
(shackle-mode t))
(use-package tab-bar
:ensure nil
:custom
;; Do not show buttons.
(tab-bar-new-button-show t)
(tab-bar-close-button-show t)
(tab-bar-tab-hints t))
(use-package tab-line
:ensure nil
:custom
(tab-line-separator " | ")
(tab-line-close-button-show nil)
(tab-line-new-button-show nil))
(use-package explain-pause-mode
:ensure (explain-pause-mode :fetcher github :repo "lastquestion/explain-pause-mode"))
Vertico (link)
Some of the config is borrowed straight from Kristoffer Balintonas blog post from
(defun my/vertico-multiform-flat-toggle ()
"Toggle between flat and reverse."
(interactive)
(vertico-multiform--display-toggle 'vertico-flat-mode)
(if vertico-flat-mode
(vertico-multiform--temporary-mode 'vertico-reverse-mode -1)
(vertico-multiform--temporary-mode 'vertico-reverse-mode 1)))
(defun my/vertico-quick-embark (&optional arg)
"Embark on candidate using quick keys."
(interactive)
(when (vertico-quick-jump)
(embark-act arg)))
(use-package vertico
:demand t
:hook ((rfn-eshadow-update-overlay . vertico-directory-tidy)
(minibuffer-setup . vertico-repeat-save))
:bind (:map vertico-map
("<tab>" . vertico-insert)
("<escape>" . minibuffer-keyboard-quit)
("?" . minibuffer-completion-help)
("C-M-n" . vertico-next-group)
("C-M-p" . vertico-previous-group)
("M-o" . my/vertico-quick-embark)
("C-l" . my/vertico-multiform-flat-toggle)
("C-i" . vertico-quick-insert)
("C-o" . vertico-quick-exit)
("M-G" . vertico-multiform-grid)
("M-F" . vertico-multiform-flat)
("M-R" . vertico-multiform-reverse)
("M-U" . vertico-multiform-unobtrusive)
("<backspace>" . vertico-directory-delete-char)
("C-w" . vertico-directory-delete-word)
("C-<backspace>" . vertico-directory-delete-word)
("RET" . vertico-directory-enter))
:custom
(vertico-resize t)
(vertico-cycle t)
(vertico-grid-separator " ")
(vertico-grid-lookahead 50)
(vertico-buffer-display-action '(display-buffer-reuse-window))
(vertico-multiform-categories
'((consult-line
posframe
(vertico-posframe-poshandler . posframe-poshandler-frame-top-center)
(vertico-posframe-border-width . 10)
(vertico-posframe-fallback-mode . vertico-buffer-mode))
(consult-grep buffer)
(consult-ripgrep buffer)
(consult-buffer reverse indexed)
(imenu buffer)
(library indexed)
(org-roam-node posframe indexed)
(t posframe)))
:config
(vertico-mode 1)
(vertico-multiform-mode 1))
(use-package vertico-posframe
:after vertico
:custom
(vertico-posframe-parameters
'((left-fringe . 8)
(right-fringe . 8))))
also helpful emacs config just for vertico
(use-package emacs
:ensure nil
:bind
("s-," . (lambda () (interactive)
(find-file (concat user-emacs-directory "README.org"))))
:init
(defun crm-indicator (args)
(cons (format "[CRM%s] %s"
(replace-regexp-in-string
"\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
crm-separator)
(car args))
(cdr args)))
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)
:custom
;; Do not allow the cursor in the minibuffer prompt
(minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
;; Emacs 28: Hide commands in M-x which do not work in the current mode.
;; Vertico commands are hidden in normal buffers.
(read-extended-command-predicate
#'command-completion-default-include-p)
;; Enable recursive minibuffers
(enable-recursive-minibuffers nil))
(use-package recursion-indicator
:demand t
:config
(recursion-indicator-mode))
Orderless (link)
(use-package orderless
:init
(setq completion-styles '(orderless basic)
completion-category-defaults nil
completion-category-overrides '((file (styles partial-completion)))))
(use-package savehist
:ensure nil
:after no-littering
:custom
(history-length 100)
:config
(savehist-mode))
Consult (link)
;; Example configuration for Consult
(use-package consult
:defer 2
;; Replace bindings. Lazily loaded due by `use-package'.
:bind (;; C-c bindings (mode-specific-map)
("C-c h" . consult-history)
("C-c m" . consult-mode-command)
("C-c b" . consult-bookmark)
("C-c k" . consult-kmacro)
;; C-x bindings (ctl-x-map)
("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command
("C-x b" . consult-buffer) ;; orig. switch-to-buffer
("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame
;; Custom M-# bindings for fast register access
("M-#" . consult-register-load)
("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated)
("C-M-#" . consult-register)
;; Other custom bindings
("M-y" . consult-yank-pop) ;; orig. yank-pop
("<help> a" . consult-apropos) ;; orig. apropos-command
;; M-g bindings (goto-map)
("M-g e" . consult-compile-error)
("M-g f" . consult-flymake) ;; Alternative: consult-flycheck
("M-g g" . consult-goto-line) ;; orig. goto-line
("M-g M-g" . consult-goto-line) ;; orig. goto-line
("M-g o" . consult-outline) ;; Alternative: consult-org-heading
("M-g m" . consult-mark)
("M-g k" . consult-global-mark)
("M-g i" . consult-imenu)
("M-g I" . consult-imenu-multi)
;; M-s bindings (search-map)
("M-s f" . consult-find)
("M-s F" . consult-locate)
("M-s g" . consult-grep)
("M-s G" . consult-git-grep)
("M-s r" . consult-ripgrep)
("M-s l" . consult-line)
("M-s L" . consult-line-multi)
("M-s m" . consult-multi-occur)
("M-s k" . consult-keep-lines)
("M-s u" . consult-focus-lines)
;; Isearch integration
("M-s e" . consult-isearch-history)
:map isearch-mode-map
("M-e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s l" . consult-line) ;; needed by consult-line to detect isearch
("M-s L" . consult-line-multi)) ;; needed by consult-line to detect isearch
;; Enable automatic preview at point in the *Completions* buffer.
;; This is relevant when you use the default completion UI,
;; and not necessary for Vertico, Selectrum, etc.
;; The :init configuration is always executed (Not lazy)
:init
;; Optionally configure the register formatting. This improves the register
;; preview for `consult-register', `consult-register-load',
;; `consult-register-store' and the Emacs built-ins.
(setq register-preview-delay 0.5
register-preview-function #'sconsult-register-format)
;; Optionally tweak the register preview window.
;; This adds thin lines, sorting and hides the mode line of the window.
(advice-add #'register-preview :override #'consult-register-window)
;; Use Consult to select xref locations with preview
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
:config
(setq consult-preview-key "M-.")
(setq consult-narrow-key "<") ;; (kbd "C-+")
(autoload 'projectile-project-root "projectile")
(setq consult-project-root-function #'projectile-project-root)
(defun consult-info-emacs ()
"Search through Emacs info pages."
(interactive)``
(consult-info "emacs" "efaq" "elisp" "cl" "compat")))
Consult Projectile (link)
(use-package consult-projectile
:bind-keymap ("C-c p" . projectile-command-map)
:bind (:map projectile-command-map
("p" . consult-projectile))
:custom
(projectile-switch-project-action 'consult-projectile))
Consult flycheck (link)
(use-package consult-flycheck
:after (consult flycheck))
Consult Dir (link)
(use-package consult-dir
:ensure t
:bind (("C-x C-d" . consult-dir)
:map vertico-map
("C-x C-d" . consult-dir)
("C-x C-j" . consult-dir-jump-file)))
(use-package tramp
:ensure nil
:custom
(tramp-inline-compress-start-size 1000)
(tramp-copy-size-limit 10000)
(vc-handled-backends '(Git))
(tramp-default-method "scp")
(tramp-use-ssh-controlmaster-options nil)
(projectile--mode-line "Projectile")
(tramp-verbose 1))
Packages
(use-package flycheck
:defer 1
:hook (prog-mode . flycheck-mode)
:custom-face
(flycheck-error ((t (:underline (:color "#e74c3c" :style wave) :background unspecified))))
(flycheck-info ((t (:underline (:color "#b6e63e" :style wave) :background unspecified))))
:custom
(flycheck-idle-change-delay 0)
(flycheck-disabled-checkers '(emacs-lisp-checkdoc)))
(use-package flycheck-rust
:after (flycheck rust-mode))
(use-package sideline
:after (flycheck lsp)
:defines sideline-backends-right
:custom
(sideline-backends-left-skip-current-line t)
(sideline-backends-right-skip-current-line t)
(sideline-order-left 'down)
(sideline-order-right 'up)
(sideline-format-left "%s ")
(sideline-format-right " %s")
(sideline-priority 100)
(sideline-display-backend-name nil))
(use-package sideline-flycheck
:hook (flycheck-mode . sideline-flycheck-setup)
:config
(add-to-list 'sideline-backends-right 'sideline-flycheck))
(use-package sideline-lsp
:after lsp
:custom
(sideline-lsp-code-actions-prefix "")
:config
(add-to-list 'sideline-backends-right 'sideline-lsp))
(use-package command-log
:ensure (command-log
:fetcher github :repo "positron-solutions/command-log")
:custom
(command-log-mouse t)
(command-log-text t)
(command-log-merge-repeats t)
(command-log-filter-commands '(self-insert-command handle-switch-frame org-self-insert-command)))
(use-package restclient
:defer t
:mode (("\\.http\\'" . restclient-mode))
:bind (:map restclient-mode-map
("C-c C-f" . json-mode-beautify)))
(use-package jq-mode
:after (org-mode json-mode)
:commands (jq-mode jq-interactively)
:mode ("\\.jq$" . js-mode)
:bind (:map json-mode-map
("C-c C-j" . jq-interactively))
:config
(org-babel-add-langs
((jq . t))))
(defun my/corfu-setup-lsp ()
"Use orderless completion style with lsp-capf instead of the
default lsp-passthrough."
(setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults))
'(orderless)))
(setq lsp-use-plists "true")
(use-package lsp-mode
:commands (lsp lsp-deferred)
:after (corfu orderless)
:hook
((lsp-mode . lsp-enable-which-key-integration)
(lsp-completion-mode . my/corfu-setup-lsp))
:custom
(lsp-log-io nil)
(lsp-file-watch-threshold 4000)
(lsp-headerline-breadcrumb-enable nil)
(lsp-headerline-breadcrumb-icons-enable nil)
(lsp-headerline-breadcrumb-enable-diagnostics nil)
(lsp-headerline-breadcrumb-segments '(file symbols))
(lsp-auto-guess-root t)
(lsp-enable-file-watchers nil)
(lsp-clients-typescript-preferences
'(:includeCompletionsForModuleExports nil :generateReturnInDocTemplate nil))
(lsp-clients-typescript-prefer-use-project-ts-server t)
(lsp-completion-provider :none)
(lsp-diagnostic-clean-after-change t)
(lsp-diagnostics-modeline-scope :workspace)
(lsp-enable-indentation nil)
(lsp-enable-on-type-formatting nil)
(lsp-javascript-display-enum-member-value-hints t)
(lsp-javascript-format-enable nil)
(lsp-keymap-prefix "s-l")
(lsp-lens-enable t)
(lsp-typescript-format-enable nil)
(lsp-yaml-schema-store-local-db
(no-littering-expand-var-file-name "./lsp/lsp-yaml-schemas.json"))
(lsp-yaml-custom-tags '("!reference sequence")))
(use-package lsp-ui
:after lsp-mode
:hook (lsp-mode . lsp-ui-mode)
:bind
(:map lsp-ui-mode-map
(([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
([remap xref-find-references] . lsp-ui-peek-find-references)))
:custom
(lsp-ui-doc-enable t)
(lsp-ui-doc-position 'at-point)
(lsp-ui-doc-alignment 'window)
(lsp-ui-doc-show-with-cursor nil)
(lsp-ui-doc-show-with-mouse t)
(lsp-ui-doc-use-childframe t)
(lsp-ui-doc-border "windowBacekgroundColor")
(lsp-ui-doc-include-signature t)
(lsp-ui-doc-max-height 15)
(lsp-ui-doc-max-width 100)
(lsp-ui-sideline-enable nil)
(lsp-lens-enable nil))
(use-package lsp-tailwindcss
:after lsp
:custom
(lsp-tailwindcss-add-on-mode t))
(use-package dabbrev
:ensure nil
;; Swap M-/ and C-M-/
:bind (("M-/" . dabbrev-completion)
("C-M-/" . dabbrev-expand))
:config
(add-to-list 'dabbrev-ignored-buffer-regexps "\\` ")
;; Since 29.1, use `dabbrev-ignored-buffer-regexps' on older.
(add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode)
(add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode))
(defun shell-maker-welcome-message-ignore (config) "")
(use-package chatgpt-shell
:preface
(defun shfx-chatgpt-dwim ()
"Run dwim in any buffer with "
(interactive)
(if (region-active-p)
(chatgpt-shell-quick-modify-region)
(chatgpt-shell-quick-insert)))
:commands
(chatgpt-shell
chatgpt-shell-prompt
chatgpt-shell-send-region
chatgpt-shell-explain-code
chatgpt-shell-refactor-code
chatgpt-shell-view-at-point
chatgpt-shell-search-history
chatgpt-shell-quick-modify-region
chatgpt-shell-quick-insert)
:bind
("C-c C-a" . shfx-chatgpt-dwim)
:custom
(chatgpt-shell-openai-key (cadr (auth-source-user-and-password "chatgpt" "shfx")))
(chatgpt-shell-welcome-function 'shell-maker-welcome-message-ignore))
(use-package proced
:ensure nil
:defer t
:custom
(proced-enable-color-flag t)
(proced-tree-flag t))
(use-package copilot
:ensure (copilot :fetcher github
:repo "zerolfx/copilot.el"
:branch "main"
:files ("dist" "*.el"))
:bind
(:map copilot-completion-map (("<tab>" . copilot-accept-completion)
("TAB" . copilot-accept-completion)
("C-TAB" . 'copilot-accept-completion-by-word)
("C-<tab>" . 'copilot-accept-completion-by-word)))
)
(use-package apheleia
:config
(apheleia-global-mode +1)
(setf (alist-get 'prisma-mode apheleia-mode-alist)
'(prettier)))
Enables tree-sitter in all programming languages supported. Should be loaded before any language package
(use-package treesit
:ensure nil
:custom
(treesit-font-lock-level 4))
(use-package treesit-auto
:custom
(treesit-auto-install 'prompt)
:functions global-treesit-auto-mode
:defines global-treesit-auto-modes
:preface
(defun my/ts-mode-p (mode)
(let* ((mode-name (symbol-name mode)))
(cond
((string-suffix-p "ts-mode" mode-name) t)
(t nil))))
(defun my/bring-previous-mode-hooks ()
(let ((mode-name (symbol-name major-mode)))
(if (not (my/ts-mode-p major-mode))
(error "Current mode does not contain -ts suffix: %s" mode-name)
(let* (
(non-ts-mode-name (concat (string-remove-suffix "-ts" (string-remove-suffix "-mode" mode-name)) "-mode"))
(non-ts-mode-hook-name (concat non-ts-mode-name "-hook")))
(if (not (intern non-ts-mode-hook-name))
(message "There is no hook list named %s" non-ts-mode-hook-name)
(run-hooks (intern non-ts-mode-hook-name))
(message "Ran hook for %s" non-ts-mode-hook-name))))))
(defun my/get-treesit-auto-modes ()
"Extracts all available treesit auto modes"
(unless global-treesit-auto-modes
(error "global-treesit-auto-modes vartable does not exist, can't transfer hooks from non treesit modes"))
(seq-filter 'my/ts-mode-p global-treesit-auto-modes))
:config
(add-to-list 'treesit-auto-langs 'svelte)
(add-to-list 'treesit-auto-recipe-list
(make-treesit-auto-recipe
:lang 'prisma
:ts-mode 'prisma-ts-mode
:remap '(prisma-mode)
:url "https://github.com/victorhqc/tree-sitter-prisma"
:revision "master"
:source-dir "src"
:ext "\\.prisma\\'"))
(add-to-list 'treesit-auto-recipe-list
(make-treesit-auto-recipe
:lang 'svelte
:ts-mode 'svelte-ts-mode
:remap 'svelte-mode
:url "https://github.com/Himujjal/tree-sitter-svelte"
:source-dir "./src"
:ext "\\.svelte\\'"))
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode)
;; add lambda function hook to list of emacs hooks
(dolist (mode (my/get-treesit-auto-modes))
(let* ((mode-name (symbol-name mode))
(hook-name (concat mode-name "-hook")))
(add-hook (intern hook-name) #'my/bring-previous-mode-hooks))))
(use-package treesit-fold
:ensure (treesit-fold :fetcher github :repo "emacs-tree-sitter/treesit-fold"))
(use-package project-tasks
:after project
:defer t
:commands (project-tasks)
:init
;; Show project-tasks when switching projects
(add-to-list 'project-switch-commands '(project-tasks "tasks") t)
;; Add action to embark-file map
(with-eval-after-load 'embark
(define-key embark-file-map (kbd "P") #'project-tasks-in-dir))
:custom
;; Set the list of tasks files
(project-tasks-files '("tasks.org"))
;; Set the ignore files
;; (project-tasks-ignore-files '("README.org"))
;; Set the function to get current project dir
;; (project-tasks-root-func #'project-tasks-project-root)
;; Set the separator between file name and task name
;; (project-tasks-separator " -> ")
:config
(add-to-list 'marginalia-prompt-categories '("select task" . project-task))
(defvar-keymap embark-project-task-actions
:doc "Keymap for actions for project-task (when mentioned by name)."
:parent embark-general-map
"j" #'project-tasks-goto-task)
(add-to-list 'embark-keymap-alist '(project-task . embark-project-task-actions))
;; Bind project-tasks to project keymap
:bind
(:map project-prefix-map ("P" . project-tasks)))
(use-package dashboard
:custom
(initial-buffer-choice (lambda () (get-buffer-create "*dashboard*")))
(dashboard-startup-banner 'logo)
(dashboard-items '((recents . 5)
(bookmarks . 5)
(projects . 5)
(agenda . 5)
(registers . 5)))
(dashboard-display-icons-p t)
(dashboard-icon-type 'all-the-icons)
(dashboard-modify-heading-icons '((recents . "file-text")
(bookmarks . "book")))
(dashboard-set-navigator t)
(dashboard-week-agenda t)
;; Format: "(icon title help action face prefix suffix)"
(dashboard-navigator-buttons
`((("Homepage"
"Browse homepage"
(lambda (&rest _) (browse-url "homepage")))
("Star" "Show stars" (lambda (&rest _) (show-stars)) warning)
("?" "" "?/h" #'show-help nil "<" ">"))
;; line 2
(("linkedin"
""
(lambda (&rest _) (browse-url "homepage")))
("⚑" nil "Show flags" (lambda (&rest _) (message "flag")) error))))
:config
(dashboard-setup-startup-hook))
(use-package bufler
:bind
("C-x C-b" . bufler-list)
:custom
(bufler-workspace-switch-buffer-sets-workspace t))
Eshell (link)
Eshell is a shell written entirely in Emacs-Lisp, and it replicates most of the features and commands from GNU CoreUtils and the Bourne-like shells. So by re-writing common commands like ls and cp in Emacs-Lisp, Eshell will function identically on any environment Emacs itself runs on.
(use-package eshell
:ensure nil
:after corfu
:functions
(eshell-previous-matching-input-from-input
eshell-next-matching-input-from-input)
:defines (eshell-mode-map eshell-hist-mode-map)
:hook
(eshell-mode
. (lambda ()
(setq-local
corfu-auto nil
corfu-quit-at-boundary t
corfu-quit-no-match t
corfu-separatvor nil)
(corfu-mode)))
(eshell-hist-mode
. (lambda ()
(unbind-key (kbd "<up>") eshell-hist-mode-map)
(unbind-key (kbd "<down>") eshell-hist-mode-map)
(unbind-key (kbd "M-r") eshell-hist-mode-map)
(define-key eshell-hist-mode-map
(kbd "C-<up>")
'eshell-previous-matching-input-from-input)
(define-key eshell-hist-mode-map
(kbd "C-<down>")
'eshell-next-matching-input-from-input)))
:bind
(:map eshell-mode-map
("<up>" . previous-line)
("<down>" . next-line)
("<down>" . next-line)
("M-r" . consult-history))
:custom
(eshell-visual-commands nil)
(eshell-banner-message "")
(eshell-scroll-to-bottom-on-input 'all)
(eshell-error-if-no-glob t)
(eshell-hist-ignoredups t)
:config
(setenv "PAGER" "cat")
(setenv "TERM" "xterm-256color"))
(use-package eat
:hook
(eshell-load . eat-eshell-mode)
:custom
(eat-term-name "xterm"))
(use-package pcmpl-args
:after eshell)
(use-package pcmpl-homebrew
:after eshell)
(defun eshell/gst (&rest args)
(magit-status (pop args) nil)
(eshell/echo))
(defun eshell/ccat (file)
"Like `cat' but output with Emacs syntax highlighting."
(with-temp-buffer
(insert-file-contents file)
(let ((buffer-file-name file))
(delay-mode-hooks
(set-auto-mode)
(if (fboundp 'font-lock-ensure)
(font-lock-ensure)
(with-no-warnings
(font-lock-fontify-buffer)))))
(buffer-string)))
(use-package multi-eshell
:ensure (multi-eshell :fetcher github :repo "emacsmirror/multi-eshell")
:bind (("s-s" . multi-eshell)
("s-n" . multi-eshell-switch)
("s-p" . multi-eshell-go-back))
:custom
(multi-eshell-shell-function '(eshell))
(multi-eshell-name "*eshell*"))
(defun corfu-send-shell (&rest _)
"Send completion candidate when inside comint/eshell."
(cond
((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input))
(eshell-send-input))
((and (derived-mode-p 'comint-mode) (fboundp 'comint-send-input))
(comint-send-input))))
(advice-add #'corfu-insert :after #'corfu-send-shell)
(use-package shrink-path
:after eshell
:custom
((eshell-prompt-regexp "^[^❯\n]* ❯ ")
(eshell-prompt-function
(lambda ()
(let ((base/dir (shrink-path-prompt default-directory)))
(concat (propertize (car base/dir)
'face 'font-lock-comment-face)
(propertize (cdr base/dir)
'face 'font-lock-constant-face)
(propertize " ❯" 'face 'eshell-prompt-face)
;; needed for the input text to not have prompt face
(propertize " " 'face 'default)))))))
(defun toggle-frame-maximized-undecorated ()
(interactive)
(let* ((frame (selected-frame))
(on? (and (frame-parameter frame 'undecorated)
(eq (frame-parameter frame 'fullscreen) 'maximized)))
(geom (frame-monitor-attribute 'geometry))
(initial-x (first geom))
(display-height (first (last geom))))
(if on?
(progn
(set-frame-parameter frame 'undecorated nil)
(toggle-frame-maximized))
(progn
(set-frame-position frame initial-x 0)
(set-frame-parameter frame 'fullscreen 'maximized)
(set-frame-parameter frame 'undecorated t)
(set-frame-height frame (- display-height 26) nil t)
(set-frame-position frame initial-x 0)))))
Scratch (link)
Scratch is an extension to Emacs that enables one to create scratch buffers that are in the same mode as the current buffer. This is notably useful when working on code in some language; you may grab code into a scratch buffer, and, by virtue of this extension, do so using the Emacs formatting rules for that language.
(use-package scratch)
Eshell Toggle (link)
Simple functionality to show/hide eshell/ansi-term (or almost any other buffer, see eshell-toggle-init-function description below) at the bottom of active window with directory of its buffer.
(use-package eshell-toggle
:after eshell
:bind
("s-`" . eshell-toggle)
:custom
(eshell-toggle-name-separator " ❯ ")
(eshell-toggle-size-fraction 3)
(eshell-toggle-use-projectile-root t))
(use-package esup)
(use-package vterm
:custom
(vterm-always-compile-module t))
(use-package multi-vterm
:after vterm
:bind (("C-c v" . multi-vterm)))
;; Enable richer annotations using the Marginalia package
(use-package marginalia
:demand t
:bind (:map minibuffer-local-map
("M-A" . marginalia-cycle))
:custom
;; (marginalia-max-relative-age)
(marginalia-align 'right)
:config
(marginalia-mode))
(use-package diff-hl
:commands global-diff-hl-mode
:hook
((magit-pre-refresh . diff-hl-magit-pre-refresh)
(magit-post-refresh . diff-hl-magit-post-refresh)
(dired-mode . diff-hl-dired-mode))
:config
(global-diff-hl-mode))
Editor Config (link)
EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.
(use-package editorconfig
:init
(editorconfig-mode 1))
(use-package posframe)
(use-package goggles
:hook ((prog-mode text-mode) . goggles-mode)
:custom
(goggles-pulse t))
(use-package expreg
:ensure t
:bind
("C-=" . expreg-expand)
("C--" . expreg-contract))
(use-package launchctl)
(use-package restart-emacs)
(use-package matching-paren-overlay
:ensure
(matching-paren-overlay
:fetcher git
:url "https://codeberg.org/acdw/matching-paren-overlay.el.git"))
(use-package emacs
:ensure nil
:preface
(set-face-attribute 'default nil :font "JetBrains Mono" :height 150)
:if (not (file-exists-p "~//Library/Fonts/JetBrainsMono[wght].ttf"))
:ensure-system-package font-jetbrains-mono)
(use-package nerd-icons
:defines nerd-icons-regexp-icon-alist
:custom
(nerd-icons-color-icons t)
:config
(add-to-list 'nerd-icons-regexp-icon-alist
'("_?test\\.rb$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-red))
(add-to-list 'nerd-icons-regexp-icon-alist
'("_?test_helper\\.rb$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-dred))
(add-to-list 'nerd-icons-regexp-icon-alist
'("_?spec\\.rb$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-red))
(add-to-list 'nerd-icons-regexp-icon-alist
'("_?spec_helper\\.rb$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-dred))
(add-to-list 'nerd-icons-regexp-icon-alist
'("-?spec\\.ts$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-blue))
(add-to-list 'nerd-icons-regexp-icon-alist
'("-?test\\.ts$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-blue))
(add-to-list 'nerd-icons-regexp-icon-alist
'("-?spec\\.js$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-lpurple))
(add-to-list 'nerd-icons-regexp-icon-alist
'("-?test\\.js$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-lpurple))
(add-to-list 'nerd-icons-regexp-icon-alist
'("-?spec\\.jsx$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-blue-alt))
(add-to-list 'nerd-icons-regexp-icon-alist
'("-?test\\.jsx$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-blue-alt)))
(use-package nerd-icons-dired
:hook (dired-mode . nerd-icons-dired-mode))
(use-package nerd-icons-ibuffer
:hook (ibuffer-mode . nerd-icons-ibuffer-mode))
(use-package nerd-icons-completion
:after corfu marginalia
:functions (nerd-icons-completion-mode nerd-icons-completion-marginalia-setup)
:config
(nerd-icons-completion-mode)
(add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))
(use-package nerd-icons-corfu
:after corfu
:config
(add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
(use-package treemacs
:bind
(:map global-map
("M-0" . treemacs-select-window)
("C-x t 1" . treemacs-delete-other-windows)
("C-x t t" . treemacs)
("C-x t d" . treemacs-select-directory)
("C-x t B" . treemacs-bookmark)
("C-x t C-t" . treemacs-find-file)
("C-x t M-t" . treemacs-find-tag))
:config
(treemacs-follow-mode t)
(treemacs-filewatch-mode t)
(treemacs-fringe-indicator-mode 'always))
(use-package treemacs-projectile
:after (treemacs projectile)
:ensure t)
(use-package treemacs-nerd-icons
:after treemacs
:config
(treemacs-load-theme "nerd-icons"))
(use-package kanagawa-themes
:ensure t
:custom-face
(markdown-header-delimiter-face ((t (:inherit markdown-header-face))))
:custom
(kanagawa-themes-comment-italic nil)
(kanagawa-themes-keyword-italic nil)
:config
(load-theme 'kanagawa-wave t)
(dolist (face '(vertico-current
flycheck-inline-info
flycheck-inline-error
flycheck-inline-warning
completions-annotations))
(when (facep face)
(make-face-unitalic face))))
;; This assumes you've installed the package via MELPA.
(use-package ligature
:functions ligature-set-ligatures global-ligature-mode
:config
;; Enable the "www" ligature in every possible major mode
(ligature-set-ligatures 't '("www"))
;; Enable traditional ligature support in eww-mode, if the
;; `variable-pitch' face supports it
(ligature-set-ligatures 'eww-mode '("ff" "fi" "ffi"))
;; Enable all Cascadia Code ligatures in programming modes
(ligature-set-ligatures 'prog-mode '("|||>" "<|||" "<==>" "<!--" "####" "~~>" "***" "||=" "||>"
":::" "::=" "=:=" "===" "==>" "=!=" "=>>" "=<<" "=/=" "!=="
"!!." ">=>" ">>=" ">>>" ">>-" ">->" "->>" "-->" "---" "-<<"
"<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->"
"<--" "<-<" "<<=" "<<-" "<<<" "<+>" "</>" "###" "#_(" "..<"
"..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~="
"~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|"
"[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:"
">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:"
"<$" "<=" "<>" "<-" "<<" "<+" "</" "#{" "#[" "#:" "#=" "#!"
"##" "#(" "#?" "#_" "%%" ".=" ".-" ".." ".?" "+>" "++" "?:"
"?=" "?." "??" ";;" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)"
"\\\\" "://"))
;; Enables ligature checks globally in all buffers. You can also do it
;; per mode with `ligature-mode'.
(global-ligature-mode t))
Projectile (link)
Projectile is a project interaction library for Emacs. Its goal is to provide a nice set of features operating on a project level without introducing external dependencies (when feasible)
(use-package projectile
:demand t
:bind-keymap
("C-c p" . projectile-command-map)
:custom
(projectile-enable-caching nil)
(projectile-sort-order 'recently-active)
(projectile-project-search-path '("~/Developer/"))
(projectile-ignored-projects `("~/"
"/opt/homebrew"
"/tmp/"
"/private/tmp/"
"~/Developer/work"
,package-user-dir))
(projectile-track-known-projects-automatically nil)
:config
(projectile-mode)
;; Projectile is testing in the reverse order so more specific must me at the end
(projectile-register-project-type
'npm '("package.json")
:compile "npm i"
:test "npm test"
:run "npm start"
:test-suffix ".spec.js")
(projectile-register-project-type
'opera
'("desktop/BUILD.gn" "desktop/gn_opera.py")
:project-file "desktop/BUILD.gn"
:run (concat "open $HOME/Developer/work/chromium/src/out/Release/Opera.app --args"
" --allow-running-insecure-content"
" --disable-web-security"
" --ignore-certificate-errors"
" --remote-debugging-port=9222"
" --sticky-site-url-override=https://gxcorner.games"
" --user-data-dir=$HOME/Developer/clean-profile/$(date +\"%Y-%m-%dT%H:%M:%S\")"
" --use-mock-keychain")
:configure "$HOME/goma/goma_ctl.py ensure_start && desktop/gn_opera.py --release product=\\\"gx\\\" use_jumbo_build=false use_remoteexec=true goma_dir=\"\\\"/Users/opera_user/goma\\\"\""
:compile "autoninja -C chromium/src/out/Release opera"))
ibuffer-projectile (link)
(use-package ibuffer-projectile
:hook
(ibuffer . (lambda ()
(ibuffer-projectile-set-filter-groups)
(unless (eq ibuffer-sorting-mode 'alphabetic)
(ibuffer-do-sort-by-alphabetic)))))
Embark (link)
(defun embark-which-key-indicator ()
"An embark indicator that displays keymaps using which-key.
The which-key help message will show the type and value of the
current target followed by an ellipsis if there are further
targets."
(lambda (&optional keymap targets prefix)
(if (null keymap)
(which-key--hide-popup-ignore-command)
(which-key--show-keymap
(if (eq (plist-get (car targets) :type) 'embark-become)
"Become"
(format "Act on %s '%s'%s"
(plist-get (car targets) :type)
(embark--truncate-target (plist-get (car targets) :target))
(if (cdr targets) "…" "")))
(if prefix
(pcase (lookup-key keymap prefix 'accept-default)
((and (pred keymapp) km) km)
(_ (key-binding prefix 'accept-default)))
keymap)
nil nil t (lambda (binding)
(not (string-suffix-p "-argument" (cdr binding))))))))
(defun embark-hide-which-key-indicator (fn &rest args)
"Hide the which-key indicator immediately when using the completing-read prompter."
(which-key--hide-popup-ignore-command)
(let ((embark-indicators
(remq #'embark-which-key-indicator embark-indicators)))
(apply fn args)))
(advice-add #'embark-completing-read-prompter
:around #'embark-hide-which-key-indicator)
(use-package embark
:after which-key
:demand t
:bind
(("s-." . embark-act) ;; pick some comfortable binding
("C-;" . embark-dwim) ;; good alternative: M-.
("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
:custom
(embark-indicators
'(embark-which-key-indicator
embark-highlight-indicator
embark-isearch-highlight-indicator))
(prefix-help-command #'embark-prefix-help-command)
:config
;; Unbind help-command so completing-read interface can do it's job
(unbind-key "C-h <help>" global-map)
(unbind-key "C-h" help-map)
;;(unbind-key "C-h" ehelp-map)
;; Hide the mode line of the Embark live/completions buffers
(add-to-list 'display-buffer-alist
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
(window-parameters (mode-line-format . none)))))
(use-package highlight-global
:ensure (highlight-global :fetcher github :repo "kaushalmodi/highlight-global")
:bind
("C-s-h" . highlight-global-hl-frame-toggle))
Embark Consult (link)
Consult users will also want the embark-consult package.
(use-package embark-consult
:after (embark consult)
:demand t
:hook
(embark-collect-mode . consult-preview-at-point-mode))
Corfu (link)
(use-package corfu
:demand t
:after orderless
:preface
(defun corfu-enable-always-in-minibuffer ()
"Enable Corfu in the minibuffer if Vertico/Mct are not active."
(unless (or (bound-and-true-p mct--active) ; Useful if I ever use MCT
(bound-and-true-p vertico--input))
(setq-local corfu-auto nil) ; Ensure auto completion is disabled
(corfu-mode 1)))
:hook (minibuffer-setup . corfu-enable-always-in-minibuffer)
:bind (:map corfu-map
("C-n" . corfu-next)
("C-p" . corfu-previous)
("<escape>" . corfu-quit)
("<return>" . corfu-insert)
("M-d" . corfu-popupinfo-show)
("M-l" . corfu-show-location)
("H-SPC" . corfu-insert-separator)
("SPC" . corfu-insert-separator))
:custom
(completion-cycle-threshold nil)
(corfu-auto t)
(corfu-auto-delay 0)
(corfu-auto-prefix 1)
(corfu-count 14)
(corfu-cycle t)
(corfu-echo-documentation t)
(corfu-min-width 80)
(corfu-max-width corfu-min-width)
(corfu-preselect-first t)
(corfu-preview-current t)
(corfu-preselect 'prompt)
(corfu-separator ?\s)
(corfu-quit-at-boundary :separator)
(corfu-quit-no-match t)
(corfu-scroll-margin 4)
(corfu-popupinfo-delay '(0.3 . 0.1))
(corfu-popupinfo-hide nil)
(tab-always-indent 'complete)
(tab-first-completion 'word-or-paren-or-punct)
(read-extended-command-predicate #'command-completion-default-include-p)
:config
(global-corfu-mode)
(corfu-history-mode)
(corfu-popupinfo-mode)
;; The advices are only needed on Emacs 28 and older.
(when (< emacs-major-version 29)
;; Silence the pcomplete capf, no errors or messages!
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
;; Ensure that pcomplete does not write to the buffer
;; and behaves as a pure `completion-at-point-function'.
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)))
;; Use dabbrev with Corfu!
(use-package dabbrev
:ensure nil
;; Swap M-/ and C-M-/
:bind (("M-/" . dabbrev-completion)
("C-M-/" . dabbrev-expand)))
Cape (link)
(use-package cape
:bind (("C-." . completion-at-point)
("C-c /" . cape-dabbrev))
:init
(add-to-list 'completion-at-point-functions #'cape-file))
Multiple Cursors (link)
Multiple cursors for Emacs. This is some pretty crazy functionality, so yes, there are kinks. Don’t be afraid tho, I’ve been using it since 2011 with great success and much merriment.
(use-package multiple-cursors
:hook
(multiple-cursors-mode
.
(lambda ()
(if multiple-cursors-mode
(progn
(message "multiple cursor on")
(corfu-mode 0))
(progn
(message "multiple cursor off")
(corfu-mode 1)))))
:bind
("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this))
(use-package phi-search
:bind
("C-s" . phi-search)
("C-r" . phi-search-backward)
("M-%" . phi-replace-query)
:custom
(phi-search-use-modeline nil))
org-mode (link)
Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text syste.
(defmacro org-babel-add-langs (langs)
`(org-babel-do-load-languages
'org-babel-load-languages
(append org-babel-load-languages
',langs)))
(defun alist-unique (alist)
(reduce (lambda (output value)
(let* ((key (car value))
(existing-value (alist-get key output)))
(cond ((not output) (list value))
((not existing-value) (append output (list value)))
(t output))))
alist :initial-value nil))
(defun append-alist-unique (values alist)
"Add unique VALUE to ALIST when car of VALUE is unique, returns ALIST otherwise"
(alist-unique (append alist values)))
(use-package org
:ensure nil
:mode (("\\.org$" . org-mode))
:hook
(org-mode . turn-on-auto-fill)
:bind
("C-c l" . org-store-link)
("C-c a" . org-agenda)
("C-c c" . org-capture)
:config
(org-babel-add-langs ((emacs-lisp . t)))
(org-indent-mode 1)
(custom-set-faces '(org-ellipsis ((t (:foreground "gray40" :underline nil)))))
(org-babel-add-langs
((ditaa . t)))
:custom
(org-src-window-setup 'current-window)
(org-modules
'(org-protocol
org-habit
org-mouse
org-tempo))
(org-blank-before-new-entry
'((heading . t)
(plain-list-item . nil)))
(org-confirm-babel-evaluate
(lambda (lang body)
(not (string= lang "restclient"))))
(org-hide-leading-stars t)
(org-src-tab-acts-natively t)
(org-startup-indented t)
(org-startup-folded "content")
(org-startup-with-inline-images t)
(org-babel-min-lines-for-block-output 1)
(org-speed-command-help t)
(org-src-preserve-indentation t)
(org-ellipsis " … " )
(org-pretty-entities t)
(org-hide-emphasis-markers t)
(org-agenda-block-separator "")
(org-fontify-whole-heading-line nil)
(org-fontify-done-headline t)
(org-fontify-quote-and-verse-blocks t)
(org-tags-column 0)
(org-indent-indentation-per-level 0)
(org-directory "~/Dropbox/org")
(org-default-notes-file "notes.org")
(org-refile-targets '((org-agenda-files :maxlevel . 1)))
(org-refile-allow-creating-parent-nodes 'confirm)
(org-auto-align-tags nil)
(org-catch-invisible-edits 'show-and-error)
(org-special-ctrl-a/e t)
(org-insert-heading-respect-content t)
(org-agenda-tags-column 0)
(org-agenda-block-separator ?─)
(org-agenda-time-grid
'((daily today require-timed)
(800 1000 1200 1400 1600 1800 2000))
" ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")
(org-agenda-current-time-string "◀── now ─────────────────────────────────────────────────")
(org-capture-templates
'(("a" "Appointment" entry (file "gcal.org" )
"* %?\n\n%^T\n\n:PROPERTIES:\n\n:END:\n\n")
("l" "Link" entry (file+headline "links.org" "Links")
"* %? %^L %^g \n%T" :prepend t)
("b" "Blog idea" entry (file+headline "todo.org" "Blog Topics:")
"* %?\n%T" :prepend t)
("t" "Todo Item" entry
(file+headline "todo.org" "Todo")
"* TODO %?\n:PROPERTIES:\n:CREATED: %u\n:END:" :prepend t :empty-lines 1)
("n" "Note" entry (file+headline "todo.org" "Note space")
"* %?\n%u" :prepend t)
("j" "Journal" entry (file+olp+datetree "journal.org")
"* %?\nEntered on %U\n %i\n %a")
)))
(use-package org-habit
:ensure nil)
(use-package org-starless
:hook (org-mode . org-starless-mode)
:ensure (org-starless :fetcher github :repo "TonCherAmi/org-starless"))
(use-package org-tree-slide
:custom
(org-tree-slide-skip-outline-level 4)
(org-tree-slide-skip-done nil)
:bind
("<f8>" . org-tree-slide-mode)
("S-<f8>" . org-tree-slide-skip-done-toggle)
(:map org-tree-slide-mode-map
("<f9>" . org-tree-slide-move-previous-tree)
("<f10>" . org-tree-slide-move-next-tree)
("<f11>" . org-tree-slide-content))
:config
(org-tree-slide-narrowing-control-profile))
;; org-babel
(org-babel-add-langs
((emacs-lisp . t)
(shell . t)))
(use-package ob-restclient
:defer 2
:custom
(org-babel-default-header-args:restclient
'((:results . "raw")
(:async . "yes")))
:config
(org-babel-add-langs
((restclient . t))))
(use-package ob-js
:ensure nil
:commands (org-mode)
:config
(org-babel-add-langs
((js . t)))
(add-to-list 'org-babel-tangle-lang-exts '("js" . "js")))
(use-package ob-deno
:defer 2
:config
(org-babel-add-langs
((deno . t))))
(use-package ob-mermaid
:ensure-system-package (mmdc . "npm install -g @mermaid-js/mermaid-cli")
:config
(org-babel-add-langs
((mermaid . t))))
(use-package ob-async)
(use-package org-super-agenda
:defer 2
:custom
(org-super-agenda-groups
;; Each group has an implicit boolean OR operator between its selectors.
'((:name "Today" ; Optionally specify section name
:time-grid t ; Items that appear on the time grid
:todo "TODAY") ; Items that have this TODO keyword
(:name "Important"
;; Single arguments given alone
:tag "bills"
:priority "A")
;; Set order of multiple groups at once
(:order-multi (2 (:name "Shopping in town"
;; Boolean AND group matches items that match all subgroups
:and (:tag "shopping" :tag "@town"))
(:name "Food-related"
;; Multiple args given in list with implicit OR
:tag ("food" "dinner"))
(:name "Personal"
:habit t
:tag "personal")
(:name "Space-related (non-moon-or-planet-related)"
;; Regexps match case-insensitively on the entire entry
:and (:regexp ("space" "NASA")
;; Boolean NOT also has implicit OR between selectors
:not (:regexp "moon" :tag "planet")))))
;; Groups supply their own section names when none are given
(:todo "WAITING" :order 8) ; Set order of this section
(:todo ("SOMEDAY" "TO-READ" "CHECK" "TO-WATCH" "WATCHING")
;; Show this group at the end of the agenda (since it has the
;; highest number). If you specified this group last, items
;; with these todo keywords that e.g. have priority A would be
;; displayed in that group instead, because items are grouped
;; out in the order the groups are listed.
:order 9)
(:priority<= "B"
;; Show this section after "Today" and "Important", because
;; their order is unspecified, defaulting to 0. Sections
;; are displayed lowest-number-first.
:order 1)
;; After the last group, the agenda will display items that didn't
;; match any of these groups, with the default order position of 99
))
(org-super-agenda-mode 1))
(defun make-orgcapture-frame ()
"Create a new frame and run org-capture."
(interactive)
(make-frame '((name . "remember") (width . 80) (height . 16)
(top . 400) (left . 300)
;; (font . "-apple-Monaco-medium-normal-normal-*-13-*-*-*-m-0-iso10646-1")
))
(select-frame-by-name "remember")
(org-capture)
(delete-other-windows))
(use-package yequake
:custom
(yequake-frames
'(("org-capture"
(buffer-fns . (yequake-org-capture))
(width . 0.75)
(height . 0.5)
(alpha . 0.95)
(frame-parameters . ((undecorated . t)
(skip-taskbar . t)
(sticky . t)))))))
(defun org-roam-node-insert-immediate (arg &rest args)
"This will allow you to quickly create new notes for topics
you're mentioning while writing so that you can go back later and
fill those notes in with more details!"
(interactive "P")
(let ((args (cons arg args))
(org-roam-capture-templates (list (append (car org-roam-capture-templates)
'(:immediate-finish t)))))
(apply #'org-roam-node-insert args)))
(defun my/org-roam-filter-by-tag (tag-name)
"returns a filter function for "
(lambda (node)
(member tag-name (org-roam-node-tags node))))
(defun my/org-roam-list-notes-by-tag (tag-name)
"Returns list of noted with given filetag"
(mapcar #'org-roam-node-file
(seq-filter
(my/org-roam-filter-by-tag tag-name)
(org-roam-node-list))))
(defun my/org-roam-refresh-agenda-list ()
"Refreshes the agenda list adding Project notes to the list"
(interactive)
(setq org-agenda-files
(append org-agenda-files
(my/org-roam-list-notes-by-tag "Project")
(my/org-roam-list-notes-by-tag "Plant"))))
(defun my/org-roam-template-dir-expand (file)
(expand-file-name (concat user-emacs-directory file)))
(use-package org-roam
:after org
:custom
(org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
(org-roam-directory "~/Dropbox/OrgRoam")
(org-roam-completion-everywhere nil)
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
("C-c n I" . org-roam-node-insert-immediate)
;; Dailies
("C-c n j" . org-roam-dailies-capture-today)
:map org-mode-map
("C-M-i" . completion-at-point)
:map org-roam-dailies-map
("Y" . org-roam-dailies-capture-yesterday)
("T" . org-roam-dailies-capture-tomorrow))
:bind-keymap
("C-c n d" . org-roam-dailies-map)
:custom-face
(org-roam-link ((t (:foreground "#e24888" :underline t))))
(org-roam-link-current ((t (:foreground "#e24888" :underline t))))
:config
(org-roam-setup)
(require 'org-roam-dailies)
(org-roam-db-autosync-mode)
(my/org-roam-refresh-agenda-list)
(setq org-roam-capture-templates
`(("d" "default" plain
"%?"
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n")
:unnarrowed t)
("e" "elisp" plain
(file ,(my/org-roam-template-dir-expand "etc/org-roam/templates/elisp.org"))
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n#+category: ${title}\n#+filetags: elisp\n")
:unnarrowed t)
("p" "project" plain
(file ,(my/org-roam-template-dir-expand "etc/org-roam/templates/project.org"))
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n#+category: ${title}\n#+filetags: Project\n")
:unnarrowed t)
("r" "proposal" plain
(file ,(my/org-roam-template-dir-expand "etc/org-roam/templates/proposal.org"))
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n#+category: ${title}\n#+filetags: Proposal\n")
:unnarrowed t)
("f" "food" plain
(file ,(my/org-roam-template-dir-expand "etc/org-roam/templates/food.org"))
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n#+category: ${title}\n#+filetags: Food\n")
:unnarrowed t)
("t" "plant" plain
(file ,(my/org-roam-template-dir-expand "etc/org-roam/templates/plant.org"))
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n#+category: ${title}\n#+filetags: Plant\n")
:unnarrowed t))))
(use-package htmlize)
org-cliplink (link)
(use-package org-cliplink
:bind ("C-x p i" . org-cliplink))
(use-package org-roam-ui
:ensure (:host github :repo "org-roam/org-roam-ui" :branch "main" :files ("*.el" "out"))
:defer 2
:after (org-roam websocket)
;; if you don't care about startup time, use
:custom
(org-roam-ui-sync-theme t)
(org-roam-ui-follow t)
(org-roam-ui-update-on-save t)
(org-roam-ui-open-on-start t)
:config
(org-roam-ui-mode 1))
(use-package org-tidy
:hook
(org-mode . org-tidy-mode))
(use-package org-download
:hook (dired-mode . org-download-enable)
:custom
(org-download-screenshot-method "screencapture -i %s"))
(use-package which-key
:init
(which-key-mode)
:config
(add-to-list 'which-key-replacement-alist '(("TAB" . nil) . ("↹" . nil)))
(add-to-list 'which-key-replacement-alist '(("RET" . nil) . ("⏎" . nil)))
(add-to-list 'which-key-replacement-alist '(("DEL" . nil) . ("⇤" . nil)))
(add-to-list 'which-key-replacement-alist '(("SPC" . nil) . ("␣" . nil)))
:custom
((which-key-sort-order #'which-key-prefix-then-key-order)
(which-key-add-column-padding 1)
(which-key-min-display-lines 6)
(which-key-side-window-location 'bottom)
(which-key-side-window-max-height 0.25)
(which-key-side-window-max-width 0.33)
(which-key-popup-type 'side-window)
(which-key-sort-uppercase-first nil)))
(use-package atomic-chrome
:config
(atomic-chrome-start-server))
(use-package helpful
:bind (("C-h f" . helpful-callable)
("C-h v" . helpful-variable)
("C-h k" . helpful-key)
("C-c C-d" . helpful-at-point)
("C-h k" . helpful-key)))
(use-package pnpm-mode
:custom
(pnpm-mode-command-prefix "C-c s-n"))
(use-package string-inflection
:bind
("C-c C-u" . string-inflection-all-cycle))
(use-package dash-at-point
:bind
("C-c d" . dash-at-point)
("C-c e" . dash-at-point-with-docset))
(use-package move-text
:config
(move-text-default-bindings))
(use-package anzu
:init
(global-anzu-mode +1)
:bind
("M-%" . anzu-query-replace)
("C-M-%" . anzu-query-replace-regexp))
(use-package doom-modeline
:custom
(doom-modeline-hud t)
(doom-modeline-icon t)
(doom-modeline-major-mode-icon t)
(doom-modeline-major-mode-color-icon t)
(doom-modeline-buffer-state-icon t)
(doom-modeline-buffer-modification-icon t)
(doom-modeline-minor-modes nil)
(doom-modeline-checker-simple-format t)
(doom-modeline-height 30)
:config
(doom-modeline-mode))
Hides modeline whenever this minor mode is active
(use-package hide-mode-line
:commands hide-mode-line-mode)
(use-package transient)
(use-package magit
:after transient
:bind ("C-x g" . magit-status)
:hook
(git-commit-mode . flyspell-mode)
:custom
(vc-handled-backends nil)
(magit-process-finish-apply-ansi-colors t)
(magit-refresh-status-buffer t)
(magit-blame-goto-chunk-hook '(magit-blame-maybe-show-message))
(magit-display-buffer-function 'magit-display-buffer-fullframe-status-v1)
(magit-bury-buffer-function 'magit-restore-window-configuration)
(magit-process-password-functions '(magit-process-password-auth-source))
:config
(remove-hook 'magit-refs-sections-hook 'magit-insert-tags)
;; TODO: add to magit-process-password-functions an auth source
(transient-define-suffix magit-submodule-update-all ()
"Update all submodules"
:description "Update All (git submodule update --init --recursive)"
(interactive)
(magit-with-toplevel
(magit-run-git-async "submodule" "update" "--init" "--recursive"))))
(use-package forge
:after magit
:config
(add-to-list 'forge-alist '("gitlab.services.ams.osa" "gitlab.services.ams.osa/api/v4" "gitlab.services.ams.osa" forge-gitlab-repository))
(add-to-list 'forge-alist '("gitlab.service.osa" "gitlab.service.osa/api/v4" "gitlab.service.osa" forge-gitlab-repository)))
magit-todos (link)
(use-package magit-todos
:after (magit)
:custom
(magit-todos-exclude-globs '(".git/"))
:config
(magit-todos-mode 1))
(use-package conventional-commit
:ensure (conventional-commit :fetcher github :repo "akirak/conventional-commit.el")
:hook
(git-commit-mode . conventional-commit-setup))
(use-package browse-at-remote
:bind ("C-c C-g" . browse-at-remote)
:custom
(browse-at-remote-remote-type-regexps
'(
(:host "^git\\.oslo\\.osa" :type "oslo")
(:host "^gitlab\\.services\\.ams\\.osa$" :type "gitlab")
(:host "^gitlab\\.service\\.osa$" :type "gitlab")
(:host "^github\\.com$" :type "github")
(:host "^bitbucket\\.org$" :type "bitbucket")
(:host "^gitlab\\.com$" :type "gitlab")
(:host "^gist\\.github\\.com$" :type "gist"))))
(defun browse-at-remote-oslo-format-url (repo-url)
"Get a gnu formatted URL."
(let* ((parts (split-string repo-url "/var/git" t))
(domain (butlast parts))
(project (car (last parts))))
(string-join
(append domain (list project)) "/")))
(defun browse-at-remote--format-region-url-as-oslo (repo-url location filename &optional linestart lineend)
"URL formatter for gnu."
(let ((repo-url (browse-at-remote-oslo-format-url repo-url)))
(cond
(linestart (format "%s/tree/%s?h=%s#n%d" repo-url filename location linestart))
(t (format "%s/tree/%s?h=%s" repo-url filename location)))))
(defun browse-at-remote--format-commit-url-as-gnu (repo-url commithash)
"Commit URL formatted for gnu"
(format "%s/commit/?id=%s" (browse-at-remote-oslo-format-url repo-url) commithash))
(use-package gitlab-pipeline
:custom
(gitlab-pipeline-host "gitlab.services.ams.osa/api/v4"))
(use-package docker
:ensure t
:bind ("C-c d" . docker))
hl-todo-mode (link)
(use-package hl-todo
:config
:hook (prog-mode . hl-todo-mode))
(use-package goto-line-preview
:bind ([remap goto-line] . goto-line-preview)
:config)
(use-package pulsar
:config
(pulsar-global-mode 1))
(use-package unfill
:bind ([remap fill-paragraph] . unfill-toggle))
(use-package yasnippet
:after lsp-mode
:hook (prog-mode . yas-minor-mode))
(use-package yasnippet-snippets
:after yasnippet
:config
(yas-reload-all))
(use-package keyfreq
:custom
(keyfreq-excluded-commands
(list ignore
mwheel-scroll
self-insert-command
forward-char
left-char
right-char
backward-char
previous-line
next-line))
:config
(keyfreq-mode 1)
(keyfreq-autosave-mode 1))
ripgrep frontend
(use-package rg
:ensure-system-package (rg . ripgrep)
:custom
(rg-custom-type-aliases
'(("svelte" . "*.svelte")
("ts" . "*.tsx?")
("env" . "\.env.*")))
:config
(rg-enable-menu))
I’ve tried ~ranger-mode~ with it’s simplier ~deer-mode~ and I must say, nothing beets good old Dired.
With some additions of course, like ~diredfl~ for colors and ~dired-quick-sort~ for better sorting with native gnu ls
(use-package dired
:ensure nil
:custom
(dired-dwim-target t)
(dired-vc-rename-file t)
(dired-auto-revert-buffer t)
:config
(cond ((string-equal system-type "darwin")
(setq insert-directory-program "gls"
dired-use-ls-dired t)
(setq dired-listing-switches "-agho --group-directories-first"))))
(use-package dired-quick-sort
:after dired
:custom
(ls-lisp-use-insert-directory-program t)
:config
(dired-quick-sort-setup))
(use-package dired-subtree
:after dired
:bind (:map dired-mode-map
("TAB" . dired-subtree-toggle)))
(use-package emacs-everywhere
:custom
(emacs-everywhere-frame-parameters '((name . "emacs-everywhere") (fullscreen) (width . 160) (height . 24)))
(emacs-everywhere-clipboard-sleep-delay 0.005)
:config
(defun emacs-everywhere--ensure-oscascript-compiled (&optional force)
"Ensure that compiled oscascript files are present.
Will always compile when FORCE is non-nil."
(unless (and (file-exists-p "app-name")
(file-exists-p "window-geometry")
(file-exists-p "window-title")
(not force))
(let ((default-directory emacs-everywhere--dir)
(app-name
"tell application \"System Events\"
set frontAppName to name of first application process whose frontmost is true
end tell
return frontAppName")
(window-geometry
"tell application \"System Events\"
set frontWindow to front window of (first application process whose frontmost is true)
set windowPosition to (get position of frontWindow)
set windowSize to (get size of frontWindow)
end tell
return windowPosition & windowSize")
(window-title
"set windowTitle to \"\"
tell application \"System Events\"
set frontAppProcess to first application process whose frontmost is true
end tell
tell frontAppProcess
if count of windows > 0 then
set windowTitle to name of front window
end if
end tell
return windowTitle"))
(dolist (script `(("app-name" . ,app-name)
("window-geometry" . ,window-geometry)
("window-title" . ,window-title)))
(write-region (cdr script) nil (concat (car script) ".applescript"))
(shell-command (format "osacompile -t osas -o %s %s"
(car script) (concat (car script) ".applescript"))))))))
(use-package display-line-numbers
:ensure nil
:hook (prog-mode . display-line-numbers-mode)
:custom
(display-line-numbers-type 'relative))
(use-package bash-mode
:ensure nil
:hook (bash-mode . lsp-deferred))
(use-package prisma-mode
:mode ("\\.prisma\\'" . prisma-mode)
:ensure (prisma-mode :fetcher github :repo "pimeys/emacs-prisma-mode" :branch "main")
:hook (prisma-mode . lsp-deferred))
(use-package emacs-lisp
:ensure nil
:bind
((:map global-map
("C-x C-e" . nil))
(:map emacs-lisp-mode-map
("C-x C-e" . eval-last-sexp))))
(use-package rust-mode
:after flycheck-rust
:mode ("\\.rs" . rust-mode)
:hook ((flycheck-mode . flycheck-rust-setup)
(rust-mode . lsp-deferred)))
(use-package rustic
:after rust-mode)
(use-package dotenv-mode
:mode ("\\.env\\..*\\'" . dotenv-mode))
(use-package elisp
:ensure nil
:mode ("\\.el\\'" . emacs-lisp-mode))
(use-package markdown-mode
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode)))
(use-package grip-mode
:bind
(:map markdown-mode-command-map
("g" . grip-mode))
:config
(let ((credential (auth-source-user-and-password "github.com")))
(setq grip-github-user (car credential)
grip-github-password (cadr credential))))
(use-package edit-indirect
:after markdown-mode)
(use-package yaml-mode
:mode "\\.yaml")
(use-package go-mode
:mode "\\.go"
:config
(add-hook 'go-mode-hook
(lambda ()
(add-hook 'before-save-hook 'gofmt-before-save)
(local-set-key (kbd "M-.") 'godef-jump))))
(use-package json-mode
:mode "\\.json$"
:hook
(json-mode . lsp-deferred)
:interpreter "json"
:config
(setq js-indent-level 2))
(use-package css-mode
:ensure nil
:mode "\\.css")
(use-package scss-mode
:mode "\\.scss"
:hook (scss-mode . lsp-deferred))
(use-package lua-mode
:mode ("\\.lua"))
(use-package typescript-mode
:after (lsp-mode)
:mode "\\.ts$"
:hook (typescript-mode . lsp-deferred))
(use-package js2-mode
:after (lsp-mode)
:mode ("\\.[cm]*js$")
:hook (js-base-mode . lsp-deferred))
(use-package eslintd-fix
:hook ((js-base-mode) . eslintd-fix-mode))
(use-package web-mode
:mode
("\\.html\\'"
"\\.svelte\\'")
:hook
(web-mode . lsp-deferred)
:custom
(web-mode-content-types-alist
'(("jsx" . "\\.tsx\\'")
("jsx" . "\\.jsx\\'")
("svelte" . "\\.svelte\\'")
("html" . "\\.html\\'")))
(web-mode-enable-auto-indentation nil)
(web-mode-indentation-params
'(("lineup-args" . t)
("lineup-calls" . t)
("lineup-concats" . t)
("lineup-quotes" . t)
("lineup-ternary" . nil)
("case-extra-offset" . t))))
(use-package python-mode
:mode "\\.py"
:interpreter "py"
:hook (python-mode . lsp-deferred)
:config
(setq python-shell-interpreter "ipython"
python-shell-interpreter-args "-i --simple-prompt"))
(use-package poetry
:after python-mode
:config
(poetry-tracking-mode))
(use-package dockerfile-mode
:mode "Dockerfile$")
(use-package docker-compose-mode
:mode "docker-compose.yml.py$")
(message ".emacs loaded successfully.")
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)