specialize a few things depending on which system
(defconst ava/host
(pcase (system-name)
("avat14" 't14)
("avalenovo" 'x220)
("avelazqu01" 'desktop)
(_ 'unknown)))(use-package modus-themes
:ensure t
:config
(load-theme 'modus-vivendi-tinted t)
(defun ava/toggle-theme ()
(interactive)
(let ((light-theme 'modus-operandi-tinted)
(dark-theme 'modus-vivendi-tinted)
(current-theme (car custom-enabled-themes)))
(mapc #'disable-theme custom-enabled-themes)
(if (eq current-theme dark-theme)
(load-theme light-theme t)
(load-theme dark-theme t)))))
(global-font-lock-mode t)
(setq font-lock-maximum-decoration t)
(set-frame-font
(pcase ava/host
('t14 "Monospace-18")
(_ "Monospace-13")))(setq display-time-format "%H:%M - %a %b %d"
display-time-24hr-format t
display-time-default-load-average nil)
(column-number-mode t)
(display-battery-mode t)
(display-time-mode 1)
(size-indication-mode t)
(use-package doom-modeline
:ensure t
:custom
(doom-modeline-env-version nil)
(doom-modeline-icon nil)
(doom-modeline-minor-modes nil)
(doom-modeline-buffer-encoding nil)
(doom-modeline-modal-icon nil) ; evil specific
:init (doom-modeline-mode 1))Disable more visuals
(blink-cursor-mode -1)
(transient-mark-mode 1)Disable audible bell
(setq ring-bell-function 'ignore)Disable startup messages and text in scratch
(setq initial-major-mode 'fundamental-mode
inhibit-startup-message t
inhibit-startup-echo-area-message t
initial-scratch-message nil)Disable suspend
(use-package frame :bind ("C-z" . nil))Mute some warnings out of our control
(setq ad-redefinition-action 'accept)reduce rendering/line scan work for emacs by not rendering cursors or regions in non-focused windows and left to right rendering only
(setq-default cursor-in-non-selected-windows nil
bidi-display-reordering 'left-to-right
bidi-paragraph-direction 'left-to-right)
(setq bidi-inhibit-bpa t)Disable common warnings
(put 'set-goal-column 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'erase-buffer 'disabled nil)
(put 'downcase-region 'disabled nil)
(setq large-file-warning-threshold (* 120 1024 1024))(setq scroll-step 1
scroll-margin 3
scroll-conservatively most-positive-fixnum
scroll-preserve-screen-position t
use-short-answers t
grep-highlight-matches t
shell-file-name "bash"
x-alt-keysym 'meta
kill-ring-max 100
save-interprogram-paste-before-kill t
kill-do-not-save-duplicates t
undo-outer-limit 50000000
make-backup-files nil
calendar-mode-line-format nil
set-mark-command-repeat-pop t
load-prefer-newer t
view-read-only t
display-raw-bytes-as-hex t
window-combination-resize t
redisplay-skip-fontification-on-input t
read-process-output-max (* 4 1024 1024)
use-dialog-box nil)
(when (version<= "29.1" emacs-version)
(pixel-scroll-precision-mode 1))
(use-package paren
:custom
(show-paren-delay 0)
(show-paren-when-point-inside-paren t)
(show-paren-context-when-offscreen 'overlay)
:config
(show-paren-mode 1))
(setq enable-recursive-minibuffers t)
(minibuffer-depth-indicate-mode)
;too slow otherwise
(unless (eq ava/host 'x220)
(setq completion-styles '(flex)))
(use-package apropos
:custom
(apropos-do-all t))
(use-package delsel
:config (delete-selection-mode t))
(use-package info
:defer t
:config
(let ((texinfo-path "~/.texinfo"))
(when (file-directory-p texinfo-path)
(f-entries texinfo-path
(lambda (path) (add-to-list 'Info-additional-directory-list path)))))
(add-hook 'Info-mode-hook 'variable-pitch-mode))
(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)(use-package saveplace
:preface
(defun ava/save-place-recenter (&rest _)
"Recenter after `save-place' restores point."
(when buffer-file-name
(ignore-errors (recenter))))
:config
(advice-remove 'save-place-find-file-hook #'ava/save-place-recenter)
(advice-add 'save-place-find-file-hook :after #'ava/save-place-recenter)
(save-place-mode))(global-hi-lock-mode 1)
(setq hi-lock-auto-select-face t)(require 'server)
(unless (server-running-p)
(server-start))kill current buffer no prompt
(defun kill-current-buffer ()
"Kill the current buffer, without confirmation."
(interactive)
(kill-buffer (current-buffer)))
(global-set-key "\C-xk" 'kill-current-buffer)(setq display-buffer-base-action
'(display-buffer-reuse-mode-window
display-buffer-reuse-window
display-buffer-same-window))
(setq even-window-sizes nil)
(add-to-list 'same-window-buffer-names "*grep*")
(add-to-list 'same-window-buffer-names "*Buffer List*")(use-package autorevert
:ensure nil
:custom
(auto-revert-verbose nil)
(global-auto-revert-non-file-buffers t)
:config
(global-auto-revert-mode 1))(setq world-clock-time-format "%a, %d %b %I:%M %p %Z"
world-clock-list '(("Europe/Berlin" "Berlin")
("America/Chicago" "Chicago")
("Asia/Hong_Kong" "Hong Kong")
("Europe/London" "London")
("America/Mexico_City" "Mexico City")
("Asia/Shanghai" "Shanghai")
("Asia/Singapore" "Singapore")
("Asia/Tokyo" "Tokyo")
("Etc/UTC" "UTC")
("Europe/Zurich" "Zurich")))(use-package winner
:preface
(defun ava/toggle-delete-other-windows ()
"Delete other windows or restore the previous layout."
(interactive)
(if (and (bound-and-true-p winner-mode)
(one-window-p))
(condition-case nil
(winner-undo)
(error (delete-other-windows)))
(delete-other-windows)))
:bind (("M-N" . winner-redo)
("M-P" . winner-undo)
("C-x 1" . ava/toggle-delete-other-windows))
:config
(when (boundp 'winner-boring-buffers-regexp)
(setq winner-boring-buffers-regexp "\\*[hH]elm.*"))
(winner-mode 1))(global-set-key (kbd "C-x l") 'align-regexp)
(global-set-key [remap eval-last-sexp] 'pp-eval-last-sexp)(global-set-key "\M-z" 'zap-up-to-char)
(global-set-key "\M-Z" (lambda (char)
(interactive "cZap back to char: ")
(zap-up-to-char -1 char)))(global-unset-key (kbd "C-x o"))(use-package isearch
:no-require t
:defer t
:config
(when (version<= "27" emacs-version)
(setq isearch-lazy-count t
isearch-allow-scroll 'unlimited))
(define-key isearch-mode-map [remap isearch-delete-char] #'isearch-del-char))(use-package proced
:defer t
:custom
(proced-sort 'pmem)
(proced-goal-attribute nil)
(proced-auto-update-flag t)
(proced-auto-update-interval 1)
(proced-enable-color-flag t)
:config
(add-to-list
'proced-format-alist
'(custom user pid pcpu pmem rss thcount start etime time state (args comm)))
(setq-default proced-format 'custom))(use-package hippie-exp
:custom
(hippie-expand-try-functions-list
'(try-expand-dabbrev
try-expand-dabbrev-all-buffers
try-expand-dabbrev-from-kill
try-complete-file-name-partially
try-complete-file-name
try-expand-all-abbrevs
try-expand-list
try-expand-line
try-complete-lisp-symbol-partially
try-complete-lisp-symbol))
:bind
([remap dabbrev-expand] . hippie-expand))(use-package eldoc
:diminish
:custom
(eldoc-documentation-strategy 'eldoc-documentation-compose-eagerly)
:hook ((emacs-lisp-mode) . eldoc-mode))(use-package tramp
:defer t
:custom
(remote-file-name-inhibit-cache nil)
:config
(put 'temporary-file-directory 'standard-value `(,temporary-file-directory))
;; https://www.gnu.org/software/emacs/manual/html_node/tramp/Frequently-Asked-Questions.html
(setq vc-ignore-dir-regexp
(format "\\(%s\\)\\|\\(%s\\)"
vc-ignore-dir-regexp
tramp-file-name-regexp)))(use-package eww
:custom
(eww-auto-rename-buffer 'title)
(browse-url-browser-function 'browse-url-firefox))(use-package midnight
:custom
(midnight-delay 25200) ;7am
(clean-buffer-list-delay-general 3)
(clean-buffer-list-kill-never-buffer-names '("*ChatGPT*" "*scratch*" "*Messages*"))
:config
(midnight-mode t))(use-package repeat
:ensure nil
:custom
(repeat-exit-timeout 10)
:config
(repeat-mode 1))if need to work in a windows environment talk to it via named pipe
;; (defun ava/on-windows (cmd &rest args)
;; (apply 'start-process "ON-WINDOWS" nil "~/scripts/linux_to_windows.sh"))
;;
;; (defun ava/on-windows-open-url (url &rest args)
;; (interactive "P")
;; (ava/on-windows "start" (or url (url-get-url-at-point))))
;; (setq browse-url-browser-function 'ava/on-windows-open-url)
;;
;; (defun ava/on-windows-serve-dir ()
;; (interactive)
;; (let ((dir-to-serve nil))
;; (if (equal major-mode 'dired-mode)
;; (progn
;; (setq dir-to-serve (dired-get-filename))
;; (when (not (file-directory-p dir-to-serve))
;; (setq dir-to-serve (file-name-directory dir-to-serve))))
;; (setq dir-to-serve (buffer-file-name))
;; (when dir-to-serve
;; (setq dir-to-serve (file-name-directory dir-to-serve))))
;; (cl-assert dir-to-serve t "could not determine directory to serve")
;; (save-excursion
;; (set-buffer (generate-new-buffer (format "httpserve %s" dir-to-serve)))
;; (async-shell-command (format "~/scripts/serve_dir_open_on_windows.sh %s" dir-to-serve) (current-buffer)))))(setq text-scale-mode-step 1.1
help-enable-symbol-autoload t)
(setq-default tab-width 4
fill-column 80
indent-tabs-mode nil)
(use-package simple
:preface
;; (defun ava/use-interactive-shell-command-switch (orig-fun &rest args)
;; "i flag makes interactive (but not login) so you can see any aliases in bashrc"
;; (let ((shell-command-switch "-ic"))
;; (apply orig-fun args)))
(defun ava/path-slug (dir)
"Returns the initials of `dir`s path, with the last part appended fully
Example: (path-slug \"/foo/bar/hello\") => \"f/b/hello\""
(let* ((path (replace-regexp-in-string "\\." "" dir))
(path (split-string path "/" t))
(path-s (mapconcat (lambda (it) (cl-subseq it 0 1)) (nbutlast (copy-sequence path) 1) "/"))
(path-s (concat path-s "/" (car (last path)))))
path-s))
(defun ava/put-command-in-async-buff-name (orig-fun &rest args)
(let* ((path-s (if default-directory (ava/path-slug default-directory) ""))
(command (car args))
(long-buffname (concat path-s " " command))
(buffname (format "*async-shell %s*" (string-trim (substring long-buffname 0 (min (length long-buffname) 150)))))
(shell-command-buffer-name-async buffname))
(apply orig-fun args)
(let ((buffer (get-buffer buffname)))
(when buffer
(with-current-buffer buffer
(setq-local ava/shell-command command))))))
:custom (async-shell-command-buffer 'new-buffer)
:config
;; (advice-add 'async-shell-command :around #'ava/use-interactive-shell-command-switch)
(advice-add 'shell-command :around #'ava/put-command-in-async-buff-name))based on https://emacs.stackexchange.com/questions/41256/using-advice-to-run-function-before-tag-symbol-lookup/41277 check if projectile root has a TAGS file and if not generate something
(defun ava/generate-tags ()
"Generate project TAGS"
(interactive)
(cl-assert (projectile-project-root) nil "not in a project")
(let* ((prjd (projectile-project-root))
(tagd (concat prjd ".tagsAndLocate"))
(tagf (concat tagd "/TAGS")))
(make-directory tagd t)
(shell-command
(format "ctags -f %s -e --verbose --totals=yes --links=no \
--kinds-c++=+p --languages=c,c++,lisp --langmap=c++:+.I \
-R %s &> %s/ctags.out" tagf prjd tagd))
(message "generated %s (%s)" tagf
(shell-command-to-string (format "du -sh %s | cut -f1 | tr -d '\n'" tagf)))))
;; TODO only needed if have to locate outside project and no lsp use
(defun ava/generate-locates ()
"Generate project locate.db for helm"
(interactive)
(cl-assert (projectile-project-root) nil "not in a project"))
(defun ava/generate-tags-and-locates ()
"Called interactivel to generate both locate.db and tags for project"
(interactive)
(ava/generate-tags)
(ava/generate-locates))
(defun ava/before-xref-find-defs (&rest _)
(when (projectile-project-root)
(let ((project-tags-file (concat (projectile-project-root) ".tagsAndLocate/TAGS")))
(if (file-exists-p project-tags-file)
(visit-tags-table project-tags-file t)
(ava/generate-tags)))))
(advice-add 'xref-find-definitions :before #'ava/before-xref-find-defs)indentation related
;;; source: https://www.reddit.com/r/emacs/comments/1bgdw0y/custom_namespace_indentation_in_ctsmode/
(use-package c-ts-mode
:preface
(defun ava/c-ts-indent-style()
"Override the built-in BSD indentation style with some additional rules.
Docs: https://www.gnu.org/software/emacs/manual/html_node/elisp/Parser_002dbased-Indentation.html
Notes: `treesit-explore-mode' can be very useful to see where you're at in the tree-sitter tree,
especially paired with `(setq treesit--indent-verbose t)' to debug what rules is being
applied at a given point."
`(;; do not indent namespace children
((n-p-gp nil nil "namespace_definition") grand-parent 0)
;; append to bsd style
,@(alist-get 'bsd (c-ts-mode--indent-styles 'cpp))))
:config
(setq c-ts-mode-indent-offset 4)
(setq c-ts-mode-indent-style #'ava/c-ts-indent-style))toggle between implementation and header
(setq cc-search-directories '("."))
(setq cc-other-file-alist
'(("\\.cpp$" (".h" ".hpp"))
("\\.h$" (".cpp" ".c"))
("\\.hpp$" (".cpp" ".c"))
("\\.C$" (".H"))
("\\.H$" (".C"))))
(add-hook 'c-mode-common-hook (lambda() (global-set-key (kbd "C-c o") 'ff-find-other-file)))(use-package compile
:preface
(defun ava/compilation-buffer-name (mode-name)
"Name compilation buffers as *<mode> <project> - <tool action>*."
(require 'subr-x)
(let* (( proj (and (fboundp 'projectile-project-name)
(ignore-errors (projectile-project-name))))
(dir (file-name-nondirectory (directory-file-name default-directory)))
(ctx (or proj dir ""))
(cmd (string-trim (or compile-command "")))
;; grab first two tokens: e.g. "bazel build", "bazel test", "ninja -C"
(kind (if (string-match "\\`\\([^ ]+\\(?: [^ ]+\\)?\\)" cmd)
(match-string 1 cmd)
""))
(suffix (if (> (length kind) 0) (concat " - " kind) "")))
(format "*%s %s%s*" mode-name ctx suffix)))
:custom
(compilation-buffer-name-function #'ava/compilation-buffer-name)
(compilation-read-command t)
(compilation-always-kill t)
(compilation-scroll-output 'first-error)
(compilation-ask-about-save nil)
(compilation-skip-threshold 2)
(next-error-message-highlight t)
:hook (compilation-filter . ansi-color-compilation-filter))(use-package diff-mode
:defer t
:bind (:map diff-mode-map ("M-o" . nil)))
(use-package ediff
:custom
(ediff-show-clashes-only t)
(ediff-highlight-all-diffs nil)
(ediff-window-setup-function #'ediff-setup-windows-plain)
(ediff-split-window-function #'split-window-horizontally)
(ediff-grab-mouse nil)
(ediff-keep-variants nil)
(ediff-diff-options "-w")
:bind (("C-c = b" . ediff-buffers)
("C-c = B" . ediff-buffers3)
("C-c = c" . compare-windows)
("C-c = f" . ediff-files)
("C-c = F" . ediff-files3)
("C-c = m" . count-matches)
("C-c = r" . ediff-revision)
("C-c = p" . ediff-patch-file)
("C-c = P" . ediff-patch-buffer)
("C-c = l" . ediff-regions-linewise)
("C-c = w" . ediff-regions-wordwise))
:config
(add-hook 'ediff-prepare-buffer-hook #'outline-show-all))bridge re-builder with query regexp replace (from https://karthinks.com/software/bridging-islands-in-emacs-1/)
(use-package re-builder
:config
(setq reb-re-syntax 'string)
(defvar ava/re-builder-positions nil
"Store point and region bounds before calling re-builder")
(advice-add 're-builder
:before
(defun ava/re-builder-save-state (&rest _)
"Save into `ava/re-builder-positions' the point and region
positions before calling `re-builder'."
(setq ava/re-builder-positions
(cons (point)
(when (region-active-p)
(list (region-beginning)
(region-end)))))))
(defun ava/reb-replace-regexp (&optional delimited)
"Run `query-replace-regexp' with the contents of re-builder. With
non-nil optional argument DELIMITED, only replace matches
surrounded by word boundaries."
(interactive "P")
(reb-update-regexp)
(let* ((re (reb-target-binding reb-regexp))
(replacement (query-replace-read-to
re
(concat "Query replace"
(if current-prefix-arg
(if (eq current-prefix-arg '-) " backward" " word")
"")
" regexp"
(if (with-selected-window reb-target-window
(region-active-p)) " in region" ""))
t))
(pnt (car ava/re-builder-positions))
(beg (cadr ava/re-builder-positions))
(end (caddr ava/re-builder-positions)))
(with-selected-window reb-target-window
(goto-char pnt) ; replace with (goto-char (match-beginning 0)) if you want
; to control where in the buffer the replacement starts
; with re-builder
(setq ava/re-builder-positions nil)
(reb-quit)
(query-replace-regexp re replacement delimited beg end))))
(define-key reb-mode-map (kbd "RET") #'ava/reb-replace-regexp)
(define-key reb-lisp-mode-map (kbd "RET") #'ava/reb-replace-regexp)
(global-set-key (kbd "C-M-%") #'re-builder))(use-package ace-window
:ensure t
:bind (("M-o" . ace-window))
:custom
(aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
(aw-background nil))(use-package ace-link
:ensure t
:config (ace-link-setup-default)
(add-hook 'ess-r-help-mode-hook #'(lambda () (bind-key "o" #'ace-link-help ess-r-help-mode-map))))(use-package tex
:ensure auctex
:defer t
:custom
(TeX-after-compilation-finished-functions #'TeX-revert-document-buffer)
:hook
(LaTeX-mode . (lambda ()
(turn-on-reftex)
(setq reftex-plug-into-AUCTeX t)
(reftex-isearch-minor-mode)
(setq TeX-source-correlate-start-server t))))
(use-package company-auctex
:after tex
:ensure t
:commands (company-auctex
company-auctext-labels
company-auctest-bibs
company-auctex-macros
company-auctext-symbols
company-auctext-environments)
:hook
(tex-mode . (lambda ()
(setq-local company-backends '((company-auctex-labels
company-auctex-bibs
company-auctex-macros
company-auctex-environments
company-auctex-symbols
company-capf))))))from karthink
(use-package avy
:ensure t
:bind (("M-j" . avy-goto-char-timer)
("M-g M-g" . avy-goto-line)
)
:custom
(avy-timeout-seconds 0.3)
(avy-keys '(?q ?e ?r ?u ?o ?p ?a ?s ?d ?f ?g ?h ?j ?k ?l ?x ?c ?v ?b ?n ?,))
:init
(bind-key "M-j" 'avy-isearch isearch-mode-map)
:config
(when (display-graphic-p)
(setq avy-background t))
(progn ;kill text
(defun avy-action-kill-whole-line (pt)
(save-excursion
(goto-char pt)
(kill-whole-line))
(select-window (cdr (ring-ref avy-ring 0))) t)
(setf (alist-get ?k avy-dispatch-alist) 'avy-action-kill-stay
(alist-get ?K avy-dispatch-alist) 'avy-action-kill-whole-line))
(progn ;copy text
(defun avy-action-copy-whole-line (pt)
(save-excursion
(goto-char pt)
(cl-destructuring-bind (start . end)
(bounds-of-thing-at-point 'line)
(copy-region-as-kill start end)))
(select-window (cdr (ring-ref avy-ring 0))) t)
(setf (alist-get ?w avy-dispatch-alist) 'avy-action-copy
(alist-get ?W avy-dispatch-alist) 'avy-action-copy-whole-line))
(progn ;yank text
(defun avy-action-yank-whole-line (pt)
(avy-action-copy-whole-line pt)
(save-excursion (yank)) t)
(setf (alist-get ?y avy-dispatch-alist) 'avy-action-yank
(alist-get ?Y avy-dispatch-alist) 'avy-action-yank-whole-line))
(progn ;transpose text
(defun avy-action-teleport-whole-line (pt)
(avy-action-kill-whole-line pt)
(save-excursion (yank)) t)
(setf (alist-get ?t avy-dispatch-alist) 'avy-action-teleport
(alist-get ?T avy-dispatch-alist) 'avy-action-teleport-whole-line))
(progn ;helpful
(defun avy-action-helpful (pt)
(save-excursion
(goto-char pt)
(helpful-at-point))
(select-window (cdr (ring-ref avy-ring 0))) t)
(setf (alist-get ?H avy-dispatch-alist) 'avy-action-helpful))
(progn ;dash
(defun avy-action-dash (pt)
(save-excursion
(goto-char pt)
(helm-dash-at-point))
(select-window (cdr (ring-ref avy-ring 0))) t)
(setf (alist-get ?D avy-dispatch-alist) 'avy-action-dash))
(progn ;man
(defun avy-action-man (pt)
(save-excursion
(goto-char pt)
(helm-man-woman nil))
(select-window (cdr (ring-ref avy-ring 0))) t)
(setf (alist-get ?M avy-dispatch-alist) 'avy-action-man)))(use-package bookmark
:custom
(bookmark-save-flag 1))(use-package company
:ensure t
:custom
(company-dabbrev-downcase nil)
(company-dabbrev-other-buffers t)
(company-idle-delay 0.2)
(company-minimum-prefix-length 3)
(company-require-match nil)
(company-show-numbers t)
(company-tooltip-limit 10)
(company-tooltip-align-annotations t)
(company-selection-wrap-around t)
(company-global-modes '(not compilation-mode magit-status-mode reb-mode))
(company-backends '(company-capf company-files
(company-dabbrev-code company-gtags company-etags company-keywords)
company-dabbrev))
:config
(define-key company-mode-map (kbd "C-:") 'company-complete-common)
(define-key company-active-map (kbd "<tab>") 'smarter-yas-expand-next-field-complete)
(global-company-mode 1)
(defun smarter-yas-expand-next-field-complete ()
"Try to `yas-expand' and `yas-next-field' at current cursor position.
If failed try to complete the common part with `company-complete-common'"
(interactive)
(if yas-minor-mode
(let ((old-point (point))
(old-tick (buffer-chars-modified-tick)))
(yas-expand)
(when (and (eq old-point (point))
(eq old-tick (buffer-chars-modified-tick)))
(ignore-errors (yas-next-field))
(when (and (eq old-point (point))
(eq old-tick (buffer-chars-modified-tick)))
(company-complete-common))))
(company-complete-common))))A much nicer frame for completion candidates
(use-package company-posframe
:ensure t
:config
(company-posframe-mode 1))(use-package helm-company
:ensure t
:config
(define-key company-mode-map (kbd "C-:") 'helm-company))use M-x copilot-login to authenticate. copilot-mode to turn it on automatically blending in with company (use C-n and C-p to control company when they overlap).
can also use M-C-<return> to summon it manually instead
(use-package editorconfig :ensure t)
(use-package copilot
:ensure t
:preface
(defvar ava/copilot-enabled-projects '("insert_project_names"))
(defun ava/copilot--project-enabled-p ()
(when (fboundp 'projectile-project-name)
(let ((name (projectile-project-name)))
(and name (member name ava/copilot-enabled-projects)))))
(defun ava/copilot-ensure ()
"Enable copilot in supported modes for allowed projects."
(when (and (derived-mode-p 'c++-mode 'c++-ts-mode 'python-mode 'python-ts-mode)
(ava/copilot--project-enabled-p))
(copilot-mode 1)))
(defun ava/copilot-quit ()
"Clear copilot ghost text on quit."
(when (bound-and-true-p copilot--overlay)
(copilot-clear-overlay)))
(defun ava/copilot-complete-or-accept ()
"Either trigger a completion or accept one if available."
(interactive)
(if (copilot--overlay-visible)
(progn
(copilot-accept-completion)
(open-line 1)
(next-line))
(copilot-complete)))
;:custom
;(copilot-max-char -1)
:bind (("M-C-<return>" . #'ava/copilot-complete-or-accept)
(:map copilot-completion-map
("M-n" . #'copilot-next-completion)
("M-p" . #'copilot-previous-completion)
("M-<return>" . #'copilot-accept-completion)))
:config
;; (add-to-list 'copilot-disable-predicates #'company--active-p)
;; (add-to-list 'copilot-disable-display-predicates #'company--active-p)
(dolist (hook '(python-mode-hook
python-ts-mode-hook
c++-mode-hook
c++-ts-mode-hook))
(add-hook hook #'ava/copilot-ensure))
(add-to-list 'copilot-major-mode-alist '("c++-ts" . "cpp"))
(add-to-list 'copilot-major-mode-alist '("python-ts" . "python"))
(advice-add 'keyboard-quit :before #'ava/copilot-quit))uses rg for fast grep
(use-package deadgrep
:ensure t
:commands deadgrep
:init
(defun ava/deadgrep--include-args (rg-args)
"https://github.com/Wilfred/deadgrep/issues/24#issuecomment-942290197"
(push "--hidden" rg-args)
(push "--no-ignore-vcs" rg-args))
:bind (("M-s g" . deadgrep)
(:map deadgrep-mode-map ("C-c C-w" . #'deadgrep-edit-mode)))
:config
(advice-add 'deadgrep--arguments :filter-return #'ava/deadgrep--include-args))(use-package devdocs-browser :ensure t)(with-eval-after-load 'dired
(require 'dired-x)
(setq
dired-recursive-copies 'always
dired-recursive-deletes 'always
dired-dwim-target t
dired-auto-revert-buffer 'dired-directory-changed-p
dired-listing-switches "-Al --si --time-style long-iso --group-directories-first"
dired-hide-details-hide-symlink-targets nil
dired-kill-when-opening-new-dired-buffer t
dired-mouse-drag-files t
; dired-guess-shell-alist-user (list '("\\.foobar$" "some command")) ;; suggestions for ! and & in Dired
wdired-allow-to-change-permissions t)
(add-hook 'dired-mode-hook (lambda () (interactive) (dired-hide-details-mode 1))))a much nicer dired (can in-place expand subdirectory contents)
(use-package dired-subtree
:ensure t
:after dired
:bind (:map dired-mode-map
("i" . dired-subtree-insert)
(";" . dired-subtree-remove)
("<tab>" . dired-subtree-cycle)))(use-package dired-narrow
:ensure t
:after dired
:bind (:map dired-mode-map
("C-c C-d n" . dired-narrow-fuzzy)
("C-c C-d r" . dired-narrow-regexp)))replaces list-directory with recentf for dirs
(use-package dired-recent
:ensure t
:config (dired-recent-mode 1))add rsync option to dired
(use-package dired-rsync-transient
:ensure t
:bind (:map dired-mode-map ("r" . dired-rsync-transient))
:custom (dired-rsync-unmark-on-completion nil)
:hook (dired-rsync-failed . dired-rsync--pop-to-rsync-failed-buf))make async friendly
(use-package async
:ensure t)
(use-package dired-async
:ensure nil
:after (dired async)
:config
(dired-async-mode 1))(use-package dumb-jump
:ensure t
:custom
(dumb-jump-selector 'helm)
(dumb-jump-confirm-jump-to-modified-file nil)
:bind
(:map prog-mode-map
(("C-c C-j" . dumb-jump-go))))Use M-w and modifiers to more efficiently save things to kill ring
(use-package easy-kill
:ensure t
:config
(global-set-key [remap kill-ring-save] #'easy-kill)
(global-set-key [remap mark-sexp] #'easy-mark)
(defun ava/easy-kill-on-buffer-file-name-with-line-number (n)
"Get `buffer-file-name' or `default-directory' with line number if N is 2.
If N is zero, remove the directory part; -, remove the file name
part; +, full path; 9, name with line number.; 8 full name with line number"
(if (easy-kill-get mark)
(easy-kill-echo "Not supported in `easy-mark'")
(pcase (or buffer-file-name default-directory)
(`nil (easy-kill-echo "No `buffer-file-name'"))
(file (let* ((file (directory-file-name file))
(text (pcase n
(`- (file-name-directory file))
(`0 (file-name-nondirectory file))
(`8 (concat file ":" (number-to-string (line-number-at-pos))))
(`9 (concat (file-name-nondirectory file) ":" (number-to-string (line-number-at-pos))))
(_ file))))
(easy-kill-adjust-candidate 'buffer-file-name text))))))
(advice-add 'easy-kill-on-buffer-file-name :override #'ava/easy-kill-on-buffer-file-name-with-line-number))(use-package eca
:ensure t
:custom
(eca-chat-use-side-window nil)
(eca-chat-trust-enable t)
(eca-worktree-mode 'isolated)
:preface
(defun ava/eca-authinfo-password (host)
"Return auth-source password for HOST using user \"apikey\"."
(require 'auth-source)
(auth-source-pick-first-password :host host :user "apikey"))
:init
(setenv "OPENAI_API_KEY" (ava/eca-authinfo-password "api.openai.com"))
(setenv "ANTHROPIC_API_KEY" (ava/eca-authinfo-password "api.anthropic.com"))
(setenv "OPENROUTER_API_KEY" (ava/eca-authinfo-password "api.openrouter.com"))
:config
(defun ava/eca-chat-display-in-new-window (buffer _alist)
"Display BUFFER in a newly split regular window for ECA chat."
(let ((window (or (ignore-errors (split-window-right))
(ignore-errors (split-window-below)))))
(unless window
(user-error "Unable to create a new window for ECA chat"))
(set-window-buffer window buffer)
window))
(defun ava/eca-chat-new-in-new-window (orig-fn &rest args)
"Make `eca-chat-new' open in a freshly split regular window."
(let ((display-buffer-overriding-action
'((ava/eca-chat-display-in-new-window)
(inhibit-same-window . t))))
(apply orig-fn args)))
(unless (advice-member-p #'ava/eca-chat-new-in-new-window 'eca-chat-new)
(advice-add 'eca-chat-new :around #'ava/eca-chat-new-in-new-window))
:bind (("C-c k e" . eca)
("C-c k ." . eca-transient-menu)
("C-c k c" . eca-chat-toggle-window)
("C-c k k" . eca-stop)
("C-c k r" . eca-restart)))(use-package helm-eca
:ensure t
:after (helm eca)
:bind (("C-c h e" . helm-eca)))(use-package eglot
:commands eglot
:init
;(defun ava/eglot-disable-flymake () (flymake-mode -1))
;(add-hook 'eglot-managed-mode-hook #'ava/eglot-disable-flymake)
;; (defvar ava/eglot-enabled-projects '("foo" "bar")) ;; <- if want to auto enable in some projects
;; (defun ava/eglot-ensure ()
;; (when (and (derived-mode-p 'c++-mode 'c++-ts-mode)
;; (member (projectile-project-name) ava/eglot-enabled-projects))
;; (eglot-ensure)))
;; (add-hook 'eglot-managed-mode-hook #'ava/eglot-ensure)
(defun ava/eglot-enable-eager-eldoc () (setq eldoc-documentation-strategy 'eldoc-documentation-compose-eagerly))
(add-hook 'eglot-managed-mode-hook #'ava/eglot-enable-eager-eldoc)
:bind (:map eglot-mode-map
("C-h ." . eldoc)
("C-c e a" . eglot-code-actions)
("C-c e r" . eglot-rename)
("C-c e q" . eglot-code-action-quickfix)
("C-c e e" . eglot-code-action-extract)
("C-c e i" . eglot-code-action-inline)
("C-c e n" . flymake-goto-next-error)
("C-c e p" . flymake-goto-prev-error))
:custom
(eglot-events-buffer-size 0)
(eglot-extend-to-xref t)
(eglot-report-progress nil)
(eldoc-echo-area-use-multiline-p nil)
(eglot-ignored-server-capabilities '(:documentHighlightProvider :inlayHintProvider))
:config
(let ((clangd-options (list "clangd"
"--malloc-trim"
"--log=info"
"--background-index"
"--clang-tidy"
"--completion-style=detailed"
"--header-insertion=never"
"--header-insertion-decorators=0"))
(clangd-modes (list 'c++-mode 'c++-ts-mode 'c-mode 'c-ts-mode)))
(let ((entry (assoc clangd-modes eglot-server-programs)))
(if entry
(setcdr entry clangd-options)
(push (cons clangd-modes clangd-options) eglot-server-programs)))))(use-package elfeed
:ensure t
:commands elfeed
:custom
(elfeed-search-filter "@1-week-ago ")
(elfeed-feeds
'(("https://www.archlinux.org/feeds/news/" arch)
("https://matklad.github.io/feed.xml" programming)
("http://www.reddit.com/r/emacs/.rss" emacs reddit)
("http://sachachua.com/blog/category/emacs-news/feed" emacs)
("http://www.masteringemacs.org/feed/" emacs)
("http://emacsredux.com/atom.xml" emacs)
("https://emacs.tv/videos.rss" emacs))))(use-package ess
:ensure t
:init (require 'ess-site)
:custom
(inferior-R-program-name "/usr/bin/R")
(inferior-R-args "--no-save --no-restore-data --quiet")
(ess-eval-visibly-p nil)
(ess-directory "~/")
(ess-use-flymake nil)
(ess-indent-with-fancy-comments nil)
(ess-ask-for-ess-directory nil)
:config
(setf (alist-get 'ess-indent-with-fancy-comments ess-style-alist)
'(nil nil nil))
(define-key ess-r-mode-map "_" #'ess-insert-assign)
(define-key inferior-ess-r-mode-map "_" #'ess-insert-assign))(use-package flycheck :ensure t); (use-package flycheck-clang-tidy
; :ensure t
; :after flycheck
; :hook (flycheck-mode . flycheck-clang-tidy-setup))(use-package git-gutter
:ensure t
:init
(global-git-gutter-mode +1))(use-package git-timemachine
:ensure t
:bind ("C-x v t" . git-timemachine-toggle))https://github.com/karthink/gptel
(use-package gptel
:ensure t
:init
(defun ava/init-gptel-mode ()
(visual-line-mode)
(setq-local gptel-expert-commands t)
(setq-local gptel--system-message (alist-get 'default gptel-directives)))
:hook (gptel-mode . ava/init-gptel-mode)
:custom
(gptel-model 'gpt-5.5)
(gptel-default-mode 'org-mode)
(gptel-track-media t)
(gptel-directives '((default . "Formatting re-enabled. You are a helpful assistant living inside Emacs. The user is a computer programmer. Your responses are always concise, succinct, and to the point. You never apologize for confusions as that wastes time. If you generate blocks using three backticks inspect your response and add the appropriate programming language after the opening backticks. Do not use the asterisk character followed by whitespace for bullet points in your responses as this can interfere with org-mode rendering (you can use a hyphen instead)")
(programmer . "You are a careful programmer. Provide code and only code as output without any additional text, prompt, or note. Do NOT use markdown backticks (```) to format your response.")
(emacser . "You are an emacs maven. Reply with the most appropriate built-in Emacs command for the task I specify. Do NOT generate any additional description or explanation.")
(cliwhiz . "You are a command line helper. Generate command line commands that do what is requested, without any additional description or explanation. Generate ONLY the command, without any markdown code fences.")
(explainer . "You are a computer programmer's assistant. Explain what this code does")
(differ . "You are a computer programmer's assistant. Explain what this code diff hunk is doing, is it trying to fix something? Is it just a refactor? What is your understanding of the diff")))
:config
;(setq gptel-log-level 'debug)
(defun ava/add-or-update-openai-model (model-name properties)
"Add a model to `gptel--openai-models` or update it if it already exists."
(let ((existing (assoc model-name gptel--openai-models)))
(if existing
(setcdr existing properties)
(add-to-list 'gptel--openai-models (cons model-name properties) t))))
(ava/add-or-update-openai-model 'gpt-5.5
'(:description "Reasoning model designed to solve hard problems across domains"
:context-window 400
:input-cost 1.25
:output-cost 10
:cutoff-date "2024-10"
:request-params (:model "gpt-5.5" :stream t :reasoning_effort "low")))
(ava/add-or-update-openai-model 'gpt5.5-thinking
'(:description "Reasoning model designed to solve hard problems across domains"
:context-window 400
:input-cost 1.25
:output-cost 10
:cutoff-date "2024-10"
:request-params (:model "gpt-5.5" :stream t :reasoning_effort "xhigh")))
(setq ava/openai-model-list
(let ((desired-models '("gpt-5.5" "gpt5.5-thinking"))
(result '()))
(dolist (desired-name desired-models)
(let ((found (assoc (intern desired-name) gptel--openai-models)))
(when found (push found result))))
(nreverse result)))
(gptel-make-anthropic "claude" :key gptel-api-key :stream t)
(setq ava/gptel-openai-backend (gptel-make-openai "ChatGPT" :key gptel-api-key :stream t :models ava/openai-model-list))
(setq-default gptel-backend ava/gptel-openai-backend)
(setf (alist-get 'org-mode gptel-prompt-prefix-alist) "*Prompt*: "
(alist-get 'org-mode gptel-response-prefix-alist) "*Response*:\n")
(with-eval-after-load 'gptel-org
(setq-default gptel-org-branching-context t)))(use-package helm
:ensure t
:diminish helm-mode
:init (helm-mode 1)
:bind (
("C-h a" . helm-apropos)
("C-x b" . helm-mini)
("M-y" . helm-show-kill-ring)
("M-x" . helm-M-x)
("C-x C-f" . helm-find-files)
("C-c h o" . helm-occur)
("C-c h b" . helm-resume)
("C-c h i" . helm-semantic-or-imenu)
("C-c h m" . helm-man-woman)
("C-c h I" . helm-imenu-in-all-buffers)
("C-c h l" . helm-locate)
("C-c h g s" . helm-grep-do-git-grep)
("C-c h g l" . helm-ls-git)
("C-c h t" . helm-top)
("C-c h x" . helm-shell-history)
("C-c h <SPC>" . helm-all-mark-rings))
:config
(setq helm-candidate-number-limit 100
helm-idle-delay 0.0
helm-input-idle-delay 0.01
helm-yas-display-key-on-candidate t
helm-quick-update t
helm-M-x-requires-pattern nil
helm-command-prefix-key "C-c h"
helm-autoresize-min-height 25
helm-autoresize-max-height 25
helm-split-window-inside-p t
helm-move-to-line-cycle-in-source t
helm-ff-search-library-in-sexp t
helm-scroll-amount 8
helm-ff-file-name-history-use-recentf t
helm-buffer-max-length nil
helm-buffer-skip-remote-checking t
helm-window-prefer-horizontal-split 'decide)
;;locate %s -d FOO -e --regex %s where FOO is : delimited from cmd updatedb -l 0 -o i.db -U path_i for all paths
;;(defvar my-locate-db-command (with-temp-buffer (insert-file-contents "path/to/cmd.txt") (buffer-string)))
;;(setq helm-locate-command my-locae-db-command)
(helm-autoresize-mode 1)
(define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action)
(define-key helm-map (kbd "C-i") 'helm-execute-persistent-action)
(define-key helm-map (kbd "C-z") 'helm-select-action)
(defun ava/around-helm-buffers-sort-transformer (candidates source)
candidates)
(advice-add 'helm-buffers-sort-transformer
:override #'ava/around-helm-buffers-sort-transformer)
(defvar ava/helm-mini-base-sources helm-mini-default-sources)
(defun ava/reset-helm-buffer-max-length (&rest ignore) (setq helm-buffer-max-length nil))
(defun ava/reset-helm-mini-default-sources (&rest ignore)
(let ((sources ava/helm-mini-base-sources))
(when (and (require 'helm-ls-git nil t)
(fboundp 'helm-ls-git-root-dir)
(ignore-errors (helm-ls-git-root-dir)))
;; `helm-ls-git' only builds `helm-source-ls-git' when its main
;; command runs, so do ithere when `helm-mini' wants to reuse it.
(unless helm-source-ls-git
(setq helm-source-ls-git
(and (fboundp 'helm-ls-git-build-ls-git-source)
(helm-ls-git-build-ls-git-source))))
(when (and helm-source-ls-git
(not (memq 'helm-source-ls-git sources)))
(setq sources (append sources '(helm-source-ls-git)))))
(setq helm-mini-default-sources sources)))
(advice-add 'helm-mini :before #'ava/reset-helm-buffer-max-length)
(advice-add 'helm-mini :before #'ava/reset-helm-mini-default-sources)
(with-eval-after-load 'isearch
(define-key isearch-mode-map (kbd "M-i") #'helm-occur-from-isearch)))(use-package helm-rg
:ensure t
:bind (("C-c h r g" . helm-rg)))(use-package helm-ls-git
:ensure t
:defer t)remap term-previous-matching-input to a helm frontend
(use-package helm-shell-history
:load-path "~/.emacs.d/lisp/helm-shell-history"
:after term vterm
:custom
(helm-shell-history-file "~/.bash_eternal_history")
(helm-shell-history-fast-parser "~/development/helm-shell-history/src/parse_history")
:config
(define-key term-mode-map (kbd "M-r") 'helm-shell-history)
(define-key vterm-mode-map (kbd "M-r") 'helm-shell-history))(use-package helm-descbinds
:ensure t
:custom
(helm-descbinds-disable-which-key nil)
:init
(helm-descbinds-mode))(use-package helm-dash
:ensure t
:bind (("C-c h d" . helm-dash-at-point))
:custom
(dash-docs-enable-debugging nil)
(dash-docs-browser-func #'eww)
:config
(require 'dash-docs)
(setq dash-docs-common-docsets '("Emacs Lisp", "Python 3" "NumPy" "Pandas")))(use-package helm-org-rifle
:ensure t
:bind
("C-c h r r" . helm-org-rifle)
("C-c h r b" . helm-org-rifle-current-buffer)
("C-c h r a" . helm-org-rifle-agenda-files)
("C-c h r o" . helm-org-rifle-org-directory))(use-package helm-xref
:ensure t
:after helm
:custom
(xref-show-xrefs-function #'helm-xref-show-xrefs)
(xref-show-definitions-function #'helm-xref-show-defs))(use-package helpful
:ensure t
:bind
(("C-h f" . helpful-callable)
("C-h v" . helpful-variable)
("C-h k" . helpful-key)
("C-c C-d" . helpful-at-point)
("C-h F" . helpful-function)
("C-h C" . helpful-command)))(use-package hydra
:ensure hydra
:init
(global-set-key
(kbd "C-c g")
(defhydra hydra-git-gutter (:body-pre (git-gutter-mode 1) :hint nil)
"
Up^^ Down^^ Miscellaneous
------------------------------------------------------------------
[_p_] Prev [_n_] Next [_<SPC>_] Show [_r_] Revert [_q_] Quit
[_h_] First [_l_] Last [_s_] Stage [_d_] Digest [_b_] Set Base Revision"
("n" git-gutter:next-hunk)
("p" git-gutter:previous-hunk)
("h" (progn (goto-char (point-min)) (git-gutter:next-hunk 1)))
("l" (progn (goto-char (point-min)) (git-gutter:previous-hunk 1)))
("<SPC>" git-gutter:popup-hunk)
("s" git-gutter:stage-hunk)
("r" git-gutter:revert-hunk)
("r" git-gutter:revert-hunk)
("d" git-gutter:statistic)
("b" git-gutter:set-start-revision)
("q" nil)))
(with-eval-after-load 'paredit
(defhydra hydra-paredit (:hint nil)
"
Forward^^ Backward^^ Miscellaneous
------------------------------------------------------------------
[_n_] Next [_p_] Next [_r_] Raise [_q_] Quit
[_s_] Slurp [_M-s_] Slurp [_l_] Splice
[_b_] Barf [_M-b_] Barf [_u_] Undo"
("n" paredit-forward)
("s" paredit-forward-slurp-sexp)
("b" paredit-forward-barf-sexp)
("p" paredit-backward)
("M-s" paredit-backward-slurp-sexp)
("M-b" paredit-backward-barf-sexp)
("r" paredit-raise-sexp)
("l" paredit-splice-sexp)
("u" undo-only)
("q" nil))
(add-hook 'paredit-mode-hook #'(lambda () (bind-key "C-c e" #'hydra-paredit/body paredit-mode-map))))
(global-set-key
(kbd "C-c w")
(defhydra hydra-windows (:hint nil)
("r" rotate-frame-clockwise "clockwise")
("\\" rotate-frame-anticlockwise "anticlockwise")
("v" flip-frame "flip")
("f" flop-frame "flop")
("j" (shrink-window -10) "down")
("k" (shrink-window 10) "up")
("h" (shrink-window 10 t) "shrink")
("l" (shrink-window -10 t) "widen")
("0" (balance-windows) "balance")
("q" nil "quit")))
(with-eval-after-load 'smerge-mode
(defhydra hydra-smerge
(:color pink :hint nil :post (smerge-auto-leave))
"
^Move^ ^Keep^ ^Diff^ ^Other^
^^-----------^^-------------------^^---------------------^^-------
_n_ext _b_ase _<_: upper/base _C_ombine
_p_rev _u_pper _=_: upper/lower _r_esolve
^^ _l_ower _>_: base/lower _k_ill current
^^ _a_ll _R_efine
^^ _RET_: current _E_diff
"
("n" smerge-next)
("p" smerge-prev)
("b" smerge-keep-base)
("u" smerge-keep-upper)
("l" smerge-keep-lower)
("a" smerge-keep-all)
("RET" smerge-keep-current)
("\C-m" smerge-keep-current)
("<" smerge-diff-base-upper)
("=" smerge-diff-upper-lower)
(">" smerge-diff-base-lower)
("R" smerge-refine)
("E" smerge-ediff)
("C" smerge-combine-with-next)
("r" smerge-resolve)
("k" smerge-kill-current)
("ZZ" (lambda ()
(interactive)
(save-buffer)
(bury-buffer))
"Save and bury buffer" :color blue)
("q" nil "cancel" :color blue))
(add-hook 'smerge-mode-hook (lambda () (bind-key "C-c ^ h" #'hydra-smerge/body smerge-mode-map)))))(use-package ibuffer
:bind ("C-x C-b" . ibuffer)
:config (define-key ibuffer-mode-map (kbd "M-o") nil))
(use-package ibuffer-vc
:ensure t
:bind (:map ibuffer-mode-map
("/ V" . ibuffer-vc-set-filter-groups-by-vc-root)))(use-package jq-mode
:ensure t
:mode "\\.jq\\'")
(with-eval-after-load 'json-ts-mode
(require 'json)
(require 'jq-mode)
(add-hook 'json-ts-mode-hook (lambda () (flycheck-mode)))
(setq json-ts-mode-indent-offset 4)
(setq json-encoding-pretty-print t)
(setq json-encoding-default-indentation " ")
(let ((map json-ts-mode-map))
(define-key map (kbd "C-c C-i") #'jq-interactively)
(define-key map (kbd "C-c C-f") #'json-pretty-print-buffer)))(can use magit-toggle-verbose-refresh to profile status buffer)
(use-package magit
:ensure t
:preface
(defun ava/format-staged ()
(interactive)
(dolist (name (magit-staged-files))
(let ((fname (expand-file-name name (magit-toplevel))))
(when (file-exists-p fname)
(pcase (file-name-extension name)
("py"
(shell-command (format "dos2unix -q %s" fname)))
((or "C" "H" "I" "c" "h" "cpp" "hpp")
(shell-command (format "dos2unix -q %s && clang-format --style=file -i %s" fname fname))))))))
:custom
(magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)
(magit-log-section-commit-count 25)
(magit-diff-refine-hunk 'all) ;nil for extra perf
(magit-no-confirm '(stage-all-changes unstage-all-changes set-and-push))
;; (magit-refresh-status-buffer nil) ;set to nil as last resort for perf
:bind
(("C-x g" . magit-status)
("C-c m" . magit-file-dispatch)
:map magit-mode-map
("#" . ava/magit-tools))
:config
;; if too slow remove some headers like this
;; (remove-hook 'magit-status-section-hook 'magit-insert-tags-header)
;; (remove-hook 'magit-status-section-hook 'magit-insert-status-headers)
;; (remove-hook 'magit-status-section-hook 'magit-insert-untracked-files)
;; (remove-hook 'magit-status-section-hook 'magit-insert-unpushed-to-pushremote)
;; (remove-hook 'magit-status-section-hook 'magit-insert-unpulled-from-upstream)
;; (remove-hook 'magit-status-section-hook 'magit-insert-unpulled-from-pushremote)
;; (remove-hook 'magit-status-section-hook 'magit-insert-unpushed-to-upstream-or-recent)
(add-hook 'magit-status-sections-hook #'magit-insert-worktrees t)
(require 'transient)
(transient-define-prefix ava/magit-tools ()
"Ava Magit Tools."
["Misc"
("f" "Format staged files" ava/format-staged)])
(transient-append-suffix 'magit-dispatch "!" '("#" "Ava tools" ava/magit-tools))
;; if we end up with other tools like open on bitbucket/github, copy link or need a make pull request without forge
;; (transient-append-suffix 'magit-file-dispatch "B" '("#" "Ava tools" ava/magit-tools))
)(use-package forge
:ensure t
:after magit
:config
(remove-hook 'magit-status-sections-hook 'forge-insert-issues))addresses the issues with variable-pitch-mode in modes like org (tables/code-blocks)
(use-package mixed-pitch
:ensure t
:defer t
:config
(dolist (face '(org-date org-priority org-tag org-special-keyword))
(add-to-list 'mixed-pitch-fixed-pitch-faces face)))meta up and down to move text or region
(use-package move-text :ensure t :config (move-text-default-bindings))- power hydra here
- ivanmalison hydra example here
- github issue on setting run once to avoid exp behavior here
- pull in phi-search as well to get incremental search while in mc
- protip: easy-kill ==C-SPC== will turn selection into region
(use-package multiple-cursors
:ensure t
:config (progn
(use-package phi-search-mc
:ensure t
:config
(phi-search-mc/setup-keys)))
(defhydra ava/multiple-cursors-hydra (:hint nil)
"
Up^^ Down^^ Miscellaneous % 2(mc/num-cursors) cursor%s(if (> (mc/num-cursors) 1) \"s\" \"\")
------------------------------------------------------------------
[_p_] Next [_n_] Next [_l_] Edit lines [_d_] Mark sym defun [_|_] Vertical align
[_P_] Skip [_N_] Skip [_a_] Mark all [_r_] Mark all regex [_q_] Quit
[_M-p_] Unmark [_M-n_] Unmark [_s_] Mark sym [_0_] Insert numbers"
("n" mc/mark-next-like-this)
("N" mc/skip-to-next-like-this)
("M-n" mc/unmark-next-like-this)
("p" mc/mark-previous-like-this)
("P" mc/skip-to-previous-like-this)
("M-p" mc/unmark-previous-like-this)
("|" mc/vertical-align)
("0" mc/insert-numbers)
("l" mc/edit-beginnings-of-lines)
("a" mc/mark-all-like-this :exit t)
("s" mc/mark-all-symbols-like-this :exit t)
("d" mc/mark-all-symbols-like-this-in-defun :exit t)
("r" mc/mark-all-in-region-regexp :exit t)
("q" nil))
:bind (("C-c i" . ava/multiple-cursors-hydra/body)
:map mc/keymap ("C-s" . phi-search)))(use-package org
:custom
(org-ellipsis " ▾")
(org-use-speed-commands 1)
(org-return-follows-link t)
(org-blank-before-new-entry nil)
(org-catch-invisible-edits 'smart)
(org-enforce-todo-dependencies t)
(org-hide-emphasis-markers t)
(org-list-description-max-indent 5)
(org-export-html-postamble nil)
(org-log-done 'time)
(org-cycle-separator-lines 0)
(org-deadline-warning-days 7)
(org-imenu-depth 10)
(org-startup-folded t)
(org-goto-auto-isearch nil)
(org-refile-targets '((nil :maxlevel . 5) (org-agenda-files :maxlevel . 5)))
(org-refile-use-outline-path 'file)
(org-outline-path-complete-in-steps nil)
(org-src-window-setup 'current-window)
(org-log-into-drawer t)
(org-todo-keywords '((sequence "TODO(t)" "WAIT(w@/!)" "|" "DONE(d)")))
(org-highlight-latex-and-related '(native script entities))
(org-format-latex-options (plist-put org-format-latex-options :scale 1.5))
(org-latex-create-formula-image-program 'dvisvgm)
(org-confirm-babel-evaluate nil)
(org-clock-history-length 20)
(org-clock-out-remove-zero-time-clocks t)
(org-link-elisp-confirm-function nil)
(org-edit-src-content-indentation 0)
(org-fontify-quote-and-verse-blocks t)
:hook
(org-mode . org-indent-mode)
(org-mode . mixed-pitch-mode)
:config
(add-to-list 'org-speed-commands '("i" . (progn (outline-show-subtree) (org-end-of-subtree))))
(add-to-list 'org-speed-commands '("b" . (unless (org-goto-sibling t) (while (org-goto-sibling)))))
(add-to-list 'org-speed-commands '("f" . (unless (org-goto-sibling) (while (org-goto-sibling t)))))
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(shell . t)
(R . t)
(python . t)
(dot . t)
(plantuml . t)))
(setq org-capture-bookmark nil
org-capture-templates
'(("n" "note" entry (file "notes.org") "* %? \n%U\n%i")
("t" "tasks")
("tt" "whenever" entry (file "todo.org") "* TODO %^{title}\n%?")
("ts" "schedule" entry (file "todo.org") "* TODO %^{title}\nSCHEDULED: %^t\n%?")
("td" "deadline" entry (file "todo.org") "* TODO %^{title}\nDEADLINE: %^t\n%?")
("ta" "sch&dead" entry (file "todo.org") "* TODO %^{title}\nSCHEDULED: %^t DEADLINE: %^t\n%?")))
(define-key global-map (kbd "C-c l") 'org-store-link)
(define-key global-map (kbd "C-c c") 'org-capture)
(require 'org-tempo)
(add-to-list 'org-structure-template-alist '("sh" . "src bash"))
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(add-to-list 'org-structure-template-alist '("R" . "src R"))
(add-to-list 'org-structure-template-alist '("cpp" . "src C"))
(add-to-list 'org-structure-template-alist '("conf" . "src conf"))
(add-to-list 'org-structure-template-alist '("xml" . "src nxml"))
(dolist (face '((org-level-1 . 1.20) (org-level-2 . 1.10) (org-level-3 . 1.05)))
(set-face-attribute (car face) nil :weight 'regular :height (cdr face))))hide emphasis markers the nice way
(use-package org-appear
:ensure t
:commands (org-appear-mode)
:hook (org-mode . org-appear-mode)
:custom
(org-appear-delay 0.5)
(org-appear-autolinks t)
(org-appear-autoemphasis t)
(org-appear-autokeywords t))(use-package org-modern
:ensure t
:hook ((org-mode . org-modern-mode)
(org-agenda-finalize . org-modern-agenda))
:custom
(org-modern-star '("◉" "○" "●" "○" "●" "○" "●"))
(org-modern-table-vertical 1)
(org-modern-progress nil)
(org-modern-block-fringe nil))(use-package org-mime
:ensure t
:config
(setq mail-host-address (getenv "HOST")
org-mime-export-options '(:section-numbers nil
:with-author nil
:with-toc nil
:with-latex imagemagick))
(add-hook 'message-mode-hook
(lambda ()
(local-set-key (kbd "C-c M-o") 'org-mime-htmlize)))
(add-hook 'org-mode-hook
(lambda ()
(local-set-key (kbd "C-c M-o") 'org-mime-org-subtree-htmlize))))(use-package orgit :ensure t)(use-package org-agenda
:after org
:custom
(org-agenda-files '("todo.org" "projects.org"))
(org-agenda-span 'day)
(org-agenda-window-setup 'current-window)
(org-agenda-restore-windows-after-quit t)
(org-agenda-todo-ignore-scheduled 'future)
(org-agenda-skip-deadline-if-done t)
(org-agenda-skip-scheduled-if-done t)
(org-agenda-skip-deadline-prewarning-if-scheduled t)
:init
(global-set-key (kbd "C-c a") 'org-agenda))(use-package org-noter
:ensure t
:custom
(org-noter-always-create-frame nil))use paredit in lisp modes (animated paredit guide)
(use-package paredit
:ensure t
:bind (
:map paredit-mode-map
("M-s" . nil) ; used for isearch
("RET" . nil) ; used during M-: to evaluate the input
("C-j" . paredit-newline) ; replacement for RET
("M-I" . paredit-splice-sexp))
:hook ((emacs-lisp-mode
lisp-mode
lisp-interaction-mode
eval-expression-minibuffer-setup
ielm-mode
lisp-data-mode) . enable-paredit-mode))(use-package pdf-tools
:ensure t
:custom
(pdf-view-display-size 'fit-page)
(pdf-view-continuous nil)
(pdf-view-use-scaling t)
:config
(pdf-tools-install)
(setq pdf-view-resize-factor 1.1)
(add-hook 'pdf-tools-enabled-hook 'pdf-view-midnight-minor-mode))(use-package projectile
:ensure t
:init
(projectile-mode +1)
:hook
(emacs-startup . projectile-known-projects)
:diminish projectile-mode
:custom
(projectile-enable-caching t)
(projectile-auto-discover nil)
(projectile-per-project-compilation-buffer t)
(projectile-project-root-functions '(projectile-root-local projectile-root-marked))
(projectile-dirconfig-file ".projectile")
:init
(when (executable-find "rg")
(setq projectile-generic-command "rg -0 --no-ignore-vcs --hidden --files --color never"))
:bind-keymap
("C-c p" . projectile-command-map)
:bind
(:map projectile-command-map ("R" . ava/generate-tags)))
(use-package helm-projectile
:ensure t
:after (helm projectile)
:custom
(projectile-completion-system 'helm)
(projectile-switch-project-action #'helm-projectile)
:config
(helm-projectile-on))make sure imenu does not override dumb-jump in python mode
(use-package python
:defer t
:config
(bind-key "C-c C-j" #'dumb-jump-go python-mode-map))To use a venv set a pyvenv-activate directory local or file local variable to the venv path
(if one gets “exited abnormally with code 1” errors run M-x elpy-rpc-reinstall-virtualenv
as per jorgenschaefer/elpy#1729)
(use-package elpy
:ensure t
:commands elpy-enable
:custom
;; (elpy-rpc-virtualenv-path 'system)
(elpy-get-info-from-shell t)
:preface
(defun ava/elpy-enable-inferior-eldoc ()
(when (and (version< "28.0.0" emacs-version)
(boundp 'eldoc-documentation-functions))
(add-hook 'eldoc-documentation-functions 'elpy-eldoc-documentation t nil)))
:init
(progn
(elpy-enable)
(setq elpy-modules
'(elpy-module-sane-defaults
elpy-module-company
elpy-module-eldoc
elpy-module-highlight-indentation
elpy-module-pyvenv
elpy-module-yasnippet
elpy-module-folding))
(eval-after-load "elpy"
'(cl-dolist (key '("C-<return>" "C-<up>" "C-<down>" "C-<left>" "C-<right>"))
(define-key elpy-mode-map (kbd key) nil))))
:bind
(:map inferior-python-mode-map
("C-c C-d" . elpy-doc))
:config
(setq python-shell-interpreter-args "-i")
(setq elpy-rpc-timeout 10)
(setq python-shell-prompt-detect-failure-warning nil)
(add-to-list 'python-shell-completion-native-disabled-interpreters "jupyter")
(add-to-list 'process-coding-system-alist '("python" . (utf-8 . utf-8)))
(add-hook 'elpy-mode-hook (lambda () (elpy-shell-toggle-dedicated-shell 1)))
(add-hook 'inferior-python-mode-hook #'ava/elpy-enable-inferior-eldoc))(use-package recentf
:custom
(recentf-max-saved-items 500)
(recentf-auto-cleanup "05:00am")
(recentf-exclude '(file-remote-p))
:config
(defun ava/recentf-cleanup-silent (fun)
"Call `recentf-cleanup' suppressing messages."
(let (message-log-max (inhibit-message t)) (funcall fun)))
(advice-add 'recentf-cleanup :around #'ava/recentf-cleanup-silent)
(recentf-mode t))(use-package reformatter
:ensure t
:config
(reformatter-define ruff-format
:program "ruff"
:args `("format" "--stdin-filename" ,buffer-file-name "-"))
(reformatter-define clang-format
:program "clang-format"
:args `("-style=file"))
(with-eval-after-load 'cc-mode
(define-key c-mode-base-map (kbd "C-c b") #'clang-format-buffer))
(with-eval-after-load 'c-ts-mode
(define-key c++-ts-mode-map (kbd "C-c b") #'clang-format-buffer))
(with-eval-after-load 'python
(define-key python-mode-map (kbd "C-c b") #'ruff-format-buffer)))(use-package smart-comment
:ensure t
:bind ("M-;" . smart-comment))(use-package transpose-frame
:ensure t
:bind (("C-x |" . rotate-frame-clockwise)
("C-x \\" . rotate-frame-anticlockwise)))(use-package treesit
:if (version<= "29" emacs-version)
:ensure nil
:custom
(treesit-font-lock-level 4))
(use-package treesit-auto
:if (version<= "29" emacs-version)
:ensure t
:custom
(treesit-auto-install 'prompt)
:config
(setq treesit-auto-langs (delete 'python treesit-auto-langs))
(treesit-auto-add-to-auto-mode-alist 'all)
(setq c-ts-base-mode-hook c-mode-common-hook)
(global-treesit-auto-mode))(use-package undo-tree
:ensure t
:diminish undo-tree-mode
:custom
(undo-tree-auto-save-history nil)
(undo-tree-enable-undo-in-region nil)
(undo-tree-visualizer-diff t)
(undo-tree-visualizer-timestamps t)
(undo-tree-incompatible-major-modes '(term-mode vterm-mode))
:config
(global-undo-tree-mode))use for opening files larger than large-file-warning-threshold
(use-package vlf
:ensure t
:custom
(vlf-save-in-place t)
:config
(require 'vlf-setup))(use-package vterm
:ensure t
:config
(setq vterm-max-scrollback 100000)
(define-key vterm-mode-map (kbd "C-c C-j") 'vterm-copy-mode))start a remote vterm
(defun ava/rvterm (&optional host)
"Start a dir-tracking vterm on HOST (prompt if nil)."
(interactive
(list (read-string "Host: " (or (thing-at-point 'symbol) ""))))
(let* ((user (or (getenv "USER") user-login-name))
(bname (format "*vterm %s*" host))
(sshcmd (format "ssh -Y %s@%s" user host))
(setup
(mapconcat
#'identity
'("function vterm_printf() { printf \"\\e]%s\\e\\\\\" \"$1\"; }"
"function vterm_prompt_end() { vterm_printf \"51;A$(whoami)@$(hostname):$(pwd)\"; }"
"if [[ -n \"$PROMPT_COMMAND\" ]]; then PROMPT_COMMAND=\"vterm_prompt_end; $PROMPT_COMMAND\"; else PROMPT_COMMAND=\"vterm_prompt_end\"; fi"
"export PROMPT_COMMAND")
"\n"))
(bigcmd (concat sshcmd "\n" setup "\n")))
(vterm bname)
(switch-to-buffer bname)
(vterm-send-string bigcmd)
(vterm-send-return)))start a few common vterms
(defun ava/start-vterms ()
"Start a few common vterms"
(interactive)
(let ((vterm-start-helper (lambda (name cmd)
(let ((bname (format "*vterm %s*" name)))
(if (eq nil (get-buffer bname))
(progn
(vterm bname)
(with-current-buffer bname
(let ((inhibit-read-only t))
(vterm-send-string (format "%s\n" cmd) t)))))))))
(save-window-excursion
(funcall vterm-start-helper "rand2" "")
(funcall vterm-start-helper "rand1" "")
(funcall vterm-start-helper "rand0" ""))))(use-package webjump
:bind (("C-c j" . webjump))
:config
(setq webjump-sites '(("Emacs Wiki" . [simple-query "www.emacswiki.org" "www.emacswiki.org/cgi-bin/wiki/" ""])
("DuckDuckGo" . [simple-query "duckduckgo.com" "duckduckgo.com/?q=" ""])
("Google" . [simple-query "www.google.com" "www.google.com/search?q=" ""])
("Google Maps" . [simple-query "www.google.com/maps" "www.google.com/maps/search/" ""])
("Wikipedia" . [simple-query "wikipedia.org" "wikipedia.org/wiki/" ""])
("AUR" . [simple-query "https://aur.archlinux.org" "https://aur.archlinux.org/packages/?O=0&K=" ""]))))- Execute one of the search commands like
projectile-ag - Use
C-x C-sto make permanent your search results to a buffer - Use
C-c C-pwithin that result buffer to executewgrep-change-to-wgrep-modeand now you can make edits to any lines you please (including regular emacs search-and-replace commands) - Use
C-c C-cto save you changes, which will be promulgated to all files you’ve chosen to edit
(use-package wgrep
:ensure t
:custom
(wgrep-auto-save-buffer t)
:config
(use-package wgrep-helm :ensure t)
(use-package wgrep-deadgrep
:ensure t
:config
(add-hook 'deadgrep-finished-hook 'wgrep-deadgrep-setup)))show options for bindings in realtime
(use-package which-key
:ensure nil
:init
(which-key-mode))magit uses this but can also use it to make crontab editing work from a running emacs
(use-package with-editor
:ensure t
:config
(defun ava/crontab ()
"Run `crontab -e` from an emacs buffer"
(interactive)
(with-editor-async-shell-command "crontab -e")))automatically encloses double quotes or parens
(use-package wrap-region
:ensure t
:config
(wrap-region-global-mode t)
:diminish wrap-region-mode)advantage over (add-hook 'before-save-hook #'delete-trailing-whitespace) is that it does mess with others whitespace
(use-package ws-butler
:ensure t
:hook
(prog-mode . ws-butler-mode)
(text-mode . ws-butler-mode))(use-package yasnippet
:ensure t
:diminish yas-minor-mode
:hook (prog-mode . yas-minor-mode))
(use-package yasnippet-snippets
:ensure t
:after yasnippet)nice directory level diffing
(use-package ztree
:ensure t
:commands ztree-diff
:bind (:map ztree-mode-map
("j" . ztree-jump-side)));; (use-package auto-package-update
;; :ensure t
;; :if (not (daemonp))
;; :custom
;; (auto-package-update-interval 90)
;; (auto-package-update-prompt-before-update t)
;; (auto-package-update-delete-old-versions t)
;; (auto-package-update-hide-results t)
;; :config
;; (auto-package-update-maybe)); (use-package clojure-mode
; :ensure t
; :mode
; (("\\.clj.*$" . clojure-mode)
; ("\\.edn.*$" . clojure-mode))
; :init
; (add-hook 'clojure-mode-hook #'yas-minor-mode)
; (add-hook 'clojure-mode-hook #'paredit-mode)
; (add-hook 'clojure-mode-hook #'eldoc-mode))
;
; ;pulls cider
; (use-package clj-refactor
; :ensure t
; :defer t
; :diminish clj-refactor-mode
; :config
; (setq cljr-warn-on-eval nil)
; (cljr-add-keybindings-with-prefix "C-c C-m"))
;
; (use-package cider
; :ensure t
; :defer t
; :init
; (add-hook 'cider-mode-hook #'clj-refactor-mode)
; (add-hook 'cider-repl-mode-hook #'paredit-mode)
; :config
; (setq cider-repl-use-clojure-font-lock t
; cider-overlays-use-font-lock t
; cider-repl-display-help-banner nil
; cider-repl-pop-to-buffer-on-connect nil
; ;nrepl-log-messages t
; ;cider-preferred-build-tool "boot" ;(if no lein)
; ;cider-prompt-save-file-on-load 'always-save
; ;cider-font-lock-dynamically '(macro core function var)
; ;nrepl-hide-special-buffers t
; )
; (cider-repl-toggle-pretty-printing));; (use-package discover-my-major
;; :ensure t
;; :bind (("C-h C-m" . discover-my-major)
;; ("C-h C-d" . discover-my-mode)))to launch applications from exwm
;;(use-package dmenu
;; :ensure t
;; :bind
;; ("s-SPC" . dmenu))Disabled as not snappy enough emacs-eaf AUR github
; (use-package eaf
; :load-path "/usr/share/emacs/site-lisp/eaf"
; :custom
; (eaf-find-alternate-file-in-dired t)
; (browse-url-browser-function 'eaf-open-browser)
; :config
; (eaf-setq eaf-pdf-default-zoom 1.25)
; (eaf-setq eaf-browser-enable-adblocker "true")
; (eaf-bind-key nil "SPC" eaf-browser-keybinding)
; (eaf-bind-key nil "p" eaf-browser-keybinding)
; (defun adviser-find-file (orig-fn file &rest args)
; (let ((fn (if (commandp 'eaf-open) 'eaf-open orig-fn)))
; (pcase (file-name-extension file)
; ("pdf" (apply fn file nil))
; ("epub" (apply fn file nil))
; (_ (apply orig-fn file args)))))
; (advice-add #'find-file :around #'adviser-find-file));; (use-package ement
;; :ensure t
;; :custom
;; (ement-save-sessions t))use M-x erc-tls to start
;; (use-package erc
;; :ensure t
;; :preface
;; (defun ava/erc-quit ()
;; "Kill ERC buffers and terminate its child process."
;; (interactive)
;; (let ((kill-buffer-query-functions nil)
;; (erc-buffers (erc-buffer-list)))
;; (dolist (buffer erc-buffers) (kill-buffer buffer)))
;; (erc-buffer-list))
;; :init
;; (require 'erc-autoaway)
;; :custom
;; (erc-lurker-hide-list '("PART" "QUIT" "JOIN"))
;; (erc-server "irc.libera.chat")
;; (erc-nick "hooxen")
;; (erc-join-buffer 'buffer)
;; (erc-interpret-mirc-color t)
;; (erc-server-reconnect-timeout 10)
;; (erc-autoaway-idle-seconds 600)
;; :config
;; (add-hook 'erc-text-matched-hook #'(lambda (match-type nickuserhost msg)
;; (shell-command-to-string (format "notify-send erc '%s'" msg))))
;; (use-package erc-colorize
;; :ensure t
;; :config (erc-colorize-mode 1)));; (use-package expand-region
;; :ensure t
;; :bind
;; (("C-=" . er/expand-region)
;; :map mode-specific-map
;; :prefix-map region-prefix-map
;; :prefix "r"
;; ("(" . er/mark-inside-pairs)
;; (")" . er/mark-outside-pairs)
;; ("'" . er/mark-inside-quotes)
;; ([34] . er/mark-outside-quotes) ; "
;; ("o" . er/mark-org-parent)
;; ("u" . er/mark-url)
;; ("b" . er/mark-org-code-block)
;; ("." . er/mark-method-call)
;; ("w" . er/mark-word)
;; ("d" . er/mark-defun)
;; ("s" . er/mark-symbol)
;; (";" . er/mark-comment)
;; ("S" . er/mark-sentence)
;; ("P" . er/mark-paragraph)));;(use-package exwm :ensure t
;; :init
;; :config
;; (setq exwm-workspace-number 4)
;; (defun exwm-rename-buffer-to-title () (exwm-workspace-rename-buffer exwm-title))
;; (add-hook 'exwm-update-title-hook 'exwm-rename-buffer-to-title)
;; (exwm-input-set-key (kbd "s-r") #'exwm-reset)
;; (exwm-input-set-key (kbd "s-w") #'exwm-workspace-switch)
;; (dotimes (i 10)
;; (exwm-input-set-key (kbd (format "s-%d" i))
;; `(lambda ()
;; (interactive)
;; (exwm-workspace-switch-create ,i))))
;; (exwm-input-set-key (kbd "s-&")
;; (lambda (command)
;; (interactive (list (read-shell-command "$ ")))
;; (start-process-shell-command command nil command)))
;; (setq exwm-input-simulation-keys
;; '(([?\C-b] . [left])
;; ([?\C-f] . [right])
;; ([?\C-p] . [up])
;; ([?\C-n] . [down])
;; ([?\C-a] . [home])
;; ([?\C-e] . [end])
;; ([?\M-v] . [prior])
;; ([?\C-v] . [next])
;; ([?\C-d] . [delete])
;; ([?\C-k] . [S-end delete])
;; ([?\C-s] . [?\C-f])
;; ([?\C-t] . [?\C-n])))
;; (exwm-enable)
;; )replaces default narrow (slow so not in use)
; (use-package fancy-narrow
; :ensure t
; :init
; (fancy-narrow-mode)
; :diminish fancy-narrow-mode); (use-package iedit
; :ensure t
; :bind ("C-;" . iedit-mode)
; :config
; (setq iedit-toggle-key-default nil)
; (define-key iedit-mode-occurrence-keymap (kbd "RET") 'iedit-mode)
; :diminish)Also run M-x irony-install-server which just needs cmake, libclang, and llvm libs (using eglot instead)
; (use-package irony
; :disabled
; :ensure t
; :init
; (add-hook 'c++-mode-hook 'irony-mode)
; (add-hook 'c-mode-hook 'irony-mode)
; (add-hook 'objc-mode-hook 'irony-mode)
; (setq-default irony-cdb-compilation-databases '(irony-cdb-libclang
; irony-cdb-json
; irony-cdb-clang-complete))
; :bind (:map irony-mode-map
; ("C-c t" . irony-get-type))
; :config
; (defun ava/irony-mode-hook ()
; (define-key irony-mode-map [remap completion-at-point]
; 'irony-completion-at-point-async)
; (define-key irony-mode-map [remap complete-symbol]
; 'irony-completion-at-point-async))
; (add-hook 'irony-mode-hook 'ava/irony-mode-hook)
; (add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options)
; (add-hook 'irony-mode-hook 'company-irony-setup-begin-commands)
; (add-hook 'irony-mode-hook #'irony-eldoc)
; (use-package irony-eldoc
; :ensure t))on MELPA from here leetcode
; (use-package leetcode
; :disabled
; :ensure t
; :config
; (setq leetcode-prefer-language "cpp")
; (setq leetcode-prefer-sql "mysql"))Some references here: ccls + lsp example A example B and B2 example C goodies lsp-ui goodies lsp-ui more goodies how-to-turn-off example D
Only use lsp with flycheck (rather than hook, manual enable via ==M-x lsp==)
;; (use-package lsp-mode
;; :ensure t
;; :after flycheck
;; :commands lsp
;; :bind
;; (:map lsp-mode-map
;; ([remap xref-find-references] . lsp-find-references)
;; ([remap xref-find-definitions] . lsp-find-definition))
;; :custom
;; (lsp-keymap-prefix "C-c u")
;; (lsp-auto-configure t)
;; (lsp-eldoc-hook nil)
;; (lsp-eldoc-enable-hover t)
;; (lsp-diagnostics-provider :none)
;; (lsp-enable-symbol-highlighting nil)
;; (lsp-headerline-breadcrumb-enable nil)
;; (lsp-lens-enable t)
;; (lsp-modeline-code-actions-enable t)
;; (lsp-modeline-diagnostics-enable nil)
;; (lsp-signature-render-documentation t)
;; (lsp-completion-show-kind t)
;; (lsp-completion-show-detail t)
;; (lsp-enable-file-watchers t)
;; (lsp-file-watch-threshold nil)
;; (lsp-enable-xref t)
;; (lsp-enable-imenu t)
;; (lsp-enable-folding nil)
;; (lsp-enable-links nil)
;; (read-process-output-max (* 1024 1024))
;; ;:config
;; ;(define-key lsp-mode-map (kbd "C-c u") 'lsp-describe-thing-at-point)
;; );; (use-package lsp-ui
;; :ensure t
;; :after lsp-mode flycheck
;; :diminish
;; :commands lsp-ui-mode
;; :bind
;; (:map lsp-ui-mode-map
;; ;("C-c u" . lsp-ui-imenu)
;; ;("C-c C-d" . lsp-ui-doc-glance)
;; ("C-c d" . lsp-ui-doc-show)
;; ("M-i" . lsp-ui-doc-focus-frame))
;; :custom
;; (lsp-ui-peek-enable t)
;; (lsp-ui-doc-enable t)
;; (lsp-ui-doc-alignment 'window)
;; (lsp-ui-doc-header t)
;; (lsp-ui-doc-max-height 45)
;; (lsp-ui-doc-position 'at-point)
;; (lsp-ui-doc-show-with-mouse nil)
;; (lsp-ui-doc-show-with-cursor nil)
;; (lsp-ui-doc-include-signature t)
;; (lsp-ui-doc-border (face-foreground 'default))
;; (lsp-ui-sideline-enable t)
;; (lsp-ui-sideline-ignore-duplicate t)
;; (lsp-ui-sideline-show-code-actions nil)
;; (lsp-ui-sideline-show-diagnostics nil)
;; (lsp-ui-sideline-show-hover nil))
;;(use-package company-lsp
;; :ensure t
;; :custom (company-lsp-cache-candidates 'auto))The smtp portion will require app specific password and will store it in ~/.authinfo after first use
;; (use-package mu4e
;; :load-path "/usr/share/emacs/site-lisp/mu4e"
;; :config
;; (setq mu4e-maildir (expand-file-name "~/mbsync"))
;; (setq mu4e-sent-folder "/sent")
;; (setq mu4e-drafts-folder "/drafts")
;; (setq mu4e-trash-folder "/trash")
;; ;;GMail/IMAP takes care of this
;; (setq mu4e-sent-messages-behavior 'delete)
;; (setq mu4e-get-mail-command "mbsync -q gmail")
;; (setq mu4e-update-interval 3600)
;; (setq mu4e-maildir-shortcuts
;; '(("/INBOX" . ?i)
;; ("/sent" . ?s)))
;; (setq mu4e-view-show-images t)
;; (setq mu4e-use-fancy-chars t)
;; (setq mu4e-view-show-addresses t)
;; (setq mu4e-headers-show-threads nil)
;; )
;; (require 'smtpmail)
;; (setq message-send-mail-function 'smtpmail-send-it
;; user-mail-address "email_username@gmail.com"
;; smtpmail-smtp-user "email_username"
;; smtpmail-local-domain "gmail.com"
;; smtpmail-default-smtp-server "smtp.gmail.com"
;; smtpmail-smtp-server "smtp.gmail.com"
;; smtpmail-smtp-service 587)a second reference setup (works with outlook)
;; (use-package mu4e
;; :load-path "path/to/mu4e/lisp"
;; :bind (("C-c 2" . mu4e))
;; :custom
;; (mu4e-mu-home "/path/to/mu/index/if/not/homedir")
;; (mu4e-mu-binary "path/to/mu/binary/if/not/in/path")
;; (mu4e-sent-folder "/sent")
;; (mu4e-drafts-folder "/drafts")
;; (mu4e-trash-folder "/trash")
;; (mu4e-get-mail-command "mbsync -q work")
;; (mu4e-update-interval 180)
;; (mu4e-sent-messages-behavior 'delete)
;; (mu4e-maildir-shortcuts '(("/Inbox" . ?i) ("/sent" . ?s)))
;; :config
;; (setq mu4e-headers-show-threads nil)
;; (setq mail-user-agent 'mu4e-user-agent) ;C-x m uses mu4e
;; (progn ; SMTP
;; (require 'smtpmail)
;; (setq message-send-mail-function 'smtpmail-send-it
;; smtpmail-default-smtp-server "foo.com"
;; smtpmail-smtp-server "foo.com"))
;; (progn ; Calendar
;; (require 'mu4e-icalendar)
;; (mu4e-icalendar-setup)
;; (setq gnus-icalendar-org-capture-file "~/calendar.org"
;; gnus-icalendar-org-capture-headline '("calendar"))
;; (gnus-icalendar-org-setup)));; (use-package org-projectile
;; :ensure t
;; :after org
;; :custom
;; (org-projectile-capture-template "* TODO %^{title}\n%?")
;; :config
;; (add-to-list 'org-capture-templates (org-projectile-project-todo-entry :capture-heading "project todo")))
;; (use-package helm-org :ensure t)
;; (use-package org-projectile-helm
;; :ensure t
;; :after (org-projectile helm-org)); (use-package rmsbolt
; :disabled
; :ensure t); (use-package speed-type
; :ensure t
; :disabled
; :commands (speed-type-text));; (use-package stan-mode
;; :ensure t)
;; (use-package company-stan
;; :ensure t
;; :hook (stan-mode . company-stan-setup))
;; (use-package eldoc-stan
;; :ensure t
;; :hook (stan-mode . eldoc-stan-setup));; (use-package switch-window
;; :ensure t
;; :bind (("C-x o" . switch-window))
;; :config
;; (setq switch-window-shortcut-style 'qwerty)
;; (setq switch-window-qwerty-shortcuts '("a" "s" "d" "f" "j" "k" "l" "w" "e" "i" "o"))
; (setq switch-window-minibuffer-shortcut ?z))Telegram support from emacs (needs visual-fill-column)
; (use-package visual-fill-column :ensure t); (require 'notifications)
; (use-package telega
; :disabled
; :load-path "~/3rdParty/telega/"
; :commands (telega)
; :config
; (setq telega-use-notifications t)
; (add-hook 'telega-chat-mode-hook (lambda ()
; (setq company-backends '(telega-company-emoji))
; (company-mode 1)))
; :defer t)make line-mode the default for terms and allow bigger buffer size
; (setq term-buffer-maximum-size 262144)
; (defun ava/default-term-line-mode (&ret ignore) (term-line-mode))
; (advice-add 'ansi-term :after #'ava/default-term-line-mode)ansi-term defaults to bash
;(defvar my-term-shell "/bin/bash")
;(defadvice ansi-term (before force-bash)
; (interactive (list my-term-shell)))
;(ad-activate 'ansi-term)start a remote term https://www.emacswiki.org/emacs/AnsiTermHints#toc4
; (defun ava/raterm ()
; (interactive)
; (setq user (read-string "User: "))
; (setq host (read-string "Host: "))
; (setq term-ansi-buffer-name (concat "term " host))
; (setq term-ansi-buffer-name (generate-new-buffer-name term-ansi-buffer-name))
; (setq term-ansi-buffer-name (apply 'make-term term-ansi-buffer-name "ssh" nil (list (concat user "@" host))))
; (set-buffer term-ansi-buffer-name)
; (term-mode)
; (term-line-mode)
; (term-set-escape-char ?\C-x)
; (switch-to-buffer term-ansi-buffer-name)
; (insert "function set-eterm-dir { \n echo -e \"\\033AnSiTu\" \"$LOGNAME\" \n echo -e \"\\033AnSiTc\" \"$(pwd)\" \n echo -e \"\\033AnSiTh\" \"$(hostname -f)\" \n history -a \n }")
; (insert "\nPROMPT_COMMAND=set-eterm-dir\n")
; (term-send-input))start a few common terms
; (defun ava/start-ansi-terms ()
; "Start a few common ansi terms"
; (interactive)
; (let ((term-start-helper (lambda (name cmd)
; (ansi-term "/bin/bash" (format "bash.%s" name))
; (with-current-buffer (format "*bash.%s*" name)
; (insert (format "%s\n" cmd))
; (term-send-input)))))
; (save-window-excursion
; ;only shells for now
; (funcall term-start-helper "rand0" "")
; (funcall term-start-helper "rand1" "")
; (funcall term-start-helper "rand2" ""))))(this is built in as treesit after emacs 29)
https://emacs-tree-sitter.github.io/installation/
;; (use-package tree-sitter-langs :ensure t)
;; (use-package tree-sitter
;; :ensure t
;; :after tree-sitter-langs
;; :config
;; (global-tree-sitter-mode)
;; (add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode))reference: visual-fill-column (to center code in wide monitors)
; (defun ava/visual-fill-column-and-center ()
; (setq visual-fill-column-center-text t
; visual-fill-column-width 134)
; (visual-fill-column-mode 1))
;
; (use-package visual-fill-column
; :hook (prog-mode . ava/visual-fill-column-and-center))