For install emacs on macos use brew:
brew install emacs-plus@28 --with-xwidgets --with-nobu417-big-sur-icon --with-no-frame-refocus --with-native-comp --with-dbus --with-imagemagick
(defvar elpaca-installer-version 0.7)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
:ref nil :depth 1
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
:build (:not elpaca--activate-package)))
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
(build (expand-file-name "elpaca/" elpaca-builds-directory))
(order (cdr elpaca-order))
(default-directory repo))
(add-to-list 'load-path (if (file-exists-p build) build repo))
(unless (file-exists-p repo)
(make-directory repo t)
(when (< emacs-major-version 28) (require 'subr-x))
(condition-case-unless-debug err
(if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
((zerop (apply #'call-process `("git" nil ,buffer t "clone"
,@(when-let ((depth (plist-get order :depth)))
(list (format "--depth=%d" depth) "--no-single-branch"))
,(plist-get order :repo) ,repo))))
((zerop (call-process "git" nil buffer t "checkout"
(or (plist-get order :ref) "--"))))
(emacs (concat invocation-directory invocation-name))
((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
"--eval" "(byte-recompile-directory \".\" 0 'force)")))
((require 'elpaca))
((elpaca-generate-autoloads "elpaca" repo)))
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
(error "%s" (with-current-buffer buffer (buffer-string))))
((error) (warn "%s" err) (delete-directory repo 'recursive))))
(unless (require 'elpaca-autoloads nil t)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" repo)
(load "./elpaca-autoloads")))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))
;; Install use-package support
(elpaca elpaca-use-package
;; Enable :ensure use-package keyword.
(elpaca-use-package-mode)
;; Assume :ensure t unless otherwise specified.
(setq elpaca-use-package-by-default t))
;; Block until current queue processed.
(elpaca-wait)
(with-eval-after-load 'general
(general-define-key
:states '(normal visual)
:prefix "SPC"
"pm" 'elpaca-status)
(general-define-key
:states '(normal)
:keymaps 'elpaca-ui-mode-map
"i" 'elpaca-ui-mark-install
"s" 'elpaca-ui-execute-marks
"S" 'elpaca-ui-search
"d" 'elpaca-ui-mark-delete
"u" 'elpaca-ui-mark-update
"U" 'elpaca-update-all
"r" 'elpaca-ui-mark-rebuild)
)
(use-package closql :ensure (closql :depth nil) :defer t)
;; (use-package seq
;; :defer t)
;; (use-package subr :ensure nil)
;; :preface
;; (unload-feature 'subr t)
;; :ensure (:type git :host github :repo "emacs-mirror/emacs"))
(use-package jsonrpc
:ensure (jsonrpc :depth 1)
:defer t)
https://www.reddit.com/r/emacs/comments/f8xwau/hack_replace_execpathfromshell/
;;; Code to replace exec-path-from-shell
;; Need to create file in $HOME/.emacs.d/.local/env
;; use this command to create the file `printenv > $home/.emacs.d/.local/env'
(defconst my-local-dir (concat user-emacs-directory ".local/"))
(defconst my-env-file (concat my-local-dir "env"))
(defun my-load-envvars-file (file &optional noerror)
"Read and set envvars from FILE.
If NOERROR is non-nil, don't throw an error if the file doesn't exist or is
unreadable. Returns the names of envvars that were changed."
(if (not (file-readable-p file))
(unless noerror
(signal 'file-error (list "Couldn't read envvar file" file)))
(let (envvars environment)
(with-temp-buffer
(save-excursion
(insert "\n")
(insert-file-contents file))
(while (re-search-forward "\n *\\([^#= \n]*\\)=" nil t)
(push (match-string 1) envvars)
(push (buffer-substring
(match-beginning 1)
(1- (or (save-excursion
(when (re-search-forward "^\\([^= ]+\\)=" nil t)
(line-beginning-position)))
(point-max))))
environment)))
(when environment
(setq process-environment
(append (nreverse environment) process-environment)
exec-path
(if (member "PATH" envvars)
(append (split-string (getenv "PATH") path-separator t)
(list exec-directory))
exec-path)
shell-file-name
(if (member "SHELL" envvars)
(or (getenv "SHELL") shell-file-name)
shell-file-name))
envvars))))
(when (and (or (display-graphic-p)
(daemonp))
(file-exists-p my-env-file))
(my-load-envvars-file my-env-file))
;;; Code to replace exec-path-from-shell
(setq warning-minimum-level :emergency)
(setq warning-suppress-log-types '((comp) (undo discard-info)))
(let* ((normal-gc-cons-threshold (* 20 1024 1024))
(init-gc-cons-threshold (* 128 1024 1024)))
(setq gc-cons-threshold init-gc-cons-threshold)
(add-hook 'emacs-startup-hook
(lambda () (setq gc-cons-threshold (* 20 1024 1024)))))
(setq read-process-output-max (* 1024 1024))
(require 'package)
(customize-set-variable 'package-archives
`(,@package-archives
("melpa" . "http://melpa.org/packages/")
("melpa" . "http://melpa.milkbox.net/packages/")
("jcs-elpa" . "https://jcs-emacs.github.io/jcs-elpa/packages/")
("melpa-stable" . "http://stable.melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")
;; ("emacswiki" . "https://mirrors.tuna.tsinghua.edu.cn/elpa/emacswiki/")
))
(customize-set-variable 'package-enable-at-startup nil)
;; (package-initialize)
(use-package fnhh
:ensure (:type git :host github :repo "a13/fnhh")
:config
(fnhh-mode 1))
;; Change backup folders
(setq backup-directory-alist '(("." . "/Users/darkawower/tmp/emacs-backups")))
(setq lock-file-name-transforms
'(("\\`/.*/\\([^/]+\\)\\'" "/var/tmp/\\1" t)))
(ignore-errors
(setq confirm-kill-emacs 'y-or-n-p)
(defalias 'yes-or-no-p 'y-or-n-p))
(setq initial-major-mode (quote fundamental-mode))
(use-package direnv
:config
(direnv-mode))
(defalias 'use-package! 'use-package
"Alias for call use-package from doom modules")
Load private configs
(ignore-errors
(load "~/apps/pure-emacs/private.el"))
(elpaca-wait)
(when (eq system-type 'darwin)
(setq browse-url-firefox-program nil)
(setq browse-url-generic-program "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
browse-url-browser-function 'browse-url-generic))
(set-default 'truncate-lines t)
(defun @reset-nw-background ()
(unless (display-graphic-p (selected-frame))
(set-face-background 'default "unspecified-bg" (selected-frame))))
(add-hook 'window-setup-hook '@reset-nw-background)
(use-package doom-lib
:ensure (doom-lib
:host github
:repo "hlissner/doom-emacs"
:files ("lisp/doom-lib.el" "lisp/lib/buffers.el")))
(defmacro pushnew! (place &rest values)
"Push VALUES sequentially into PLACE, if they aren't already present.
This is a variadic `cl-pushnew'."
(let ((var (make-symbol "result")))
`(dolist (,var (list ,@values) (with-no-warnings ,place))
(cl-pushnew ,var ,place :test #'equal))))
(defun doom-unquote (exp)
"Return EXP unquoted."
(declare (pure t) (side-effect-free t))
(while (memq (car-safe exp) '(quote function))
(setq exp (cadr exp)))
exp)
(defmacro add-hook! (hooks &rest rest)
"A convenience macro for adding N functions to M hooks.
This macro accepts, in order:
1. The mode(s) or hook(s) to add to. This is either an unquoted mode, an
unquoted list of modes, a quoted hook variable or a quoted list of hook
variables.
2. Optional properties :local, :append, and/or :depth [N], which will make the
hook buffer-local or append to the list of hooks (respectively),
3. The function(s) to be added: this can be a quoted function, a quoted list
thereof, a list of `defun' or `cl-defun' forms, or arbitrary forms (will
implicitly be wrapped in a lambda).
\(fn HOOKS [:append :local [:depth N]] FUNCTIONS-OR-FORMS...)"
(declare (indent (lambda (indent-point state)
(goto-char indent-point)
(when (looking-at-p "\\s-*(")
(lisp-indent-defform state indent-point))))
(debug t))
(let* ((hook-forms (doom--resolve-hook-forms hooks))
(func-forms ())
(defn-forms ())
append-p local-p remove-p depth)
(while (keywordp (car rest))
(pcase (pop rest)
(:append (setq append-p t))
(:depth (setq depth (pop rest)))
(:local (setq local-p t))
(:remove (setq remove-p t))))
(while rest
(let* ((next (pop rest))
(first (car-safe next)))
(push (cond ((memq first '(function nil))
next)
((eq first 'quote)
(let ((quoted (cadr next)))
(if (atom quoted)
next
(when (cdr quoted)
(setq rest (cons (list first (cdr quoted)) rest)))
(list first (car quoted)))))
((memq first '(defun cl-defun))
(push next defn-forms)
(list 'function (cadr next)))
((prog1 `(lambda (&rest _) ,@(cons next rest))
(setq rest nil))))
func-forms)))
`(progn
,@defn-forms
(dolist (hook (nreverse ',hook-forms))
(dolist (func (list ,@func-forms))
,(if remove-p
`(remove-hook hook func ,local-p)
`(add-hook hook func ,(or depth append-p) ,local-p)))))))
(defun doom--resolve-hook-forms (hooks)
"Converts a list of modes into a list of hook symbols.
If a mode is quoted, it is left as is. If the entire HOOKS list is quoted, the
list is returned as-is."
(declare (pure t) (side-effect-free t))
(let ((hook-list (ensure-list (doom-unquote hooks))))
(if (eq (car-safe hooks) 'quote)
hook-list
(cl-loop for hook in hook-list
if (eq (car-safe hook) 'quote)
collect (cadr hook)
else collect (intern (format "%s-hook" (symbol-name hook)))))))
(defvar @before-buffer-changed-hook nil
"Hook run before a buffer is changed.")
(use-package transient :ensure t)
Add additional space before link insert
(defun my-add-additional-space-when-not-exist (_)
"Add additional sapce if previous char is not space!"
(unless (eq (char-before) ? )
(insert " ")))
(advice-add 'org-insert-link :before 'my-add-additional-space-when-not-exist)
Format org mode block
(defun format-org-mode-block ()
"Format org mode code block"
(interactive "p")
(org-edit-special)
(format-all-ensure-formatter)
(format-all-buffer)
(org-edit-src-exit))
Init org mode faces for headlines
(defun @setup-org-mode-faces ()
"Setup faces for org mode"
(custom-set-faces
'(org-document-title ((t (:inherit outline-1 :height 2.5)))))
;; '(org-level-1 ((t (:inherit outline-5 :height 2.0))))
;; '(org-level-2 ((t (:inherit outline-5 :height 2.0))))
;; '(org-level-3 ((t (:inherit outline-5 :height 2.0))))
;; '(org-level-4 ((t (:inherit outline-5 :height 2.0))))
;; '(org-level-5 ((t (:inherit outline-5 :height 2.0)))))
)
(defun my-switch-to-xwidget-buffer (&optional a b)
"Switch to xwidget buffer."
(interactive)
(switch-to-first-matching-buffer "xwidget webkit"))
(defun my-toggle-default-browser ()
"Toggle default browser for preview"
(interactive)
(if (eq browse-url-browser-function #'browse-url-default-browser)
(progn (setq browse-url-browser-function #'xwidget-webkit-browse-url)
(advice-add 'browse-url :after #'my-switch-to-xwidget-buffer))
(progn
(setq browse-url-browser-function #'browse-url-default-browser)
(advice-remove 'browse-url #'my-switch-to-xwidget-buffer))))
(defun switch-to-first-matching-buffer (regex)
(switch-to-buffer (car (remove-if-not (apply-partially #'string-match-p regex)
(mapcar #'buffer-name (buffer-list))))))
Focus buffer by name
(defun +select-window-by-name (regexp)
"Selects the window with buffer NAME"
(select-window
(car (seq-filter
(lambda (window)
(string-match-p regexp (buffer-name (window-buffer window))))
(window-list-1 nil 0 t)))))
(defun toggle-maximize-buffer ()
"Maximize buffer"
(interactive)
(if (= 1 (length (window-list)))
(jump-to-register '_)
(progn
(window-configuration-to-register '_)
(delete-other-windows))))
Copy selected text to special register
(defun xah-copy-to-register-1 ()
"Copy current line or text selection to register 1.
See also: `xah-paste-from-register-1', `copy-to-register'.
;;;; Register copy past
URL `http://xahlee.info/emacs/emacs/elisp_copy-paste_register_1.html'
Version 2017-01-23"
(interactive)
(let ($p1 $p2)
(if (region-active-p)
(progn (setq $p1 (region-beginning))
(setq $p2 (region-end)))
(progn (setq $p1 (line-beginning-position))
(setq $p2 (l(defun xah-paste-from-register-1 ()
"Paste text from register 1.
See also: `xah-copy-to-register-1', `insert-register'.
URL `http://xahlee.info/emacs/emacs/elisp_copy-paste_register_1.html'
Version 2015-12-08"
(interactive)
(when (use-region-p)
(delete-region (region-beginning) (region-end)))
(insert-register ?1 t))ine-end-position))))
(copy-to-register ?1 $p1 $p2)
(message "Copied to register 1: 「%s」." (buffer-substring-no-properties $p1 $p2))))
Paste copied text from register
(defun xah-paste-from-register-1 ()
"Paste text from register 1.
See also: `xah-copy-to-register-1', `insert-register'.
URL `http://xahlee.info/emacs/emacs/elisp_copy-paste_register_1.html'
Version 2015-12-08"
(interactive)
(when (use-region-p)
(delete-region (region-beginning) (region-end)))
(insert-register ?1 t))
(defun @delete-this-file (&optional path force-p)
"Delete PATH, kill its buffers and expunge it from vc/magit cache.
If PATH is not specified, default to the current buffer's file.
If FORCE-P, delete without confirmation."
(interactive
(list (buffer-file-name (buffer-base-buffer))
current-prefix-arg))
(let* ((path (or path (buffer-file-name (buffer-base-buffer))))
(short-path (and path (abbreviate-file-name path))))
(unless path
(user-error "Buffer is not visiting any file"))
(unless (file-exists-p path)
(error "File doesn't exist: %s" path))
(unless (or force-p (y-or-n-p (format "Really delete %S?" short-path)))
(user-error "Aborted"))
(let ((buf (current-buffer)))
(unwind-protect
(progn (delete-file path t) t)
(if (file-exists-p path)
(error "Failed to delete %S" short-path)
;; Ensures that windows displaying this buffer will be switched to
;; real buffers (`doom-real-buffer-p')
(doom/kill-this-buffer-in-all-windows buf t)
(doom-files--update-refs path)
(message "Deleted %S" short-path))))))
(defun @forge-browse-buffer-file ()
(interactive)
(browse-url
(let
((rev (cond ((and (boundp git-timemachine-mode) git-timemachine-mode) (git-timemachine-kill-revision))
((and (boundp magit-gitflow-mode) magit-gitflow-mode) (magit-copy-buffer-revision))
(t "master")))
(repo (forge-get-repository 'stub))
(file (magit-file-relative-name buffer-file-name))
(highlight
(if
(use-region-p)
(let ((l1 (line-number-at-pos (region-beginning)))
(l2 (line-number-at-pos (- (region-end) 1))))
(format "#L%d-L%d" l1 l2))
""
)))
(if (not file)
(if-let ((path (forge--split-remote-url (forge--get-remote))))
(message "https://%s/%s/%s/commit/%s" (nth 0 path) (nth 1 path) (nth 2 path) rev)
(user-error "Cannot browse non-forge remote %s" (forge--get-remote)))
(forge--format repo "https://%h/%o/%n/blob/%r/%f%L"
`((?r . ,rev) (?f . ,file) (?L . ,highlight)))))))
(use-package selection-highlight-mode
:ensure (selection-highlight-mode :type git
:host github
:repo "balloneij/selection-highlight-mode")
:config (selection-highlight-mode))
(setq my-transparency-disabled-p t)
(defun @toggle-transparency ()
"Toggle transparency"
(interactive)
(let* ((not-transparent-p (and (boundp 'my-transparency-disabled-p) my-transparency-disabled-p))
(alpha (if not-transparent-p 100 85)))
(setq my-transparency-disabled-p (not not-transparent-p))
(message "%s" alpha)
(progn
(set-frame-parameter (selected-frame) 'alpha `(,alpha . ,alpha))
(add-to-list 'default-frame-alist `(alpha . (,alpha . ,alpha))))))
Base function
(defun @insert--todo-by-current-git-branch (todo-type)
"Insert todo for current git branch."
(let* ((branch-name (magit-get-current-branch))
(vw (string-match "\\(?1:[A-Za-z0-9]+\/\\)\\(?2:VW-[0-9]+\\)" branch-name))
(task-number (match-string 2 branch-name))
(todo-msg (or task-number branch-name)))
(insert (format "%s: %s " todo-type todo-msg))
(comment-line 1)
;; (forward-line 1)
(previous-line)
(end-of-line)
(indent-according-to-mode)
(evil-insert 1)))
(defun @insert-todo-by-current-git-branch ()
"Insert todo for current git branch."
(interactive)
(@insert--todo-by-current-git-branch "TODO"))
(defun @insert-debug-by-current-git-branch ()
"Insert debug for current git branch."
(interactive)
(@insert--todo-by-current-git-branch "DEBUG"))
(defun @insert-note-by-current-git-branch ()
"Insert note for current git branch."
(interactive)
(@insert--todo-by-current-git-branch "NOTE"))
(defun @insert-tab ()
"Insert simple tab"
(interactive)
(insert "\t"))
TODO: check why it doesn;t work
(defun @open-emacs-config ()
"Open folder with emacs config"
(interactive)
(let ((default-directory "~/apps/pure-emacs/README.org"))
(call-interactively 'find-file)))
(defun @window-split-toggle ()
"Toggle between horizontal and vertical split with two windows."
(interactive)
(if (> (length (window-list)) 2)
(error "Can't toggle with more than 2 windows!")
(let ((func (if (window-full-height-p)
#'split-window-vertically
#'split-window-horizontally)))
(delete-other-windows)
(funcall func)
(save-selected-window
(other-window 1)
(switch-to-buffer (other-buffer))))))
For correct work you need to install sass-lint-auto-fix
yarn global add sass-lint-auto-fix
(defun @run-sass-auto-fix ()
"Run sass auto fix if cli tool exist"
(interactive)
(save-window-excursion
(let ((default-directory (file-name-directory buffer-file-name)))
(async-shell-command "sass-lint-auto-fix")
;; (revert-buffer-no-confirm)
(message "SASS FORMATTED"))))
Need to steal from doom emacs!
(defun @open-messages ()
"Open *Messages* buffer."
(interactive)
(if (one-window-p)
(split-window-horizontally))
(pop-to-buffer "*Messages*"))
(defun @open-clear-messages ()
"Open *Messages* buffer and clear it."
(interactive)
(if (one-window-p)
(split-window-horizontally))
(pop-to-buffer "*Messages*")
(read-only-mode -1)
(erase-buffer))
(defun @find-definition ()
"Find lsp definition when lsp exist and enabled, or find evil definition."
(interactive)
(cond ((bound-and-true-p lsp-bridge-mode) (lsp-bridge-find-def))
((and (bound-and-true-p eglot--managed-mode) eglot--managed-mode) (evil-goto-definition))
((and (bound-and-true-p lsp-mode) (bound-and-true-p lsp-ui-mode) lsp-ui-mode) (lsp-ui-peek-find-definitions))
((and (bound-and-true-p lsp-mode) lsp-mode) (lsp-find-definition))
(t (evil-goto-definition))))
(defun @avy-go-to-definition ()
(interactive)
(evil-avy-goto-word-1 nil)
(@find-definition))
Uncomment when u need to profile ;p
(use-package explain-pause-mode
:ensure (explain-pause-mode :type git :host github :repo "lastquestion/explain-pause-mode")
:defer t)
(use-package esup)
(setq use-package-verbose t)
(use-package all-the-icons
:ensure t)
;; :config
;; (set-fontset-font t 'unicode (font-spec :family "all-the-icons") nil 'prepend)
;; (set-fontset-font t 'unicode (font-spec :family "file-icons") nil 'prepend)
;; (set-fontset-font t 'unicode (font-spec :family "Material Icons") nil 'prepend)
;; (set-fontset-font t 'unicode (font-spec :family "github-octicons") nil 'prepend)
;; (set-fontset-font t 'unicode (font-spec :family "FontAwesome") nil 'prepend)
;; (set-fontset-font t 'unicode (font-spec :family "Weather Icons") nil 'prepend)
;; (setq inhibit-compacting-font-caches t))
(use-package all-the-icons-completion
:after (marginalia all-the-icons)
:hook (marginalia-mode . all-the-icons-completion-marginalia-setup)
:init
(all-the-icons-completion-mode))
(add-to-list 'default-frame-alist '(fullscreen . maximized))
(setq inhibit-splash-screen t)
(setq inhibit-startup-message t)
Very pretty titlebar for Mac os
(use-package ns-auto-titlebar
:config
(when (eq system-type 'darwin) (ns-auto-titlebar-mode)))
(setq +m-color-main "#61AFEF"
+m-color-secondary "#FF3399"
+m-color-yellow "#FFAA00"
+m-color-blue "#00AEE8"
+m-color-cyan "#00CED1"
+m-color-green "#00D364"
+org-todo-onhold "#FFAA00")
(defface +org-todo-onhold-face
`((t (:foreground ,+org-todo-onhold :weight bold)))
"Face for TODO items with the ONHOLD keyword."
:group 'org-faces)
Custom italic-like faces
(defface italic-string-face
'((t (:inherit font-lock-string-face :slant italic)))
"Face for italic strings."
:group 'faces)
Custom italic build-in face
(defface italic-builtin-face
'((t (:inherit font-lock-builtin-face :slant italic)))
"Face for italic keywords."
:group 'faces)
(use-package all-the-icons-dired
:after dired
:hook (dired-mode . all-the-icons-dired-mode))
(use-package hl-todo
:ensure (hl-todo :depth nil)
:defer 2
:config
(setq hl-todo-keyword-faces
'(("TODO" . "#E5C07B")
("FIXME" . "#E06C75")
("DEBUG" . "#C678DD")
("REFACTOR" . "#C678DD")
("GOTCHA" . "#FF4500")
("NOTE" . "#98C379")
("QUESTION" . "#98C379")
("STUB" . "#61AFEF")))
(global-hl-todo-mode 1))
(use-package colorful-mode
:ensure (:type git :host github :repo "DevelopmentCool2449/colorful-mode"))
(pixel-scroll-mode)
(use-package scroll-on-jump
:custom
(scroll-on-jump-smooth t)
(scroll-on-jump-duration 0.1337)
:config
(scroll-on-jump-advice-add beginning-of-buffer)
(scroll-on-jump-advice-add end-of-buffer)
(scroll-on-jump-advice-add flyspell-goto-next-error)
(when (featurep 'smartparens)
(define-key smartparens-mode-map
(kbd "C-M-f") (scroll-on-jump-interactive 'sp-forward-sexp))
(define-key smartparens-mode-map
(kbd "C-M-b") (scroll-on-jump-interactive 'sp-backward-sexp)))
;; (scroll-on-jump-with-scroll-advice-add scroll-up-command)
(scroll-on-jump-with-scroll-advice-add View-scroll-half-page-backward)
(scroll-on-jump-with-scroll-advice-add View-scroll-half-page-backward)
(scroll-on-jump-with-scroll-advice-add evil-scroll-down)
(scroll-on-jump-with-scroll-advice-add evil-scroll-up)
;; (scroll-on-jump-with-scroll-advice-add ccm-scroll-down)
;; (scroll-on-jump-with-scroll-advice-add ccm-scroll-up)
(scroll-on-jump-with-scroll-advice-add isearch-update)
(scroll-on-jump-with-scroll-advice-add recenter-top-bottom))
(use-package spacious-padding
:config
(spacious-padding-mode))
(defun @correct-my-fringe (&optional ignore)
"Set fringes for current active window."
(interactive)
(unless (eq fringe-mode '16)
(fringe-mode '16)))
(add-hook 'after-init-hook #'@correct-my-fringe)
(add-hook 'buffer-list-update-hook #'@correct-my-fringe)
(setq-default left-margin-width 2 right-margin-width 2)
(use-package display-fill-column-indicator
:defer t
:ensure nil
:config
(setq display-fill-column-indicator-column 80))
(use-package centered-cursor-mode
:hook (prog-mode . centered-cursor-mode)
:demand)
(defvar after-load-theme-hook nil
"Hook run after a color theme is loaded using `load-theme'.")
(defadvice load-theme (after run-after-load-theme-hook activate)
"Run `after-load-theme-hook'."
(run-hooks 'after-load-theme-hook))
(add-hook 'after-load-theme-hook #'@reset-nw-background)
(defadvice load-theme (before theme-dont-propagate activate)
(mapcar #'disable-theme custom-enabled-themes))
(fringe-mode '16)
Doesn’t work for mac os unfortunately ;c
(progn
(set-frame-parameter (selected-frame) 'alpha '(100 . 100))
(add-to-list 'default-frame-alist '(alpha . (100 . 100))))
(use-package doom-themes
:ensure t
:config
;; Global settings (defaults)
(setq doom-themes-enable-bold t ; if nil, bold is universally disabled
doom-themes-enable-italic t) ; if nil, italics is universally disabled
(load-theme 'doom-moonlight t)
;; Enable flashing mode-line on errors
(doom-themes-visual-bell-config)
;; Enable custom neotree theme (all-the-icons must be installed!)
(doom-themes-neotree-config)
;; or for treemacs users
(setq doom-themes-treemacs-theme "doom-atom") ; use "doom-colors" for less minimal icon theme
(doom-themes-treemacs-config)
;; Corrects (and improves) org-mode's native fontification.
(doom-themes-org-config))
(use-package doom-modeline
:defer t
:hook (after-init . doom-modeline-mode)
:config
(setq doom-modeline-buffer-file-name-style 'file-name))
(use-package hide-mode-line
:hook
(prog-mode . hide-mode-line-mode)
(text-mode . hide-mode-line-mode)
(org-mode . hide-mode-line-mode))
(setq window-divider-default-places t
window-divider-default-bottom-width 1
window-divider-default-right-width 0)
(window-divider-mode +1)
(defun @set-catppucin-theme ()
(interactive)
(message "AUTO DARK SET CATPPUCIN")
(setq catppuccin-flavor (if (eq auto-dark--last-dark-mode-state 'dark) 'frappe 'latte))
(message "CATppUCCIN FLAVOR %s" catppuccin-flavor)
(catppuccin-reload))
(use-package catppuccin-theme
:after auto-dark
:config
(defface font-lock-object-key-face
`((t (:inherit font-lock-property-name-face :foreground ,(catppuccin-get-color 'lavender))))
"Face for object keys."
:group 'font-lock-faces)
;; (set-face-attribute 'font-lock-property-name-face nil :foreground (catppuccin-get-color 'lavender))
(add-hook 'auto-dark-dark-mode-hook #'@set-catppucin-theme)
(add-hook 'auto-dark-light-mode-hook #'@set-catppucin-theme)
(@set-catppucin-theme)
(set-face-attribute 'highlight nil :background "#dce0e8")
;; https://github.com/catppuccin/emacs/issues/55
(add-hook 'yaml-mode-hook
(lambda ()
(face-remap-add-relative 'font-lock-variable-name-face
(list :foreground (catppuccin-get-color 'blue))))))
(use-package autothemer
:ensure t)
Doesn’t work with chemacs and emacs 29 emacs-dashboard/emacs-dashboard#421
(use-package dashboard
:config
(dashboard-setup-startup-hook))
(set-frame-font "JetBrainsMono Nerd Font 14" nil t)
;; (set-frame-font "Monaspace Neon 14" nil t)
;; (set-frame-font "Menlo 14" nil t)
;; (set-frame-font "Monaco Font 15" nil t)
(defconst jetbrains-ligature-mode--ligatures
'("-->" "//" "/**" "/*" "*/" "<!--" ":=" "->>" "<<-" "->" "<-"
"<=>" "==" "!=" "<=" ">=" "=:=" "!==" "&&" "||" "..." ".."
"|||" "///" "&&&" "===" "++" "--" "=>" "|>" "<|" "||>" "<||"
"|||>" "<|||" ">>" "<<" "::=" "|]" "[|" "{|" "|}"
"[<" ">]" ":?>" ":?" "/=" "[||]" "!!" "?:" "?." "::"
"+++" "??" "###" "##" ":::" "####" ".?" "?=" "=!=" "<|>"
"<:" ":<" ":>" ">:" "<>" "***" ";;" "/==" ".=" ".-" "__"
"=/=" "<-<" "<<<" ">>>" "<=<" "<<=" "<==" "<==>" "==>" "=>>"
">=>" ">>=" ">>-" ">-" "<~>" "-<" "-<<" "=<<" "---" "<-|"
"<=|" "/\\" "\\/" "|=>" "|~>" "<~~" "<~" "~~" "~~>" "~>"
"<$>" "<$" "$>" "<+>" "<+" "+>" "<*>" "<*" "*>" "</>" "</" "/>"
"<->" "..<" "~=" "~-" "-~" "~@" "^=" "-|" "_|_" "|-" "||-"
"|=" "||=" "#{" "#[" "]#" "#(" "#?" "#_" "#_(" "#:" "#!" "#="
"&="))
(sort jetbrains-ligature-mode--ligatures (lambda (x y) (> (length x) (length y))))
(dolist (pat jetbrains-ligature-mode--ligatures)
(set-char-table-range composition-function-table
(aref pat 0)
(nconc (char-table-range composition-function-table (aref pat 0))
(list (vector (regexp-quote pat)
0
'compose-gstring-for-graphic)))))
Function for setting terminal color after theme switch
(defun @set-colors-after-theme-loaded ()
"Change color of autocomplete inside vterm"
(interactive)
;; Face for completion navigation
(set-face-attribute 'highlight nil :background "#dce0e8")
(when (facep 'vterm-color-black)
(set-face-attribute 'vterm-color-black nil :foreground +m-color-secondary :background +m-color-secondary)))
Override function for auto-dark mode for applying function for nano theme changing, instead of them applying
(use-package auto-dark
:after posframe
:config
(add-hook 'auto-dark-dark-mode-hook #'@set-colors-after-theme-loaded)
(add-hook 'auto-dark-light-mode-hook #'@set-colors-after-theme-loaded)
(add-hook 'auto-dark-dark-mode-hook #'posframe-delete-all)
(add-hook 'auto-dark-light-mode-hook #'posframe-delete-all)
(setq auto-dark-dark-theme 'catppuccin)
(setq auto-dark-light-theme 'catppuccin)
(auto-dark-mode))
(menu-bar-mode -1)
(tool-bar-mode -1)
(toggle-scroll-bar -1)
(setq ring-bell-function 'ignore)
(use-package which-key
:defer t
:config
(which-key-setup-side-window-right)
(which-key-mode))
(define-key global-map (kbd "C-h") (make-sparse-keymap))
(global-set-key (kbd "C-S-l") 'enlarge-window-horizontally)
(global-set-key (kbd "C-S-h") 'shrink-window-horizontally)
(global-set-key (kbd "<C-S-up>") 'shrink-window)
(global-set-key (kbd "C-S-j") 'enlarge-window)
(global-set-key (kbd "<C-S-down>") 'enlarge-window)
(global-set-key (kbd "C-S-k") 'shrink-window)
(general-define-key
:states '(normal visual)
:keymaps 'override
"C-u" 'evil-scroll-up
"C-e" 'pixel-scroll-up
"gf" '@avy-go-to-definition
"C-y" 'pixel-scroll-down
"s-Y" 'xah-copy-to-register-1
"s-r" (lambda () (interactive) (set-mark-command nil) (evil-avy-goto-char))
"s-P" 'xah-paste-from-register-1)
(general-define-key
:keymaps '(minibuffer-local-map read--expression-map minibuffer-local-shell-command-map evil-ex-completion-map)
"C-w" 'backward-kill-word
"C-k" 'previous-history-element
"C-p" 'previous-history-element
"C-u" 'evil-delete-back-to-indentation
;; "<tab>" 'completion-at-point
;; "<tab>" 'completion-at-point
"C-j" 'next-history-element
"C-n" 'next-history-element
"<escape>" 'keyboard-escape-quit
"C-x" (lambda () (interactive) (end-of-line) (kill-whole-line)))
(general-define-key
:states '(visual normal)
:keymaps 'override
:prefix "\\"
"f" 'avy-goto-char
"b" 'my-switch-to-xwidget-buffer
"w" 'avy-goto-word-0
"]" 'flycheck-next-error
"[" 'flycheck-previous-error
"d" 'dap-debug
"o" 'org-mode
"q" 'kill-current-buffer
"v" 'vterm
"`" 'vterm-toggle-cd
"i" 'git-messenger:popup-message
"t" 'google-translate-smooth-translate
"T" 'google-translate-query-translate
"a" 'counsel-org-agenda-headlines
"c" 'dired-create-empty-file
"s" 'publish-org-blog
"g" 'codegpt
;; Evil
"=" 'evil-record-macro
"-" 'evil-execute-macro
"0" 'my-toggle-default-browser
"h" 'lsp-ui-doc-toggle
"e" 'lsp-treemacs-errors-list
"l" 'lsp-execute-code-action
"r" 'treemacs-select-window
"m" 'toggle-maximize-buffer)
(use-package char-fold
:ensure nil
:custom
(char-fold-symmetric t)
(search-default-mode #'char-fold-to-regexp))
(use-package reverse-im
:demand t ; always load it
:after char-fold ; but only after `char-fold' is loaded
:custom
(reverse-im-char-fold t) ; use lax matching
(reverse-im-read-char-advice-function #'reverse-im-read-char-include)
(reverse-im-input-methods '("russian-computer")) ; translate these methods
:config
(reverse-im-mode t))
Patch for recover visual line after shifting
(define-key evil-visual-state-map (kbd ">") '@evil-shift-right-visual)
(define-key evil-visual-state-map (kbd "<") '@evil-shift-left-visual)
(define-key evil-visual-state-map [tab] '@evil-shift-right-visual)
(define-key evil-visual-state-map [S-tab] '@evil-shift-left-visual)
(defun @evil-shift-left-visual ()
(interactive)
(evil-shift-left (region-beginning) (region-end))
(evil-normal-state)
(evil-visual-restore))
(defun @evil-shift-right-visual ()
(interactive)
(evil-shift-right (region-beginning) (region-end))
(evil-normal-state)
(evil-visual-restore))
Evil should respect visual line mode
(defun evil-next-line--check-visual-line-mode (orig-fun &rest args)
(if visual-line-mode
(apply 'evil-next-visual-line args)
(apply orig-fun args)))
(advice-add 'evil-next-line :around 'evil-next-line--check-visual-line-mode)
(defun evil-previous-line--check-visual-line-mode (orig-fun &rest args)
(if visual-line-mode
(apply 'evil-previous-visual-line args)
(apply orig-fun args)))
(advice-add 'evil-previous-line :around 'evil-previous-line--check-visual-line-mode)
(use-package evil-collection
:after evil
:config
(evil-collection-init))
(use-package evil
:init
(setq evil-want-keybinding nil)
:config
(modify-syntax-entry ?_ "w")
(setq evil-v$-excludes-newline t)
<<evil-shifting-config>>
<<evil-respect-visual-line-mode>>
(setq evil-respect-visual-line-mode t)
(evil-set-undo-system 'undo-fu)
(setq-default evil-kill-on-visual-paste nil)
(evil-mode 1)
<<general-minibuffer-mode-map>>)
(use-package evil-commentary
:bind (:map evil-normal-state-map
("gc" . evil-commentary)))
Bookmark for navigation inside file
(use-package bm
:defer t
:custom-face
(bm-face ((t (:foreground ,+m-color-secondary :background unspecified))))
:custom
(bm-in-lifo-order t)
:bind (("C-M-n" . bm-next)
("C-M-p" . bm-previous)
("s-b" . bm-toggle)))
(use-package avy
:defer t
:general
(:states '(normal visual)
:keymaps 'override
"f" 'avy-goto-word-1
"gD" '@avy-go-to-definition
"SPC k l" 'avy-kill-whole-line
"SPC k r" 'avy-kill-region)
(:keymaps '(minibuffer-local-mode-map read--expression-map)
"C-l" 'avy-goto-char
"C-f" 'avy-goto-char)
:custom
(avy-single-candidate-jump t)
(avy-keys '(?q ?w ?e ?r ?t ?y ?u ?i ?o ?p ?a ?s ?d ?f ?h ?j ?k ?l ?z ?x ?c ?v ?b ?n ?m)))
(defun @avy-ignore-current-buffer ()
"Ignore current buffer when using avy."
(interactive)
(add-to-list 'aw-ignored-buffers (buffer-name)))
(use-package ace-window
:general
(:keymaps 'override
:states
'(normal visual insert)
"s-." #'ace-window
"s-g" #'ace-window)
:bind (:map evil-normal-state-map
("s-." . ace-window)
("s-g" . ace-window)
("SPC a i" . @avy-ignore-current-buffer))
:defer t
:config
(setq aw-ignored-buffers (delq 'treemacs-mode aw-ignored-buffers))
;; (add-to-list 'aw-ignored-buffers 'dap-ui--locals-buffer)
<<avy-ignore-current-buffer-fn>>)
(use-package evil-matchit
:hook
(html-mode . evil-matchit-mode)
(ng2-html-mode . evil-matchit-mode)
(web-mode . evil-matchit-mode)
:init
(evilmi-load-plugin-rules '(ng2-html-mode) '(html)))
(defun @better-jump-preserve-pos-advice (oldfun &rest args)
"Preserve position when jumping."
(let ((old-pos (point)))
(apply oldfun args)
(when (> (abs (- (line-number-at-pos old-pos) (line-number-at-pos (point))))
1)
(better-jumper-set-jump old-pos))))
(use-package better-jumper
:demand t
:general
(:states '(normal, visual)
"C-o" 'better-jumper-jump-backward
"C-i" 'better-jumper-jump-forward
"SPC sp" 'better-jumper-set-jump)
:custom
;; (better-jumper-add-jump-behavior #'replace)
(better-jumper-use-evil-jump-advice nil)
:config
<<better-jump-fn>>
(advice-add 'evil-next-line :around #'@better-jump-preserve-pos-advice)
(advice-add 'evil-previous-line :around #'@better-jump-preserve-pos-advice)
(advice-add '@find-definition :before (lambda () (call-interactively #'better-jumper-set-jump)))
(advice-add 'evil-jump-item :around #'@better-jump-preserve-pos-advice)
(better-jumper-mode 1))
(use-package frog-jump-buffer
:ensure (:host github :repo "waymondo/frog-jump-buffer")
:bind
(("s-t" . frog-jump-buffer))
:config
(setq frog-jump-buffer-default-filter 'frog-jump-buffer-filter-same-project)
;; (defun frog-jump-buffer-filter-persp-buffers (buffer)
;; (with-current-buffer buffer
;; (let ((persp-name (if (and (fboundp 'safe-persp-name) (fboundp 'get-current-persp))
;; (safe-persp-name (get-current-persp))
;; "default"))
;; )
;; )
;; (-any? #'derived-mode-p '(comint-mode magit-mode inf-ruby-mode rg-mode compilation-mode))))
;; (setq frog-jump-buffer-filter-actions
;; '(("p" "[persp]" frog-jump-buffer-filter-persp-buffers)))
(defun frog-jump-buffer-same-project ()
(interactive)
(let ((frog-jump-buffer-current-filter-function #'frog-jump-buffer-filter-same-project))
(frog-jump-buffer)))
(setq frog-jump-buffer-use-all-the-icons-ivy t)
(dolist (regexp '("TAGS" "^\\*" "^\\*elpaca" "^\\*lsp" "^\\*calendar" "^\\*Google" "^\\*copilot" "^\\*dashboard" "^\\*direnv" "^\\*Compile-log" "-debug\\*$" "^\\:" "errors\\*$" "^\\*Backtrace" "-ls\\*$"
"stderr\\*$" "^\\*Flymake" "^\\*vc" "^\\*Warnings" "^\\*eldoc" "\\^*Shell Command"))
(push regexp frog-jump-buffer-ignore-buffers)))
(setq global-auto-revert-mode nil)
(setq auto-revert-verbose nil)
(use-package treemacs
:defer t
:bind
(:map treemacs-mode-map
("@" . evil-execute-macro)
:map evil-normal-state-map
("SPC o p" . treemacs))
:custom-face
(font-lock-doc-face ((t (:inherit nil))))
(doom-themes-treemacs-file-face ((t (:inherit font-lock-doc-face :slant italic))))
(doom-themes-treemacs-root-face ((t (:inherit nil :slant italic))))
(treemacs-root-face ((t (:inherit variable-pitch :slant italic))))
:custom
(treemacs-width 45)
:config
(setq doom-themes-treemacs-theme "doom-colors") ; use "doom-colors" for less minimal icon theme
(doom-themes-treemacs-config)
(doom-themes-org-config))
Treemacs projectile
(use-package treemacs-projectile
:after treemacs projectile
:defer t)
(use-package dired
:defer t
:ensure nil
:general
(:keymaps 'override
:states 'normal
"SPC fi" 'image-dired)
(:keymaps 'dired-mode-map
"C-c C-e" 'wdired-change-to-wdired-mode)
:config
(setq dired-dwim-target t)
(setq insert-directory-program "gls" dired-use-ls-dired t)
(add-hook 'dired-mode-hook 'auto-revert-mode))
Doesn’t work on mac properly. Very laggy unfortunately Dirvish.
(use-package dirvish
:init
(dirvish-override-dired-mode)
:custom
(dirvish-quick-access-entries ; It's a custom option, `setq' won't work
'(("h" "~/" "Home")
("d" "~/Downloads/" "Downloads")))
:config
;; (dirvish-peek-mode) ; Preview files in minibuffer
;; (dirvish-side-follow-mode) ; similar to `treemacs-follow-mode'
;; (remove-hook 'dired-mode-hook 'treemacs-icons-dired-mode)
;; (remove-hook 'dired-after-readin-hook 'treemacs-icons-dired--display)
;; (setq dirvish-mode-line-format
;; '(:left (sort symlink) :right (omit yank index)))
(setq dirvish-attributes
'(file-time collapse subtree-state))
;; (setq dirvish-attributes
;; '(file-time collapse subtree-state vc-state git-msg))
(setq delete-by-moving-to-trash t)
;; (setq dired-listing-switches
;; "-l --almost-all --human-readable --group-directories-first --no-group")
:bind
;; Bind `dirvish|dirvish-side|dirvish-dwim' as you see fit
(("C-c f" . dirvish)
:map dirvish-mode-map
("q" . dirvish-quit)
:map dired-mode-map ; Dirvish respects all the keybindings in this map
("q" . dirvish-quit)
("h" . dired-up-directory)
("j" . dired-next-line)
("k" . dired-previous-line)
("l" . dired-find-file)
("i" . wdired-change-to-wdired-mode)
("." . dired-omit-mode)
("b" . dirvish-bookmark-jump)
("f" . dirvish-file-info-menu)
("y" . dirvish-yank-menu)
("N" . dirvish-narrow)
("^" . dirvish-history-last)
("s" . dirvish-quicksort) ; remapped `dired-sort-toggle-or-edit'
("?" . dirvish-dispatch) ; remapped `dired-summary'
("TAB" . dirvish-subtree-toggle)
("M-n" . dirvish-history-go-forward)
("M-p" . dirvish-history-go-backward)
("M-l" . dirvish-ls-switches-menu)
("M-m" . dirvish-mark-menu)
("M-f" . dirvish-toggle-fullscreen)
("M-s" . dirvish-setup-menu)
("M-e" . dirvish-emerge-menu)
("M-j" . dirvish-fd-jump)))
(use-package casual-dired
:ensure (:type git :host github :repo "kickingvegas/casual-dired")
:general
(:states '(normal visual)
:kemaps '(dired-mode-map)
"E" 'casual-dired-tmenu))
(use-package file-info
:bind
(("C-c d" . 'file-info-show)
("s-'" . 'file-info-show))
:defer t
:config
(setq hydra-hint-display-type 'posframe)
(setq hydra-posframe-show-params '(:poshandler posframe-poshandler-frame-center
:internal-border-width 2
:internal-border-color "#61AFEF"
:left-fringe 16
:right-fringe 16)))
(use-package reveal-in-osx-finder
:defer t
:bind (:map evil-normal-state-map
("SPC o f" . reveal-in-osx-finder))
:ensure t)
Clear vterm history.
(defun @clear-term-history ()
"Clear terminal history inside vterm."
(interactive)
(when (eq major-mode 'vterm-mode)
(vterm--self-insert)
(vterm-send-string "clear")
(vterm-send-return)))
(advice-add 'vterm-clear-scrollback :before #'@clear-term-history)
Open vterm in the current buffer. When vterm doesn’t exist, create one.
(defun @vterm-open-here ()
"Open vterm inside current buffer!"
(interactive)
(let ((nodejs-repl-buffer-name "*vterm*"))
(if (get-buffer nodejs-repl-buffer-name)
(switch-to-buffer nodejs-repl-buffer-name)
(progn
(pop-to-buffer vterm-buffer-name)
(vterm)))))
(defun @vterm-open-last ()
"Open vterm inside current buffer!"
(interactive)
(let ((vterm-buffer-name "*vterm*"))
(if (get-buffer vterm-buffer-name)
(pop-to-buffer vterm-buffer-name)
(progn
(pop-to-buffer vterm-buffer-name)
(vterm)))))
(use-package vterm
:defer t
:hook (vterm-mode . (lambda () (set-face-attribute 'vterm-color-black nil :foreground +m-color-secondary :background +m-color-secondary)))
:custom
(vterm-max-scrollback 5000)
:general
(:states '(normal visual)
"SPC ov" 'vterm
"SPC oV" '@vterm-open-here
"SPC oL" '@vterm-open-last)
(:keymaps '(vterm-mode-map vterm-copy-mode-map)
"C-u" 'vterm--self-insert)
(:keymaps '(vterm-mode-map vterm-copy-mode-map)
:states '(normal visual)
"SPC mc" 'vterm-copy-mode)
:config
(set-face-attribute 'vterm-color-black nil :foreground +m-color-secondary :background +m-color-secondary)
<<vterm-function-clear>>)
(defun @vterm-change-current-directory-to-active-buffer-pwd ()
"Just exec CD to pwd of active buffer."
(interactive)
(when-let* ((file-name (buffer-file-name))
(file-dir (file-name-directory file-name))
(file-dir (replace-regexp-in-string " " "\\\\\ " file-dir)))
;; (save-window-excursion
(vterm-toggle-show)
(switch-to-first-matching-buffer "vterm")
(evil-insert 0)
(vterm-send-C-c)
(vterm-send-string (concat "cd " file-dir))
(vterm-send-return)
;; )
(evil-window-down 1)))
(use-package vterm-toggle
:defer t
:commands (vterm-toggle-show)
:general (:states '(normal visual)
:keymaps 'override
"SPC oh" (lambda () (interactive)
(+vterm/toggle t))
"SPC th" 'vterm-toggle-hide
"SPC ot" 'vterm-toggle-cd
"SPC oT" '@vterm-change-current-directory-to-active-buffer-pwd
"SPC tk" 'my-open-kitty-right-here)
(:states '(normal visual)
:keymaps 'vterm-mode-map
"SPC t]" 'vterm-toggle-forward
"SPC t[" 'vterm-toggle-backward
"SPC tn" (lambda () (interactive)
(let ((current-buffer-name (buffer-name)))
(vterm-toggle--new)
(delete-window)
(display-buffer current-buffer-name)
(vterm-toggle-forward)))
"SPC tx" (lambda (args) (interactive "P")
(when (string-match "vterm" (buffer-name))
(let ((kill-buffer-query-functions nil))
(kill-this-buffer)
(+vterm/toggle args)))))
:config
(setq vterm-always-compile-module t)
(setq vterm-kill-buffer-on-exit nil)
(setq vterm-toggle-scope 'project)
<<vterm-open-bottom-config>>)
(defun @projectile-detached-shell-command ()
"Execute detached shell command at the project root."
(interactive)
(projectile-with-default-dir (projectile-acquire-root)
(call-interactively #'detached-shell-command)))
(use-package detached
:init
(detached-init)
:general
(:states '(normal visual)
:keymaps 'override
"SPC dj" '@projectile-detached-shell-command
"SPC dv" 'detached-list-sessions)
(:keymaps 'detached-list-mode-map
"x" 'detached-list-kill-session)
:bind (;; Replace `async-shell-command' with `detached-shell-command'
([remap async-shell-command] . detached-shell-command)
;; Replace `compile' with `detached-compile'
([remap compile] . detached-compile)
([remap recompile] . detached-compile-recompile)
;; Replace built in completion of sessions with `consult'
([remap detached-open-session] . detached-consult-session))
:custom ((detached-show-output-on-attach t)
(detached-terminal-data-command system-type)))
Something like screensaver
(use-package redacted
:ensure (:type git :host github :repo "bkaestner/redacted.el")
:defer t)
(defun @persp-kill-other-buffers ()
"Kill all buffers except current buffer."
(interactive)
(let ((current-buffer (current-buffer))
(killed-buffer-count 0))
(mapc (lambda (buffer)
(unless (eq buffer current-buffer)
(setq killed-buffer-count (1+ killed-buffer-count))
(kill-buffer buffer)))
(persp-buffer-list))
(message "Killed %s buffers" killed-buffer-count)))
(load "~/apps/pure-emacs/vendor/doom-workspaces.el")
(elpaca-wait)
(persp-autokill-buffer-on-remove 'kill-weak)
(persp-reset-windows-on-nil-window-conf nil)
(persp-add-buffer-on-after-change-major-mode t)
(persp-nil-hidden t)
(persp-nil-name "default")
(persp-auto-save-fname "autosave")
(persp-save-dir (concat default-directory "workspaces/"))
(persp-set-last-persp-for-new-frames t)
(persp-switch-to-added-buffer nil)
(persp-kill-foreign-buffer-behaviour 'kill)
(persp-remove-buffers-from-nil-persp-behaviour nil)
(persp-auto-resume-time -1) ; Don't auto-load on startup
(persp-auto-save-opt (if noninteractive 0 1))
(persp-save-dir "~/tmp/workspaces/")
Add new buffer to current persp
(add-hook 'after-switch-to-buffer-functions
#'(lambda (bn) (when (and persp-mode
(not persp-temporarily-display-buffer))
(persp-add-buffer bn))))
Variables for define colors of tab
(defface +workspace-tab-selected-face
'((t :inherit nano-face-header-popout))
"Face for selected persp tab bar"
:group 'persp-tabbar)
(defface +workspace-tab-face
'((t :inherit nano-face-popout ))
"Face for persp tab bar"
:group 'persp-tabbar)
(defvar +workspaces-main "main"
"The name of the primary and initial workspace, which cannot be deleted.")
(defvar +workspaces-switch-project-function #'doom-project-find-file
"The function to run after `projectile-switch-project' or
`counsel-projectile-switch-project'. This function must take one argument: the
new project directory.")
(defvar +workspaces-on-switch-project-behavior 'non-empty
"Controls the behavior of workspaces when switching to a new project.")
(add-hook! '(persp-mode-hook persp-after-load-state-functions)
(defun +workspaces-ensure-no-nil-workspaces-h (&rest _)
(when persp-mode
(dolist (frame (frame-list))
(when (string= (safe-persp-name (get-current-persp frame)) persp-nil-name)
;; Take extra steps to ensure no frame ends up in the nil perspective
(persp-frame-switch (or (cadr (hash-table-keys *persp-hash*))
+workspaces-main)
frame))))))
(add-hook! 'persp-mode-hook
(defun +workspaces-init-first-workspace-h (&rest _)
"Ensure a main workspace exists."
(when persp-mode
(let (persp-before-switch-functions)
;; Try our best to hide the nil perspective.
(when (equal (car persp-names-cache) persp-nil-name)
(pop persp-names-cache))
;; ...and create a *real* main workspace to fill this role.
(unless (or (persp-get-by-name +workspaces-main)
;; Start from 2 b/c persp-mode counts the nil workspace
(> (hash-table-count *persp-hash*) 2))
(persp-add-new +workspaces-main))
;; HACK Fix #319: the warnings buffer gets swallowed when creating
;; `+workspaces-main', so display it ourselves, if it exists.
(when-let (warnings (get-buffer "*Warnings*"))
(save-excursion
(display-buffer-in-side-window
warnings '((window-height . shrink-window-if-larger-than-buffer))))))))
(defun +workspaces-init-persp-mode-h ()
(cond (persp-mode
;; `uniquify' breaks persp-mode. It renames old buffers, which causes
;; errors when switching between perspective (their buffers are
;; serialized by name and persp-mode expects them to have the same
;; name when restored).
(when uniquify-buffer-name-style
(setq +workspace--old-uniquify-style uniquify-buffer-name-style))
(setq uniquify-buffer-name-style nil)
;; Ensure `persp-kill-buffer-query-function' is last
(remove-hook 'kill-buffer-query-functions #'persp-kill-buffer-query-function)
(add-hook 'kill-buffer-query-functions #'persp-kill-buffer-query-function t)
;; Restrict buffer list to workspace
(advice-add #'doom-buffer-list :override #'+workspace-buffer-list))
(t
(when +workspace--old-uniquify-style
(setq uniquify-buffer-name-style +workspace--old-uniquify-style))
(advice-remove #'doom-buffer-list #'+workspace-buffer-list)))))
(defun +workspace/quick-new ()
"Create new workspace quickly"
(interactive)
(let ((name (format "#%s" (+workspace--generate-id))))
(persp-switch name)
(switch-to-buffer (doom-fallback-buffer))
(with-current-buffer (doom-fallback-buffer)
(delete-other-windows)
(+workspace/display))))
(use-package workgroups)
(:keymaps 'global
:states '(normal visual insert)
"C-1" '+workspace/switch-to-0
"C-2" '+workspace/switch-to-1
"C-3" '+workspace/switch-to-2
"C-4" '+workspace/switch-to-3
"C-5" '+workspace/switch-to-4
"C-6" '+workspace/switch-to-5
"C-7" '+workspace/switch-to-6
"C-8" '+workspace/switch-to-7
"C-9" '+workspace/switch-to-8
"s-1" '+workspace/switch-to-0
"s-2" '+workspace/switch-to-1
"s-3" '+workspace/switch-to-2
"s-4" '+workspace/switch-to-3
"s-5" '+workspace/switch-to-4
"s-6" '+workspace/switch-to-5
"s-7" '+workspace/switch-to-6
"s-8" '+workspace/switch-to-7
"s-9" '+workspace/switch-to-8)
(:keymaps 'override
:states '(normal visual)
"SPC bO" '@persp-kill-other-buffers
"SPC bb" 'consult-projectile-switch-to-buffer
"SPC bk" 'persp-kill-buffer
"SPC pc" 'persp-copy
"SPC pk" 'persp-kill
"SPC pS" '+workspace/save
"SPC ps" 'persp-save-state-to-file
"SPC pL" '+workspace/load
"SPC pl" 'persp-load-state-from-file
"SPC pd" '+workspace/delete
"SPC <tab>d" '+workspace/delete
"SPC TAB d" '+workspace/delete
"SPC pr" '+workspace/rename
"SPC pj" 'persp-switch
"SPC pn" '+workspace/quick-new
"SPC <tab>n" '+workspace/quick-new
"SPC TAB n" '+workspace/quick-new
"SPC po" '+workspace/other
"SPC b O" '@persp-kill-other-buffers
"SPC <tab> <tab>" '+workspace/display
"SPC TAB TAB" '+workspace/display
"SPC b i" (lambda (arg)
(interactive "P")
(with-persp-buffer-list () (ibuffer arg))))
TODO: change binding to general
(use-package persp-mode
:after workgroups
:general
<<persp-mode-map-general>>
:init
(add-hook 'window-setup-hook (lambda () (persp-mode 1)))
:custom
<<persp-mode-custom>>
:config
(set-persp-parameter 'dont-save-to-file t nil)
<<kill-other-buffers-fn>>
<<persp-buffer-advices>>
(persp-mode 1)
;; <<persp-add-buffer>>
<<workspaces-doom-config>>
<<workspaces-doom-patch>>)
This function also stolen from doom emacs. It provide functionality for automatic switch to workspace when you open buffer from ibuffer.
(defun +ibuffer/visit-workspace-buffer (&optional select-first)
"Visit buffer, but switch to its workspace if it exists."
(interactive "P")
(let ((buf (ibuffer-current-buffer t)))
(unless (buffer-live-p buf)
(user-error "Not a valid or live buffer: %s" buf))
(if-let (workspaces
(cl-loop for wk in (+workspace-list)
if (+workspace-contains-buffer-p buf wk)
collect wk))
(+workspace-switch
(if (and (not select-first) (cdr workspaces))
(or (completing-read "Select workspace: " (mapcar #'persp-name workspaces))
(user-error "Aborted"))
(persp-name (car workspaces))))
;; Or add the buffer to the current workspace
(persp-add-buffer buf))
(switch-to-buffer buf)))
(use-package ibuffer
:defer t
:ensure nil
:general
(:states '(normal visual)
:keymaps 'override
"SPC bI" 'projectile-ibuffer
"SPC bi" 'ibuffer)
(:states '(normal visual)
:keymaps 'ibuffer-mode-map
"<return>" '+ibuffer/visit-workspace-buffer))
(with-eval-after-load "ibuffer"
(require 'ibuf-ext)
(define-ibuffer-filter persp
"Toggle current view to buffers of current perspective."
(:description "persp-mode"
:reader (persp-prompt nil nil (safe-persp-name (get-frame-persp)) t))
(find buf (safe-persp-buffers (persp-get-by-name qualifier))))
(defun persp-add-ibuffer-group ()
(let ((perspslist (mapcar #'(lambda (pn)
(list pn (cons 'persp pn)))
(nconc
(delete* persp-nil-name
(persp-names-current-frame-fast-ordered)
:test 'string=)
(list persp-nil-name)))))
(setq ibuffer-saved-filter-groups
(delete* "persp-mode" ibuffer-saved-filter-groups
:test 'string= :key 'car))
(push
(cons "persp-mode" perspslist)
ibuffer-saved-filter-groups)))
(defun persp-ibuffer-visit-buffer ()
(let ((buf (ibuffer-current-buffer t))
(persp-name (get-text-property
(line-beginning-position) 'ibuffer-filter-group)))
(persp-switch persp-name)
(switch-to-buffer buf)))
(define-key ibuffer-mode-map (kbd "RET") 'persp-ibuffer-visit-buffer)
(add-hook 'ibuffer-mode-hook
#'(lambda ()
(persp-add-ibuffer-group)
(ibuffer-switch-to-saved-filter-groups "persp-mode"))))
(use-package persp-mode-project-bridge
:after persp-mode
:config
(with-eval-after-load "persp-mode-projectile-bridge-autoloads"
(add-hook 'persp-mode-projectile-bridge-mode-hook
#'(lambda ()
(if persp-mode-projectile-bridge-mode
(persp-mode-projectile-bridge-find-perspectives-for-all-buffers)
(persp-mode-projectile-bridge-kill-perspectives))))
(add-hook 'after-init-hook
#'(lambda ()
(persp-mode-projectile-bridge-mode 1))
t)))
(use-package no-littering
:demand t
:config
(setq backup-directory-alist `(("." . "~/.emacs-saves")))
(setq auto-save-file-name-transforms
`((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))
(setq backup-by-copying t))
(use-package origami
:hook ((org-mode
dart-mode
yaml-mode
js-ts-mode
yaml-ts-mode
python-mode
python-ts-mode
html-mode
ng2-html-mode
emacs-lisp-mode
typescript-ts-mode
go-ts-mode
python-ts-mode) . origami-mode)
:after evil)
(defun @fold-close-all ()
"Close all folds."
(interactive)
(cond ((equal major-mode 'org-mode) (+org/close-all-folds))
((bound-and-true-p origami-mode) (call-interactively 'origami-close-all-nodes))
((bound-and-true-p treesit-fold-mode) (treesit-fold-close-all))
(t (evil-close-folds))))
(defun @fold-close ()
"Close the fold under the cursor."
(interactive)
(cond ((equal major-mode 'org-mode) (+org/close-fold))
((bound-and-true-p origami-mode) (call-interactively 'origami-close-node))
((bound-and-true-p treesit-fold-mode) (treesit-fold-close))
(t (evil-close-fold))))
(defun @fold-open-all ()
"Open all folds."
(interactive)
(cond ((equal major-mode 'org-mode) (+org/open-all-folds))
((bound-and-true-p origami-mode) (call-interactively 'origami-open-all-nodes))
((bound-and-true-p treesit-fold-mode) (treesit-fold-open-all))
(t (evil-open-folds))))
(defun @fold-open ()
"Open the fold under the cursor."
(interactive)
(cond ((equal major-mode 'org-mode) (+org/open-fold))
((bound-and-true-p origami-mode) (call-interactively 'origami-open-node))
((bound-and-true-p treesit-fold-mode) (treesit-fold-open))
(t (evil-open-fold))))
(defun @fold-toggle-all ()
"Toggle all folds."
(interactive)
(cond ((equal major-mode 'org-mode) (+org/toggle-fold))
((bound-and-true-p origami-mode) (call-interactively 'origami-toggle-all-nodes))
((bound-and-true-p treesit-fold-mode) (treesit-fold-toggle-all))
(t (evil-toggle-fold))))
(defun @fold-toggle ()
"Toggle fold at point."
(interactive)
(save-excursion
(end-of-line)
(cond ((equal major-mode 'org-mode) (+org/toggle-fold))
((bound-and-true-p origami-mode) (call-interactively 'origami-toggle-node))
((bound-and-true-p treesit-fold-mode) (treesit-fold-toggle))
(t (evil-toggle-fold)))))
(defun @fold-next ()
"Go to the next fold."
(interactive)
(cond ((bound-and-true-p origami-mode) (call-interactively 'origami-next-fold))
((bound-and-true-p treesit-fold-mode) (treesit-fold-next))
(t (evil-next-fold))))
(defun @fold-previous ()
"Go to the previous fold."
(interactive)
(cond ((bound-and-true-p origami-mode) (call-interactively 'origami-previous-fold))
((bound-and-true-p treesit-fold-mode) (treesit-fold-previous))
(t (evil-previous-fold))))
(defun @treesit-fold-init ()
"Init ts-fold."
(interactive)
(when (and (bound-and-true-p tree-sitter-mode)
(member major-mode '(ng2-ts-mode
typescript-mode
js-mode
python-mode
html-mode
json-mode
go-mode
scss-mode
css-mode
typescript-ts-mode
go-ts-mode
bash-ts-mode
python-ts-mode
json-ts-mode
html-ts-mode
scss-ts-mode
css-ts-mode
bash-mode)))
(treesit-fold-mode 1)))
(use-package treesit-fold
:ensure (treesit-fold :type git :host github :repo "abougouffa/treesit-fold")
:hook ((tree-sitter-mode
web-mode
ng2-html-mode
ng2-ts-mode
typescript-mode
js-mode
python-mode
html-mode
json-mode
go-mode
bash-mode
css-mode
scss-mode
go-ts-mode
typescript-ts-mode) . @treesit-fold-init)
:general
<<ts-fold-general-keybindings>>
:config
(add-to-list 'ts-fold-range-alist '(ng2-ts-mode . ((export_clause . ts-fold-range-seq)
(statement_block . ts-fold-range-seq)
(comment . ts-fold-range-c-like-comment))) t)
(add-to-list 'ts-fold-range-alist '(web-mode . (html-mode
(element . ts-fold-range-html)
(comment ts-fold-range-seq 1 -1))))
(add-to-list 'ts-fold-range-alist '(ng2-html-mode . (html-mode
(element . ts-fold-range-html)
(comment ts-fold-range-seq 1 -1))))
(add-to-list 'ts-fold-range-alist '(scss-mode . ((keyframe_block_list . ts-fold-range-seq)
(block . ts-fold-range-seq)
(comment . ts-fold-range-c-like-comment))) t)
(add-to-list 'ts-fold-range-alist '(typescript-ts-mode . ((export_clause . ts-fold-range-seq)
(statement_block . ts-fold-range-seq)
(comment . ts-fold-range-c-like-comment))))
(add-to-list 'ts-fold-range-alist `(typescript-ts-mode . ,(ts-fold-parsers-typescript)))
(add-to-list 'ts-fold-range-alist `(go-ts-mode . ,(ts-fold-parsers-go)))
;; (add-to-list 'ts-fold-range-alist '(go-ts-mode . ts-fold-summary-go))
;; TODO: DOESN'T WORK for scss, needs another rules (check it later for custom pareser)
(add-to-list 'ts-fold-range-alist '(scss-mode . (css-mode
(keyframe_block_list . ts-fold-range-seq)
(block . ts-fold-range-seq)
(comment . ts-fold-range-c-like-comment)))))
;; TODO: check changes for correct mode cast
;; (add-to-list 'ts-fold-foldable-node-alist '(ng2-ts-mode comment statement_block export_clause))
;; (add-to-list 'ts-fold-foldable-node-alist '(web-mode comment element))
;; (add-to-list 'ts-fold-foldable-node-alist '(scss-mode comment block keyframe_block_list))
;; (add-to-list 'ts-fold-foldable-node-alist '(ng2-html-mode comment element)))
Display buffer of quick note always at bottom
(add-to-list 'display-buffer-alist '("^\\*scratch\\*$" (display-buffer-below-selected) (window-height . 0.4)))
(add-to-list 'display-buffer-alist '("^\\*quicknote\\*$"
(display-buffer-in-side-window)
(inhibit-same-window . t)
(side . bottom)
(window-width . full)
(window-height . 0.3)))
(defun @switch-to-scratch ()
"Switch to scratch buffer"
(interactive)
;; (persistent-scratch-autosave-mode -1)
(let* ((buffer-name "*quicknote*")
(buffer (get-buffer buffer-name)))
(unless buffer
(persistent-scratch-setup-default)
(setq buffer (get-buffer-create buffer-name))
(persistent-scratch-restore))
(message "current buffer: %s" buffer)
(with-current-buffer buffer
(pop-to-buffer buffer)
;; (when (equal (s-trim (buffer-substring-no-properties (point-min) (point-max))) "")
;; (message "Persistent scratch restored")
;; (persistent-scratch-setup-default))
;; (goto-char (point-max))
;; (unless (eq major-mode 'org-mode)
;; (org-mode))
(org-mode)
(evil-insert-state))))
Override function for autosaving
(defvar @persistent-scratch-last-content nil)
(defun @persistent-scratech-savable-p ()
"Return non-nil if the current buffer is savable."
(when-let* ((current-buffer-scratch-p (string= (buffer-name) "*quicknote*"))
(scratch-buffer (get-buffer "*quicknote*"))
(scratch-buffer-content (with-current-buffer scratch-buffer
(buffer-string)))
(scratch-buffer-content-not-empty (not (equal scratch-buffer-content ""))))
;; (scratch-buffer-content-changed (not (equal scratch-buffer-content @persistent-scratch-last-content)))
;; (scratch-string-not-nil (not (equal scratch-buffer-content "nil"))))
;; (setq @persistent-scratch-last-content scratch-buffer-content)
;; (message "buffer name %s, buffer content %s, content true? %s"
;; (get-buffer "*quicknote*")
;; (with-current-buffer "*quicknote*"
;; (buffer-string))
;; (with-current-buffer "*quicknote*"
;; (not (equal (buffer-string) ""))))
t))
(defun @save-scratch-buffer-p ()
"Return non-nil if the current buffer is the scratch buffer."
(let ((persistent-scrach-savable-p (@persistent-scratech-savable-p)))
persistent-scrach-savable-p))
(setq persistent-scratch-scratch-buffer-p-function #'@save-scratch-buffer-p)
(defun @preserve-persistent-scratch ()
"Preserve the persistent scratch buffer. Make backup."
(interactive)
(persistent-scratch-save)
(persistent-scratch-new-backup))
(defun persistent-scratch-save (&optional file)
"Save the current state of scratch buffers.
When FILE is non-nil, the state is saved to FILE; when nil or when called
interactively, the state is saved to `persistent-scratch-save-file'.
What state exactly is saved is determined by `persistent-scratch-what-to-save'.
When FILE is nil and `persistent-scratch-backup-directory' is non-nil, a copy of
`persistent-scratch-save-file' is stored in that directory, with a name
representing the time of the last `persistent-scratch-new-backup' call."
(interactive)
(let* ((actual-file (or file persistent-scratch-save-file))
(tmp-file (concat actual-file ".new"))
(saved-state (persistent-scratch--save-buffers-state)))
(when (car saved-state)
(let ((old-umask (default-file-modes)))
(set-default-file-modes #o600)
(unwind-protect
(let ((coding-system-for-write 'utf-8-unix))
(write-region (cdr saved-state) nil tmp-file nil 0))
(set-default-file-modes old-umask)))
(run-hook-with-args 'persistent-scratch-before-save-commit-functions tmp-file)
(rename-file tmp-file actual-file t)
(dolist (buffer (car saved-state))
(with-current-buffer buffer
(set-buffer-modified-p nil)))
(when (called-interactively-p 'interactive)
(message "Wrote persistent-scratch file %s" actual-file)))
(unless file
(persistent-scratch--update-backup)
(persistent-scratch--cleanup-backups))))
Override autosave function. What is the sense save buffer whic doesn’t exist???
(use-package persistent-scratch
:demand t
:general
(:states '(normal visual)
:keymaps 'override
"SPC x" '@switch-to-scratch)
:config
<<persistent-scratch-save>>
(setq persistent-scratch-backup-directory "~/apps/pure-emacs/backups")
(persistent-scratch-autosave-mode)
(setq persistent-scratch-autosave-interval 5)
)
Override autosave function. What is the sense save buffer whic doesn’t exist???
(use-package tempel
:general
(:keymaps 'override
:states '(normal visual insert)
"s-\\" 'tempel-done)
(:keymaps 'override
:states '(insert)
"s-y" 'tempel-complete
"s-Y" 'tempel-insert)
:init
;; Setup completion at point
(defun tempel-setup-capf ()
;; Add the Tempel Capf to `completion-at-point-functions'.
;; `tempel-expand' only triggers on exact matches. Alternatively use
;; `tempel-complete' if you want to see all matches, but then you
;; should also configure `tempel-trigger-prefix', such that Tempel
;; does not trigger too often when you don't expect it. NOTE: We add
;; `tempel-expand' *before* the main programming mode Capf, such
;; that it will be tried first.
(setq-local completion-at-point-functions
(cons #'tempel-expand
completion-at-point-functions)))
(add-hook 'prog-mode-hook 'tempel-setup-capf)
(add-hook 'text-mode-hook 'tempel-setup-capf)
;; Optionally make the Tempel templates available to Abbrev,
;; either locally or globally. `expand-abbrev' is bound to C-x '.
;; (add-hook 'prog-mode-hook #'tempel-abbrev-mode)
;; (global-tempel-abbrev-mode)
:config
;; FIX https://github.com/minad/tempel/issues/34#issuecomment-1035915789
(defun tempel--disable (&optional st)
"Disable last template."
(let* ((region-start (tempel--beginning))
(region-end (tempel--end)))
(when-let (st (pop tempel--active))
(lsp-on-change region-start region-end (- region-end region-start))
(mapc #'delete-overlay (car st))
(unless tempel--active
(setq minor-mode-overriding-map-alist
(delq (assq-delete-all 'tempel--active minor-mode-overriding-map-alist)
minor-mode-overriding-map-alist))))))
;; TODO: main need to get all from directory.
(setq tempel-path
'("~/apps/pure-emacs/templates/common"
"~/apps/pure-emacs/templates/readme"
"~/apps/pure-emacs/templates/org-mode"
"~/apps/pure-emacs/templates/emacs-lisp"
"~/apps/pure-emacs/templates/golang")))
(use-package tempel-collection
:ensure t
:after tempel)
(use-package lsp-snippet-tempel
:ensure (lsp-snippet-tempel :type git
:host github
:repo "svaante/lsp-snippet")
:config
(lsp-snippet-tempel-lsp-mode-init))
(setq-default indent-tabs-mode nil)
(setq-default tab-width 2)
(use-package prettier
:defer t
:bind (:map evil-normal-state-map
("SPC fp" . prettier-prettify))
:config
(add-to-list 'prettier-major-mode-parsers '(typescript-ts-mode . (typescript babel-ts))))
Another all formtter. Based on prettier and black
(use-package apheleia
:hook (prog-mode . apheleia-global-mode)
:general
(:states '(normal visual)
:keymaps 'override
"\\p" 'apheleia-format-buffer)
:config
(add-to-list 'apheleia-mode-alist '(emacs-lisp-mode . lisp-indent))
(add-to-list 'apheleia-mode-alist '(html-mode . prettier)))
(use-package flycheck
:general (:keymaps 'flycheck-mode-map
:states '(normal visual)
"C-j" 'flycheck-next-error
"C-k" 'flycheck-previous-error)
:bind
(:map evil-normal-state-map
("SPC f ]" . flycheck-next-error)
("SPC f [" . flycheck-previous-error)
("SPC e l" . flycheck-list-errors))
:init
(global-flycheck-mode)
:config
;; Change flycheck errors on save
(setq flycheck-check-syntax-automatically '(save idle-change new-line mode-enabled))
(setq flycheck-idle-change-delay 0.2)
(set-face-attribute 'flycheck-fringe-error nil :background nil :foreground +m-color-secondary)
(set-face-attribute 'flycheck-error-list-error nil :background nil :foreground +m-color-secondary)
(set-face-attribute 'error nil :background nil :foreground +m-color-secondary)
(flycheck-add-mode 'javascript-eslint 'web-mode)
(flycheck-add-mode 'javascript-eslint 'typescript-mode)
(flycheck-add-mode 'javascript-eslint 'ng2-ts-mode)
(flycheck-add-mode 'javascript-eslint 'typescript-ts-mode))
(defun @setup-typescript-highlights ()
"Setup TypeScript highlights via treesit."
(interactive)
(message "SETUP TS MODE")
(setq typescript--treesit-settings
(treesit-font-lock-rules
:language 'typescript
:feature 'decorator-identifier
:override t
'((decorator (call_expression function: (identifier) @font-lock-number-face)))
:language 'typescript
:feature 'decorator-identifier
:override t
'((decorator (identifier) @font-lock-number-face))
:language 'typescript
:feature 'named-import
:override t
'((import_specifier) @font-lock-number-face)
:language 'typescript
:feature 'this
:override t
'((member_expression object: (this) @font-lock-builtin-face))
:language 'typescript
:feature 'predefined
:override t
'((predefined_type) @font-lock-builtin-face)
:language 'typescript
:feature 'property
:override t
'((object (pair key: (property_identifier) @font-lock-object-key-face)))
:language 'typescript
:feature 'object-values
:override t
'((object (pair key: (property_identifier) value: (string) @italic-string-face)))
:language 'typescript
:feature 'object-values
:override t
'((object (pair key: (property_identifier) value: (true) @italic-string-face)))
:language 'typescript
:feature 'object-values
:override t
'((object (pair key: (property_identifier) value: (false) @italic-builtin-face)))
:language 'typescript
:feature 'object-values
:override t
'((object (pair key: (property_identifier) value: (true) @italic-builtin-face)))
:language 'typescript
:feature 'object-values
:override t
'((object (pair key: (property_identifier) value: (null) @italic-builtin-face)))
:language 'typescript
:feature 'object-values
:override t
'((object (pair key: (property_identifier) value: (undefined) @italic-builtin-face)))
:language 'typescript
:feature 'object-values
:override t
'((object (pair key: (property_identifier) value: (number) @italic-builtin-face)))
:language 'typescript
:feature 'object-values
:override t
'((object (pair key: (property_identifier) value: (identifier) @italic)))
;; :language 'typescript
;; :feature 'class-property
;; :override t
;; '((accessibility_modifier) name: (property_identifier) @font-lock-variable-name-face)
))
(setq-local treesit-font-lock-settings (append treesit-font-lock-settings typescript--treesit-settings))
;; (setq-local treesit-font-lock-settings typescript--treesit-settings)
(setq-local treesit-font-lock-rules typescript--treesit-settings)
(setq-local treesit-font-lock-feature-list
'((comment declaration identifier class-property)
(keyword string escape-sequence named-import decorator-identifier type-annotation predefined_type decorator)
(constant expression identifier number pattern property predefined this)
(operator function bracket delimiter object-values)))
(treesit-major-mode-setup))
(use-package combobulate
:after treesit
:ensure (:host github :repo "mickeynp/combobulate")
:preface
;; You can customize Combobulate's key prefix here.
;; Note that you may have to restart Emacs for this to take effect!
(setq combobulate-key-prefix "C-c o")
:hook
((python-ts-mode . combobulate-mode)
(js-ts-mode . combobulate-mode)
(html-ts-mode . combobulate-mode)
(css-ts-mode . combobulate-mode)
(yaml-ts-mode . combobulate-mode)
(typescript-ts-mode . combobulate-mode)
(json-ts-mode . combobulate-mode)
(tsx-ts-mode . combobulate-mode))
;; Amend this to the directory where you keep Combobulate's source
;; code.
)
(use-package treesit ;
:ensure nil
;; :commands (treesit-install-language-grammar nf/treesit-install-all-languages)
;; :hook ((typescript-ts-base-mode
;; go-ts-mode
;; python-ts-mode
;; css-ts-mode) . init-tree-sitter-hl-mode)
:hook
(go-ts-mode . (lambda () (setq-local tab-width 2)))
:custom
(go-ts-mode-indent-offset 2)
:config
(add-hook 'typescript-ts-mode-hook #'@setup-typescript-highlights)
(setq treesit-font-lock-level 4))
(use-package treesit-auto
:config
(setq treesit-auto-install 'prompt)
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode))
(use-package ts-hopper
:ensure (ts-hopper :type git :host github :repo "artawower/ts-hopper.el")
:init
(ts-hopper-init)
:general (:states '(normal visual)
:keymaps 'override
"\'" 'ts-hopper-define-context
"\\k" 'ts-hopper-mode
"," 'ts-hopper-select
"[" 'ts-hopper-hop-prev-context
"]" 'ts-hopper-hop-next-context)
:config
(add-hook 'ts-hopper--after-hop-hook (lambda () (call-interactively 'evil-scroll-line-to-center))))
(use-package corfu
;; Optional customizations
:defer 2
:custom
(corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
(corfu-auto t) ;; Enable auto completion
(corfu-commit-predicate t) ;; Do not commit selected candidates on next input
(corfu-quit-at-boundary t) ;; Automatically quit at word boundary
(corfu-quit-no-match t) ;; Automatically quit if there is no match
(corfu-auto-delay 0.1)
(corfu-echo-documentation nil) ;; Do not show documentation in the echo area
(corfu-preselect-first t)
(corfu-auto-prefix 2)
(corfu-separator ?\s)
;; Optionally use TAB for cycling, default is `corfu-complete'.
:general
(:keymaps 'corfu-map
"TAB" 'corfu-next
[tab] 'corfu-next
"C-j" 'corfu-next
"C-k" 'corfu-previous
"S-TAB" 'corfu-previous
"<return>" 'corfu-insert
"C-<return>" 'corfu-insert-seporator
[backtab] 'corfu-previous)
(:keymaps 'override
:map evil-insert-state-map
"C-x C-o" 'completion-at-point
"C-SPC" 'completion-at-point)
:config
;; (advice-add 'corfu--setup :after 'evil-normalize-keymaps)
;; (advice-add 'corfu--teardown :after 'evil-normalize-keymaps)
(evil-make-overriding-map corfu-map)
(setq lsp-completion-provider :none)
(global-corfu-mode))
(global-company-mode -1)
(company-mode -1)
(add-hook 'prog-mode-hook (lambda () (company-mode -1)))
(use-package corfu-popupinfo
:ensure (corfu-info :host github :repo "minad/corfu" :files ("extensions/corfu-popupinfo.el"))
:after corfu
:config
(setq corfu-popupinfo-delay '(0.5 . 0.5)))
(use-package corfu-history
:ensure (corfu-history :host github :repo "minad/corfu" :files ("extensions/corfu-history.el"))
:after corfu
:config
(with-eval-after-load 'safehist
(cl-pushnew 'corfu-history savehist-additional-variables))
(setq corfu-sort-override-function 'corfu-history--sort)
(corfu-history-mode))
(use-package corfu-popupinfo
:ensure (corfu-popupinfo :host github :repo "minad/corfu" :files ("extensions/corfu-popupinfo.el"))
:bind (:map corfu-map
("C-m" . corfu-popupinfo-documentation))
:custom
(corfu-echo-delay nil)
:after corfu
:config
(corfu-popupinfo-mode))
(use-package kind-icon
:after corfu
:custom
(kind-icon-default-face 'corfu-default) ; to compute blended backgrounds correctly
:config
(add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))
(show-paren-mode 1)
(custom-set-faces
`(show-paren-mismatch ((t (:foreground ,+m-color-secondary)))))
(use-package lsp-sonarlint
:ensure (:files ("*.el" "languages" "languages/*/*.el" "server" "server/*"))
:after lsp-mode
:config
(setq lsp-sonarlint-server-path (expand-file-name "sonarlint-language-server.jar" (concat user-emacs-directory "/elpaca/builds/lsp-sonarlint/server")))
(add-to-list 'lsp-sonarlint-modes-enabled 'ng2-ts-mode)
(add-to-list 'lsp-sonarlint-modes-enabled 'ng2-html-mode)
(add-to-list 'lsp-sonarlint-modes-enabled 'ng2-mode)
(require 'lsp-sonarlint-go)
(setq lsp-sonarlint-go-enabled t)
(require 'lsp-sonarlint-html)
(setq lsp-sonarlint-html-enabled t)
(require 'lsp-sonarlint-javascript)
(setq lsp-sonarlint-javascript-enabled t)
(require 'lsp-sonarlint-typescript)
(setq lsp-sonarlint-typescript-enabled t)
(setq lsp-sonarlint-ng2-ts-enabled t))
(defun @lsp/uninstall-server (dir)
"Delete a LSP server from `lsp-server-install-dir'."
(interactive
(list (read-directory-name "Uninstall LSP server: " lsp-server-install-dir nil t)))
(unless (file-directory-p dir)
(user-error "Couldn't find %S directory" dir))
(delete-directory dir 'recursive)
(message "Uninstalled %S" (file-name-nondirectory dir)))
(use-package lsp-mode
;; :ensure (:host github :repo "emacs-lsp/lsp-mode" :rev "8c57bcfa4b0cf9187011425cf276aed006f27df4")
:after (flycheck lsp-sonarlint)
:hook
((clojure-mode
scss-mode
go-mode
css-mode
js-mode
typescript-mode
vue-mode
web-mode
html-mode
ng2-ts-mode
python-mode
dart-mode
typescript-tsx-mode
;; Treesit
html-ts-mode
typescript-ts-mode
go-ts-mode
js-ts-mode
bash-ts-mode
tsx-ts-mode) . lsp-deferred)
(web-mode . lsp-deferred)
(lsp-completion-mode . my/lsp-mode-setup-completion)
:general (:states '(normal visual)
:keymaps 'override
"SPC fn" 'flycheck-next-error
"gi" 'p-goto-implementation
"SPC la" 'lsp-execute-code-action
"SPC im" 'lsp-ui-imenu
"SPC lr" 'lsp-find-references
"SPC lw" 'lsp-workspace-restart
"SPC rl" 'lsp
"gd" '@find-definition
"SPC la" 'lsp-execute-code-action
"SPC cr" 'lsp-rename)
:init
(setq lsp-headerline-breadcrumb-enable nil)
;; Configuration for corfu
;; https://github.com/minad/corfu/wiki#configuring-corfu-for-lsp-mode
(defun my/lsp-mode-setup-completion ()
(setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults))
'(flex))) ;; Configure flex
:custom
(lsp-headerline-breadcrumb-enable nil)
(lsp-idle-delay 0.3)
(lsp-completion-provider :capf)
(lsp-enable-on-type-formatting nil)
(lsp-eldoc-render-all nil)
(lsp-prefer-flymake nil)
(lsp-modeline-diagnostics-scope :workspace)
;; (lsp-clients-typescript-server-args '("--stdio" "--tsserver-log-file" "/dev/stderr"))
(lsp-clients-typescript-server-args '("--stdio"))
(lsp-completion-default-behaviour :insert)
(lsp-yaml-schemas '((kubernetes . ["/auth-reader.yaml", "/deployment.yaml"])))
(lsp-disabled-clients '(html-ls))
(setq lsp-pyright-venv-path (concat (getenv "HOME") "/.virtualenvs"))
;; (lsp-completion-provider :none)
;; (lsp-completion-provider :capf)
;; Disable bottom help info
(lsp-signature-render-documentation nil)
(lsp-signature-auto-activate nil)
(lsp-enable-snippet nil)
;; (lsp-use-plists t)
(lsp-enable-file-watchers t)
(lsp-file-watch-threshold 8000)
:config
(add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\.bun\\'")
(add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\.npm\\'")
(setq lsp-auto-execute-action nil)
(setq lsp-javascript-display-return-type-hints t)
(setq lsp-json-schemas
`[
(:fileMatch ["ng-openapi-gen.json"] :url "https://raw.githubusercontent.com/cyclosproject/ng-openapi-gen/master/ng-openapi-gen-schema.json")
(:fileMatch ["package.json"] :url "http://json-schema.org/draft-07/schema")
])
(set-face-attribute 'lsp-face-highlight-read nil :foreground "#61AFEF" :bold t :underline nil)
;; Flycheck patch checkers
(require 'flycheck)
(require 'lsp-diagnostics)
(lsp-diagnostics-flycheck-enable)
(mapc #'lsp-flycheck-add-mode '(typescript-mode js-mode css-mode vue-html-mode))
;; Golang
(defun lsp-go-install-save-hooks ()
(flycheck-add-next-checker 'lsp '(warning . go-gofmt) 'append)
(flycheck-add-next-checker 'lsp '(warning . go-golint))
(flycheck-add-next-checker 'lsp '(warning . go-errcheck))
(flycheck-add-next-checker 'lsp '(warning . go-staticcheck))
;; (add-hook 'before-save-hook #'lsp-format-buffer t t)
(add-hook 'before-save-hook #'lsp-organize-imports t t))
(add-hook 'go-mode-hook #'lsp-go-install-save-hooks)
(setq lsp-enable-symbol-highlighting t
lsp-enable-snippet nil ;; Not supported by company capf, which is the recommended company backend
lsp-pyls-plugins-flake8-enabled nil)
(set-face-foreground 'lsp-face-highlight-read +m-color-secondary)
(set-face-foreground 'lsp-face-highlight-textual +m-color-secondary)
(add-to-list 'lsp-file-watch-ignored "[/\\\\]\\venv\\'")
(add-to-list 'lsp-file-watch-ignored "[/\\\\]\\pyenv\\'")
(add-to-list 'lsp-file-watch-ignored "[/\\\\]\\.cache\\'")
(set-face-attribute 'lsp-face-highlight-textual nil :background "#c0caf5")
;; Install corfu completion for lsp
;; (defun corfu-lsp-setup ()
;; (setq-local completion-styles '(orderless basic)
;; completion-category-defaults nil))
;; (add-hook 'lsp-mode-hook #'corfu-lsp-setup)
(@setup-compilation-errors)
(setq lsp-disabled-clients '(html-ls))
(setq lsp-eldoc-hook nil))
(use-package yaml-pro
:defer t
:hook (yaml-mode . yaml-pro-mode))
(use-package lsp-ui
:hook (lsp-mode . lsp-ui-mode)
:bind (:map lsp-ui-peek-mode-map
("C-j" . lsp-ui-peek--select-next)
("C-k" . lsp-ui-peek--select-prev))
:config
(setq lsp-ui-sideline-diagnostic-max-line-length 100
lsp-ui-sideline-diagnostic-max-lines 8
lsp-ui-doc-delay 1
lsp-ui-doc-position 'top
lsp-ui-doc-show-with-mouse nil
lsp-ui-doc-border +m-color-main))
(use-package lsp-dart
:defer t
:hook (dart-mode . (lambda () (interactive)
(add-hook 'after-save-hook
(lambda ()
;; (flutter-run-or-hot-reload)
(flutter-hot-restart)
)
t t)))
:custom
(lsp-dart-dap-flutter-hot-reload-on-save t)
:config
(defun lsp-dart-flutter-widget-guide--add-overlay-to (buffer line col string)
"Add to BUFFER at LINE and COL a STRING overlay."
(save-excursion
(goto-char (point-min))
(forward-line line)
(move-to-column col)
(when (string= lsp-dart-flutter-widget-guide-space (string (following-char)))
(let ((ov (make-overlay (point) (1+ (point)) buffer)))
(overlay-put ov 'category 'lsp-dart-flutter-widget-guide)
(overlay-put ov 'display (propertize string
'face 'custom-comment-tag)))))))
See detail
;; (define-advice json-parse-buffer (:around (old-fn &rest args) lsp-booster-parse-bytecode)
;; "Try to parse bytecode instead of json."
;; (or
;; (when (equal (following-char) ?#)
;; (let ((bytecode (read (current-buffer))))
;; (when (byte-code-function-p bytecode)
;; (funcall bytecode))))
;; (apply old-fn args)))
;; (define-advice lsp-resolve-final-command (:around (old-fn cmd &optional test?) add-lsp-server-booster)
;; "Prepend emacs-lsp-booster command to lsp CMD."
;; (let ((orig-result (funcall old-fn cmd test?)))
;; (if (and (not test?) ;; for check lsp-server-present?
;; (not (file-remote-p default-directory)) ;; see lsp-resolve-final-command, it would add extra shell wrapper
;; lsp-use-plists
;; (not (functionp 'json-rpc-connection)) ;; native json-rpc
;; (executable-find "emacs-lsp-booster"))
;; (progn
;; (message "Using emacs-lsp-booster for %s!" orig-result)
;; (cons "emacs-lsp-booster" orig-result))
;; orig-result)))
(defun compile-eslint--find-filename ()
"Find the filename for current error."
(save-match-data
(save-excursion
(when (re-search-backward (rx bol (group "/" (+ any)) eol))
(list (match-string 1))))))
(add-to-list 'display-buffer-alist '("^\\*compilation\\*$" . (display-buffer-at-bottom)))
(defun @display-buffer-other-vertical (buffer &optional alist)
"Display BUFFER in another window. If only one window, split vertical before."
(message "is one window? %s " (one-window-p))
(if (one-window-p)
(split-window-horizontally))
(display-buffer-use-some-window buffer alist))
(add-to-list 'display-buffer-alist
'(("\\*Messages\\*"
(display-buffer-reuse-window display-buffer-in-side-window @display-buffer-other-vertical display-buffer-use-some-window)
(side . right))))
(defun @setup-compilation-errors ()
(interactive)
(setq compilation-scroll-output t)
(setq compilation-error-regexp-alist '())
(setq compilation-error-regexp-alist-alist '())
;; eslint https://github.com/Fuco1/compile-eslint/blob/master/compile-eslint.el
(when (not compilation-error-regexp-alist-alist)
(setq compilation-error-regexp-alist-alist '()))
(let ((form `(eslint
,(rx-to-string
'(and (group (group (+ digit)) ":" (group (+ digit)))
(+ " ") (or "error" "warning")))
compile-eslint--find-filename
2 3 2 1)))
(if (assq 'eslint compilation-error-regexp-alist-alist)
(setf (cdr (assq 'eslint compilation-error-regexp-alist-alist)) (cdr form))
(push form compilation-error-regexp-alist-alist)))
(push 'eslint compilation-error-regexp-alist)
(add-to-list 'compilation-error-regexp-alist '("^[[:blank:]]*\\([/_-\\.[:alnum:]]+\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\) - error.*$" 1 2 3))
;; React
(add-to-list 'compilation-error-regexp-alist '("[[:blank:]]*\\([/_\\.[:alnum:]-]+\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\) - error.*$" 1 2 3))
;; Angular
(add-to-list 'compilation-error-regexp-alist '("^Error: \\([_[:alnum:]-/.]*\\):\\([0-9]+\\):\\([0-9]+\\)" 1 2 3))
;; Angular vite
(add-to-list 'compilation-error-regexp-alist '("\\([_[:alnum:]-/.]*\\):\\([0-9]+\\):\\([0-9]+\\)" 1 2 3))
;; New eslint
(add-to-list 'compilation-error-regexp-alist '("^\\([_[:alnum:]-/.]*\\)\n[[:blank:]]*\\([0-9]+\\):\\([0-9]+\\)" 1 2 3))
;; Flutter
;; (add-to-list 'compilation-error-regexp-alist '("[[:blank:]]*\\([/_\\.[:alnum:]-]+\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\): Error.*$"))
(add-to-list 'compilation-error-regexp-alist 'dart-analyze)
(add-to-list 'compilation-error-regexp-alist-alist '(dart-analyze "\\([^ ]*\\.dart\\):\\([0-9]+\\):\\([0-9]+\\)" 1 2 3)))
By default compile-goto-error
open new window. Its redundant.
(defun display-buffer-from-compilation-p (_buffer-name _action)
(unless current-prefix-arg
(with-current-buffer (window-buffer)
(derived-mode-p 'compilation-mode))))
(push '(display-buffer-from-compilation-p
display-buffer-use-some-window
(inhibit-same-window . nil))
display-buffer-alist)
(use-package compile
:defer t
:ensure nil
:general
(:states '(normal visual)
:keymaps 'override
"SPC cc" 'projectile-compile-project
"SPC cC" 'recompile
"SPC cv" (lambda ()
(interactive)
(compilation-display-error)
(+select-window-by-name "*compilation.*")))
(:states '(normal visual)
:keymaps 'compilation-mode-map
"C-j" 'compilation-next-error
"C-k" 'compilation-previous-error)
:config
<<display-compilation-buffer>>
(@setup-compilation-errors))
(use-package floobits
:defer t)
Context: https://www.reddit.com/r/emacs/comments/1bg7tgn/introducing_chromeemacs_elevate_your_live_coding/
(use-package atomic-chrome
:defer t
:demand t
:ensure
(atomic-chrome
:repo "KarimAziev/atomic-chrome"
:type git
:flavor nil
:host github)
:commands
(atomic-chrome-start-server)
:config
(setq-default atomic-chrome-extension-type-list '(atomic-chrome))
(setq-default atomic-chrome-buffer-open-style 'frame)
(setq-default atomic-chrome-auto-remove-file t)
(setq-default atomic-chrome-url-major-mode-alist
'(("ramdajs.com" . js-ts-mode)
("github.com" . gfm-mode)
("gitlab.com" . gfm-mode)
("leetcode.com" . typescript-ts-mode)
("codesandbox.io" . js-ts-mode)
("typescriptlang.org" . typescript-ts-mode)
("jsfiddle.net" . js-ts-mode)
("w3schools.com" . js-ts-mode)))
(add-to-list 'atomic-chrome-create-file-strategy
'("~/repos/ts-scratch/src/" :extension
("js" "ts" "tsx" "jsx" "cjs" "mjs")))
(atomic-chrome-start-server))
Clone this repo for js debug git@github.com:microsoft/vscode-js-debug.git
(use-package dape
:defer 2
:ensure (dape :type git :host github :repo "svaante/dape")
:bind (:map evil-normal-state-map
("SPC d d" . dape)
("SPC d n" . dape-next)
("SPC d i" . dape-step-in)
("SPC d o" . dape-step-out)
("SPC d b" . dape-breakpoint-toggle)
("SPC d c" . dape-continue)
("SPC d q" . dape-disconnect-quit)
("SPC d r" . dape-restart)
("SPC d k" . dape-kill)
("SPC d X" . dape-remove-breakpoint-at-point)
("SPC d s" . dape-select-stack)
("SPC d t" . dape-select-thread)
("SPC d x" . dape-breakpoint-remove-all))
:config
(setq dape-inline-variables t))
(use-package rainbow-delimiters
:defer t
:hook (prog-mode . rainbow-delimiters-mode))
(use-package codemetrics
:hook (typescript-mode . codemetrics-mode)
:ensure (:host github :repo "jcs-elpa/codemetrics")
:defer t)
(use-package undo-fu
:defer t
:bind (:map evil-normal-state-map
("u" . undo-fu-only-undo)
("C-r" . undo-fu-only-redo)))
(use-package undo-fu-session
:config
(global-undo-fu-session-mode))
Package for quick editing/deleting brackets and bracket-likes symbols
(use-package evil-surround
:config
(global-evil-surround-mode 1))
TODO: check copilot + blamer
(use-package copilot
:defer 5
:ensure (:host github :repo "copilot-emacs/copilot.el" :files ("*.el"))
:hook
(prog-mode . copilot-mode)
(text-mode . copilot-mode)
:general
(:keymaps 'override
"s-]" 'copilot-next-completion
"s-[" 'copilot-previous-completion
"s-l" 'copilot-accept-completion
"s-j" 'copilot-complete
"s-;" 'copilot-accept-completion-by-word
"s-/" 'copilot-accept-completion-by-line)
:custom
(copilot-idle-delay 0.3)
:config
(setq copilot--previous-point nil)
(setq copilot--previous-window-width nil)
(copilot-diagnose)
;; (global-copilot-mode)
(add-hook 'evil-insert-state-entry-hook (lambda ()
(setq blamer--block-render-p t)
(when (fboundp 'blamer--clear-overlay)
(blamer--clear-overlay))))
(add-hook 'evil-normal-state-entry-hook (lambda ()
(setq blamer--block-render-p nil)
(copilot-clear-overlay))))
(use-package electric
:ensure nil
:hook
(html-mode . sgml-electric-tag-pair-mode)
(ng2-html-mode . sgml-electric-tag-pair-mode)
:config
(setq electric-pair-preserve-balance t
electric-pair-delete-adjacent-pairs t
electric-pair-skip-whitespace nil
electric-pair-open-newline-between-pairs t)
(electric-pair-mode))
Correct position after blamer flicker
(defun @electric-pair--verify-cursor-position (&optional char)
"Verify cusor position after inserting CHAR bracket."
(when (member (char-before) '(?\) ?}))
;; (when (member (char-before) '(?\) ))
(copilot-clear-overlay)
(backward-char))
(when (and (member (char-after) '(?\( ?\{))
(member (chart-after (1+ (point))) '(?\) ?\})))
(forward-char)))
(advice-add 'electric-pair--insert :after #'@electric-pair--verify-cursor-position)
(use-package turbo-log
:defer t
:ensure (turbo-log :type git :host github :repo "Artawower/turbo-log.el" :branch "feat/treesit-migration")
:commands (turbo-log--get-context)
:bind (("C-s-l" . turbo-log-print)
("C-s-i" . turbo-log-print-immediately)
("C-s-h" . turbo-log-comment-all-logs)
("C-s-s" . turbo-log-uncomment-all-logs)
("C-s-x" . turbo-log-delete-all-logs)
("C-s-[" . turbo-log-paste-as-logger )
("C-s-]" . turbo-log-paste-as-logger-immediately))
:custom
(turbo-log-allow-insert-without-tree-sitter-p t)
;; (turbo-log-payload-format-template "")
;; (turbo-log-payload-format-template "\x1b[35m%s: ")
(turbo-log-payload-format-template "%s: ")
:config
(turbo-log-configure
:modes (typescript-ts-mode tsx-ts-mode typescript-mode js2-mode web-mode ng2-ts-mode js-mode)
:strategy merge
:post-insert-hooks ((lambda () (interactive) (call-interactively 'apheleia-format-buffer)) lsp)
;; :msg-format-template "'🦄: %s'"
:msg-format-template "'✎: %s'"))
Patch for correct flycheck run, see emacs-vs/auto-rename-tag#9 (comment)
(defvar auto-rename-tag--after-change-active nil)
(defun auto-rename-tag--before-change-functions (_begin _end)
"Do stuff before buffer is changed.
BEGIN : beginning of the changes.
END : end of the changes."
(unless auto-rename-tag--after-change-active
;; Reset record.
(setq auto-rename-tag--record-prev-word "")
;; Reset flag.
(setq auto-rename-tag--pre-command-actived nil)
(when (and (not undo-in-progress)
(auto-rename-tag--inside-tag-p)
(not (auto-rename-tag--self-tag-p)))
(save-excursion
;; Set active flag.
(setq auto-rename-tag--pre-command-actived t)
(setq auto-rename-tag--record-prev-word (auto-rename-tag--get-tag-name-at-point))
(when (string= auto-rename-tag--record-prev-word "/")
(setq auto-rename-tag--record-prev-word ""))
;; Ensure `auto-rename-tag--record-prev-word' is something other than nil.
(unless auto-rename-tag--record-prev-word
(setq auto-rename-tag--record-prev-word ""))))))
(defun auto-rename-tag--after-change-function (_begin _end _length)
"Do stuff after buffer is changed.
BEGIN : beginning of the changes.
END : end of the changes.
LENGTH : deletion length."
(when auto-rename-tag--pre-command-actived
(run-at-time 0 nil (lambda ()
(save-excursion
(let ((is-end-tag nil)
(current-word "") (pair-tag-word "")
(auto-rename-tag--after-change-active nil))
;; Goto the first character inside the tag.
(auto-rename-tag--goto-the-start-of-tag-name)
(setq is-end-tag (auto-rename-tag--is-closing-tag-p))
(setq current-word (auto-rename-tag--get-tag-name-at-point))
(unless (string= current-word auto-rename-tag--record-prev-word)
;; NOTE: Is closing tag.
(when is-end-tag
(auto-rename-tag--resolve-nested 'backward)
;; Get the tag name and ready to be compare.
(setq pair-tag-word (auto-rename-tag--get-tag-name-at-point))
;; Ensure `pair-tag-word' is something other than nil.
(unless pair-tag-word (setq pair-tag-word ""))
(when (string= auto-rename-tag--record-prev-word pair-tag-word)
;; Delete the pair word.
(unless (string= pair-tag-word "")
(auto-rename-tag--delete-tag-name))
;; Insert new word.
(insert current-word)))
;; NOTE: Is opening tag.
(unless is-end-tag
(auto-rename-tag--resolve-nested 'forward)
(setq is-end-tag (auto-rename-tag--is-closing-tag-p))
;; Get the tag name and ready to be compare.
(setq pair-tag-word (auto-rename-tag--get-tag-name-at-point))
;; Ensure `pair-tag-word' is something other than nil.
(unless pair-tag-word (setq pair-tag-word ""))
(when (string= auto-rename-tag--record-prev-word pair-tag-word)
;; Delete the pair word.
(unless (string= pair-tag-word "")
(auto-rename-tag--delete-tag-name))
;; Insert new word.
(insert current-word))))))))))
(use-package auto-rename-tag
:defer t
:hook ((html-mode ng2-html-mode-hook vue-mode web-mode) . auto-rename-tag-mode)
:config
(auto-rename-tag-mode 1)
<<auto-rename-tag-patch>>)
Allow to transform PASCAL_CASE -> camelCase -> snake_case
(use-package string-inflection
:defer t
:bind ("C-s-c" . string-inflection-all-cycle))
(use-package persistent-soft
:defer t)
(use-package persistent-kmacro
:ensure (:host github :repo "artawower/persistent-kmacro.el")
:defer t
:general (:keymaps 'override
:states 'normal
"SPC me" 'persistent-kmacro-execute-macro
"SPC ma" 'persistent-kmacro-name-last-kbd-macro
"SPC mr" 'persistent-kmacro-remove-macro))
(use-package magit
:defer t
:ensure t
:commands
(magit-get-current-branch)
:general
(:keymaps 'magit-mode-map
:states '(normal visual)
"C-1" 'magit-section-show-level-1
"C-2" 'magit-section-show-level-2
"C-3" 'magit-section-show-level-3
"C-4" 'magit-section-show-level-4
"q" 'kill-current-buffer
"Q" 'bury-buffer
"Z" 'magit-stash
"zz" 'evil-scroll-line-to-center
"1" 'digit-argument
"2" 'digit-argument
"3" 'digit-argument
"4" 'digit-argument
"P" 'magit-fetch
"f" 'evil-avy-goto-word-1)
:custom-face
(git-commit-overlong-summary ((t :inherit error :weight bold)))
:bind (:map magit-mode-map
("s-<return>" . magit-diff-visit-worktree-file)
:map evil-normal-state-map
("SPC g g" . magit-status)
("SPC g n" . magit-todo-list)
("SPC g i" . (lambda () (interactive) (wakatime-ui--clear-modeline) (magit-status))))
:hook
(magit-process-mode . compilation-minor-mode)
:config
(setq magit-process-timestamp-format "%H:%M")
(setq magit-display-buffer-function #'magit-display-buffer-fullcolumn-most-v1)
(define-key transient-map "q" 'transient-quit-one)
(define-key transient-edit-map "q" 'transient-quit-one)
(define-key transient-sticky-map "q" 'transient-quit-seq)
(add-hook 'magit-process-mode #'disable-magit-hooks)
;; (add-hook 'magit-process-mode-hook #'compilation-mode)
(setcdr magit-process-mode-map (cdr (make-keymap)))
(set-keymap-parent magit-process-mode-map special-mode-map)
(advice-add
'ansi-color-apply-on-region
:before
#'my-remove-cr)
(setq magit-process-finish-apply-ansi-colors t))
(use-package magit-todos
:defer t
:general
(:states '(normal visual)
:keymaps 'override
"SPC g n" 'magit-todos-list))
(use-package jist
:ensure t
:custom
(jist-github-token (getenv "GITHUB_TOKEN"))
:general
(:keymaps 'override
:states '(normal visual)
"SPC gcl" 'jist-commit
"SPC glg" 'jist-list
"SPC gpg" 'jist-refetch-gists)
(:keymaps 'jist-gist-list-mode-map
:states '(normal visual)
"<return>" 'jist-browse-gist)
)
(use-package git-gutter
:after git-gutter-fringe
:bind (:map evil-normal-state-map
("SPC g [" . git-gutter:previous-hunk)
("SPC g ]" . git-gutter:next-hunk)
("SPC g r" . git-gutter:revert-hunk))
:config
(setq git-gutter:update-interval 2)
(set-face-foreground 'git-gutter:modified +m-color-main) ;; background color
(set-face-foreground 'git-gutter:added +m-color-green)
(set-face-foreground 'git-gutter:deleted +m-color-secondary)
:init
(global-git-gutter-mode))
Improved styles for git changes
(use-package git-gutter-fringe
:config
(define-fringe-bitmap 'git-gutter-fr:added [224] nil nil '(center repeated))
(define-fringe-bitmap 'git-gutter-fr:modified [224] nil nil '(center repeated))
(define-fringe-bitmap 'git-gutter-fr:deleted [128 192 224 240] nil nil 'bottom))
(use-package blamer
;; :ensure (:type git :host github :repo "artawower/blamer.el" :branch "fix/emacs-buffers-spawns")
:bind (("C-c i" . blamer-show-commit-info)
("C-c h" . (lambda () (interactive) (blamer-show-commit-info 'visual)))
("s-i" . blamer-show-posframe-commit-info))
:custom
(blamer-idle-time 0.8)
(blamer-min-offset 20)
(blamer-max-commit-message-length 65)
(blamer-commit-formatter "◉ %s")
(blamer-view 'overlay)
(blamer-uncommitted-changes-message "uncommitted yet")
:custom-face
(blamer-face ((t :inherit font-lock-comment-face
:italic t
:font "Fira Code 14"
:height 0.9
:background unspecified)))
:config
(tooltip-mode)
(setq blamer-tooltip-function 'blamer-tooltip-commit-message)
(defun blamer-callback-show-commit-diff (commit-info)
(interactive)
(let ((commit-hash (plist-get commit-info :commit-hash)))
(when commit-hash
(magit-show-commit commit-hash))))
(defun blamer-callback-open-remote (commit-info)
(interactive)
(let ((commit-hash (plist-get commit-info :commit-hash)))
(when commit-hash
(forge-browse-commit commit-hash))))
(setq blamer-bindings '(("<mouse-3>" . blamer-callback-open-remote)
("<mouse-1>" . blamer-callback-show-commit-diff)))
(global-blamer-mode 1))
(use-package git-timemachine
:defer t
:bind (:map evil-normal-state-map
("SPC g t" . git-timemachine)))
(global-set-key (kbd "C-c l") 'smerge-keep-lower)
(global-set-key (kbd "C-c u") 'smerge-keep-upper)
(global-set-key (kbd "C-c a") 'smerge-keep-all)
(global-set-key (kbd "C-c j") 'smerge-next)
(global-set-key (kbd "C-c k") 'smerge-prev)
(use-package browse-at-remote
:defer t
:general
(:states '(normal visual)
:keymaps 'override
"SPC o r" 'browse-at-remote))
(use-package forge
:after magit
:config
(setq auth-sources '("~/.authinfo")))
(use-package code-review
:defer t
:general
(:states '(normal insert) :keymaps 'magit-mode-map
"C-c C-r" 'code-review-forge-pr-at-point)
(:states '(normal insert) :keymaps 'code-review-mode-map
"r" 'code-review-transient-api)
:config
(setq code-review-fill-column 80)
(setq code-review-download-dir "/tmp/code-review/")
(setq code-review-new-buffer-window-strategy #'switch-to-buffer)
(setq code-review-auth-login-marker 'forge))
(use-package paren-face :defer t)
(use-package elisp-mode
:defer t
:ensure nil
:hook ((emacs-lisp-mode . paren-face-mode)
(emacs-lisp-mode . (lambda () (setq fill-column 80))))
:bind (("C-c o" . outline-cycle)
("C-c r" . outline-show-all)
("C-c m" . outline-hide-body)
("C-c ]" . outline-next-heading)
("C-c [" . outline-previous-heading)
("C-c c" . counsel-outline)
("C-c e" . outline-hide-entry)
("C-c t" . outline-toggle-children)
("C-c b" . outline-cycle-buffer)
;; TODO: eval buffer or region
("C-c C-c" . eval-buffer))
:config
(add-hook 'emacs-lisp-mode-hook (lambda () (setq rainbow-delimiters-mode -1))))
(use-package package-build
:defer t)
(use-package package-lint
:defer t)
(use-package clojure-mode
:hook ((clojure-mode . paren-face-mode))
:defer t)
(use-package cider
:defer t)
(setenv "TSSERVER_LOG_FILE" "/tmp/tsserver.log")
(use-package typescript-mode
:defer t
:hook (typescript-mode . (lambda () (setq-local fill-column 120)))
;; (typescript-ts-mode)))
:custom
(lsp-clients-typescript-server-args '("--stdio"))
:config
(setq typescript-indent-level 2)
;; (add-to-list 'auto-mode-alist '("\.ts\'" . typescript-mode))
(@setup-compilation-errors))
(use-package ng2-mode
:after typescript-mode
:hook
(ng2-html-mode . web-mode)
:config
(setq lsp-clients-angular-language-server-command
'("node"
"/opt/homebrew/lib/node_modules/@angular/language-server"
"--ngProbeLocations"
"/opt/homebrew/lib/node_modules"
"--tsProbeLocations"
"/opt/homebrew/lib/node_modules"
"--stdio")))
(use-package js2-mode
:defer t
:hook (js2-mode . js2-highlight-unused-variables-mode)
:config
(setq js-indent-level 2))
(use-package npm
:ensure (npm :repo "Artawower/npm.el" :host github)
:defer t)
(defun @open-nodejs-repl-here ()
"Open nodejs repl inside current buffer!"
(interactive)
(let ((nodejs-repl-buffer-name "*nodejs*"))
(if (get-buffer nodejs-repl-buffer-name)
(switch-to-buffer nodejs-repl-buffer-name)
(progn
(switch-to-buffer nodejs-repl-buffer-name)
(nodejs-repl)))))
(use-package nodejs-repl
:ensure t
:general
(:states '(normal visual)
:keymaps 'override
"SPC rn" 'nodejs-repl)
(:states '(insert)
:keymaps 'nodejs-repl-mode-map
"C-j" 'comint-next-input
"C-k" 'comint-previous-input)
:defer t
:config
<<nodejs-repl-buffer-func>>
(add-to-list 'display-buffer-alist '("^\\*nodejs\\*$" . (display-buffer-same-window))))
(use-package go-playground
:defer t)
(defun rk/rustic-mode-hook ()
(when buffer-file-name
(setq-local buffer-save-without-query t)))
(use-package rustic
:defer t
:bind (:map rustic-mode-map
("M-j" . lsp-ui-imenu)
("M-?" . lsp-find-references)
("C-c C-c l" . flycheck-list-errors)
("C-c C-c a" . lsp-execute-code-action)
("C-c C-c r" . lsp-rename)
("C-c C-c q" . lsp-workspace-restart)
("C-c C-c Q" . lsp-workspace-shutdown)
("C-c C-c s" . lsp-rust-analyzer-status))
:config
(setq rustic-format-on-save t
rustic-format-display-method 'ignore)
(add-hook 'rustic-mode-hook 'rk/rustic-mode-hook))
Function for open repl in the current buffer
(defun @open-ipython-repl-here ()
"Open python repl inside current buffer!"
(interactive)
(let ((python-repl-buffer-name "*Python*"))
(if (get-buffer python-repl-buffer-name)
(switch-to-buffer python-repl-buffer-name)
(progn
(switch-to-buffer python-repl-buffer-name)
(run-python)))))
(use-package python
:defer t
:ensure nil
:general
(:states '(normal visual)
:keymaps 'override
"SPC r p" '@open-ipython-repl-here)
:config
(setq python-shell-interpreter "ipython"
python-interpreter "python3"
python-shell-interpreter-args "--simple-prompt -i"))
(use-package python-mode
:defer t
:after treesit
:ensure nil
:config
(setq python-indent-level 4)
(add-hook 'python-mode-hook
(lambda ()
(require 'lsp-pyright)
;; (lsp-deferred)
(setq indent-tabs-mode nil)
(setq tab-width 4))))
(setq lsp-pyright-multi-root nil)
(use-package lsp-pyright
:hook (python-mode . (lambda ()
(require 'lsp-pyright)
(lsp-deferred)))
:config
(setq lsp-pyright-auto-import-completions t)
(setq lsp-pyright-auto-search-paths t)
(setq lsp-pyright-log-level "trace")
(setq lsp-pyright-multi-root nil)
(setq lsp-pyright-use-library-code-for-types t)
;; (setq lsp-pyright-venv-directory "/Users/darkawower/.local/share/virtualenvs/spice-farm-YhO8T07I")
(setq lsp-pyright-diagnostic-mode "workspace"))
(use-package pipenv
:defer t
:hook (python-mode . pipenv-mode)
:config
(setenv "WORKON_HOME" (concat (getenv "HOME") "/.virtualenvs"))
(add-hook 'pyvenv-post-activate-hooks #'lsp-restart-workspace)
;; This hook will copy venv from pyvenv to lsp pyright
(add-hook 'pyvenv-post-activate-hooks (lambda ()
(setq lsp-pyright-venv-directory pyvenv-virtual-env)
(lsp-restart-workspace)))
(setq pipenv-projectile-after-switch-function #'pipenv-projectile-after-switch-extended))
I don’t remember why I need this code. Currently commented.
(setq python-mode-map
(let ((map (make-sparse-keymap)))
;; Movement
(define-key map [remap backward-sentence] 'python-nav-backward-block)
(define-key map [remap forward-sentence] 'python-nav-forward-block)
(define-key map [remap backward-up-list] 'python-nav-backward-up-list)
(define-key map [remap mark-defun] 'python-mark-defun)
(define-key map "\C-c\C-j" 'imenu)
;; Indent specific
(define-key map "\177" 'python-indent-dedent-line-backspace)
(define-key map (kbd "<backtab>") 'python-indent-dedent-line)
(define-key map "\C-c<" 'python-indent-shift-left)
(define-key map "\C-c>" 'python-indent-shift-right)
;; Skeletons
(define-key map "\C-c\C-tc" 'python-skeleton-class)
(define-key map "\C-c\C-td" 'python-skeleton-def)
(define-key map "\C-c\C-tf" 'python-skeleton-for)
(define-key map "\C-c\C-ti" 'python-skeleton-if)
(define-key map "\C-c\C-tm" 'python-skeleton-import)
(define-key map "\C-c\C-tt" 'python-skeleton-try)
(define-key map "\C-c\C-tw" 'python-skeleton-while)
;; Shell interaction
(define-key map "\C-c\C-p" 'run-python)
(define-key map "\C-c\C-s" 'python-shell-send-string)
(define-key map "\C-c\C-e" 'python-shell-send-statement)
(define-key map "\C-c\C-r" 'python-shell-send-region)
(define-key map "\C-\M-x" 'python-shell-send-defun)
(define-key map "\C-c\C-c" 'python-shell-send-buffer)
(define-key map "\C-c\C-l" 'python-shell-send-file)
(define-key map "\C-c\C-z" 'python-shell-switch-to-shell)
;; Some util commands
(define-key map "\C-c\C-v" 'python-check)
(define-key map "\C-c\C-f" 'python-eldoc-at-point)
(define-key map "\C-c\C-d" 'python-describe-at-point)
;; Utilities
(substitute-key-definition 'complete-symbol 'completion-at-point
map global-map)
(easy-menu-define python-menu map "Python Mode menu"
'("Python"
:help "Python-specific Features"
["Shift region left" python-indent-shift-left :active mark-active
:help "Shift region left by a single indentation step"]
["Shift region right" python-indent-shift-right :active mark-active
:help "Shift region right by a single indentation step"]
"-"
["Start of def/class" beginning-of-defun
:help "Go to start of outermost definition around point"]
["End of def/class" end-of-defun
:help "Go to end of definition around point"]
["Mark def/class" mark-defun
:help "Mark outermost definition around point"]
["Jump to def/class" imenu
:help "Jump to a class or function definition"]
"--"
("Skeletons")
"---"
["Start interpreter" run-python
:help "Run inferior Python process in a separate buffer"]
["Switch to shell" python-shell-switch-to-shell
:help "Switch to running inferior Python process"]
["Eval string" python-shell-send-string
:help "Eval string in inferior Python session"]
["Eval buffer" python-shell-send-buffer
:help "Eval buffer in inferior Python session"]
["Eval statement" python-shell-send-statement
:help "Eval statement in inferior Python session"]
["Eval region" python-shell-send-region
:help "Eval region in inferior Python session"]
["Eval defun" python-shell-send-defun
:help "Eval defun in inferior Python session"]
["Eval file" python-shell-send-file
:help "Eval file in inferior Python session"]
["Debugger" pdb :help "Run pdb under GUD"]
"----"
["Check file" python-check
:help "Check file for errors"]
["Help on symbol" python-eldoc-at-point
:help "Get help on symbol at point"]
["Complete symbol" completion-at-point
:help "Complete symbol before point"]))
map))
(use-package web-mode
:defer t
:mode
("\\.vue\\'" . web-mode)
;; ("\\.tsx\\'" . typescript-tsx-mode)
("\\.tsx\\'" . web-mode)
("\\.jsx\\'" . web-mode)
("\\.astro\\'" . web-mode)
:config
(setq web-mode-enable-auto-quoting nil)
(setq web-mode-comment-formats
'(("java" . "/*")
("javascript" . "//")
("typescript" . "//")
("vue" . "//")
("php" . "/*")
("pug" . "//")
("css" . "/*")))
(setq web-mode-script-padding 0)
(setq web-mode-style-padding 0)
(setq web-mode-code-indent-offset 2)
(setq web-mode-css-indent-offset 2))
(use-package pug-mode
:defer t)
(use-package emmet-mode
:hook ((scss-mode . emmet-mode) (css-mode . emmet-mode) (ng2-html-mode . emmet-mode) (html-mode . emmet-mode))
:general
(:keymaps 'override
:states 'insert
"s-e" 'emmet-expand-line)
:defer t)
(use-package css-mode
:ensure nil
:defer 10
:config
(setq css-indent-offset 2)
(defun revert-buffer-no-confirm ()
"Revert buffer without confirmation."
(interactive)
(revert-buffer :ignore-auto :noconfirm)))
(use-package lsp-tailwindcss
:init
(setq lsp-tailwindcss-add-on-mode t)
:config
(add-hook 'before-save-hook 'lsp-tailwindcss-rustywind-before-save))
(use-package json-mode
:defer 5
:hook (json-mode . format-all-mode)
:config
(setq js-indent-level 2))
(use-package dart-mode
:defer t
;; Optional
:hook (dart-mode . flutter-test-mode))
(use-package flutter
:after dart-mode
:general
(:keymaps 'dart-mode-map
"C-c C-r" #'flutter-run-or-hot-reload)
(:states '(normal visual)
:keymaps '(dart-mode-map flutter-mode-map)
"SPC m f s" #'flutter-run
"SPC m f R" #'flutter-hot-restart
"SPC m f r" #'flutter-run-or-hot-reload)
:custom
(flutter-sdk-path "/Applications/flutter/"))
(use-package lua-mode
:defer t)
(use-package docker-compose-mode
:defer t)
(use-package dockerfile-mode
:defer t
:config
(add-hook 'compilation-filter-hook #'my-remove-cr -90))
(use-package docker
:defer t
:ensure t)
(use-package jenkinsfile-mode
:defer t
:config)
(use-package kubernetes
:defer 6
:commands (kubernetes-overview)
:bind (:map evil-normal-state-map
("SPC o K" . kubernetes-overview))
:config
(setq kubernetes-poll-frequency 3600
kubernetes-redraw-frequency 3600))
(use-package k8s-mode
:defer t)
(use-package kubernetes-evil
:after kubernetes)
(use-package nginx-mode
:defer t)
(use-package jinja2-mode
:defer t)
(defun @markdown-toc ()
"Extract level 2 and 3 headings from the current Markdown buffer.
The generated and indented TOC will be inserted at point."
(interactive)
(let (toc-list markdown-toc)
(save-excursion
(goto-char (point-min))
(while (re-search-forward "^\\(##+\\)\\s-+\\(.*\\)" nil t)
(let* ((level (length (match-string 1)))
(heading-text (match-string 2))
(heading-id (downcase (replace-regexp-in-string "[[:space:]]+" "-" heading-text))))
(push (cons level (cons heading-text heading-id)) toc-list))))
(setq toc-list (reverse toc-list))
(dolist (item toc-list)
(let* ((level (car item))
(heading-text (cadr item))
(heading-id (cddr item))
(indentation (make-string (* 2 (1- level)) ?\ ))
(line (format "- [%s](#%s)\n" heading-text heading-id)))
(setq markdown-toc (concat markdown-toc (concat indentation line)))))
(insert markdown-toc)))
(custom-set-faces
`(markdown-table-face ((t (:inherit default :foreground ,+m-color-secondary)))))
(use-package grip-mode
:defer t
:custom
(browse-url-browser-function 'browse-url-generic)
;; (grip-url-browser #'browse-url-firefox-program)
:config
(let ((credential (auth-source-user-and-password "api.github.com")))
(setq grip-github-user (car credential)
grip-github-password (cadr credential))))
(use-package markdown-xwidget
:after markdown-mode
:ensure (markdown-xwidget
:type git
:host github
:repo "cfclrk/markdown-xwidget"
:files (:defaults "resources"))
:bind (:map markdown-mode-command-map
("x" . markdown-xwidget-preview-mode))
:custom
(markdown-xwidget-command "pandoc")
(markdown-xwidget-github-theme "light")
(markdown-xwidget-mermaid-theme "default")
(markdown-xwidget-code-block-theme "default"))
(use-package org-crypt
:ensure nil
:config
(org-crypt-use-before-save-magic)
(setq org-tags-exclude-from-inheritance (quote ("crypt")))
;; GPG key to use for encryption
;; Either the Key ID or set to nil to use symmetric encryption.
(setq org-crypt-key nil))
(use-package ob-async
:defer t
:config
(setq ob-async-no-async-languages-alist '("ipython")))
Dependency
(use-package restclient
:after org)
(use-package ob-restclient
:after org)
(use-package ob-dart
:after org
:defer t
:config
(add-to-list 'org-babel-load-languages '(dart . t)))
(use-package ob-typescript
:after org)
(elpaca-wait)
(use-package ob-go :after org)
(org-babel-do-load-languages
'org-babel-load-languages
'((sql . t)))
(use-package ob-rust :after org)
(use-package org
:ensure nil
:defer t
:mode (("\\.org$" . org-mode))
:hook
(org-mode . org-indent-mode)
(org-mode . (lambda () (setq corfu-mode -1)))
:general
(:states '(normal visual)
:keymaps 'override
"SPC m t" 'org-todo
"SPC m n" 'org-store-link
"SPC m l l" 'org-insert-link
"SPC nl" 'org-store-link
"SPC dt" 'org-time-stamp-inactive
"SPC mlt" 'org-toggle-link-display)
(:states '(normal visual)
:keymaps 'org-mode-map
"SPC dt" 'org-time-stamp-inactive
"SPC st" 'org-set-tags-command
"SPC mx" 'org-toggle-checkbox
"<return>" '+org/dwim-at-point)
(:keymaps 'org-read-date-minibuffer-local-map
"C-s" 'org-goto-calendar)
(:keymaps 'calendar-mode-map
"<return>" 'org-calendar-select)
:bind (:map evil-normal-state-map
("SPC h ]" . org-next-visible-heading)
("SPC h [" . org-previous-visible-heading))
:config
(setq org-babel-python-command "python3")
(setq org-confirm-babel-evaluate nil)
(setq org-src-preserve-indentation t)
(setq org-latex-create-formula-image-program 'dvisvgm)
(setq org-format-latex-options (plist-put org-format-latex-options :scale 2.0))
;; https://www.reddit.com/r/orgmode/comments/jwf7ya/python_org_code_blocks_and_indentation/
(setq org-adapt-indentation nil)
(add-hook 'org-mode-hook
(lambda () (imenu-add-to-menubar "Imenu")))
(setq org-imenu-depth 8)
(@setup-org-mode-faces)
(setq org-src-window-setup 'current-window)
(setq org-todo-keywords
'((sequence
"TODO(t)" ; A task that needs doing & is ready to do
"PROJ(p)" ; A project, which usually contains other tasks
"IDEA(i)" ; Idea
"PROGRESS(s)" ; A task that is in progress
"WAIT(w)" ; Something external is holding up this task
"TEST(c)" ; In TEST statement
"BLOCK(b)" ; task blocked
"REJECTED(x)" ; somebody rejected idea :(
"FEEDBACK(f)" ; Feedback required
"REVIEW(r)" ; Somebody reviewed your feature
"HOLD(h)" ; This task is paused/on hold because of me
"|"
"DONE(d)" ; Task successfully completed
"KILL(k)") ; Task was cancelled, aborted or is no longer applicable
(sequence
"[ ](T)" ; A task that needs doing
"[-](S)" ; Task is in progress
"[?](W)" ; Task is being held up or paused
"|"
"[X](D)")) ; Task was completed
org-todo-keyword-faces
'(("[-]" . +org-todo-active)
("PROGRESS" . org-todo)
("DONE" . org-todo)
("IDEA" . org-todo)
("[?]" . +org-todo-onhold-face)
("WAIT" . +org-todo-onhold-face)
("TEST" . +org-todo-active-face)
("FEEDBACK" . +org-todo-onhold-face)
("REVIEW" . +org-todo-onhold-face)
("HOLD" . +org-todo-onhold-face)
("PROJ" . +org-todo-project)
("BLOCK" . +org-todo-cancel)
("REJECTED" . +org-todo-cancel)
("KILL" . +org-todo-cancel)))
(setq org-hide-emphasis-markers t)
(setq org-use-property-inheritance t)
(add-to-list 'org-tag-faces '("@.*" . (:foreground "red")))
;; Increase priorities count
(setq org-highest-priority ?A
org-default-priority ?C
org-lowest-priority ?E)
(defun publish-org-blog()
"Publish this note to du-blog!"
(interactive)
(require 'ox-gfm)
(setq org-export-with-sub-superscripts '{})
(defun org-gfm-format-toc (headline) "")
(org-gfm-export-to-markdown)
(let ((file-path (replace-regexp-in-string " " "\\\\\ " (buffer-file-name))))
(shell-command
(concat
"node /Users/darkawower/projects/pet/it-blog/emacs-blog/index.js "
file-path))))
(setenv "NODE_PATH"
(concat
(getenv "HOME") "/org-node/node_modules" ":"
(getenv "NODE_PATH")))
(org-babel-do-load-languages
'org-babel-load-languages
'(
;; (typescript . t)
(js . t)
(python . t)
(restclient . t)
(shell . t)))
(defun org-babel-execute:typescript (body params)
(let ((org-babel-js-cmd "npx ts-node < "))
(org-babel-execute:js body params)))
(defvar org-babel-js-function-wrapper
""
"Javascript code to print value of body.")
;; Applications for opening from org files
;; (if (assoc "\\.pdf\\'" org-file-apps)
;; (setcdr (assoc "\\.pdf\\'" org-file-apps) 'emacs)
;; (add-to-list 'org-file-apps '("\\.pdf\\'" . emacs) t))
;; (add-to-list 'org-file-apps
;; '("\\.pdf\\'" . (lambda (file link)
;; (org-pdfview-open link))))
(add-hook 'org-mode-hook
(lambda () (imenu-add-to-menubar "Imenu"))))
(add-hook 'org-mode-hook (lambda ()
"Beautify Org Checkbox Symbol"
(push '("[ ]" . "☐") prettify-symbols-alist)
(push '("[X]" . "☑" ) prettify-symbols-alist)
(push '("[-]" . "❍" ) prettify-symbols-alist)
(push '("#+BEGIN_SRC" . "↦" ) prettify-symbols-alist)
(push '("#+END_SRC" . "⇤" ) prettify-symbols-alist)
(push '("#+BEGIN_EXAMPLE" . "↦" ) prettify-symbols-alist)
(push '("#+END_EXAMPLE" . "⇤" ) prettify-symbols-alist)
(push '("#+BEGIN_QUOTE" . "↦" ) prettify-symbols-alist)
(push '("#+END_QUOTE" . "⇤" ) prettify-symbols-alist)
(push '("#+begin_quote" . "↦" ) prettify-symbols-alist)
(push '("#+end_quote" . "⇤" ) prettify-symbols-alist)
(push '("#+begin_example" . "↦" ) prettify-symbols-alist)
(push '("#+end_example" . "⇤" ) prettify-symbols-alist)
(push '("#+begin_src" . "↦" ) prettify-symbols-alist)
(push '("#+end_src" . "⇤" ) prettify-symbols-alist)
(push '("#+TITLE:" . "") prettify-symbols-alist)
(push '("#+DESCRIPTION:" . "") prettify-symbols-alist)
(push '("#+LANG:" . "") prettify-symbols-alist)
(push '("#+ID:" . "") prettify-symbols-alist)
(push '("#+FILETAGS:" . "") prettify-symbols-alist)
(push '("#+STARTUP:" . "") prettify-symbols-alist)
(push '("#+ACTIVE:" . "") prettify-symbols-alist)
(push '("#+START_SPOILER" . "") prettify-symbols-alist)
(push '("#+CLOSE_SPOILER" . "") prettify-symbols-alist)
(push '("#+BEGIN_HIDDEN" . "") prettify-symbols-alist)
(push '("#+END_HIDDEN" . "") prettify-symbols-alist)
;; (push '("#+TITLE:" . "") prettify-symbols-alist)
;; (push '("#+DESCRIPTION:" . "") prettify-symbols-alist)
;; (push '("#+ID:" . "") prettify-symbols-alist)
;; (push '("#+FILETAGS:" . "") prettify-symbols-alist)
;; (push '("#+STARTUP:" . "") prettify-symbols-alist)
;; (push '("#+ACTIVE:" . "") prettify-symbols-alist)
;; (push '("#+START_SPOILER" . "") prettify-symbols-alist)
;; (push '("#+CLOSE_SPOILER" . "") prettify-symbols-alist)
;; (push '("#+BEGIN_HIDDEN" . "") prettify-symbols-alist)
;; (push '("#+END_HIDDEN" . "") prettify-symbols-alist)
(prettify-symbols-mode)))
(use-package org-fancy-priorities
:after org
:ensure t
:hook (org-mode . org-fancy-priorities-mode)
:config
(setq org-fancy-priorities-list '((?A . "🔥")
(?B . "⬆")
(?C . "❗")
(?D . "⬇")
(?E . "❓")
(?1 . "🔥")
(?2 . "⚡")
(?3 . "⮮")
(?4 . "☕")
(?I . "Important"))))
(use-package org-superstar
:after org
:hook (org-mode . org-superstar-mode)
:config
(setq org-directory "~/Yandex.Disk.localized/Dropbox/org"))
One of the best Zettelkasten implementation
(use-package org-roam
;; :ensure (:package "org-roam" :protocol https :inherit t :depth 1 :fetcher github :repo "org-roam/org-roam")
:bind
(:map evil-normal-state-map
("SPC n r i" . org-roam-node-insert)
("SPC n r f" . org-roam-node-find))
(:map evil-visual-state-map
("SPC n r i" . org-roam-node-insert))
:init
(setq org-roam-v2-ack t)
:config
(org-roam-db-autosync-enable)
(cl-defmethod org-roam-node-mtitle ((node org-roam-node))
"Return customized title of roam node"
(let* ((tags (org-roam-node-tags node))
(title (org-roam-node-title node)))
(if (not tags)
title
(setq joined-text (string-join tags ", "))
(concat (propertize (format "(%s) " joined-text) 'face `(:foreground ,+m-color-main :weight bold :slant italic)) title))))
;; (setq org-roam-completion-system 'ivy)
(setq org-roam-completion-system 'vertico)
(setq org-roam-node-display-template "${mtitle:100}")
(setq org-roam-directory (file-truename "~/org-roam")))
(use-package websocket
:after org-roam)
(use-package org-yt
:after org
:ensure (:host github :repo "TobiasZawada/org-yt")
:config
(defun org-image-link (protocol link _description)
"Interpret LINK as base64-encoded image data."
(cl-assert (string-match "\\`img" protocol) nil
"Expected protocol type starting with img")
(let ((buf (url-retrieve-synchronously (concat (substring protocol 3) ":" link))))
(cl-assert buf nil
"Download of image \"%s\" failed." link)
(with-current-buffer buf
(goto-char (point-min))
(re-search-forward "\r?\n\r?\n")
(buffer-substring-no-properties (point) (point-max)))))
(org-link-set-parameters
"imghttp"
:image-data-fun #'org-image-link)
(org-link-set-parameters
"imghttps"
:image-data-fun #'org-image-link))
My own package for publish roam files
(use-package orgnote
:ensure (:host github :repo "Artawower/orgnote.el")
:general
(:states '(normal visual)
:keymaps 'org-mode-map
"SPC np" 'orgnote-publish-file)
(:states '(normal visual)
:keymaps 'override
"SPC nP" 'orgnote-publish-all
"SPC nL" 'orgnote-load
"SPC nF" 'orgnote-force-sync
"SPC nS" 'orgnote-sync)
:custom
(orgnote-debug-p t)
(orgnote-execution-script "node /Users/darkawower/projects/pet/orgnote/orgnote-cli/dist/index.js"))
(use-package org-insert
:after org
:bind (:map org-mode-map
("<C-return>" . +org/insert-item-below)
("<C-S-return>" . +org/insert-item-above))
:ensure (org-insert
:type git
:host github
:repo "hlissner/doom-emacs"
:files ("modules/lang/org/autoload/org.el")
:main "modules/lang/org/autoload/org.el"))
(use-package org-make-toc
:after org
:bind (:map org-mode-map
("C-c g" . org-make-toc)))
(use-package ox-gfm
:defer t
:ensure (ox-gfm :type git :host github :repo "larstvei/ox-gfm"))
Debug for my own project
(use-package org-latex-impatient
:defer t
:hook (org-mode . org-latex-impatient-mode)
:init
(setq org-latex-impatient-tex2svg-bin
;; location of tex2svg executable
"tex2svg"))
(use-package org-ai
:ensure nil
:load-path (lambda () "~/apps/pure-emacs/vendor/org-ai")
:commands (org-ai-mode)
:init
(add-hook 'org-mode-hook #'org-ai-mode)
:config
(setq org-ai-openai-api-token open-ai-key)
(advice-add 'keyboard-quit :before #'org-ai-keyboard-quit))
(use-package org-download
:defer 2
:hook (dired-mode-hook . org-download-enable)
:ensure (org-download :type git :host github :repo "abo-abo/org-download")
:config
(setq org-download-method 'directory)
(setq org-download-link-format "[[./%s]]\n")
(setq org-download-heading-lvl nil))
(defun my-set-spellfu-faces ()
"Set faces for correct spell-fu working"
(interactive)
(setq spell-fu-faces-include '(tree-sitter-hl-face:comment
tree-sitter-hl-face:doc
tree-sitter-hl-face:string
tree-sitter-hl-face:function
tree-sitter-hl-face:variable
tree-sitter-hl-face:type
tree-sitter-hl-face:method
tree-sitter-hl-face:function.method
tree-sitter-hl-face:function.special
tree-sitter-hl-face:attribute
font-lock-comment-face
font-lock-doc-face
font-lock-string-face
lsp-face-highlight-textual
default))
(if (boundp 'spell-fu-faces-exclude)
(setq spell-fu-faces-exclude (append spell-fu-faces-exclude
'(diredfl-file-name)))
(defvar spell-fu-faces-exclude
'(diredfl-file-name))))
(use-package spell-fu
:bind (:map evil-normal-state-map
("z g" . spell-fu-word-add))
:defer 5
:config
(setq ispell-program-name "aspell")
(setq spell-fu-directory "~/.doom.d/dictionary")
(setq ispell-program-name "aspell"
;; ;; Notice the lack of "--run-together"
ispell-extra-args '("--sug-mode=ultra" "--lang=en_US" "--run-together" "--run-together-limit=56"))
(setq spell-fu-ignore-modes '(dired-mode vterm-mode elfeed-search-mode))
(add-hook 'spell-fu-mode-hook
(lambda ()
(spell-fu-dictionary-add (spell-fu-get-ispell-dictionary "en"))
(spell-fu-dictionary-add (spell-fu-get-ispell-dictionary "ru"))
(spell-fu-dictionary-add
(spell-fu-get-personal-dictionary "en-personal" "/Users/darkawower/.doom.d/dictionary/.pws"))
(spell-fu-dictionary-add
(spell-fu-get-personal-dictionary "ru-personal" "/Users/darkawower/.doom.d/dictionary/ru.pws"))))
;; Camel case support
(setq-default spell-fu-word-regexp
(rx
(or
;; lowercase
(seq
(one-or-more lower)
(opt
(any "'’")
(one-or-more lower)
word-end))
;; capitalized
(seq
upper
(zero-or-more lower)
(opt
(any "'’")
(one-or-more lower)
word-end))
;; uppercase
(seq
(one-or-more upper)
(opt
(any "'’")
(one-or-more upper)
word-end)))))
(defun cs/spell-fu-check-range (pos-beg pos-end)
(let (case-fold-search)
(spell-fu-check-range-default pos-beg pos-end)))
(setq-default spell-fu-check-range #'cs/spell-fu-check-range)
(global-spell-fu-mode)
(my-set-spellfu-faces))
Didn’t mange to start work
(use-package lsp-grammarly
:hook
(text-mode . (lambda ()
(require 'lsp-grammarly)
(lsp-deferred))))
(use-package lsp-ltex
:ensure t)
;; :hook
;; (text-mode . (lambda ()
;; (require 'lsp-ltex)
;; (lsp-deferred))) ; or lsp-deferred
;; (org-mode . (lambda ()
;; (require 'lsp-ltex)
;; (lsp-deferred)))
;; :init
;; (setq lsp-ltex-version "15.2.0-mac-x64"))
(use-package google-translate
:defer 10
:bind (:map google-translate-minibuffer-keymap
("C-k" . google-translate-next-translation-direction)
("C-n" . google-translate-next-translation-direction)
:map evil-normal-state-map
("\\ t" . google-translate-smooth-translate))
:config
(require 'google-translate-smooth-ui)
(setq google-translate-backend-method 'curl)
(setq google-translate-pop-up-buffer-set-focus t)
(setq google-translate-translation-directions-alist
'(("en" . "ru") ("ru" . "en") ))
(defun google-translate--search-tkk () "Search TKK." (list 430675 2721866130)))
(use-package reverso
:general
(:states '(normal visual) :keymaps 'override
"SPC rr" 'reverso
"SPC rt" 'reverso-translate
"SPC rh" 'reverso-history)
:ensure (:host github :repo "SqrtMinusOne/reverso.el"))
(use-package wakatime-mode
:defer 2
:config
(global-wakatime-mode))
(use-package wakatime-ui
:after wakatime-mode
:ensure (wakatime-ui :host github :repo "Artawower/wakatime-ui.el")
:custom
(wakatim-ui-schedule-url "https://wakatime.com/share/@darkawower/af1bfb85-2c8b-44e4-9873-c4a91b512e8d.png")
:config
(wakatime-ui-mode))
(use-package recentf
:after consult
:ensure nil
:init
(recentf-mode 1)
:config
(setq recentf-max-menu-items 100))
(use-package projectile
:ensure nil
:general
(:states 'normal
"SPC pa" 'projectile-add-known-project
"SPC ki" '@kill-invisible-buffers)
:config
<<projectile-persp-hook>>
(projectile-mode +1))
(defun @set-perps-workspace-name-by-switched-project ()
"Set perps workspace name by switched project"
(interactive)
(when (and (bound-and-true-p persp-mode)
(bound-and-true-p projectile-mode))
(persp-rename (projectile-project-name))))
(add-hook 'projectile-after-switch-project-hook
#'@set-perps-workspace-name-by-switched-project)
(add-hook 'projectile-find-file-hook
#'@set-perps-workspace-name-by-switched-project)
(defun @kill-invisible-buffers ()
"Kill all buffers that are invisible in the current project."
(interactive)
(dolist (buf (project-buffers (project-current)))
;; when buffer name doesn't start with a *
(when (and (not (string-prefix-p "*" (buffer-name buf)))
;; and buffer is not visible
(not (get-buffer-window buf 'visible)))
;; kill buffer
(kill-buffer buf))))
(use-package helpful
:defer t
:bind (("C-h k" . helpful-key)
:map evil-normal-state-map
("SPC h v" . helpful-variable)
("SPC h f" . helpful-function)
("SPC h ." . helpful-at-point)))
(use-package vertico
:ensure (:host github :repo "minad/vertico" :files ("vertico.el" "extensions/*.el"))
:bind (:map evil-normal-state-map
("SPC ;" . vertico-repeat-last)
("SPC '" . vertico-repeat)
:map vertico-map
("C-j" . vertico-next)
("C-k" . vertico-previous)
("C-n" . vertico-next-group)
("C-p" . vertico-previous-group)
("C-l" . vertico-quick-jump)
("C-d" . vertico-scroll-up)
("C-u" . vertico-scroll-down)
("C-o" . embark-act)
("C-q" . vertico-exit-input)
("C-n" . vertico-next-group)
("C-p" . vertico-previous-group)
("<escape>" . abort-minibuffers)
("C-d" . (lambda ()
(interactive)
(kill-whole-line)
(insert "~/")))
("C-o" . (lambda ()
(interactive)
(embark-act)))
("C-r" . (lambda ()
(interactive)
(kill-whole-line)
(insert "/"))))
:init
(vertico-mode)
(setq vertico-cycle t)
:config
(setq read-file-name-completion-ignore-case t
read-buffer-completion-ignore-case t
completion-ignore-case t)
(require 'vertico-repeat)
(add-hook 'minibuffer-setup-hook 'vertico-repeat-save))
(elpaca-wait)
(use-package vertico-repeat
:ensure nil
:after vertico)
(use-package orderless
:init
(setq completion-styles '(orderless)
completion-category-defaults nil
completion-category-overrides '((file (styles partial-completion)))))
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
:ensure nil
:config
(savehist-mode))
;; A few more useful configurations...
(use-package emacs
:ensure nil
:init
;; Add prompt indicator to `completing-read-multiple'.
;; Alternatively try `consult-completing-read-multiple'.
(defun crm-indicator (args)
(cons (concat "[CRM] " (car args)) (cdr args)))
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)
;; Do not allow the cursor in the minibuffer prompt
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
;; Emacs 28: Hide commands in M-x which do not work in the current mode.
;; Vertico commands are hidden in normal buffers.
;; (setq read-extended-command-predicate
;; #'command-completion-default-include-p)
;; Enable recursive minibuffers
(setq enable-recursive-minibuffers t))
(setq completion-in-region-function
(lambda (&rest args)
(apply (if vertico-mode
#'consult-completion-in-region
#'completion--in-region)
args)))
(use-package marginalia
:after vertico
;; Either bind `marginalia-cycle` globally or only in the minibuffer
:bind (("M-A" . marginalia-cycle)
:map minibuffer-local-map
("M-A" . marginalia-cycle))
;; The :init configuration is always executed (Not lazy!)
:init
(marginalia-mode)
:config
(pushnew! marginalia-command-categories
'(+default/find-file-under-here . file)
'(flycheck-error-list-set-filter . builtin)
'(persp-switch-to-buffer . buffer)
'(projectile-find-file . project-file)
'(projectile-recentf . project-file)
'(projectile-switch-to-buffer . buffer)
'(projectile-switch-project . project-file)))
**
Function for search in buffer depends or visual or normal line
(defun @consult-line-or-region ()
"Search in buffer depends or visual or normal line"
(interactive)
(if (region-active-p)
(let ((substring (buffer-substring (region-beginning) (region-end))))
(deactivate-mark)
(consult-line substring))
(consult-line)))
(use-package consult
:defer t
:general (:states '(normal visual)
:keymaps 'override
"s-f" '@consult-line-or-region
"SPC bB" 'consult-buffer
"SPC fP" '@open-emacs-config
"SPC /" 'consult-ripgrep
"SPC *" (lambda () (interactive) (consult-ripgrep nil (thing-at-point 'symbol)))
"SPC si" 'consult-imenu
"SPC RET" 'consult-bookmark
"SPC cm" 'consult-mark
"SPC fR" 'consult-recent-file
"SPC fr" 'projectile-recentf
"SPC SPC" 'consult-projectile-find-file
"M-n" (lambda () (interactive) (search-forward (car consult--line-history)))
"M-p" (lambda () (interactive) (search-backward (car consult--line-history))))
;; Enable automatic preview at point in the *Completions* buffer. This is
;; relevant when you use the default completion UI. You may want to also
;; enable `consult-preview-at-point-mode` in Embark Collect buffers.
:hook (completion-list-mode . consult-preview-at-point-mode)
;; 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 recentf-max-saved-items 3000)
(setq register-preview-delay 0
register-preview-function #'consult-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)
;; Optionally replace `completing-read-multiple' with an enhanced version.
;; (advice-add #'completing-read-multiple :override #'consult-completing-read-multiple)
;; Use Consult to select xref locations with preview
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
;; Configure other variables and modes in the :config section,
;; after lazily loading the package.
:config
;; Optionally configure preview. The default value
;; is 'any, such that any key triggers the preview.
;; (setq consult-preview-key 'any)
;; (setq consult-preview-key (kbd "M-."))
;; (setq consult-preview-key (list (kbd "<S-down>") (kbd "<S-up>")))
;; For some commands and buffer sources it is useful to configure the
;; :preview-key on a per-command basis using the `consult-customize' macro.
(consult-customize
consult-projectile-find-file consult-git-grep consult-grep consult-projectile-recentf consult-ripgrep
consult-bookmark consult-recent-file consult-xref consult--source-bookmark consult--source-file-register
consult--source-recent-file consult--source-project-recent-file
;; my/command-wrapping-consult ;; disable auto previews inside my command
:preview-key (list :debounce 0.2 "C-SPC"))
;; Optionally configure the narrowing key.
;; Both < and C-+ work reasonably well.
(setq consult-narrow-key "<") ;; (kbd "C-SPC")
;; Optionally make narrowing help available in the minibuffer.
;; You may want to use `embark-prefix-help-command' or which-key instead.
;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)
;; Optionally configure a function which returns the project root directory.
;; There are multiple reasonable alternatives to chose from.
;;;; 1. project.el (project-roots)
(setq consult-project-root-function
(lambda ()
(when-let (project (project-current))
(car (project-roots project)))))
;;;; 2. projectile.el (projectile-project-root)
;; (autoload 'projectile-project-root "projectile")
;; (setq consult-project-root-function #'projectile-project-root)
;;;; 3. vc.el (vc-root-dir)
;; (setq consult-project-root-function #'vc-root-dir)
;;;; 4. locate-dominating-file
;; (setq consult-project-root-function (lambda () (locate-dominating-file "." ".git")))
)
(use-package consult-flycheck
:after consult)
(use-package consult-lsp
:defer t
:general (:states 'normal
"SPC ss" 'consult-lsp-symbols
"SPC sl" 'consult-lsp-diagnostics))
(use-package consult-projectile
:general (:states 'normal
"SPC pp" 'consult-projectile-switch-project
"SPC pi" 'projectile-invalidate-cache
"SPC pa" 'projectile-add-known-project)
:config
(setq consult-projectile-use-projectile-switch-project t)
(add-to-list 'projectile-globally-ignored-directories "node_modules")
:defer t)
Copy only content (not category) For more details check https://www.reddit.com/r/emacs/comments/zou9x0/comment/j1afu1c/?utm_source=share&utm_medium=web2x&context=3
(defun copy-grep-results-as-kill (strings)
(embark-copy-as-kill
(mapcar (lambda (string)
(substring string
(1+ (next-single-property-change
(1+ (next-single-property-change 0 'face string))
'face string))))
strings)))
(add-to-list 'embark-multitarget-actions 'copy-grep-results-as-kill)
(defvar-keymap embark-consult-grep-map
:doc "Keymap for actions for consult-grep results."
:parent embark-general-map
"w" #'copy-grep-results-as-kill)
(setf (alist-get 'consult-grep embark-keymap-alist) 'embark-consult-grep-map)
Delete project
(defvar-keymap embark-projectile-map
:doc "Example keymap with a few file actions"
:parent embark-general-map
"d" #'projectile-remove-known-project)
(add-to-list 'embark-keymap-alist '(consult-projectile-project . embark-projectile-map))
(defun +vertico/embark-preview ()
"Previews candidate in vertico buffer, unless it's a consult command"
(interactive)
(unless (bound-and-true-p consult--preview-function)
(save-selected-window
(let ((embark-quit-after-action nil))
(embark-dwim)))))
(use-package embark
:custom
(embark-indicators '(embark-minimal-indicator embark-highlight-indicator embark-isearch-highlight-indicator))
:general
("C-." 'embark-act ;; pick some comfortable binding
"C-;" 'embark-dwim ;; good alternative: M-.
"C-h B" 'embark-bindings)
(:keymaps '(minibuffer-local-mode-map read--expression-map vertico-map)
"C-SPC" '+vertico/embark-preview
;; "C-SPC" 'consult-preview-at-point
;; "C-SPC" 'consult--buffer-preview
"C-u" 'evil-delete-back-to-indentation
"C-<return>" '+vertico/embark-preview)
:init
;; Optionally replace the key help with a completing-read interface
(setq prefix-help-command #'embark-prefix-help-command)
:config
(add-to-list 'display-buffer-alist '("^\\*Embark Export\\*$" (display-buffer-in-side-window) (window-height . 0.4)))
<<embark-delete-project>>
<<embark-content-copy-function>>)
;; Consult users will also want the embark-consult package.
(use-package embark-consult
:after (embark consult)
:demand t ; only necessary if you have the hook below
;; if you want to have consult previews as you move around an
;; auto-updating embark collect buffer
:hook
(embark-collect-mode . consult-preview-at-point-mode))
(use-package wgrep
:general
(:keymaps 'override
"C-c C-w" 'wgrep-change-to-wgrep-mode)
:after vertico)
(use-package tramp
:ensure nil
:config
(setenv "SHELL" "/bin/bash")
(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)
(add-to-list 'tramp-connection-properties
(list (regexp-quote "/sshx:user@host:")
"remote-shell" "/usr/bin/bash"))
(add-to-list 'tramp-connection-properties
(list ".*" "locale" "LC_ALL=C")))
(use-package pdf-tools
:ensure t
:defer t
:config
(pdf-tools-install))
;; (use-package org-pdftools)
;; :hook (org-mode . org-pdftools-setup-link))
(use-package pocket-reader
:general
(:keymaps 'override
:states '(normal visual)
"SPC ep" 'pocket-reader)
(:keymaps 'pocket-reader-mode-map
:states '(normal visual)
"<return>" 'pocket-reader-open-in-external-browser
"s" 'pocket-reader-search
"d" 'pocket-reader-delete
"r" 'pocket-reader-refresh
"a" 'pocket-reader-add-link
"ta" 'pocket-reader-add-tags
"m" 'pocket-reader-more
"w" 'pocket-reader-copy-url
"tf" 'pocket-reader-tag-search)
:defer t)
(use-package gptel
:config
;; (setq gptel-api-key gpt-key)
;; Make gpt4all the default
;; (setq-default
;; gptel-backend
;; (gptel-make-openai ;Not a typo, same API as OpenAI
;; "llama-cpp" ;Any name
;; :stream t ;Stream responses
;; :protocol "http"
;; :host "localhost:8080" ;Llama.cpp server location, typically localhost:8080 for Llamafile
;; :key nil ;No key needed
;; :models '("test")))
;; (setq-default gptel-model "test")
(setq-default gptel-backend
(gptel-make-ollama
"Ollama"
:host "localhost:11434"
:models '("codellama:latest")
:stream t))
(setq-default gptel-model "codellama")
;; (setq-default
;; gptel-backend
;; (gptel-make-gpt4all
;; "GPT4All" ;Any name of your choosing
;; :protocol "http"
;; :host "localhost:4891" ;Where it's running
;; :models '("mistral-7b-openorca.Q4_0.gguf"))) ;Available models
;; Don't limit token count:
(setq-default gptel-max-tokens 800)
)
(use-package plantuml-mode
:defer t
:init
(add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode))
(add-to-list 'auto-mode-alist '("\\.pu\\'" . plantuml-mode))
(add-to-list 'auto-mode-alist '("\\.puml\\'" . plantuml-mode))
:config
(setq plantuml-indent-level 2)
(setq plantuml-output-type "png")
(setq plantuml-exec-mode 'executable)
(setq plantuml-jar-path "/usr/share/plantuml/plantuml.jar"))
(use-package telega
:commands (telega)
:custom
(telega-use-docker nil)
:defer t)