1. Table of Contents
- init & globals
- input & security
- ui & themes
- bindings & interaction
- text & editing
- files & projects
- frames & windows & buffers & tabs
- utils
- org
- org
- org-babel
- capture templates
- keywords & tags
- evil-org
- org-agenda
- org-agenda custom commands
- org-agenda colorize clocks
- clock & notify
- org-journal
- org-gcal
- jira
- presentations
- calfw & calendar
- org-download
- org-images
- easydraw
- utilities
- plantuml
- gnuplot
- prettify
- others
- individual visibility
- personal configs
- prog
- system
- user
- custom
- simple.el
- provide
Available at https://github.com/thatwist/.emacs.d
2. init & globals
2.1. early-init.el
(setq byte-compile-docstring-max-column 250) ;; don't want those wider-then-80 warnings (if (and (fboundp 'native-comp-available-p) (native-comp-available-p)) (progn (message "Native compilation is available") (setq native-comp-async-report-warnings-errors nil) (setq comp-deferred-compilation t) (add-to-list 'native-comp-eln-load-path (expand-file-name "eln-cache/" user-emacs-directory)) (setq package-native-compile t)) (message "Native complation is *not* available")) (push (concat user-emacs-directory "lisp") load-path)
2.2. init.el
(require 'config) ;; native compilation gives only 0.2s init time boost.. nah ;;(load-library "config") ;;(load-file "~/.emacs.d/lisp/config.el") ;;(native-elisp-load (comp-lookup-eln (expand-file-name "lisp/config.el" user-emacs-directory))) ;;(setf native-comp-speed 2 native-comp-debug 0 native-comp-verbose 0 comp-libgccjit-reproducer nil comp-async-compilation t) ;;(setf native-comp-debug 0 native-comp-verbose 0) ;;(native-compile "/home/twist/.config/emacs/lisp/config.el") ;;(native-compile "~/.emacs.d/lisp/config.el")
2.3. messages ts
(defun my-message-with-timestamp (old-func fmt-string &rest args) "Prepend current timestamp (with microsecond precision) to a message" (when fmt-string ;; did this because of some vr/replace empty messages getting into echo area in minibuffer (apply old-func (concat (format-time-string "[%T.%3N] ") fmt-string) args))) (define-minor-mode message-ts-mode "Enable timestamp in messages." :lighter "" ;; " T" :global t (if message-ts-mode (advice-add 'message :around #'my-message-with-timestamp) (advice-remove 'message #'my-message-with-timestamp))) (with-eval-after-load 'pretty-hydra (pretty-hydra-define+ toggle-hydra nil ("Emacs" (("C-m" message-ts-mode "message-ts-mode" :toggle t)))))
2.4. dependency tree
(defvar my/require-tree nil) (defun require--advice (orig-fun feature &rest args) (setq my/require-tree (append my/require-tree (list (let ((my/require-tree (list feature))) (apply orig-fun feature args) my/require-tree))))) (advice-add 'require :around 'require--advice)
2.5. package management
2.5.1. package.el & load-path
(setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/") ;;("org" . "https://orgmode.org/elpa/") ("nongnu" . "https://elpa.nongnu.org/nongnu/") ("melpa" . "https://melpa.org/packages/") ("melpa-stable" . "http://stable.melpa.org/packages/") ) package-archive-priorities '( ("melpa-stable" . 5) ("nongnu" . 20) ("gnu" . 10) ("melpa" . 25))) ;; started using melpa first (require 'package) (package-initialize)
(push (concat user-emacs-directory "lisp") load-path)
2.5.2. use-package
(unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (require 'use-package) (setq ;; Enable ensure by default for use-package ;;use-package-always-ensure ;; actually, when using this + ensure-nil, macro still generates code - when using byte-compilation there will be warnings use-package-always-defer t use-package-compute-statistics t use-package-verbose 'debug use-package-minimum-reported-time 0 ;; I want to see order and timing ) (use-package use-package-ensure-system-package :ensure) (use-package system-packages :ensure)
2.5.3. benchmark-init
(use-package benchmark-init :disabled :ensure :demand :config ;; To disable collection of benchmark data after init is done. (add-hook 'after-init-hook 'benchmark-init/deactivate) )
2.5.4. quelpa
(use-package quelpa :ensure :demand :init (setq quelpa-update-melpa-p nil) (setq quelpa-checkout-melpa-p nil) (setq quelpa-update-melpa-p nil) (setq quelpa-update-melpa-p nil) (setq quelpa-upgrade-interval 7)) (use-package quelpa-use-package :ensure :demand :init (setq quelpa-use-package-inhibit-loading-quelpa t) :config (quelpa-use-package-activate-advice))
2.6. global vars & modes
(setq is-android (string= "Android" (string-trim (shell-command-to-string "uname -o")))) (use-package diminish :ensure :demand) ;; TODO - sort this (use-package emacs :demand :custom (user-full-name "Yuri Ostapchuk") (user-mail-address "twist522@gmail.com") ;; startup (inhibit-startup-message t) (initial-scratch-message "") (initial-buffer-choice nil) ;;(initial-major-mode 'fundamental-mode) ; I don't want to load prog-mode hooks ;;(setq debug-on-error t) (create-lockfiles nil) (make-backup-files nil) ;; editing ;;(show-paren-delay 0.5) (sentence-end-double-space nil) (save-interprogram-paste-before-kill t) ;; (mouse-yank-at-point t) (mouse-drag-copy-region t) ;; ui (global-hl-line-mode 1) ; highlight current line (fringe-mode 16) (size-indication-mode 1) ;; interaction (scroll-error-top-bottom t) (enable-recursive-minibuffers t) ;; experimental - minibuffer within minibuffer (browse-url-browser-function 'browse-url-default-browser) (eww-search-prefix "https://google.com/search?q=") :config ;; ui (menu-bar-mode -1) (tool-bar-mode -1) ;; for windows - easier integration with Dropbox/org paths (when (eq system-type 'window-nt) (setenv "HOME" "C:\\Users\\Admin")) ;; When running from containers I have annoyances with symbolic links ;; (when (eq system-type 'gnu/linux) (setenv "HOME" "/home/twist")) ;; for mac ;;(setq mac-option-modifier 'meta) ;;(setq mac-command-modifier 'super) (with-eval-after-load 'eldoc (diminish 'eldoc-mode "")) :hook (after-init . (lambda () ;; these stuff gets overwritten if run during init (tooltip-mode -1) (save-place-mode 1) ; remember file position in the visited previously file ;; ui (when (display-graphic-p) ;; (display-battery-mode 1) (set-scroll-bar-mode nil)) ;; interaction (auto-insert-mode t) ;; editing ;;(electric-indent-mode 0) ;; it makes indentations messy in org, I'm using org-indent-mode (delete-selection-mode 1) ;; omg how could I live without this - to remove selection (if active) when inserting text (global-so-long-mode 1) (eval-after-load 'prog-mode (show-paren-mode 1)) ;; todo - local? )))
2.7. context-menu
;; (global-set-key [(down-mouse-2)] 'menu-bar-open) ;; (global-set-key [double-down-mouse-3] 'mouse-yank-at-click) ;; (global-set-key [double-mouse-3] 'mouse-yank-at-click) ;; (global-set-key [down-mouse-3] 'context-menu-open) ;; (global-set-key [down-mouse-3] nil) ;; (define-key context-menu-mode-map [double-down-mouse-3] 'mouse-yank-at-click) ;; (define-key context-menu-mode-map [down-mouse-3] nil) (use-package mouse :demand :custom (context-menu-functions '(context-menu-undo context-menu-region context-menu-middle-separator context-menu-toolbar context-menu-global context-menu-local context-menu-minor context-menu-buffers context-menu-vc context-menu-ffap hi-lock-context-menu occur-context-menu Man-context-menu dictionary-context-menu)) (touch-screen-display-keyboard t) (touch-screen-precision-scroll t) :config (context-menu-mode 1) ;; https://ruzkuku.com/texts/emacs-mouse.html (require 'eww) (defun mouse-online-search-at-point (e) "Search for word at point or selection." (interactive "e") (let ((query (if (use-region-p) (buffer-substring (region-beginning) (region-end)) (save-excursion (mouse-set-point e) (thing-at-point 'symbol))))) (unless query (user-error "Nothing to search for")) (browse-url (concat eww-search-prefix (mapconcat #'url-hexify-string (split-string query) "+"))))) (defun context-menu-online-search (menu click) "Populate MENU with command to search online." (save-excursion (mouse-set-point click) (define-key-after menu [online-search-separator] menu-bar-separator) (define-key-after menu [online-search-at-mouse] '(menu-item "Online search" mouse-online-search-at-point :help "Search for region or word online"))) menu) (add-hook 'context-menu-functions #'context-menu-online-search) )
2.8. package menu
(use-package paradox :ensure)
2.9. benchmark
(use-package benchmark-init :ensure ;;:disabled ) ;; this package fails to compile
2.10. hydra init
(use-package posframe :ensure :defer 0.4) (use-package hydra :ensure) (use-package pretty-hydra :ensure :demand) (use-package hydra-posframe ;; :when (display-graphic-p) :demand :after (hydra posframe) :quelpa (hydra-posframe :fetcher github :repo "Ladicle/hydra-posframe") :config (hydra-posframe-mode) ;(setq hydra-hint-display-alist nil) ) (use-package major-mode-hydra :ensure :demand :after hydra :hook (evil-mode . (lambda () (evil-define-key 'motion global-map (kbd "<leader>m") 'major-mode-hydra))) :preface (defun with-alltheicon (icon str &optional height v-adjust) "Displays an icon from all-the-icon." (s-concat (all-the-icons-alltheicon icon :v-adjust (or v-adjust 0) :height (or height 1)) " " str)) (defun with-material (icon str &optional height v-adjust) "Displays an icon from material." (s-concat (all-the-icons-material icon :v-adjust (or v-adjust 0) :height (or height 1)) " " str)) (defun with-faicon (icon str &optional height v-adjust) "Displays an icon from Font Awesome icon." (s-concat (all-the-icons-faicon icon :v-adjust (or v-adjust 0) :height (or height 1)) " " str)) (defun with-fileicon (icon str &optional height v-adjust) "Displays an icon from the Atom File Icons package." (s-concat (all-the-icons-fileicon icon :v-adjust (or v-adjust 0) :height (or height 1)) " " str)) (defun with-octicon (icon str &optional height v-adjust) "Displays an icon from the GitHub Octicons." (s-concat (all-the-icons-octicon icon :v-adjust (or v-adjust 0) :height (or height 1)) " " str)))
2.11. profiling
; find bug in init.el (use-package bug-hunter :ensure :disabled) ;(setq ;garbage-collection-messages t ; see when gc happens ; gc-cons-threshold #x40000000 ; gc-cons-percentage 0.3 ;) (defmacro k-time (&rest body) "Measure and return the time it takes evaluating BODY." `(let ((time (current-time))) ,@body (float-time (time-since time)))) ; When idle for 15sec run the GC no matter what. (defvar k-gc-timer (run-with-idle-timer 15 t (lambda () (message "Garbage Collector has run for %.06fsec" (k-time (garbage-collect)))))) ; startup profiler (use-package esup :ensure :commands (esup)) ;; esup, didn't work, trying this: ;; workaround chemacs: ;; mv .emacs.d .emacs.d.tmp ;; ln -s .config/emacs .emacs.d ;; emacs -Q -l /home/twist/.config/emacs/lisp/profile-dotemacs.el --eval "(progn (setq user-emacs-directory \"~/.config/emacs/\") (profile-dotemacs))" ;; rm .emacs.d ;; mv .emacs.d.tmp .emacs.d ; startup time (defun my/display-startup-time () (message "Emacs loaded in %s with %d garbage collections." (format "%.2f seconds" (float-time (time-subtract after-init-time before-init-time))) gcs-done)) (add-hook 'emacs-startup-hook #'my/display-startup-time) (defun byte-recompile-init-file () "Byte-recompile user init files." (interactive) (byte-recompile-file (concat user-emacs-directory "lisp/config.el")) (message (format "byte-compile finished")) ;; this doesn't work - subprocess needs correct load-path being populated ;; (async-start ;; `(lambda () (require 'bytecomp) (byte-recompile-file ,out-file) ,out-file) ;; `(lambda (result2) ;; (message (format "byte-recompile finished for: %s" result2)))) )
2.12. safe vars
(setq safe-local-variable-values '( (eval add-hook 'after-save-hook (lambda nil (my/tangle-async)) nil t) (eval add-hook 'after-save-hook (lambda nil (my/tangle-async-and-byte-compile-init-file)) nil t) (org-archive-location . "~/Dropbox/org/archive/%s_archive.gpg::") (org-tags-column . -65) (eval setq org-cycle-include-plain-lists 'integrate) (eval load-file "ledger-kredo-regex.el.gpg") (doom-modeline-buffer-file-name-style . truncate-with-project) (doom-modeline-buffer-file-name-style quote truncate-with-project) (org-hugo-footer . " [//]: # \"Exported with love from a post written in Org mode\" [//]: # \"- https://github.com/kaushalmodi/ox-hugo\"") (checkdoc-minor-mode . t) (flycheck-disabled-checkers emacs-lisp-checkdoc) (eval visual-line-mode t)) ; tramp theme custom-safe-themes '("6ebdb33507c7db94b28d7787f802f38ac8d2b8cd08506797b3af6cdfd80632e0" default) )
2.13. feature checks
(if (functionp 'json-serialize) (message "Native JSON is available") (message "Native JSON is *not* available"))
2.14. native & byte comp
2.15. server
;; (server-start)
2.16. elisp tools
2.16.1. debug hooks
this tools for debugging hooks came from here – https://emacs.stackexchange.com/a/19582/29202
(defun my/call-logging-hooks (command &optional verbose) "Call COMMAND, reporting every hook run in the process. Interactively, prompt for a command to execute. Return a list of the hooks run, in the order they were run. Interactively, or with optional argument VERBOSE, also print a message listing the hooks." (interactive "CCommand to log hooks: \np") (let* ((log nil) (logger (lambda (&rest hooks) (setq log (append log hooks nil))))) (my/with-advice ((#'run-hooks :before logger)) (call-interactively command)) (when verbose (message (if log "Hooks run during execution of %s:" "No hooks run during execution of %s.") command) (dolist (hook log) (message "> %s" hook))) log)) (defmacro my/with-advice (adlist &rest body) "Execute BODY with temporary advice in ADLIST. Each element of ADLIST should be a list of the form (SYMBOL WHERE FUNCTION [PROPS]) suitable for passing to `advice-add'. The BODY is wrapped in an `unwind-protect' form, so the advice will be removed even in the event of an error or nonlocal exit." (declare (debug ((&rest (&rest form)) body)) (indent 1)) `(progn ,@(mapcar (lambda (adform) (cons 'advice-add adform)) adlist) (unwind-protect (progn ,@body) ,@(mapcar (lambda (adform) `(advice-remove ,(car adform) ,(nth 2 adform))) adlist))))
2.16.2. eval-after-all
(defun eval-after-load-all (my-features form) "Run FORM after all MY-FEATURES are loaded. See `eval-after-load' for the possible formats of FORM." (if (null my-features) (if (functionp form) (funcall form) (eval form)) (eval-after-load (car my-features) `(lambda () (eval-after-load-all (quote ,(cdr my-features)) (quote ,form))))))
2.16.3. save/read variables into file
(defun my/dump-vars-to-file (varlist filename) "simplistic dumping of variables in VARLIST to a file FILENAME" (save-excursion (let ((buf (find-file-noselect filename))) (set-buffer buf) (erase-buffer) (my/dump-vars varlist buf) (save-buffer) (kill-buffer)))) (defun my/dump-vars (varlist buffer) "insert into buffer the setq statement to recreate the variables in VARLIST" (cl-loop for var in varlist do (print (list 'setq var (list 'quote (symbol-value var))) buffer)))
2.16.4. eldoc
(with-eval-after-load 'elisp-mode (defadvice elisp-get-fnsym-args-string (after add-docstring activate compile) "Add a 1st line of docstring to ElDoc's function information." (when ad-return-value (let* ((doc (elisp--docstring-first-line (documentation (ad-get-arg 0) t))) (w (frame-width)) (color-doc (propertize doc 'face 'font-lock-comment-face))) (when (and doc (not (string= doc ""))) (setq ad-return-value (concat ad-return-value " " color-doc)) (when (> (length doc) w) (setq ad-return-value (substring ad-return-value 0 (1- w)))))) ad-return-value)))
2.16.5. other tools
;; why isn't it a part of standart lib (defun delete-from-alist-by-key (list-var elem) "Interactively remove element from alist." (interactive (let ((var (helpful--read-symbol "Variable: " (helpful--variable-at-point) #'(lambda (symb) (and (boundp symb) (listp (symbol-value symb)) (helpful--variable-p symb)))))) (list var (completing-read "Choose element to delete from: " (symbol-value var) nil t)))) (message "deleting %s from %s=%s" elem list-var (symbol-value list-var)) (set list-var (assoc-delete-all elem (symbol-value list-var))))
3. input & security
3.1. input & langs
;; input method (setq default-input-method "ukrainian-computer") ;; free binding for iedit (customize-set-variable 'flyspell-auto-correct-binding [(meta control ?\;)]) (customize-set-variable 'flyspell-mode-line-string " FS") ;; turn it manually on demand ;;(add-hook 'text-mode-hook #'flyspell-mode) (when (eq system-type 'windows-nt) (with-eval-after-load "ispell" (setq ispell-dictionary "en_US") (setq ispell-hunspell-dictionary-alist '( ("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" t ("-d" "en_US") nil utf-8) ;; TODO - doesn't work ;;(setenv "LANG" "en_US.UTF-8") ;;(setq ispell-dictionary "uk_UA,en_US") ;;(setq ispell-hunspell-dictionary-alist '(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" t ("-d" "en_US") nil utf-8) ;; ("uk_UA" "[[:alpha:]]" "[^[:alpha:]]" "[']" t ("-d" "uk_UA") nil utf-8) ;; )) ;;(ispell-set-spellchecker-params) ;;(ispell-hunspell-add-multi-dic "uk_UA,en_US") )))) ;(set-language-environment "UTF-8") (set-default-coding-systems 'utf-8)
3.2. clipboard
;; clipboard share with x11 (use-package xclip :ensure :if window-system :unless (eq system-type 'windows-nt) :defer 1 :config (xclip-mode 1))
3.3. sessions
(use-package desktop ;; :init (desktop-save-mode 1) :custom ((desktop-modes-not-to-save '(tags-table-mode org-mode helpful-mode)) ;;(desktop-files-not-to-save "\\(\\`/[^/:]*:\\|(ftp)\\|(\\.gz)\\'\\)") (desktop-files-not-to-save ".*") (desktop-load-locked-desktop t) ; do not ask that lock-file exists, this fixes the issue with daemon wait answer (desktop-buffers-not-to-save ".*")) ;; actually, I dont' want it to save any buffers ) (use-package super-save :ensure :diminish :defer 1.1 :config ;; add integration with ace-window ;;(add-to-list 'super-save-triggers 'ace-window) (add-to-list 'super-save-triggers 'ivy-switch-buffer) (add-to-list 'super-save-triggers 'tab-line-switch-to-next-tab) (add-to-list 'super-save-triggers 'tab-line-switch-to-prev-tab) (add-to-list 'super-save-triggers 'tab-line-next-tab-cycle) (add-to-list 'super-save-triggers 'tab-line-prev-tab-cycle) ;; save on find-file (add-to-list 'super-save-hook-triggers 'find-file-hook) ;; after list change (super-save-mode +1) :custom ;; these are actually global configs, but I keep them under super-save (backup-directory-alist `(("." . ,(expand-file-name (concat user-emacs-directory "backups"))))) (auto-save-file-name-transforms `((".*" ,(concat user-emacs-directory "auto-save/") t))) (super-save-idle-duration 20) (super-save-auto-save-when-idle t))
3.4. accessibility
;(load-file "/usr/share/festival/festival.el") ;(autoload 'say-minor-mode "festival" "Menu for using Festival." t) ;(say-minor-mode t)
3.5. security & encryption
;;(add-hook 'after-init-hook ;; #'(lambda() ;; (require 'epa-file) ;; (epa-file-enable))) ;;(use-package epa ;; :defer t ;; :custom ;; (epg-gpg-program "gpg") ;; (epa-pinentry-mode nil)) (use-package epg :config (setq epg-pinentry-mode 'loopback)) ;; used for prompts on gpg - if pinentry program = emacs (use-package pinentry :ensure) ;; This should force Emacs to use its own internal password prompt instead of an external pin entry program (setenv "GPG_AGENT_INFO" nil) ;; password store (use-package password-store :ensure :config (when (eq system-type 'windows-nt) (setq password-store-executable (executable-find "pass.bat")))) (use-package pass :ensure) (use-package auth-source-pass :disabled :demand :after auth-source :config (auth-source-pass-enable) ) ;; was used until auth-source-pass came ;;(setq auth-sources '("~/.authinfo.gpg" "~/.netrc")) ;; when preserving emacs buffers between sessions, ;; close buffers which may ask for user input (decryption password) ;; on the next startup and would prevent emacs-server to start in backgroud (add-hook 'kill-emacs-hook (lambda() (save-some-buffers t) (kill-matching-buffers ".*.gpg" nil t) (kill-matching-buffers "ejc-sql-editor" nil t) ;; this may ask for authinfo on next load ))
3.6. edit-server
;; edit server for chrome plugin (use-package edit-server :disabled :ensure :commands edit-server-start ;;:init ;; (add-hook 'after-init-hook ;; #'(lambda() (edit-server-start)))) :config (setq edit-server-new-frame-alist '((name . "Edit with Emacs FRAME") (top . 200) (left . 200) (width . 80) (height . 25) (minibuffer . t) (menu-bar-lines . t) (window-system . x))))
4. ui & themes
4.1. fonts
;; set default (if (eq system-type 'windows-nt) (set-face-attribute 'default nil :font "Fira Mono" :height 114) ;; defaults to 139 (set-face-attribute 'default nil :font "Input Mono Narrow" :height 112)) ;; (if (eq system-type 'windows-nt) ;; (set-face-attribute 'default nil :font "Fira Mono" :height 114) ;; defaults to 139 ;; (set-face-attribute 'default nil :font "Fira Mono" :height 114) ;; defaults to 139 ;; ;; ;; ;;(set-face-attribute 'default nil :font "Source Code Pro-11") ;; ;; equivalent ;; ;;(add-to-list 'default-frame-alist '(font . "Input Mono Narrow-9")) ;; ;;(add-to-list 'default-frame-alist '(font . "Source Code Pro-10")) ;; ) ;(set-face-attribute 'bold nil :height 95) ;; good way to emphasize ;(set-face-attribute 'default nil :font "Input Mono Narrow" :height 95) ;;(set-face-attribute 'default nil :font "Source Code Pro" :height 150) ;; defaults to 139 ;;(set-face-attribute 'default nil :font "Source Code Pro Medium") ;; equivalent of ;;(set-frame-font "Source Code Pro Medium" nil t) ;; or use M-x menu-set-font, or use M-x set-frame-font ;; testing ;;(set-fontset-font t 'latin "Noto Sans") ;; something for icons? (setq inhibit-compacting-font-caches t)
4.2. frame alpha
(if (eq system-type 'windows-nt) (add-to-list 'default-frame-alist '(alpha . (98 . 98))) (add-to-list 'default-frame-alist '(alpha . (98 . 98)))) (defun frame-update-alpha (updfunc) "Apply a given function to existing alpha parameter of the selected frame. UPDFUNC function which accepts current alpha and returns new" (when (functionp updfunc) (let* ((current-alpha (car (frame-parameter nil 'alpha))) (new-alpha (funcall updfunc current-alpha)) (new-alpha (min 100 (max 0 new-alpha)))) (set-frame-parameter (selected-frame) 'alpha (list new-alpha new-alpha))))) (defun frame-incr-alpha () "Increment existing frame alpha by 3." (interactive) (frame-update-alpha (lambda (alpha) (+ alpha 3)))) (defun frame-decr-alpha () "Decrement existing frame alpha by 3." (interactive) (frame-update-alpha (lambda (alpha) (- alpha 3))))
4.3. icons
(use-package all-the-icons :ensure :demand) (use-package nerd-icons :ensure :demand) ;; bad with hidpi - icons modeline ;;(use-package mode-icons :config (mode-icons-mode -1)) ;; in terminal (but it actually doesn't work for doom-modeline) (use-package icons-in-terminal :quelpa (icons-in-terminal :fetcher github :repo "seagle0128/icons-in-terminal.el") )
4.4. modeline
;; (nerd-icons-install-fonts) (use-package doom-modeline :ensure :defer 0.1 :config (doom-modeline-mode) :custom ((column-number-mode t) ;; these will hardcode height and zoom-frm will not work for mode-line ;;(set-face-attribute 'mode-line nil :height 90) ;;(set-face-attribute 'mode-line-inactive nil :height 50) (doom-modeline-height 25) (doom-modeline-bar-width 6) (doom-modeline-workspace-name nil) ;; tab-bar-mode displays this in the top (doom-modeline-indent-info t) (doom-modeline-window-width-limit 140) ; works for: ;(window-font-width nil 'mode-line) ; 20 ;(window-font-height nil 'mode-line) ; 42 ;; scala projects may have very long file paths, in that case doommodeline doesn't truncate it ;;:custom (doom-modeline-buffer-file-name-style 'truncate-with-project) (doom-modeline-minor-modes t) (doom-modeline-modal-icon t) ;; its better with nerd-icons now (doom-modeline-major-mode-icon t) (doom-modeline-buffer-state-icon t) )) ;; nice (use-package minions :ensure :defer 1 :config (global-set-key [S-down-mouse-3] 'minions-minor-modes-menu))
4.5. themes
(use-package gruvbox-theme :ensure :defer 0.1 :init (defvar my/toggle-dark t) (defun my/tab-line--set-faces () (custom-set-faces `(tab-line-tab-inactive ((t (:background ,gruvbox-bg :foreground ,gruvbox-light0)))) `(tab-line-tab ((t (:background ,gruvbox-dark2 :foreground ,gruvbox-light0)))) `(tab-line ((t (:background ,gruvbox-bg :foreground ,gruvbox-light0)))) `(tab-line-highlight ((t (:inherit (tab-line-tab))))) ;; mouseover `(tab-line-tab-current ((t (:extend t :background ,gruvbox-dark2 :foreground ,gruvbox-light0 :weight bold ;;:underline t :box '(:line-width (1 . 1) :style released-button))))))) (defun my/load-dark-theme () (mapc #'disable-theme custom-enabled-themes) (load-theme 'gruvbox-dark-hard t) ;; can't find a way to get those colors from the theme def itself (let* ((gruvbox-dark0_hard "#1d2021") (gruvbox-dark2 "#504945") (gruvbox-light0 "#fdf4c1") (gruvbox-bg gruvbox-dark0_hard)) (my/tab-line--set-faces))) (defun my/load-light-theme () (mapc #'disable-theme custom-enabled-themes) (load-theme 'gruvbox-light-soft t) (let* ((gruvbox-dark0_soft "#f2e5bc") (gruvbox-dark2 "#d5c4a1") (gruvbox-light0 "#282828") (gruvbox-bg gruvbox-dark0_soft)) (my/tab-line--set-faces))) (defun my/toggle-light-dark () (interactive) (if (eq (car custom-enabled-themes) 'gruvbox-light-soft) (progn (my/load-dark-theme) (setq my/toggle-dark t)) (progn (my/load-light-theme) (setq my/toggle-dark nil)))) :config ;;(load-theme 'gruvbox-dark-medium t) (my/load-dark-theme) ) (use-package doom-themes :ensure :init (defun my/restore-mode-line () "Restore modeline after doom-themes ding, sometimes it gets stuck into doom-modeline-error state" (interactive) (setq face-remapping-alist (delete (assq 'mode-line face-remapping-alist) face-remapping-alist))) :defer 0.1 :config ;(load-theme 'doom-one t) ;(load-theme 'doom-gruvbox t) (doom-themes-visual-bell-config) ;(doom-themes-neotree-config) ;(doom-themes-treemacs-config) (doom-themes-org-config) :custom (doom-themes-enable-bold t) (doom-themes-enable-italic t))
4.6. theme auto changers
;; todo - doesn't work ;; (use-package theme-changer ;; :config ;; (setq calendar-location-name "Dallas, TX") ;; (setq calendar-latitude 32.85) ;; (setq calendar-longitude -96.85) ;; (change-theme nil 'dracula-theme) ;; ) ;(use-package modus-operandi-theme) ;(use-package modus-vivendi-theme) ;; Define coordinates ;(setq calendar-latitude 49.784443 ; calendar-longitude 24.056473) ;; Light at sunrise ;(load-theme 'modus-operandi t t) ;(run-at-time (nth 1 (split-string (sunrise-sunset))) ; (* 60 60 24) ; (lambda () ; (enable-theme 'modus-operandi))) ;;; Dark at sunset ;(load-theme 'modus-vivendi t t) ;(run-at-time (nth 4 (split-string (sunrise-sunset))) ; (* 60 60 24) ; (lambda () ; (enable-theme 'modus-vivendi)))
4.7. dashboard
(use-package dashboard :disabled :unless (eq system-type 'windows-nt) ;; it takes a lot of time on windows :ensure :demand ;:defer 0.9 :init (defun dashboard-performance-statement (list-size) (insert (propertize " Think" 'face 'dashboard-heading)) (insert (propertize "\n\t★ SLEEP\n\t★ ROUTINE\n\t★ NUTRITION\n\t★ SPORT\n\t★ REST" 'face '(:height 110)))) :custom ((dashboard-banner-logo-title "With Great Power Comes Great Responsibility") (dashboard-startup-banner 'official) ;; 1,2,3,'logo,'official (dashboard-center-content t) (dashboard-items '((performance) )) ;(elfeed . 10) (agenda . 5) (recents . 5) (projects . 5) (bookmarks . 5) (registers . 5) (dashboard-set-file-icons t) (dashboard-set-heading-icons t) (dashboard-set-init-info t) (dashboard-set-navigator t)) :config (add-to-list 'dashboard-item-generators '(performance . dashboard-performance-statement)) ;;(add-to-list 'dashboard-item-generators '(elfeed . dashboard-elfeed)) (dashboard-setup-startup-hook) ;; this is for emacsclient ;;(setq initial-buffer-choice (lambda () (get-buffer "*dashboard*"))) )
4.8. other faces
(custom-set-faces '(region ((t (:extend t :background "dark slate blue"))))) ;;(custom-set-faces '(fringe ((t (:background "#282828" :weight extra-bold :height 3.0 :width extra-expanded))))
4.9. auto dim inactive buffer
(use-package auto-dim-other-buffers :ensure :defer 0.7 :disabled ;; bug :config (auto-dim-other-buffers-mode t)) (use-package dimmer :ensure :config (dimmer-configure-which-key) (dimmer-configure-company-box) (dimmer-configure-hydra) (dimmer-configure-magit) (dimmer-configure-org) (dimmer-configure-posframe) ;; (dimmer-mode t) (add-to-list 'dimmer-buffer-exclusion-regexps "^ \\*lsp-ui-doc.*\\*$") :custom (dimmer-adjustment-mode :both) (dimmer-use-colorspace :cielab) (dimmer-fraction 0.25))
5. bindings & interaction
5.1. general.el
;; some problem with use-package and \" probably (with-eval-after-load 'general (general-define-key :states '(normal visual motion) :keymaps 'override "C-\"" (general-simulate-key "<leader>"))) (use-package general :ensure :demand :after evil :config (general-evil-setup) (general-imap "k" (general-key-dispatch 'self-insert-command :timeout 0.1 "j" 'evil-escape "m" (general-simulate-key "RET"))) (general-imap "л" (general-key-dispatch 'self-insert-command :timeout 0.05 ;; "о" 'evil-escape ;; cyrillic "j" 'evil-escape ;; when it dispatches it actually handles 'j' (as "о" translates into it) ;; "ь" (general-simulate-key "RET") "m" (general-simulate-key "RET") )) ;; ;; todo - try for 'override keymap to make it generic? (advice-add 'evil-collection-ivy-setup :after #'(lambda (&rest r) (general-nmap :keymaps 'ivy-minibuffer-map "k" (general-key-dispatch 'ivy-previous-line :timeout 0.1 "j" 'evil-escape "m" 'ivy-done)) )) ;; trick to exit from god-mode using kj same way (general-def god-local-mode-map "k" (general-key-dispatch (general-simulate-key "C-k") :timeout 0.1 "j" 'keyboard-quit)) ;;evil-normal-state (general-imap "M-," 'god-execute-with-current-bindings) ;; todo - cannot make this work (dispatches ',m' as two keys so god exits on ','?) ;; (general-imap "," ;; (general-key-dispatch 'self-insert-command ;; :timeout 0.1 ;; "m" 'god-execute-with-current-bindings)) )
5.2. god
(use-package god-mode :after general evil :ensure :demand :diminish god-local-mode :config (with-eval-after-load 'which-key (which-key-enable-god-mode-support)) ;; (defun my-god-mode-update-cursor-type () ;; (setq cursor-type (if (or god-local-mode buffer-read-only) 'hollow 'box))) ;; (add-hook 'post-command-hook #'my-god-mode-update-cursor-type) :general (:states '(visual normal motion) "," 'god-execute-with-current-bindings) (:keymaps 'god-local-mode-map "i" #'god-local-mode) (:keymaps 'god-local-mode-map "," #'keyboard-quit) )
5.3. ivy
(use-package prescient :ensure :preface (declare-function prescient-persist-mode "prescient") ;:functions (prescient-persist-mode) :config (prescient-persist-mode t) :custom (prescient-filter-method '(literal regexp initialism)) (prescient-sort-full-matches-first t)) (use-package amx :ensure)
(use-package counsel :pin melpa :ensure :demand :after ivy :functions counsel-mode :diminish :config (counsel-mode) (with-eval-after-load 'ivy ;; some stupid order of init? (run-with-idle-timer 1 nil #'(lambda () (diminish 'counsel-mode nil)))) :custom (counsel-mode-override-describe-bindings nil) :bind (("M-y" . counsel-yank-pop) ("M-Y" . counsel-evil-registers))) (global-set-key (kbd "M-x") 'counsel-M-x) (global-set-key (kbd "C-x C-f") 'counsel-find-file)
(use-package ivy-prescient :ensure :disabled :demand :after ivy prescient ;:config (ivy-prescient-mode) ; annoying - I need to find how to configure it :custom (ivy-prescient-sort-commands '(:not swiper swiper-isearch ivy-switch-buffer)))
(use-package ivy :ensure :after evil-collection :diminish :bind (("C-c C-r" . ivy-resume) ("C-x b" . ivy-switch-buffer) ("C-x B" . ivy-switch-buffer-other-window) ("C-c v" . ivy-push-view) ("C-c V" . ivy-pop-view) ("<s-up>" . ivy-push-view) ("<s-S-up>" . ivy-pop-view) ("<s-down>" . ivy-switch-view) (:map ivy-minibuffer-map ("C-c C-c" . hydra-ivy/body))) :custom (ivy-extra-directories '("../" "./")) (ivy-count-format "(%d/%d) ") (ivy-use-virtual-buffers t) :config (ivy-mode) (setq ivy-re-builders-alist '( (ivy-switch-buffer . ivy--regex-fuzzy) ;; be careful with fuzzy - grep command doesn't like the transformed query (counsel-projectile-grep . ivy--regex-plus) (counsel-projectile-ag . ivy--regex-plus) (counsel-projectile-rg . ivy--regex-plus) (counsel-rg . ivy--regex-plus) (counsel-ag . ivy--regex-plus) (counsel-git-grep . ivy--regex-plus) (swiper . ivy--regex-plus) (swiper-isearch . ivy--regex-plus) (t . ivy--regex-fuzzy))) (with-eval-after-load 'evil-collection ;; all fuzzy init ;;(setq ivy-initial-inputs-alist nil) (evil-collection-ivy-setup) ;; todo - <spc> is not a prefix key ;;(evil-collection-define-key 'normal 'ivy-minibuffer-map (kbd "<SPC> <SPC>") 'ivy-done) (evil-collection-define-key 'normal 'ivy-minibuffer-map (kbd "C-f") 'ivy-scroll-up-command) ; this is very missing in evil-collection (evil-collection-define-key 'normal 'ivy-minibuffer-map (kbd "C-b") 'ivy-scroll-down-command)) ) (use-package find-file-in-project :ensure) ;;required by ivy?
(use-package ivy-hydra :ensure :after ivy) (defun ivy-rich-switch-buffer-icon (candidate) (with-current-buffer (get-buffer candidate) (let ((icon (all-the-icons-icon-for-mode major-mode))) (if (symbolp icon) (all-the-icons-icon-for-mode 'fundamental-mode) icon)))) (use-package ivy-rich :ensure :pin melpa :demand :after counsel ivy :custom (ivy-virtual-abbreviate 'full ivy-rich-switch-buffer-align-virtual-buffer t ivy-rich-path-style 'abbrev) (ivy-rich-display-transformers-list '(ivy-switch-buffer (:columns ( (ivy-rich-switch-buffer-icon (:width 2)) (ivy-rich-candidate (:width 30)) (ivy-rich-switch-buffer-size (:width 7)) (ivy-rich-switch-buffer-indicators (:width 4 :face error :align right)) (ivy-rich-switch-buffer-major-mode (:width 12 :face warning)) (ivy-rich-switch-buffer-project (:width 15 :face success)) (ivy-rich-switch-buffer-path (:width (lambda (x) (ivy-rich-switch-buffer-shorten-path x (ivy-rich-minibuffer-width 0.3))))) ) :predicate (lambda (cand) (get-buffer cand))))) :config (ivy-rich-mode 1) (ivy-rich-project-root-cache-mode 1) ;; speed-up ) (use-package nerd-icons-ivy-rich :ensure :demand :after ivy-rich nerd-icons :init (nerd-icons-ivy-rich-mode 1) (run-with-idle-timer 1 nil #'nerd-icons-ivy-rich-reload) ;; omg why do I need this ) (use-package all-the-icons-ivy-rich :ensure :demand :after ivy-rich all-the-icons :disabled ;;nerds :config (all-the-icons-ivy-rich-mode 1)) (use-package all-the-icons-ivy :ensure :disabled ;; nerds :demand :after all-the-icons ivy-rich :config ;; (require 'all-the-icons) (setq all-the-icons-ivy-file-commands '(counsel-find-file counsel-file-jump counsel-recentf counsel-projectile-find-file counsel-projectile-find-dir)) (all-the-icons-ivy-setup) ) ; why :bind doesn't work? (global-set-key (kbd "C-s") 'swiper) (use-package swiper :ensure :after ivy :bind* ("C-s" . swiper)) (use-package ivy-posframe :ensure :custom (ivy-posframe-display-functions-alist '((swiper . ivy-posframe-display-at-point) (counsel-M-x . ivy-posframe-display-at-window-bottom-left) (t . ivy-posframe-display-at-frame-center))) )
5.4. helpers & info
(use-package which-key :ensure :after evil :defer 0.6 :diminish :custom (which-key-add-column-padding 0) (which-key-allow-evil-operators t) (which-key-max-description-length 50) (which-key-idle-delay 0.7) (which-key-show-operator-state-maps t) (which-key-side-window-max-height 0.4) :config (which-key-mode) (evil-define-key '(normal motion visual) global-map "?" 'which-key-show-full-major-mode)) (use-package which-key-posframe ;; :when (display-graphic-p) :ensure :demand :after which-key evil :config (which-key-posframe-mode)) (use-package helpful :ensure :after evil general :general (:states 'motion "<leader>h" 'hydra-help/body) (:states '(normal motion visual) :keymaps '(help-mode-map helpful-mode-map) "q" 'quit-window-kill-buffer) ;; I don't want dangling helpful buffers :commands (hydra-help/body) :custom (help-window-select t) ;; these are not from helpful but here is the place (describe-bindings-outline t) (apropos-do-all t) :config ;; fix this annoying popping help buffers ;; possible, but doesn't work if I navigate elisp after help in that window ;; (add-to-list 'display-buffer-alist ;; '("\\*helpful" . (display-buffer-reuse-mode-window . ((mode . (helpful-mode)))))) ;; this one is fine but doesn't quite work when from treemacs buffer in multiple tabs ;; from https://emacs.stackexchange.com/questions/50650/how-to-display-help-buffers-below-one-specific-window (add-to-list 'display-buffer-alist '("\\*helpful" ;; see https://www.gnu.org/software/emacs/manual/html_node/elisp/Displaying-Buffers-in-Side-Windows.html (display-buffer-reuse-window display-buffer-in-side-window) ;; see https://www.gnu.org/software/emacs/manual/html_node/elisp/Buffer-Display-Action-Alists.html (side . bottom) (slot . 0) ; in the middle bottom (window-height . 0.5) (reusable-frames . nil))) :bind ;; in terminal C-h is basically a backspace (("C-c C-h" . help-command) ("C-h f" . helpful-callable) ("C-h v" . helpful-variable) ("C-h k" . helpful-key) ;; ("C-h C-b" . describe-prefix-bindings) ; it is actuall works like that: press C-h after prefix key ("C-h j" . helpful-at-point) ("C-h F" . helpful-function) ("C-h C" . helpful-command) ("C-h M-m" . helpful-macro)) ;;todo - use general? ;;("C-h" . help-hydra/body) :pretty-hydra (hydra-help (:color teal :quit-key "q" :title (with-faicon "stethoscope" "Help" 1 -0.05)) ("Functions & Variables" (("f" helpful-callable "callable") ("v" helpful-variable "variable") ("j" helpful-symbol "symbol") ("c" helpful-command "command") ("h" helpful-at-point "at-point") ("F" helpful-function "function") ("M" helpful-macro "macro") ("l" apropos-local-value "local value") ("M-l" apropos-local-variable "local variable")) "Info, Pkgs, Other" (("I" counsel-info-lookup-symbol "counsel info symbol") ("i" info-lookup-symbol "info symbol") ("r" info-emacs-manual "emacs info") ("R" info-display-manual "pick info") ("p" describe-package "package") ("L" counsel-find-library "library") ("P" counsel-package "counsel pkg") ("uf" counsel-describe-face "describe face") ("uF" counsel-faces "faces")) "Keys & Bindings" (("k" helpful-key "key") ("C-k" describe-key-briefly "key brief") ("m" describe-mode "mode") ("M-m" describe-minor-mode "minor mode") ("b" describe-bindings "bindings") ("B" counsel-descbinds "counsel binds") ("M-k" describe-keymap "keymap") ("E" evil-collection-describe-bindings "evil-collection") ("C-l" view-lossage) ("C-c" list-command-history "command history") ("M-K" describe-personal-keybindings "personal bind-keys") ("wk" which-key-show-full-keymap "full keymap") ("wM" which-key-show-full-major-mode "full major") ("wm" which-key-show-full-minor-mode-keymap "full minor"))))) ;;(use-package discover-my-major) ;; not very helpful (use-package info+ :unless (eq system-type 'windows-nt) :requires bookmark+ ;; :disabled ;; requires bmkp, which requires something else that doesn't work in 29.1 :demand :after info evil-collection bookmark+ :quelpa (info+ :fetcher wiki) :config (general-def :states '(motion normal visual insert) :keymaps 'Info-mode-map "M-h" 'tab-line-prev-tab-cycle)) (use-package info-colors :ensure :hook (Info-selection . info-colors-fontify-node)) (use-package keyfreq :ensure) (use-package ace-link :ensure :general (:keymaps 'Info-mode-map :modes 'normal "o" 'ace-link-info))
5.5. other
(unless is-android (use-package back-button :ensure :demand :diminish ;; " <" :general ;; (:keymaps '(evil-normal-state-map) ;; "C-o" 'back-button-global-backward ;; "C-i" 'back-button-global-forward) ;; ("M-<left>" 'back-button-local-backward ;; "M-<right>" 'back-button-local-forward ;; "M-S-<left>" 'back-button-global-backward ;; "M-S-<right>" 'back-button-global-forward) ("C-<" 'back-button-local-backward "C->" 'back-button-local-forward "C-S-<" 'back-button-global-backward "C-S->" 'back-button-global-forward) :config (back-button-mode 1) )) (with-eval-after-load 'general (general-def 'motion "gX" 'browse-url-of-file)) ;; testing (use-package better-jumper :ensure :after evil :custom (better-jumper-use-evil-jump-advice t) :config (better-jumper-mode +1) (with-eval-after-load 'evil-maps (define-key evil-motion-state-map (kbd "C-o") 'better-jumper-jump-backward) (define-key evil-motion-state-map (kbd "C-i") 'better-jumper-jump-forward))) (use-package nerd-icons-completion :ensure :after nerd-icons)
5.6. evil
(use-package evil :ensure :defer 0.2 :init (setq evil-want-C-i-jump nil) ;; these 2 are for evil-collection (setq evil-want-integration t) ;; This is optional since it's already set to t by default. (setq evil-want-keybinding nil) (global-unset-key (kbd "C-z")) :config (evil-mode) (evil-set-leader 'motion (kbd "<SPC>")) (evil-set-leader 'insert (kbd "s-,")) (add-to-list 'evil-emacs-state-modes 'debugger-mode) (define-key prog-mode-map [(double-mouse-1)] 'evil-goto-definition) ;; amazing (when (display-graphic-p) (define-key input-decode-map [(control ?i)] [control-i]) (define-key input-decode-map [(control ?I)] [(shift control-i)]) (define-key evil-motion-state-map [tab] nil) (define-key evil-motion-state-map [control-i] 'evil-jump-forward)) ;; ;; annoying - when I select and paste it puts selected into register ;; (defun evil-paste-after-from-0 () ;; (interactive) ;; (let ((evil-this-register ?0)) ;; (call-interactively 'evil-paste-after))) ;; (define-key evil-visual-state-map "p" 'evil-paste-after-from-0) ;; (define-key evil-visual-state-map "p" 'evil-paste-after) ;; These are the keybindings evil makes in insert state by default: ;; +-----+----------------------------+----------------------+ ;; |key |command |emacs | ;; | | |default | ;; +-----+----------------------------+----------------------+ ;; |C-v |quoted-insert |scroll-up-command | ;; +-----+----------------------------+----------------------+ ;; |C-k |evil-insert-digraph |kill-line | ;; +-----+----------------------------+----------------------+ ;; |C-o |evil-execute-in-normal-state|open-line | ;; +-----+----------------------------+----------------------+ ;; |C-r |evil-paste-from-register |isearch-backward | ;; +-----+----------------------------+----------------------+ ;; |C-y |evil-copy-from-above |yank | ;; +-----+----------------------------+----------------------+ ;; |C-e |evil-copy-from-below |move-end-of-line | ;; +-----+----------------------------+----------------------+ ;; |C-n |evil-complete-next |next-line | ;; +-----+----------------------------+----------------------+ ;; |C-p |evil-complete-previous |previous-line | ;; +-----+----------------------------+----------------------+ ;; |C-x |evil-complete-next-line |set-goal-column | ;; |C-n | | | ;; +-----+----------------------------+----------------------+ ;; |C-x |evil-complete-previous-line |mark-page | ;; |C-p | | | ;; +-----+----------------------------+----------------------+ ;; |C-t |evil-shift-right-line |transpose-chars | ;; +-----+----------------------------+----------------------+ ;; |C-d |evil-shift-left-line |delete-char | ;; +-----+----------------------------+----------------------+ ;; |C-a |evil-paste-last-insertion |move-beginning-of-line| ;; +-----+----------------------------+----------------------+ ;; |C-w |evil-delete-backward-word or|kill-region | ;; | |evil-window-map | | ;; +-----+----------------------------+----------------------+ (with-eval-after-load "evil-maps" ;; these are absolutely useless for me (evil-global-set-key 'insert "\C-y" nil) (evil-global-set-key 'insert "\C-e" nil) (evil-global-set-key 'insert "\C-a" nil)) :custom ;; this is required even by evil-collection-ivy (evil-want-minibuffer t) (evil-want-Y-yank-to-eol t) ;; experimenting (evil-cross-lines t) ;; experimenting (evil-want-fine-undo t) ;; experimenting (evil-want-visual-char-semi-exclusive t) ;; makes v$ not select newline (annoying) (evil-undo-system 'undo-redo))
(use-package evil-collection :ensure :demand :after evil :init (setq evil-collection-setup-minibuffer t) ;; before 'require' otherwise it doesn't work (setq evil-collection-want-unimpaired-p nil) ;; conflicts [,] bindings in org-evil-agenda :config (setq evil-collection-mode-list (delete 'ediff evil-collection-mode-list)) ;; having trouble with this guy (evil-collection-init) ;;fix space for some modes, see evil-org-agenda as well (general-def '(motion normal) (dired-mode-map help-mode-map Info-mode-map custom-mode-map Custom-mode-map process-menu-mode-map) "SPC" (general-simulate-key "<leader>")) )
;; surround using S<symbol> or yS<symb> (use-package evil-surround :ensure :after evil :config ;;(global-evil-surround-mode 1) ; will toggle on-demand in hydra-toggle (add-to-list 'evil-surround-operator-alist '(evil-cp-change . change)) (add-to-list 'evil-surround-operator-alist '(evil-cp-delete . delete))) (use-package multiple-cursors :ensure :after evil :init (defvar my-mc-map (make-sparse-keymap) "Keymap for \"mutliple-cursors\" shortcuts.") (define-key evil-normal-state-map (kbd "g y") my-mc-map) :bind (:map my-mc-map ("s" . mc/edit-lines) ("n" . mc/mark-next-like-this) ("p" . mc/mark-previous-like-this) ("a" . mc/mark-all-like-this))) (use-package evil-mc :ensure :after evil evil-collection :config (evil-collection-evil-mc-setup) ;; conflict with evil-collection (defvar my-evil-mc-map (make-sparse-keymap) "Keymap for \"evil-mc\" shortcuts.") (define-key evil-normal-state-map (kbd "g s") my-evil-mc-map) (define-key my-evil-mc-map "m" 'evil-mc-make-all-cursors) (define-key my-evil-mc-map "u" 'evil-mc-undo-all-cursors) (define-key my-evil-mc-map "s" 'evil-mc-pause-cursors) (define-key my-evil-mc-map "r" 'evil-mc-resume-cursors) (define-key my-evil-mc-map "f" 'evil-mc-make-and-goto-first-cursor) (define-key my-evil-mc-map "l" 'evil-mc-make-and-goto-last-cursor) (define-key my-evil-mc-map "h" 'evil-mc-make-cursor-here) (define-key my-evil-mc-map "j" 'evil-mc-make-cursor-move-next-line) (define-key my-evil-mc-map "k" 'evil-mc-make-cursor-move-prev-line) (define-key my-evil-mc-map "n" 'evil-mc-skip-and-goto-next-match) (define-key my-evil-mc-map "p" 'evil-mc-skip-and-goto-prev-match) (define-key my-evil-mc-map "N" 'evil-mc-skip-and-goto-next-cursor) (define-key my-evil-mc-map "P" 'evil-mc-skip-and-goto-prev-cursor) (define-key my-evil-mc-map (kbd "M-n") 'evil-mc-make-and-goto-next-cursor) (define-key my-evil-mc-map (kbd "M-p") 'evil-mc-make-and-goto-prev-cursor) (define-key my-evil-mc-map (kbd "C-n") 'evil-mc-make-and-goto-next-match) (define-key my-evil-mc-map (kbd "C-p") 'evil-mc-make-and-goto-prev-match) (define-key my-evil-mc-map (kbd "C-t") 'evil-mc-skip-and-goto-next-match)) ;; 'localized' avy (use-package evil-snipe :ensure :demand :after evil :diminish (evil-snipe-local-mode . "") ;; " +" :custom (evil-snipe-scope 'visible) (evil-snipe-smart-case t) :config (add-to-list 'evil-snipe-disabled-modes 'ibuffer-mode) (evil-snipe-mode 1) (evil-snipe-override-mode 1)) ;; number of matches when searching (use-package evil-anzu :disabled ;; I'm mostly using swiper :ensure :after evil anzu) ;; evil-anzu actually requires this (use-package anzu :disabled ;; I'm mostly using swiper :ensure :init (global-anzu-mode +1))
(use-package evil-escape :ensure :demand :after evil ;; :config ;; I'm using general to handle actual keypress ;; (evil-escape-mode) ;; (setq-default evil-escape-key-sequence "kj") ;; (setq evil-escape-delay 0.1) )
6. text & editing
6.1. scroll
;; finally! (use-package good-scroll :ensure ;;:disabled ;; TODO-fix: it actually adds up ~2% of extra cpu all-time - becuase of constant re-rendering :disabled ;; seems like default is good enough at this point :defer 0.8 :config ;; this doesn't move to the very top of the window ;;(evil-define-key 'motion global-map (kbd "C-f") 'good-scroll-up-full-screen) ;;(evil-define-key 'motion global-map (kbd "C-b") 'good-scroll-down-full-screen) ;; (define-key evil-motion-state-map (kbd "s-j") 'evil-scroll-down) ;; (define-key evil-motion-state-map (kbd "s-k") 'evil-scroll-up) (defun my/good-scroll-up-30%-screen () "Scroll up." (interactive) (good-scroll-move (ffloor (* 0.3 (good-scroll--window-usable-height))))) (defun my/good-scroll-down-30%-screen () "Scroll down." (interactive) (good-scroll-move (ffloor (* -0.3 (good-scroll--window-usable-height))))) (when (display-graphic-p) (good-scroll-mode 1) (global-set-key [next] #'good-scroll-up-full-screen) (global-set-key [prior] #'good-scroll-down-full-screen) (define-key evil-motion-state-map (kbd "s-j") 'my/good-scroll-up-30%-screen) (define-key evil-motion-state-map (kbd "s-k") 'my/good-scroll-down-30%-screen) (define-key evil-motion-state-map (kbd "C-e") 'good-scroll-up) (define-key evil-motion-state-map (kbd "C-y") 'good-scroll-down) (evil-define-key 'emacs global-map (kbd "C-v") 'good-scroll-up-full-screen) (evil-define-key 'emacs global-map (kbd "M-v") 'good-scroll-down-full-screen) ) :custom (good-scroll-duration 0.15) ;; below snippet came from somewhere, i keep it under good-scroll as a related ;; https://www.masteringemacs.org/article/improving-performance-emacs-display-engine ;; https://www.reddit.com/r/emacs/comments/8sw3r0/finally_scrolling_over_large_images_with_pixel/ ;; https://www.reddit.com/r/emacs/comments/9rwb4h/why_does_fast_scrolling_freeze_the_screen/ ;; https://emacs.stackexchange.com/questions/10354/smooth-mouse-scroll-for-inline-images ;; https://emacs.stackexchange.com/questions/28736/emacs-pointcursor-movement-lag (redisplay-dont-pause t) ;; Fully redraw the display before it processes queued input events. (next-screen-context-lines 2) ;; Number of lines of continuity to retain when scrolling by full screens (scroll-conservatively 10000) ;; only 'jump' when moving this far off the screen (scroll-step 1) ;; Keyboard scroll one line at a time (mouse-wheel-progressive-speed nil) ;; Don't accelerate scrolling (mouse-wheel-follow-mouse t) ;; Scroll window under mouse (fast-but-imprecise-scrolling t) ;; No (less) lag while scrolling lots. (auto-window-vscroll nil) ;; Cursor move faster ) ;; experimenting (use-package inertial-scroll :disabled :quelpa (inertial-scroll :fetcher "github" :repo "kiwanami/emacs-inertial-scroll") :custom (inertias-friction 110) :bind (("<mouse-4>" . inertias-down-wheel) ;; Replace mwheel-scroll ("<mouse-5>" . inertias-up-wheel ) ;; Replace mwheel-scroll ("<wheel-up>" . inertias-down-wheel) ("<wheel-down>" . inertias-up-wheel ))) ;; (with-eval-after-load 'evil ;; (define-key evil-motion-state-map (kbd "s-j") 'evil-scroll-down) ;; (define-key evil-motion-state-map (kbd "s-k") 'evil-scroll-up) ;; ) ;; scroll one line at a time (less "jumpy" than defaults) ;(setq mouse-wheel-scroll-amount '(1 ((shift) . 1)((meta)) ((control) . text-scale))) ;; one line at a time ;(setq mouse-wheel-progressive-speed t);;nil ;; (not) accelerate scrolling ;(setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse ;(setq scroll-step 1) ;; keyboard scroll one line at a time ;; multiple problems with this package: 1. no font size change. 2. line separator ^L problem (page-break-lines) ;;(use-package display-line-numbers :custom (global-display-line-numbers-mode t)) ;; horizontal scroll (setq mouse-wheel-tilt-scroll t) (setq mouse-wheel-flip-direction t) ;; I'm using pinch with libinput-gestures (global-set-key [pinch] 'ignore) ;; experimental (use-package scrollkeeper :disabled :quelpa (scrollkeeper :fetcher github :repo "alphapapa/scrollkeeper.el") :general ;; ([remap scroll-up-command] #'scrollkeeper-contents-up ;; [remap scroll-down-command] #'scrollkeeper-contents-down) ([remap evil-scroll-page-down] #'scrollkeeper-contents-up [remap evil-scroll-page-up] #'scrollkeeper-contents-down) )
6.2. various (to sort)
(setq-default indent-tabs-mode nil tab-width 4) (use-package text-mode :custom (adaptive-fill-mode t) :diminish ((auto-fill-function . " fil") (visual-line-mode . " vis")) :hook (text-mode . (lambda () ;; (auto-fill-mode) (paragraph-indent-minor-mode) ;; (visual-line-mode t) ;; (visual-fill-column-mode) ))) (use-package nlinum :ensure :hook (prog-mode . linum-mode)) (use-package page-break-lines :ensure :diminish (page-break-lines-mode . "^L")) ;;(use-package beacon ;; :custom ;; (beacon-color "#f1fa8c") ;; :hook (after-init . beacon-mode)) ;; show indents in all modes ;; bad performance ;;(use-package indent-guide ;; :hook (prog-mode . indent-guide-mode)) ;; string manipulation (not really using directly right now) ;;(use-package s) (use-package visual-regexp :ensure :bind (("M-%" . vr/replace) ("M-C-%" . vr/query-replace) ("C-c m" . vr/mc-mark))) ;; todo - into text hydra (use-package expand-region :ensure :after evil :commands 'er/expand-region :init (evil-define-key 'motion global-map (kbd "<leader>v") 'er/expand-region)) (defun contextual-backspace () "Hungry whitespace or delete word depending on context." (interactive) (if (looking-back "[[:space:]\n]\\{2,\\}" (- (point) 2)) (while (looking-back "[[:space:]\n]" (- (point) 1)) (delete-char -1)) (cond ((and (boundp 'smartparens-strict-mode) smartparens-strict-mode) (sp-backward-kill-word 1)) ((and (boundp 'subword-mode) subword-mode) (subword-backward-kill 1)) (t (backward-kill-word 1))))) (global-set-key (kbd "C-M-<backspace>") 'contextual-backspace) (global-auto-revert-mode t) (global-set-key (kbd "C-c w") 'toggle-truncate-lines); wrap (use-package mixed-pitch :ensure ;;:hook ;; If you want it in all text modes: ;;(text-mode . mixed-pitch-mode) ) ;; writing (use-package olivetti :ensure :custom (olivetti-body-width 140) ) (use-package wc-mode :ensure) (use-package writegood-mode :ensure) (defun my/enter-writing-mode () "Apply various modes and settings for writing" (interactive) (org-narrow-to-subtree) (olivetti-mode 1) (wc-mode) (writegood-mode) ;;(mixed-pitch-mode 1) (variable-pitch-mode 1) ;;(set-face-attribute 'variable-pitch nil :family "IBM Plex Serif" :height 110) (set-face-attribute 'variable-pitch nil :family "DejaVu Serif" :height 110) ;;(set-face-attribute 'default nil :family "DejaVu Sans Mono" :height 130) ;;(set-face-attribute 'fixed-pitch nil :family "DejaVu Sans Mono") ) ;; testing (use-package writeroom-mode :ensure) ;; thesaurus (use-package synosaurus :ensure :custom (synosaurus-choose-method 'default) :config (synosaurus-mode)) (use-package flycheck-grammarly :ensure) ;; testing (use-package iedit :ensure :bind ("C-;" . iedit-mode)) (use-package shrink-whitespace :ensure :bind ("M-\\" . shrink-whitespace)) ;; bad performance, really bad (use-package highlight-indentation :ensure :disabled) (use-package focus :disabled ;; meh :ensure) (use-package aggressive-indent :ensure :hook (emacs-lisp-mode . aggressive-indent-mode) (css-mode . aggressive-indent-mode)) (use-package editorconfig :ensure ;; :demand :after prog-mode :diminish ;; " EC" :config (editorconfig-mode 1)) (use-package mwim :ensure :general ("C-a" 'mwim-beginning "C-e" 'mwim-end) ) (use-package view-mode :general (normal view-mode-map "SPC" nil))
6.3. large files
(use-package vlf :functions ivy-add-actions :ensure :after (ivy counsel) :init (ivy-add-actions 'counsel-find-file '(("l" vlf "view large file"))))
6.4. avy hydra
;; navigate text in the buffer (use-package avy :ensure :after evil :commands (hydra-avy/body avy-goto-char-timer) :init (evil-define-key 'motion global-map (kbd "<leader>J") 'hydra-avy/body (kbd "<leader>j") 'avy-goto-char-timer) :pretty-hydra (hydra-avy (:exit t :hint nil :title "Avy") ("Line" (("y" avy-copy-line) ("m" avy-move-line) ("k" avy-kill-whole-line)) "Region" (("Y" avy-copy-region) ("M" avy-move-region) ("K" avy-kill-region)) "Goto" (("j" avy-goto-char-timer) ("w" avy-goto-word-1) ("l" avy-goto-line)) "" (("c" avy-goto-char) ("W" avy-goto-word-0) ("L" avy-goto-end-of-line) ("C" avy-goto-char-2)))))
6.5. tex
(use-package auctex :ensure :config (setq preview-auto-cache-preamble nil)) (use-package auto-complete-auctex :ensure :demand :after auctex) ;; it came from here https://github.com/karthink/.emacs.d/blob/f25889bb31e7b4f39243b5a80485a75a2ce65430/init.el#L1090 (use-package cdlatex :ensure :hook (LaTeX-mode . turn-on-cdlatex) :config (progn (setq cdlatex-command-alist '(("vc" "Insert \\vect{}" "\\vect{?}" cdlatex-position-cursor nil nil t) ("smat" "Insert smallmatrix env" "\\left( \\begin{smallmatrix} ? \\end{smallmatrix} \\right)" cdlatex-position-cursor nil nil t) ("bmat" "Insert bmatrix env" "\\begin{bmatrix} ? \\end{bmatrix}" cdlatex-position-cursor nil nil t) ("pmat" "Insert pmatrix env" "\\begin{pmatrix} ? \\end{pmatrix}" cdlatex-position-cursor nil nil t) ("equ*" "Insert equation* env" "\\begin{equation*}\n?\n\\end{equation*}" cdlatex-position-cursor nil t nil) ("sn*" "Insert section* env" "\\section*{?}" cdlatex-position-cursor nil t nil) ("ss*" "Insert subsection* env" "\\subsection*{?}" cdlatex-position-cursor nil t nil) ("sss*" "Insert subsubsection* env" "\\subsubsection*{?}" cdlatex-position-cursor nil t nil))) (setq cdlatex-math-symbol-alist '((?F ("\\Phi")) (?o ("\\omega" "\\mho" "\\mathcal{O}")) (?6 ("\\partial")) (?v ("\\vee" "\\forall")))) (setq cdlatex-math-modify-alist '((?b "\\mathbb" "\\textbf" t nil nil) (?B "\\mathbf" "\\textbf" t nil nil))) (setq cdlatex-paired-parens "$[{(")) )
7. files & projects
7.1. dired
(use-package async :ensure) (use-package dired-avfs ;; archives :ensure :demand :after dired ;; :ensure-system-package avfs ) (use-package dired-hide-dotfiles :ensure :demand :after dired) (use-package dired-filter :ensure :demand :after dired) ;; additional filter keymap (use-package dired-open :ensure :demand :after dired) ;; xdg-open (use-package dired-subtree :ensure :demand :after dired :config (general-def normal dired-mode-map "C-M-p" 'dired-subtree-previous-sibling "C-M-n" 'dired-subtree-next-sibling) :custom (dired-subtree-line-prefix " ")) ;;" └───" (use-package dired-narrow :ensure :after dired) ;; narrow-fuzzy (use-package dired-hacks-utils :ensure :demand :after dired) (use-package dired-du :ensure :after dired) (use-package dired-collapse :ensure :after dired;; displays dir1/dir2/.., bad when trying to copy/move those files ;; :hook (dired-mode . dired-collapse-mode) ) ;; it seems like it doesn't work with dired-fl (use-package dired-rainbow :ensure :after dired :config (dired-rainbow-define html "#4e9a06" ("htm" "html" "xhtml")) (dired-rainbow-define log (:inherit default :italic t) ".*\\.log") ; highlight executable files, but not directories (dired-rainbow-define-chmod executable-unix "Green" "-[rw-]+x.*") ;; see github documentation of dired-hack-utils for more ) ;;(use-package ranger) ;; don't like it (use-package dired-rainbow :ensure :after dired) ;; not sure if it's really being used - more colorful faces ;;(use-package ranger) ;; don't like it ;;(use-package treemacs-icons-dired :ensure :after treemacs dired) (use-package all-the-icons-dired :ensure :after dired all-the-icons :diminish " Icons" :disabled ;; nerds are better :hook (dired-mode . all-the-icons-dired-mode) ) (use-package nerd-icons-dired :ensure :after dired nerd-icons :diminish :hook (dired-mode . nerd-icons-dired-mode)) ;;preview like in ranger (or dirvish, but dirvish is better) (use-package peep-dired :ensure :after evil general dired :init ;; kind of ranger preview (defvar my/display-buffer-alist-on-right '((".*" (display-buffer-reuse-window display-buffer-in-side-window) (side . right) (slot . 0) (window-width . 0.7) (reusable-frames . nil))) "Display buffers on right side.") (defun my/peep-dired-next-file () (interactive) (let ((display-buffer-alist my/display-buffer-alist-on-right)) (peep-dired-next-file))) (defun my/peep-dired-prev-file () (interactive) (let ((display-buffer-alist my/display-buffer-alist-on-right)) (peep-dired-prev-file))) (defun my/peep-dired () (interactive) (let ((display-buffer-alist my/display-buffer-alist-on-right)) (peep-dired))) :config (with-eval-after-load 'golden-ratio (add-to-list 'golden-ratio-inhibit-functions #'(lambda () peep-dired))) :general (:states 'normal :keymaps 'peep-dired-mode-map "M-<SPC>" 'peep-dired-scroll-page-down "M-S-<SPC>" 'peep-dired-scroll-page-up "<backspace>" 'peep-dired-scroll-page-up "q" 'peep-dired ")" 'peep-dired "j" 'my/peep-dired-next-file "k" 'my/peep-dired-prev-file) (:states 'normal :keymaps 'dired-mode-map ")" 'my/peep-dired "M-k" #'(lambda () (interactive) (peep-dired-cleanup) (quit-window-kill-buffer))) ;; :custom (peep-dired-cleanup-eagerly t) :hook (peep-dired . evil-normalize-keymaps)) (use-package image-dired :hook (image-dired-thumbnail-mode . (lambda () (setq-local global-hl-line-mode nil) ;; disable global mode )) :config (when (eq system-type 'windows-nt) (setq image-dired-cmd-create-thumbnail-program "magick.exe" image-dired-cmd-create-temp-image-program "magick.exe" image-dired-cmd-rotate-original-program "jpegtran.exe" image-dired-cmd-rotate-thumbnail-program "magick.exe") (add-to-list 'image-dired-cmd-create-thumbnail-options "convert") (add-to-list 'image-dired-cmd-create-temp-image-options "convert") (add-to-list 'image-dired-cmd-rotate-thumbnail-options "mogrify")) :custom (image-dired-thumbnail-storage 'standard-large)) ;; Addtional syntax highlighting for dired (use-package diredfl :ensure :after dired :hook (dired-mode . diredfl-mode)) ;; Testing - Drop-in replacement for find-dired (use-package fd-dired :ensure :after dired :bind (:map dired-mode-map ("C-c C-f" . fd-dired))) (use-package dired :after evil-collection general :custom (dired-listing-switches "-AGhlv --group-directories-first --time-style=long-iso") (dired-recursive-deletes 'always) (delete-by-moving-to-trash t) ;;(put 'dired-find-alternate-file 'disabled nil) ;;(define-key dired-mode-map (kbd "RET") #'dired-find-alternate-file) ;; instead of above, since ver28 simply: (dired-kill-when-opening-new-dired-buffer t) (all-the-icons-dired-monochrome nil) (dired-dwim-target t) ;; copy between vertical windows :init (defun dired-here () (interactive) (dired ".")) :general ("C-x C-d" 'dired-here) :config (put 'all-the-icons-dired-mode 'safe-local-variable #'listp) ;; safe var property (evil-collection-define-key 'motion 'dired-mode-map "/" 'dired-narrow-fuzzy) (evil-collection-define-key 'normal 'dired-mode-map "l" 'dired-open-file) (evil-collection-define-key 'normal 'dired-mode-map "h" 'dired-up-directory) ;;(evil-collection-define-key 'normal 'dired-mode-map (kbd "M-RET") 'dired-open-xdg) (evil-collection-define-key 'motion 'dired-mode-map (kbd "C-<return>") 'dired-open-xdg) (evil-collection-define-key 'normal 'dired-mode-map "q" 'kill-this-buffer) (evil-collection-define-key 'normal 'image-dired-thumbnail-mode-map (kbd "M-<SPC>") 'image-dired-display-next-thumbnail-original) (evil-collection-define-key 'normal 'image-dired-thumbnail-mode-map (kbd "M-S-<SPC>") 'image-dired-display-previous-thumbnail-original) (evil-collection-define-key 'normal 'image-dired-thumbnail-mode-map (kbd "U") 'image-dired-unmark-all-marks) (general-def 'motion dired-mode-map "SPC" (general-simulate-key "<leader>")) (with-eval-after-load 'evil-collection-dired (with-eval-after-load 'dired-subtree ;; no way to control order of with-eval-after-load in evil-collection-dired+dired-subtree (run-with-idle-timer 1 nil #'(lambda () (general-def '(motion normal visual) dired-mode-map "M-j" nil "M-k" nil))))) (evil-define-key 'normal dired-mode-map (kbd "f") dired-filter-map) ;; following stuff is disabled due to performance concerns ;;(require 'treemacs-icons-dired) ; all-the-icons are better ;;(require 'dired-du) ; performance ;;; this one produces "Permission denied" on listing in Win10 with JUNCTION folders ;;(add-hook 'dired-mode-hook #'dired-du-mode) ;;(require 'dired-collapse) ; performance :hook (dired-mode . dired-utils-format-information-line-mode) (evil-collection-setup . (lambda (mode map) (when (eq mode 'dired) (message "dired evil-collection setup hook") (evil-collection-define-key 'normal 'dired-mode-map "." 'dired-hide-dotfiles-mode)))) (dired-mode . dired-async-mode) (dired-mode . dired-hide-details-mode) )
7.2. dirvish
(use-package dirvish :disabled :ensure :after dired ;; otherwise it failes to initialize :init (set-frame-parameter nil 'dirvish--hash (make-hash-table :test 'equal)) :config ;; Override dired with dirvish globally ;;(dirvish-override-dired-mode) ;; Enable file preview when narrowing files in minibuffer. ;; This feature only support `vertico/selectrum' for now. ;;(dirvish-peek-mode) :bind (:map global-map ("C-x D" . dirvish-dired) ("C-x C-d" . dirvish)) ;; (:map dired-mode-map ;; ("SPC" . dirvish-show-history) ;; ([remap drivish-yank] . ) ;; ([remap mode-line-other-buffer] . dirvish-other-buffer) ;; ) )
7.3. grep tools
(use-package ag :ensure :custom (ag-highlight-search t) (ag-reuse-buffers t) :config (add-to-list 'ag-arguments "--word-regexp")) (use-package ripgrep :ensure) (use-package flx :ensure) (use-package wgrep :ensure) (use-package wgrep-ag :ensure) (use-package fzf :ensure :unless (eq system-type 'windows-nt))
7.4. projectile
(use-package projectile :ensure :after evil :init (setq projectile-use-git-grep t) (evil-define-key 'motion global-map (kbd "<leader>p") 'hydra-projectile/body) (defun projectile-mini-mode-line () "Minimal projectile mode-line" projectile-mode-line-prefix) :bind-keymap ("C-c p" . projectile-command-map) :custom (projectile-completion-system 'ivy) ;;(projectile-project-search-path (list "~/Documents")) ;; (projectile-mode-line-function #'projectile-default-mode-line) (projectile-mode-line-function #'projectile-mini-mode-line) (projectile-mode-line-prefix "") ;; " P" :functions (projectile-project-name) :commands (hydra-projectile/body) :pretty-hydra (hydra-projectile (:hint nil :color teal :quit-key "q" :title (with-faicon "rocket" "Projectile" 1 -0.05)) ("Buffers" (("b" counsel-projectile-switch-to-buffer "list") ("k" projectile-kill-buffers "kill all") ("S" projectile-save-project-buffers "save all")) "Find" (("d" counsel-projectile-find-dir "directory") ("F" projectile-recentf "recent files") ("D" projectile-dired "dired") ("g" counsel-projectile-find-file-dwim "file dwim") ("f" counsel-projectile-find-file "file") ("p" counsel-projectile-switch-project "project")) "Other" (("i" projectile-invalidate-cache "reset cache") ("x" projectile-remove-known-project "remove known project") ("z" projectile-cache-current-file "cache current file") ("X" projectile-cleanup-known-projects "cleanup known projects")) "Search" (("r" projectile-replace "replace") ("o" projectile-multi-occur "occur") ("R" projectile-replace-regexp "regexp replace") ("sr" counsel-projectile-grep "grep") ("sa" counsel-projectile-ag "ag") ("sg" counsel-projectile-rg "rg") ("ss" counsel-rg "search"))))) (use-package counsel-projectile :functions counsel-projectile-mode :ensure :demand :after (projectile counsel) :config (counsel-projectile-mode))
7.5. treemacs
(use-package treemacs-evil :after evil :ensure) (use-package treemacs-projectile :ensure) (use-package treemacs-magit :ensure) (use-package treemacs-all-the-icons :ensure) (use-package treemacs-nerd-icons :ensure) (use-package treemacs-tab-bar :ensure :demand :after tab-bar treemacs) (use-package treemacs :ensure :after evil :init (evil-define-key 'motion global-map (kbd "<leader>t") 'treemacs) ;;treemacs-add-and-display-current-project ;; this will add projectile project automatically :config (require 'treemacs-themes) (require 'treemacs-icons) (require 'treemacs-all-the-icons) (require 'treemacs-nerd-icons) (require 'treemacs-evil) (require 'treemacs-projectile) (require 'treemacs-magit) (treemacs-load-theme 'nerd-icons) ;; (treemacs-follow-mode -1) ;; kills remote mounts (treemacs-follow-mode 1) (treemacs-project-follow-mode) ;; this is what I need - treemacs buffer show 1 project exclusively and follows ;; (treemacs-resize-icons 15) (general-def treemacs-mode-map "M-l" nil "M-h" nil) :custom (treemacs-follow-after-init t) (treemacs-width 33) (treemacs-wide-toggle-width 67) :functions (treemacs-follow-mode treemacs-load-theme) :commands treemacs-modify-theme ;; :custom ;; (treemacs-fringe-indicator-mode t) )
7.6. xah-find
Nice pure lisp find-grep replacement – works on windows well
(when (eq system-type 'windows-nt) (use-package xah-find :after evil :ensure :general (:modes '(normal motion) :keymaps 'xah-find-output-mode-map "RET" 'xah-find--jump-to-place)))
7.7. bookmarks
;; is used by info+ (at least) (use-package bookmark+ :unless (eq system-type 'windows-nt) ;; :disabled t :quelpa (bookmark+ :fetcher wiki :files ("bookmark+.el" "bookmark+-mac.el" "bookmark+-bmu.el" "bookmark+-1.el" "bookmark+-key.el" "bookmark+-lit.el" "bookmark+-doc.el" "bookmark+-chg.el")) :defer 2 :custom (bmkp-crosshairs-flag nil) ;; ugly ) (use-package crosshairs :quelpa (crosshairs :fetcher wiki)) (use-package col-highlight :quelpa (col-highlight :fetcher wiki)) (use-package hl-line+ :quelpa (hl-line+ :fetcher wiki))
7.8. other
;; todo - filter out archive files from org (setq recentf-max-saved-items 100)
8. frames & windows & buffers & tabs
8.1. tab-bar
(use-package tab-bar :demand :after evil :functions (my/name-tab-by-project-or-default) :commands (hydra-tab/body my/init-my-tabs tab-bar-select-tab) :general ('motion global-map "<leader><tab>" 'hydra-tab/body) :init (defun my/init-my-tabs () "Initialize usual tabs in case desktop save was broken." (interactive) (tab-bar-history-mode); it doesn't really work, see winner-mode and fix this one (tab-rename "🕐 org") ;;(tab-group "personal") (tab-new) (tab-rename "🖮 emacs") ;; (tab-group "personal") (tab-new) (tab-rename "🚀 system") ;; (tab-group "personal") (tab-new) (tab-rename "🍛 dk") ;; (tab-group "work") (tab-new) (tab-rename "👷 work") ;; (tab-group "work") ) :init ;; Experimental (define-minor-mode buffer-tab-assign-mode "Enable automatic buffer move to dedicated tab (per project)." :lighter "" ;; " B" :global t (if buffer-tab-assign-mode (progn (require 'projectile) ;; todo - package this stuff (add-hook 'window-configuration-change-hook #'assign-buffer-to-tab-by-project) ;; (assign-buffer-to-tab-by-project) ) (remove-hook 'window-configuration-change-hook #'assign-buffer-to-tab-by-project) )) ;; with-eval-after-load 'projectile (defvar buffer-assignment-in-progress nil "Flag is used to avoid recursive window-configuration-change-hook calls") (defcustom buffer-assignment-tab-alist '(("\\*scratch\\*" . "emacs") (".*\\*helpful.*" . "emacs") ("provision.org" . "configs") (".*\\*Backtrace.*" . "emacs") (".*\\*Help.*" . "emacs") ("\\*info\\*" . "emacs") ("\\*Messages\\*" . "emacs")) "Assignment of buffers to tabs based on regexp.") ;; (defcustom buffer-assignment-tab-func ) (defun buffer-assignment-tab-func (buffer-name) "Return name of the tab to assign buffer to." ;; (cl-loop for (key . value) in buffer-assignment-tab-alist ;; collect (cons value key)) (let ((tab-name (projectile-project-name))) (dolist (x buffer-assignment-tab-alist) (when (string-match (car x) (buffer-name)) (setq tab-name (cdr x)))) tab-name)) ;; WIP (require 'cl-lib) (defun open-all-assigned-buffers () (interactive) "Open all assigned buffers in tab-line" (let* ((next-buffers (window-next-buffers)) (prev-buffers (window-prev-buffers)) (current-tab-name (cdr (assq 'name (tab-bar--current-tab)))) (all-buffers (projectile-project-buffers) ;;(buffer-list) ) (new-next-buffers (append next-buffers (cl-remove-if-not #'(lambda (el) (string= current-tab-name (buffer-assignment-tab-func (buffer-name el)))) (cl-set-difference all-buffers prev-buffers))))) (set-window-next-buffers nil next-buffers) (force-mode-line-update) )) (defun assign-buffer-to-tab-by-project () "Experimental: move buffers to dedicated tabs (workspaces) per project." (interactive) (when tab-bar-mode (let* ((buffer (window-buffer)) (buffer-name (buffer-name buffer)) (is-lame-buffer (string-match "\\ \\*" (buffer-name buffer)))) ;; (when is-lame-buffer (message "lame buffer %s" (buffer-name (window-buffer)))) (when (not is-lame-buffer) ;; (when buffer-assignment-in-progress (message "debug: buffer-assignment-in-progress")) (when (not buffer-assignment-in-progress) (let ((buffer-assignment-in-progress t)) (let (window-configuration-change-hook) (let ((current-tab-name (cdr (assq 'name (tab-bar--current-tab)))) (tab-name (buffer-assignment-tab-func buffer-name))) ;; (when (string= current-tab-name project-name) (message "debug: buffer already belongs to %s" current-tab-name)) (when (not (string= current-tab-name tab-name)) (quit-window) ;; bury? (when (not (tab-bar--tab-index-by-name tab-name)) (let ((tab-bar-new-tab-choice buffer-name)) ;; todo - debug, this does not work (message (format "creating new tab %s" tab-name)) (tab-bar-new-tab) (tab-bar-rename-tab tab-name) ;; stupid, but tab-bar-show=1 lags without this (run-with-idle-timer 1 nil #'tab-bar--update-tab-bar-lines) ;; todo - do proper cleanup without dangling prev buffer in new tab (set-window-prev-buffers nil nil) (set-window-next-buffers nil nil) )) (tab-bar-select-tab-by-name tab-name) ;; (message "debug: moving buffer %s to tab %s" buffer project-name) (switch-to-buffer buffer) ))) (run-hooks 'window-configuration-change-hook))))))) (bind-key "M-i" 'assign-buffer-to-tab-by-project) (if is-android (progn (tab-bar-mode -1)) (progn ;; (display-time-mode 1) (tab-bar-mode 1) (buffer-tab-assign-mode 1) ;; (tab-bar-rename-tab "default") ;; (tab-bar-rename-tab (projectile-project-name)) )) ;; (setq tab-bar-tab-name-function #'name-tab-by-project-or-default) ;; (defun name-tab-by-project-or-default () ;; "Return project name if in a project, or default tab-bar name if not. ;; The default tab-bar name uses the buffer name." ;; (let ((project-name (projectile-project-name))) ;; (if (string= "-" project-name) ;; (tab-bar-tab-name-current) ;; (projectile-project-name)))) ;; :init (require 'projectile) ;; (customize-set-variable 'tab-bar-tab-name-function #'projectile-project-name) :config ;; WIP (defface tab-bar-tab-org '((t :inherit tab-tab-tab :foreground "PaleVioletRed1")) "face for org tab-bar tab") (defun my/tab-bar-colorize (tab) (message "tab-bar-name=%s" (alist-get 'name tab)) (if (string= "org" (alist-get 'name tab)) 'tab-bar-tab-org (tab-bar-tab-face-default tab))) (setq tab-bar-tab-face-function #'my/tab-bar-colorize) ;; WIP (require 'powerline) (defvar my/tab-bar-height 36) (defvar my/tab-bar-left (powerline-wave-right 'tab-bar 'tab-bar my/tab-bar-height)) (defvar my/tab-bar-right (powerline-wave-left 'tab-bar 'tab-bar my/tab-bar-height)) (defun my/tab-bar-tab-name-format-function (tab i) (powerline-render (list my/tab-bar-left ;; (format " %s " (buffer-name buffer)) ;; (tab-bar-tab-name-format-default tab i) (concat (if tab-bar-tab-hints (format "%d " i) "") (alist-get 'name tab)) my/tab-bar-right))) ;; (setq tab-bar-tab-name-format-function #'my/tab-bar-tab-name-format-function) ;; (setq tab-bar-tab-name-format-function #'tab-bar-tab-name-format-default) (defun tab-bar-custom-format () ;;https://github.com/jimeh/.emacs.d/blob/c845af831690d1ab575b691020fbe91ce6435647/modules/workspaces/siren-tab-bar.el#L119-L138 (defgroup siren-tab-bar nil "Siren specific tweaks to tar-bar-mode." :group 'tab-bar) (defface siren-tab-bar-tab `((t :inherit 'tab-bar-tab ;; :inverse-video t ;; :foreground ,(face-attribute 'font-lock-keyword-face :foreground nil t) ;; :foreground ,(face-attribute 'font-lock-constant-face :foreground nil t) :weight bold ;; :foreground "#e4a2f4" :foreground "#ffffaf" )) "Face for active tab in tab-bar." :group 'siren-tab-bar) (defface siren-tab-bar-tab-hint `((t :inherit 'siren-tab-bar-tab :foreground ,(face-attribute 'tab-bar-tab-inactive :foreground nil t))) "Face for active tab hint in tab-bar." :group 'siren-tab-bar) (defface siren-tab-bar-tab-inactive `((t :inherit 'tab-bar-tab-inactive :foreground ,(face-attribute 'font-lock-comment-face :foreground nil t))) "Face for inactive tab in tab-bar." :group 'siren-tab-bar) (defface siren-tab-bar-tab-hint-inactive `((t :inherit 'siren-tab-bar-tab-inactive :foreground ,(face-attribute 'tab-bar-tab-inactive :foreground nil t))) "Face for inactive tab hint in tab-bar." :group 'siren-tab-bar) (defun siren-tab-bar-tab-name-format-default (tab i) (let* ((current-p (eq (car tab) 'current-tab)) (tab-face (if current-p 'siren-tab-bar-tab 'siren-tab-bar-tab-inactive)) (hint-face (if current-p 'siren-tab-bar-tab-hint 'siren-tab-bar-tab-hint-inactive))) (concat ;; (powerline-render ;; (list ;; my/tab-bar-left ;; " n " ;; ;; (format " %s " (buffer-name buffer)) ;; ;; (tab-bar-tab-name-format-default tab i) ;; ;; (concat (if tab-bar-tab-hints (format "%d " 1) "") ;; ;; (alist-get 'name (tab-bar--current-tab))) ;; my/tab-bar-right)) (propertize (if tab-bar-tab-hints (format " %d:" i) " ") 'face hint-face) (propertize (concat (alist-get 'name tab) (or (and tab-bar-close-button-show (not (eq tab-bar-close-button-show (if current-p 'non-selected 'selected))) tab-bar-close-button) "") " ") 'face tab-face)))) (setq tab-bar-tab-name-format-function #'siren-tab-bar-tab-name-format-default)) ;; again, order of defface matters (run-with-idle-timer 1 nil #'tab-bar-custom-format) :general ("M-n" 'tab-bar-switch-to-next-tab "M-p" 'tab-bar-switch-to-prev-tab) :custom ((tab-bar-tab-hints t) ; t (tab-bar-tab-name-function #'(lambda () "emacs")) ;; experiment (tab-bar-show 1) (tab-bar-select-tab-modifiers '(meta)) (tab-bar-format '(tab-bar-format-menu-global tab-bar-format-tabs-groups tab-bar-separator tab-bar-format-align-right tab-bar-format-global)) (tab-bar-history-limit 30) (tab-bar-close-button-show nil) (tab-bar-close-button-show nil) (display-time-use-mail-icon t) (display-time-mail-directory nil); "~/.mail/gmail/Inbox/new" ; using mu4e (display-time-day-and-date nil)) :pretty-hydra (hydra-tab (:hint nil :color amaranth :quit-key "q" :title (with-material "tab" "Tab" 1 -0.05)) ("Tabs" (("<tab>" tab-bar-select-tab-by-name "Switch tab") ("n" tab-bar-new-tab "New tab") ("j" tab-next "Next tab") ("k" tab-previous "Previous tab") ("g" tab-group "Group") ("m" tab-move "Move") ("r" tab-bar-rename-tab "Rename tab") ("R" tab-bar-rename-tab-by-name "Rename tab by name") ("d" tab-bar-close-tab "Close tab") ("D" tab-bar-close-tab-by-name "Close tab by name") ("1" tab-bar-close-other-tabs "Close other tabs")))) )
8.2. tab-line
(use-package tab-line ;;:defer 0.5 :bind ("M-l" . tab-line-next-tab-cycle) ("M-h" . tab-line-prev-tab-cycle) ;; I want to hide window if this is the last tab shown (see set-last-tab-window-quit-restore) ("M-j" . quit-window) ("M-k" . quit-window-kill-buffer) ;; todo - this fails here cause term is not loaded yet ;;(global-set-key (kbd "<s-left>") 'tab-bar-history-back) ;;(global-set-key (kbd "<s-right>") 'tab-bar-history-forward) :bind* ("M-<left>" . tab-line-prev-tab-cycle) ;; using this with libinput-gestures ("M-<right>" . tab-line-next-tab-cycle) :init (global-tab-line-mode) (defun quit-window-kill-buffer () "Simply quit-window with killing current buffer" (interactive) (quit-window t)) (defun tab-line-next-tab-cycle () "Fixing original tab-line-switch-to-next-tab to properly work cycling and preserving order of tabs. This implementation would cycle through tabs visible in the window currently, without switching to buried/other tabs." (interactive) (let* ((tabs (funcall tab-line-tabs-function)) (pos (seq-position tabs (current-buffer) (lambda (tab buffer) (if (bufferp tab) (eq buffer tab) (eq buffer (cdr (assq 'buffer tab))))))) (new-pos (if pos (if (<= (length tabs) (1+ pos)) 0 ;; cycle to the first tab (1+ pos)))) (tab (if (= new-pos 0) (car tabs) (nth new-pos tabs))) (buffer (if (bufferp tab) tab (cdr (assq 'buffer tab))))) (when (bufferp buffer) (if (= new-pos 0) (switch-to-buffer buffer) (switch-to-next-buffer))))) (defun tab-line-prev-tab-cycle () "See `tab-line-next-tab-cycle'." (interactive) (let* ((tabs (funcall tab-line-tabs-function)) (pos (seq-position tabs (current-buffer) (lambda (tab buffer) (if (bufferp tab) (eq buffer tab) (eq buffer (cdr (assq 'buffer tab))))))) (last-pos (1- (length tabs))) (new-pos (if pos (if (<= pos 0) last-pos;; cycle to the last tab (1- pos)))) (tab (nth new-pos tabs)) (buffer (if (bufferp tab) tab (cdr (assq 'buffer tab))))) (when (bufferp buffer) (if (= new-pos last-pos) (switch-to-buffer buffer) (switch-to-prev-buffer))))) ;; :custom-face ;; (tab-line-highlight ((t (:inherit (tab-line-tab))))) ;; mouseover ;; (tab-line-tab-current ;; active tab in current window ;; ((t (:extend t :background "#504945" :foreground "#fdf4c1" :weight bold :underline t ;:box '(:line-width (1 . 1) :color "grey75" :style released-button) ;; )))) ;; (tab-line-tab-inactive ;; inactive tab ;; ((t (:foreground "#fdf4c1" :background "#1d2021")))) ;; (tab-line-tab ((t (:extend t :background "#504945" :foreground "#fdf4c1")))) ;; active tab in another window ;; (tab-line ((t (:foreground "#fdf4c1" :background "#1d2021" :distant-foreground "gray20")))) ;; background behind tabs ;; WIP - trying to colorize tabs (defface tab-line-tab-non-file '((t :inherit tab-line-tab-inactive :foreground "grey65")) "face for non-file tabs") (defface tab-line-tab-org-mode '((t :inherit tab-line-tab-inactive :foreground "LightGoldenrod1")) "face for org-mode tabs") (defface tab-line-tab-term-mode '((t :inherit tab-line-tab-inactive :foreground "LightSlateBlue")) "face for term-mode tabs") (defface tab-line-tab-prog-mode '((t :inherit tab-line-tab-inactive :foreground "CadetBlue1")) "face for prog-mode tabs") (defface tab-line-tab-inactive-dired '((t :inherit tab-line-tab-inactive :foreground "DarkOrange")) "face for dired tab-line tabs") (defface tab-line-tab-inactive-agenda '((t :inherit tab-line-tab-inactive :foreground "PaleVioletRed1")) "face for org agenda tab-line tabs") (defun my/tab-line-colorize (tab _tabs face buffer-p _selected-p) ;; TODO - use some 'case' syntax here (when (not (buffer-file-name tab)) (setf face `(:inherit (tab-line-tab-non-file ,face)))) (when (and buffer-p (eq (buffer-local-value 'major-mode tab) 'term-mode)) (setf face `(:inherit (tab-line-tab-term-mode ,face)))) (when (and buffer-p (eq (buffer-local-value 'major-mode tab) 'dired-mode)) (setf face `(:inherit (tab-line-tab-inactive-dired ,face)))) (when (and buffer-p (provided-mode-derived-p (buffer-local-value 'major-mode tab) 'prog-mode)) (setf face `(:inherit (tab-line-tab-prog-mode ,face)))) (when (and buffer-p (eq (buffer-local-value 'major-mode tab) 'org-mode)) (setf face `(:inherit (tab-line-tab-org-mode ,face)))) (when (and buffer-p (eq (buffer-local-value 'major-mode tab) 'org-agenda-mode)) (setf face `(:inherit (tab-line-tab-inactive-agenda ,face)))) face) :config ;; no idea - it doesn't work when set right away (when is-android (run-with-idle-timer 1 nil #'(lambda () (custom-set-faces (backquote (tab-line-tab-current ((t (:background "#504945" :underline '(:color foreground-color :style line))))))) ))) ;; https://amitp.blogspot.com/2020/06/emacs-prettier-tab-line.html ;; WIP (defun tab-line-wave () (interactive) (require 'powerline) (defvar my/tab-height 36) (defvar my/tab-left (powerline-wave-right 'tab-line nil my/tab-height)) (defvar my/tab-right (powerline-wave-left nil 'tab-line my/tab-height)) (defun my/tab-line-tab-name-buffer (buffer &optional _buffers) (powerline-render (list my/tab-left ;; (format " %s " (buffer-name buffer)) (tab-line-tab-name-truncated-buffer buffer _buffers) my/tab-right))) (setq tab-line-tab-name-function #'my/tab-line-tab-name-buffer) (set-face-attribute 'tab-line nil ;; background behind tabs :foreground "#fdf4c1" :background "#1d2021" ;; :distant-foreground "#fdf4c1" ;; :distant-foreground 'unspecified ;; :family "Fira Sans Condensed" :box nil) (set-face-attribute 'tab-line-tab nil ;; active tab in another window :inherit 'tab-line :background "#1d2021") (set-face-attribute 'tab-line-tab-current nil ;; active tab in current window :inverse-video t :box nil) (set-face-attribute 'tab-line-tab-inactive nil ;; inactive tab :background "#3c3836") (set-face-attribute 'tab-line-highlight nil ;; mouseover :background "#4c4846" :foreground 'unspecified)) ;; hmmm (run-with-idle-timer 1 nil #'tab-line-wave) :custom ((tab-line-new-button-show nil) (tab-line-close-button-show nil) (tab-line-tab-name-function #'tab-line-tab-name-truncated-buffer) (tab-line-tab-name-truncated-max 30) ;; there is a problem with cycling logic because of internal switch-to-buffer vs switch-to-next-buffer and ordering of buffers being changed ;; (tab-line-tabs-function #'(lambda () (tab-line-tabs-window-buffers))) ;; experimenting - M-h/M-l would cycle ;; (tab-line-switch-cycling t) (tab-line-tabs-function #'tab-line-tabs-window-buffers) ;;(tab-line-tabs-function #'tab-line-tabs-buffer-groups) (tab-line-tab-face-functions '(my/tab-line-colorize tab-line-tab-face-modified tab-line-tab-face-special)))) ;;tab-line-tab-face-group tab-line-tab-face-inactive-alternating) [/sourcecode] </div> </div> <div id="outline-container-org5608b75" class="outline-3"> <h3 id="org5608b75">windows & buffers</h3> <div class="outline-text-3" id="text-org5608b75"> (use-package ace-window :ensure) (use-package frame-fns :quelpa (frame-fns :fetcher wiki)) (use-package frame-cmds :quelpa (frame-cmds :fetcher wiki)) (use-package zoom-frm :after frame-fns frame-cmds :commands (zoom-frm-in zoom-frm-out) :quelpa (zoom-frm :fetcher wiki)) (use-package golden-ratio :ensure :diminish :after which-key :init (golden-ratio-mode) :custom (golden-ratio-adjust-factor 1.0) (golden-ratio-inhibit-functions '((lambda () which-key--pages-obj) ;; otherwise which-key looks too high (lambda () (and (fboundp 'multi-term-dedicated-window-p) (multi-term-dedicated-window-p))) (lambda () (and (boundp 'ediff-this-buffer-ediff-sessions) (or ediff-this-buffer-ediff-sessions ediff-diff-buffer))) )) (golden-ratio-exclude-buffer-regexp '("lsp-help" "lsp-ui-imenu" "lsp-diagnostics")) (golden-ratio-exclude-modes '("ediff-mode" ;"sql-interactive-mode" "dirvish-mode" "lsp-ui-flycheck-list" "ranger-mode" "reb-mode" "treemacs-mode" "minibuffer-mode"))) (use-package popwin :ensure :disabled :defer 0.1 ;;:config ;;(popwin-mode) ; sometimes it annoys me ) (use-package windmove :bind* (("M-H" . windmove-left) ("M-J" . windmove-down) ("M-K" . windmove-up) ("M-L" . windmove-right) ("C-S-h" . windmove-swap-states-left) ("C-S-j" . windmove-swap-states-down) ("C-S-k" . windmove-swap-states-up) ("C-S-l" . windmove-swap-states-right)) :config ;; no way to override this in other way right now - this gets remapped in org mode from outline mode which is changed by evil-collection (add-hook 'evil-collection-setup-hook #'(lambda (mode map) (when (eq mode 'outline) (evil-collection-define-key 'normal 'outline-mode-map (kbd "M-h") nil (kbd "M-j") nil (kbd "M-k") nil (kbd "M-l") nil ))))) ;; using it until I fix tab-bar-history (use-package winner :defer 0.5 :init (winner-mode 1) :bind ("M-P" . winner-undo) ("M-N" . winner-redo)) ;; experimenting (use-package rotate :ensure :commands rotate-layout-reserve-sides :config ;; I'm using golden-mode, so 'main/even' rotations are the same for me (setq rotate-functions '(rotate:main-horizontal rotate:main-vertical rotate:tiled)) (defun rotate-layout-preserve-sides () "Side windows (e.g. treemacs) don't like rotate-layout implementation." (interactive) (window-toggle-side-windows) (rotate-layout) (window-toggle-side-windows)) (defun rotate-window-preserve-sides () "Side windows (e.g. treemacs) don't like rotate-window implementation." (interactive) (window-toggle-side-windows) (rotate-window) (window-toggle-side-windows)) ) (use-package window :after evil :commands (hydra-windows/body close-and-kill-next-pane close-and-kill-current-pane) :bind ("C-x 4 1" . close-and-kill-next-pane) ("M-o" . other-window) ("M-O" . other-previous-window) ("M-m" . push-buffer-to-the-next-window) :init (evil-define-key 'motion global-map (kbd "<leader>s") 'save-buffer (kbd "<leader>d") 'delete-window (kbd "<leader>k") 'close-and-kill-current-pane (kbd "<leader>w") 'hydra-windows/body (kbd "<leader>b") 'ivy-switch-buffer (kbd "<leader>B") 'ivy-switch-buffer-other-window (kbd "<leader><SPC>") 'other-window (kbd "z j") 'evil-next-buffer (kbd "z k") 'evil-prev-buffer) (defun close-and-kill-next-pane () "If there are multiple windows, then close the other pane and kill the buffer in it also." (interactive) (other-window 1) (kill-buffer (current-buffer)) (if (not (one-window-p)) (delete-window))) (defun close-and-kill-current-pane () "Kill current buffer and close the pane, works differently to 'kill-buffer-and-window' as it check whether there are other windows at all." (interactive) (kill-buffer (current-buffer)) (if (not (one-window-p)) (delete-window))) (defun push-buffer-to-the-next-window () "Push the buffer from the current window to the next non-dedicated window" (interactive) (when (< 1 (length (window-list))) (let* ((this (selected-window)) (other (next-window)) (this-buffer (window-buffer this))) (while (window-dedicated-p other) ;; cycle until window is not dedicated (setq other (next-window other))) (set-window-buffer other this-buffer) ;; this will bury buffer by default, and close window (see set-last-tab-window-quit-restore hook) (quit-window) (select-window other)))) (defun set-last-tab-window-quit-restore () "Sets 'quit-restore' window parameter if this is the last tab so the window is closed. When it's last window in the current tab-bar-tab - close that tab." (let* ((tab-line-tabs (tab-line-tabs-window-buffers)) (windows (window-list)) (this-window (selected-window)) (this-buffer (window-buffer this-window))) (when (= 1 (length tab-line-tabs)) ;; when it's last tab - hide window (if (= 1 (length windows)) ;; and (= 1 (length (tab-bar-tabs))) ;; when it's last window in the tab-bar-tab - close tab-bar-tab ;; see 'window.el:5175 quit-restore-window' (set-window-parameter this-window 'quit-restore `(window tab ,(previous-window) ,this-buffer)) ;; (run-with-idle-timer 1 nil #'tab-bar--update-tab-bar-lines) (set-window-parameter this-window 'quit-restore `(window window ,(previous-window) ,this-buffer)))))) (defun other-previous-window () (interactive) "Simply select previous window" (other-window -1)) :hook (quit-window . set-last-tab-window-quit-restore) :pretty-hydra (hydra-windows (:hint nil :forein-keys warn :quit-key "q" :title (with-faicon "windows" "Windows & Buffers" 1 -0.05)) ("Windows & Frames" (("d" delete-window "delete window") ("o" delete-other-windows "delete others" :exit t) ("v" split-window-horizontally "split right") ("h" split-window-vertically "split below") ("a" ace-window "ace" :exit t) ("w" other-window "other window" :exit t) ("fk" delete-frame "delete frame") ("fo" delete-other-frames "delete others") ("fn" make-frame-command "make frame") ("u" winner-undo) ("U" winner-redo)) "Move & Size" (("B" balance-windows "balance") ("L" shrink-window-horizontally "narrow") ("H" enlarge-window-horizontally "widen") ("J" shrink-window "lower") ("K" enlarge-window "heighten") ("s" window-swap-states "swap") ("m" rotate-window-preserve-sides "rotate window") ("l" rotate-layout-preserve-sides "rotate layout")) "Buffer" (("r" rename-buffer "rename" :exit t) ("c" clone-buffer "clone" :exit t) ("p" previous-buffer "previous") ("n" next-buffer "next") ("b" bury-buffer "bury") ("k" kill-current-buffer "kill") ("K" close-and-kill-current-pane "kill buf+win" :exit t)) "Zoom & Alpha" (("-" zoom-frm-out "zoom out") ("+" zoom-frm-in "zoom in") ("=" zoom-frm-unzoom "reset") ("0" text-scale-adjust "buffer" :exit t) ("<" frame-decr-alpha "alpha -") (">" frame-incr-alpha "alpha +") ))))
8.3. shuckle
testing it
https://gist.github.com/rksm/8c07d9ccc9e15adf752d3dd73dd9a61e
(shackle-mode)
https://gist.github.com/rksm/8c07d9ccc9e15adf752d3dd73dd9a61e
(shackle-mode)
(defun rk/open-compilation-buffer (&optional buffer-or-name shackle-alist shackle-plist) "Helper for selecting window for opening *compilation* buffers." ;; find existing compilation window left of the current window or left-most window (let ((win (or (cl-loop for win = (if win (window-left win) (get-buffer-window)) when (or (not (window-left win)) (string-prefix-p "*compilation" (buffer-name (window-buffer win)))) return win) (get-buffer-window)))) ;; if the window is dedicated to a non-compilation buffer, use the current one instead (when (window-dedicated-p win) (let ((buf-name (buffer-name (window-buffer win)))) (unless (string-prefix-p "*compilation" buf-name) (setq win (get-buffer-window))))) (set-window-buffer win (get-buffer buffer-or-name)) (set-frame-selected-window (window-frame win) win))) (use-package shackle :ensure :diminish :config (shackle-mode) :custom (shackle-rules '( (compilation-mode :custom rk/open-compilation-buffer :select t) ;;("\\*Apropos\\|Help\\|Occur\\|tide-references\\*" :regexp t :same t :select t :inhibit-window-quit t) ("\\*magit" :regexp t :same t :select t) ("\\*shell.*" :regexp t :same t :select t) ("\\*PowerShell.*" :regexp t :same t :select t) ("\\*Cargo.*" :regexp t :other t :select nil) ("*Messages*" :select nil :other t) ("*go-guru-output*" :select t :same t) ("*Proced*" :select t :same t) ("*Buffer List*" :select t :same t) ("\\*Pp Eval" :regexp t :same nil :select t :other t) ("*Messages*" :same nil :other t :select t :inhibit-window-quit t) ;; slime ("*slime-source*" :select nil :same nil :other t) ("*slime-description*" :select nil :other t :inhibit-window-quit t) ("\\*slime-repl" :regexp t :same nil :select nil :other t) ;; ("\\*sldb" :regexp t :other t :inhibit-window-quit t :select t) ("\\*slime-compilation" :regexp t :same nil :select nil :other t) ("*slime-scratch*" :same nil :select t :other t) ;; ert ("*ert*" :select nil :same nil :other t) ;; clojure ("*sesman CIDER browser*" :inhibit-window-quit t :select t :same t) ("\\*cider-repl" :regexp t :same nil :other t))) (shackle-default-rule nil))
8.4. ibuffer
;; show invisible buffers: C-u g r (use-package ibuffer ;; :disabled t ;; trying bufler :ensure ;; :custom ;; (ibuffer-saved-filter-groups ;; '(("ibuffer-groups" ;; ("help" (or (mode . helpful-mode) (mode . help-mode) (name . "help"))) ;; ("non-file" (and (not (mode . dired-mode)) (not visiting-file) (not (name . "config.org")))) ;; ("work" (or (name . "work\\/") (directory . "Documents/work"))) ;; ("emacs" (or (directory . "/usr/local/share/emacs") (directory . "\\.config/emacs") (name . "config.org"))) ;; ("system" (or (directory . "\\.config") (directory . "configs"))) ;; ("org" (or (name . "Org Agenda") (directory . "Dropbox/org"))) ;; ))) ;; (ibuffer-saved-filters ;; '(("help" ;; (or ;; (mode . helpful-mode) ;; (mode . help-mode) ;; (name . "help"))) ;; ("programming" ;; (or ;; (derived-mode . prog-mode) ;; (mode . ess-mode) ;; (mode . compilation-mode))) ;; ("text document" ;; (and ;; (derived-mode . text-mode) ;; (not ;; (starred-name)))) ;; ("mail" ;; (or ;; (mode . message-mode) ;; (mode . mail-mode) ;; (mode . gnus-group-mode) ;; (mode . gnus-summary-mode) ;; (mode . gnus-article-mode))))) :bind ("C-x C-b" . ibuffer)) (use-package all-the-icons-ibuffer :ensure :after ibuffer :disabled :hook (ibuffer-mode . all-the-icons-ibuffer-mode)) (use-package nerd-icons-ibuffer :ensure :after ibuffer nerd-icons :hook (ibuffer-mode . nerd-icons-ibuffer-mode)) ;; much better than all-the-icons-ibuffer (use-package ibuffer-vc :ensure :demand :after ibuffer :config (add-hook 'ibuffer-hook (lambda () (ibuffer-vc-set-filter-groups-by-vc-root) (unless (eq ibuffer-sorting-mode 'alphabetic) (ibuffer-do-sort-by-alphabetic)))) (setq ibuffer-formats '((mark modified read-only vc-status-mini " " (name 23 23 :left :elide) " " (size 9 -1 :right) " " (mode 16 16 :left :elide) " " (vc-status 16 16 :left) " " vc-relative-file))) )
8.5. bufler
(use-package bufler :disabled t :ensure :after tab-bar ;;:config (bufler-tabs-mode) :bind ("C-x C-b" . bufler) ("C-x b" . bufler-switch-buffer))
8.6. various
(defun my/display-buffer-please-no (buf &rest ignore) (error "Inhibited buffer: %s" (buffer-name buf))) (add-to-list 'display-buffer-alist '("\\*Quail Completions" . (my/display-buffer-please-no)))
8.7. under test
;(unless (package-installed-p 'workgroups2) (package-install 'workgroups2)) ;(setq wg-prefix-key "C-c z") ;(require 'workgroups2) ; ok, this one is very buggy ;(workgroups-mode) ;; (defun install (pkg) ;; "Install package if not installed already." ;; (unless (package-installed-p pkg) (package-install pkg))) ;; (install 'eyebrowse) ;; (with-eval-after-load 'eyebrowse ;; (eyebrowse-setup-opinionated-keys) ;; (with-eval-after-load 'evil ;; (eyebrowse-setup-evil-keys))) ;; ;(eyebrowse-mode t) (use-package burly :ensure :disabled) ; didn't like any of these ;(use-package persp-mode) ;(use-package perspective) ;(use-package treemacs-perspective)
9. utils
(use-package crux :ensure :bind ("M-<backspace>" . crux-kill-line-backwards)) ;; testing (use-package easy-kill :ensure :bind ([remap kill-ring-save] . easy-kill) ([remap mark-sexp] . easy-mark) ;; sort of evil-surround but different :custom (kill-ring-max 300)) ;; testing (use-package key-chord :ensure :disabled :config (key-chord-mode 1) (key-chord-define-global "hj" 'undo) (key-chord-define-global ",." "<>\C-b"))
9.1.1. utils-hydra
(with-eval-after-load 'evil (evil-define-key 'motion global-map (kbd "<leader>u") 'utils-hydra/body) (evil-define-key 'motion global-map (kbd "<leader>Q") 'save-buffers-kill-emacs)) ;;(kbd "<leader>qq") 'save-buffers-kill-terminal (pretty-hydra-define utils-hydra (:hint nil :color blue :quit-key "q" :exit t :title (with-fileicon "fancy" "Utils")) ("Emacs" (("eps" profiler-start "profile") ("epc" #'(lambda () (interactive) (profiler-start 'cpu)) "profile cpu") ("epm" #'(lambda () (interactive) (profiler-start 'mem)) "profile mem") ("epq" profiler-stop "profile stop") ("epr" profiler-report "profile report") ("el" list-packages) ("xt" counsel-load-theme "theme") ("xu" counsel-unicode-char "unicode") ("xs" counsel-set-variable "set variable")) "User" (("ue" elfeed) ("um" mu4e) ("uM" mu4e-fast-update-mail-and-index "mu4e upd") ("uc" calculator) ("ut" google-translate-smooth-translate "ggl-trnsl") ("up" pass) ("ui" password-store-insert "pass insert") ("ue" password-store-edit "pass edit") ("j" hledger-run-command "hledger")) "System" (("sc" counsel-compile "compile") ("sj" counsel-file-jump "file jump") ("sl" counsel-locate "locate") ("sa" counsel-linux-app "linux app") ("st" counsel-tramp "tramp") ("sz" counsel-fzf "fzf") ("sd" proced) ("so" ovpn) ("sp" prodigy) ("p" list-processes "processes") ("o" crux-open-with "open-with")) "Files & Buffers" (("gG" counsel-git "git") ("gg" counsel-rg "rg") ("gr" counsel-git-grep "git grep") ("gl" counsel-git-log "git log") ("go" counsel-org-file "org file") ("gd" find-grep-dired "grep dired") ("c" crux-kill-buffer-truename "cp buffer name") ("b" counsel-bookmark "bookmark") ("r" rename-buffer "rename buffer") ("R" rename-file-and-buffer "rename file and buffer") ("yn" copy-file-name "copy file name") ("yp" copy-file-path "copy file path") ("d" crux-delete-file-and-buffer "delete file and buffer") ("fs" crux-create-scratch-buffer "scratch") ("fe" crux-visit-shell-buffer "find eshell buffer") ("fE" crux-visit-term-buffer "find term buffer") ("i" find-user-init-file "find config.org") ("I" byte-recompile-init-file "byte-recompile config") ("D" toggle-window-dedicated "toggle dedicated window")))) ;; define binding lookup for init.el (defun find-user-init-file () "Edit the `user-init-file', in another window." (interactive) ;;(find-file-other-window (concat user-emacs-directory "config.org")) (find-file (file-truename (concat user-emacs-directory "config.org")))) (defun toggle-window-dedicated () "Control whether or not Emacs is allowed to display another buffer in current window." (interactive) (message (if (let (window (get-buffer-window (current-buffer))) (set-window-dedicated-p window (not (window-dedicated-p window)))) "%s: Can't touch this!" "%s is up for grabs.") (current-buffer))) (defun rename-file-and-buffer () "Rename the current buffer and file it is visiting." (interactive) (let ((filename (buffer-file-name))) (if (not (and filename (file-exists-p filename))) (message "Buffer is not visiting a file!") (let ((new-name (read-file-name "New name: " filename))) (cond ((vc-backend filename) (vc-rename-file filename new-name)) (t (rename-file filename new-name t) (set-visited-file-name new-name t t))))))) ;; next two taken from spacemacs (defun get-file-path () "Retrieve the file path of the current buffer. Returns: - A string containing the file path in case of success. - `nil' in case the current buffer does not have a directory." (when-let (file-path (buffer-file-name)) (file-truename file-path))) (defun copy-file-name () "Copy and show the file name of the current buffer." (interactive) (if-let* ((file-path (get-file-path)) (file-name (file-name-nondirectory file-path))) (progn (kill-new file-name) (message "%s" file-name)) (message "WARNING: Current buffer is not attached to a file!"))) (defun copy-file-path () "Copy and show the file path of the current buffer." (interactive) (if-let* ((file-path (get-file-path))) (progn (kill-new file-path) (message "%s" file-path)) (message "WARNING: Current buffer is not attached to a file!"))) ;; todo - add dedicated window to modeline ;; (setq global-mode-string ;; (cond ((consp global-mode-string) ;; (add-to-list 'global-mode-string (t (:eval my-func)))) ;; ((not global-mode-string) ;; (list my-string)) ;; ((stringp global-mode-string) ;; (list global-mode-string my-string))))
9.1.2. toggle-hydra
(with-eval-after-load 'evil (evil-define-key 'motion global-map (kbd "<leader>x") 'toggle-hydra/body)) ;; silence byte-compiler (declare-function lsp-mode "lsp") (pretty-hydra-define+ toggle-hydra (:hint nil :color amaranth :quit-key "q" :title (with-faicon "toggle-on" "Toggle" 1 -0.05)) ("Emacs" (("C-s" desktop-save-mode "desktop mode" :toggle t) ("M-s" auto-sudoedit-mode "auto-sudoedit-mode" :toggle t) ("de" toggle-debug-on-error "debug on error" :toggle debug-on-error) ("dq" toggle-debug-on-quit "debug on C-g" :toggle debug-on-quit)) "Text" (("c" global-company-mode "company (g)" :toggle t) ("y" yas-global-mode "yas (g)" :toggle t) ("a" abbrev-mode "abbrev" :toggle t) ("n" auto-insert-mode "auto-insert" :toggle t) ("m" evil-mc-mode "evil-mc" :toggle t) ("+" evil-snipe-mode "evil-snipe" :toggle t) ("t" toggle-truncate-lines "trunc-lines" :toggle truncate-lines) ("u" global-evil-surround-mode "evil surround (g)" :toggle t)) "Prog" (("e" electric-operator-mode "electric operator" :toggle t) ("f" flycheck-mode "flycheck" :toggle t) ("F" global-flycheck-mode "flycheck (g)" :toggle t) ("l" lsp-mode "lsp" :toggle t) ("H" hl-todo-mode "hl-todo" :toggle t) ("o" origami-mode "origami" :toggle t) ("H" hs-minor-mode "hide-show" :toggle t) ("C" editorconfig-mode "editorconfig" :toggle t) ("P" smartparens-strict-mode "smartpar strct" :toggle t) ("S" show-smartparens-mode "show smartparens" :toggle t) ("s" smartparens-mode "smartparens" :toggle t)) "UI" (("i" ivy-rich-mode "ivy-rich" :toggle t) ("b" buffer-tab-assign-mode "auto-buf-tab" :toggle t) ("h" back-button-mode "back-button" :toggle t) ("pw" which-key-posframe-mode "wk-posframe" :toggle t) ("ph" hydra-posframe-mode "hydra-posframe" :toggle t) ("pi" ivy-posframe-mode "ivy-posframe" :toggle t) ("g" good-scroll-mode :toggle t) ("G" golden-ratio-mode :toggle t) ("T" my/toggle-light-dark "light/dark theme" :toggle my/toggle-dark) ("n" linum-mode "linum (g)" :toggle t) ("w" global-whitespace-mode "whitespace (g)" :toggle t) ("r" rainbow-mode "rainbow" :toggle t) ("B" page-break-lines-mode "page brks" :toggle t) ("L" global-hl-line-mode "hl-line (g)" :toggle t) ("D" dimmer-mode "dim others" :toggle t) )))
10. org
10.1. org
(use-package org-contrib :ensure :demand :after org :custom (org-expiry-inactive-timestamps t) :config (require 'org-expiry) :hook ;; adds CREATED property - works after each capture ((org-capture-before-finalize . (lambda() (save-excursion (org-back-to-heading) (org-expiry-insert-created)))) ;; adds CREATED property - works after changing state (org-after-todo-state-change . (lambda () (when (string= org-state "TODO") (save-excursion (org-back-to-heading) (org-expiry-insert-created))))))) (use-package org ;;:ensure org-contrib ;; this is how it works - name of the actual package to load :defines (org-state) ;; to silence byte-compiling on after-state-change hooks (see at the bottom of :config) :after evil :init (evil-define-key 'motion global-map (kbd "<leader>o") 'hydra-org/body (kbd "<leader>a") 'org-agenda (kbd "<leader>i") 'org-capture) (evil-define-key 'motion org-mode-map (kbd "<leader>/") 'org-goto) (general-def '(normal motion) org-mode-map "M-l" nil "M-h" nil "M-j" nil "M-k" nil) :config (define-key org-mode-map [(double-mouse-1)] 'org-cycle) :bind (:map org-src-mode-map ("C-c C-c" . org-edit-src-exit)) :commands (org-capture hydra-org/body) :custom ((org-archive-location "~/Dropbox/org/archive/%s_archive::") (org-directory "~/Dropbox/org/") (org-tags-exclude-from-inheritance (quote ("project" "area"))) (org-tags-column 0) ;; -70 ;; more modules - longer load time (org-modules '( ;;ol-bbdb ol-bibtex ;;org-crypt ;;ol-docview ;;ol-eww org-id ;;ol-info ;;org-inlinetask org-mouse org-tempo ;;ol-w3m ol-eshell ;;org-annotate-file ol-bookmark org-checklist org-choose ;;org-learn org-screenshot orgtbl-sqlinsert org-toc )) ;;(org-format-latex-options (plist-put org-format-latex-options :scale 1.5)) ;; refile (org-outline-path-complete-in-steps nil) ; Refile in a single go (org-refile-use-outline-path 'file) ; Show full paths for refiling - trick to refile in 0 level (org-refile-allow-creating-parent-nodes 'confirm) ; create new parent on the fly (org-goto-interface 'outline-path-completion) (org-outline-path-complete-in-steps nil) ;; id (org-id-link-to-org-use-id nil) ;; will create id on C-c C-l ;;'create-if-interactive-and-no-custom-id (org-link-search-must-match-exact-headline nil) ;; headline search link ;; experiments (bidi-paragraph-direction t) (org-hide-emphasis-markers t) (org-fontify-done-headline t) (org-fontify-whole-heading-line t) (org-fontify-quote-and-verse-blocks t) (org-cycle-emulate-tab t) ;; default setting - TAB in org fallbacks to indent (org-startup-folded 'fold) (org-return-follows-link t) ;; ret follows link (in evil, go to <insert> and then return) (org-priority-default ?C) (org-priority-lowest ?D) (org-log-done t) (org-use-property-inheritance nil) ;'("GOAL" "VISION")) ;; we can control inheritance directly in function org-entry-get (org-log-into-drawer "LOGBOOK") ;; log into LOGBOOK (org-adapt-indentation t) ;;(org-checkbox-hierarchical-statistics t) (org-hierarchical-todo-statistics nil) ;; same as using :COOKIE_DATA: recursive - will count '%' recursively not only direct children (org-checkbox-hierarchical-statistics nil) ;; this will count not only direct children checks ;;(org-enforce-todo-checkbox-dependencies t) ;; effort & column view ;;(org-columns-default-format "%25ITEM %TODO %3PRIORITY %TAGS") (org-columns-default-format-for-agenda "%60ITEM(Task) %6Effort(Estim){:}") (org-global-properties nil ;; '(("Effort_ALL" . "0 0:05 0:10 0:15 0:25 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 7:00 10:00 15:00 24:00")) ) (org-attach-dir-relative t) (org-attach-preferred-new-method 'dir) (org-link-abbrev-alist '(("att" . org-attach-expand))) ;; this allows using links to e.g. images attachments as att:1.png ) :config (require 'org-attach) (with-eval-after-load 'org-indent (diminish 'org-indent-mode "")) (define-key org-mode-map [(control tab)] nil) ;; unset - C-tab used for tab cycling (define-key org-mode-map (kbd "M-h") nil) ;; unset - M-h used for previous-buffer ;;(org-indent-mode t) ;; todo - electric-indent-mode ;;this one seems to work only with deadlines ;; (when (display-graphic-p) ;; (require 'org-notify)) ;;(org-notify-start) (with-eval-after-load 'ox-html (add-to-list 'org-html-inline-image-rules '("https" . "lh3.googleusercontent.com"))) ;; google photos links are without extension :pretty-hydra (hydra-org (:hint nil :color teal :quit-key "q" :title (with-fileicon "org" "Org" 1 -0.05)) ("Action" (("a" org-agenda "agenda") ("b" org2blog-user-interface "org2blog") ("j" org-goto "goto") ("C" cfw:open-org-calendar "calfw-org") ;; ("s" my/org-ql-goals "goals") ("c" org-capture "capture") ;;("g" org-gcal-fetch "gcal fetch") ("g" my/org-set-goal "set goal") ("G" org-gcal-sync "gcal sync") ("S" org-insert-structure-template "structure template") ("L" org-store-link "store-link") ("l" org-insert-link-global "insert-link") ("i" org-id-copy "copy id") ("A" org-archive-done-in-file "archive done in file") ("d" org-decrypt-entry "decrypt") ("I" org-info-find-node "org info find") ("k" org-cut-subtree "cut-subtree") ("o" org-open-at-point-global "open-link") ("r" org-refile "refile") ("t" org-show-todo-tree "todo-tree")))) :init ;; (defun my/org-ql-goals () ;; (interactive) ;; (org-ql-search (org-agenda-files) '(and (todo) (not (todo "GOAL")) (not (todo "VISION"))) ;; :super-groups '((:auto-map ;; (lambda (item) ;; (-when-let* ((goal-link (org-entry-get (org-super-agenda--get-marker item) "GOAL"))) ;; (message goal-link) ;; (org-link-open-from-string goal-link) ;; (org-get-heading 'notags 'notodo))))))) ;;;; archive all DONEs in file ;;;; ;; in-progress, but not needed actually - do the same - C-c a T DONE * B $ (defun org-archive-done-in-file () (interactive) (org-map-entries 'org-archive-subtree "/DONE" 'file)) )
10.2. org-babel
;; babel header info - https://org-babel.readthedocs.io/en/latest/header-args/#results (use-package ob ;org-babel :after org :commands (my/tangle-async) :config (require 'async) (defun my/tangle-async () "Tangle asynchronously current file." (interactive) (let ((file (buffer-file-name))) (async-start `(lambda () (require 'org) (org-babel-tangle-file ,file)) `(lambda (result) (message (format "tangle-async finished for: %s" result)) (mapcar (lambda (out-file) ;; make it a flag input arg? (when (string-match-p ".el$" out-file) ;;(message out-file) ;; byte/native-compilation doesn't really speed up init ;;(byte-recompile-file out-file) ;; native compile ;; async native-compile has some problems, only synchronous works with native-compile ;;(native-compile-async out-file) ;nil t nil) ;; load file after async finish )) result) ;;(message (format "byte&native recompile finished")) )))) (diminish 'org-src-mode) :custom ((org-confirm-babel-evaluate (lambda (lang body) (not (member lang '("plantuml" "emacs-lisp" "sql" "sh" "sqlite" "sql-mode"))))) (org-babel-load-languages '((emacs-lisp . t) ;(gnuplot . t) ;(python . t) (plantuml . t) (shell . t) ;(ledger . t) ;(sqlite . t) (sql . t))) (org-plantuml-jar-path (expand-file-name "/usr/share/java/plantuml/plantuml.jar")) (add-to-list 'org-src-lang-modes '("plantuml" . plantuml)) (org-src-preserve-indentation t) ;; without this it gets crazy when editing src inline (org-src-fontify-natively t) (org-src-window-setup 'current-window) ; 'plain 'split-window-right ;reorganize-frame;'current-window (org-src-tab-acts-natively t)) :hook ;; auto redisplay image after C-c C-c otherwise need to manually C-cxv (org-babel-after-execute . org-redisplay-inline-images) ;; automatically open src edit when in the src block (org-mode . (lambda() (make-local-variable 'evil-insert-state-entry-hook) (add-hook 'evil-insert-state-entry-hook #'org-edit-src-code)))) (use-package ob-async :ensure :after org)
10.3. capture templates
(setq org-capture-templates '( ("i" "[inbox]" entry (file "~/Dropbox/org/inbox.org" ) "* %i%?") ("g" "Goal" entry (file "~/Dropbox/org/goals.org") "* GOAL *%^{Goal title}* \t:%^G:goal:\n\ :PROPERTIES:\n:CREATED: %U\n:END:\n\ %^{Goal description}") ("p" "Project" entry (file "~/Dropbox/org/inbox.org") "* PROJECT *%^{Project title}* [%] :%^G:project:\n\ :PROPERTIES:\n:CREATED: %U\n:END:\n\ GOAL: %^{Project goal}\n\ - [ ] %^{item1}") ("h" "Habit" entry (file+headline "~/Dropbox/org/personal.org" "*habits*") "* %?\n\ SCHEDULED: <%<%Y-%m-%d %a .+1d>>\n\ :PROPERTIES:\n\ :CREATED: %U\n\ :STYLE: habit\n\ :REPEAT_TO_STATE: \n\ :LOGGING: DONE(!)\n\ :ARCHIVE: archive/%s_archive::* Habits\n\ :END:\n") ("a" "Appointment" entry (file "~/Dropbox/org/gcal/personal.org") "* %?\n\n%^T") ("j" "Journal" entry (file+olp+datetree "~/Dropbox/org/journal.org") "* %<%H:%M> %?\n %i From: %a" :empty-lines 1) ("e" "Word [english]" entry (file "~/Dropbox/org/english.org") "* %i%?") ("o" "Org idea" entry (file+olp "~/Dropbox/org/org.org" "ideas" "org ideas") "*** TODO %i%?") ("b" "Buylist" entry (file+olp "~/Dropbox/org/personal.org" "*buylist*") "** TODO %i%?") ("m" "Meal" entry (file+olp "~/Dropbox/org/food.org" "_MEAL_") "** %t meal\n\t- breakfast: %^{Breakfast}\n\t- lunch: %^{Lunch}\n\t- snack: %^{Snack}\n\t- dinner: %^{Dinner}") ("t" "Personal task" entry (file+olp "~/Dropbox/org/personal.org" "_TASKS_") "** TODO %i%?\n SCHEDULED: <%<%Y-%m-%d %a>>") ("I" "Idea") ("Ib" "talk/blog" entry (file+olp "~/Dropbox/org/ideas.org" "*talk/blog*") "** TODO %i%?") ("E" "Emacs todo" entry (file+headline "~/Dropbox/org/emacs.org" "ideas / todo") "* TODO %i%?"))) ;; description of capture ;;(setq org-capture-templates '(( ;; "t" ; key ;; "Todo" ; description ;; entry ; type ;; (file+headline "C:/.../org/notes.org" "tasks") ; target ;; "* TODO [#B] %^{Todo} %(org-set-tags) \n:PROPERTIES:\n:Created: %U\n:END:\n\n%?" ; template ;; :prepend t ; properties ;; :empty-lines 1 ; properties ;; :created t ; properties ;; )))
10.4. keywords & tags
(setq org-todo-keywords '( (sequence "TODO(t)" "DRAFT(l)" "IN-PROGRESS(i)" "PROCESS(P)" "WAITING(w!)" "DELEGATED(e@/!)" "ON-HOLD(h@/!)" "|") (sequence "IDEA(i)" "MAYBE(m)" "SOMEDAY(s)" "PROJECT(p)" "|") (sequence "VISION(v)" "GOAL(g)" "FOCUS(f)" "MODE(o)" "|") (type "WEAKNESS(n)" "TECHNIQUE(q)" "HABIT(j)" "SKILL(k)" "CHEATSHEET(a)" "RESOLUTION(r)") (type "BOOK(z)" "|") (sequence "|" "DONE(d!)" "CLOSED(c@/!)" "CANCELLED(C@/!)" "DUPLICATE(D)" "SKIPPED(S/!)") ) ) ;; Setting Colours (faces) for todo states to give clearer view of work ;; lookup by M-x list-colors-display (setq org-todo-keyword-faces '( ("PROJECT" . "maroon2") ("GOAL" . "SeaGreen4") ("VISION" . "DeepSkyBlue") ("FOCUS" . "orange") ("IDEA" . "orange") ("WEAKNESS" . "violet") ("RESOLUTION" . "turquoise") ("TECHNIQUE" . "aquamarine") ("BOOK" . "darkorange") ("CHEATSHEET" . "turquoise") ("SKILL" . "PaleGreen") ("HABIT" "coral") ("MODE" . "peru") ;;("TODO" . "orange red") ("DRAFT" . "orange red") ("SOMEDAY" . "IndianRed2") ("MAYBE" . "IndianRed2") ("IN-PROGRESS" . "dark goldenrod") ("PROCESS" . "goldenrod") ("WAITING" . "blue violet") ("DELEGATED" . "dark olive green") ("ON-HOLD" . "orange") ("DONE" . "forest green") ("CLOSED" . "cyan4") ("DUPLICATE" . "cyan4") ("CANCELLED" . "cyan4") ("SKIPPED" . "cyan4") ) ) ;; TODO=#fe450e") (setq org-tag-alist '( ("@office" . ?O) ("@home" . ?H) ("@rivne" . ?r) ("@phone" . ?o) ("@computer" . ?c) ("@internet" . ?i) ("@shop" . ?S) ("@grocery" . ?g) ("@pharmacy" . ?R) ("work" . ?w) ("blocking" . ?B) ("delegated" . ?D) ("goal" . ?G) ("family" . ?f) ("personal" . ?p) ("project" . ?P) ("area" . ?A) ("health" . ?h) ("buy" . ?b) ("car" . ?a) ("sell" . ?s) ("income" . ?I) ("expense" . ?E) ("ptashka" . ?k) ("deep" . ?d) ) )
10.5. evil-org
(use-package evil-org :ensure :diminish :after evil org :hook (org-mode . evil-org-mode) :custom (evil-org-key-theme '(navigation insert textobjects calendar)) ; no 'additional' - conflict with windmove ) (use-package evil-org-agenda :demand :after evil-org org-agenda :config (evil-org-agenda-set-keys) (general-def 'motion org-agenda-mode-map "SPC" (general-simulate-key "<leader>")) (evil-define-key 'motion org-agenda-mode-map (kbd "M-k") nil (kbd "M-j") nil ;; free up for windmove "ZK" 'org-habit-toggle-display-in-agenda "ZD" 'org-agenda-toggle-deadlines "T" 'org-agenda-todo-yesterday))
10.6. org-agenda
(use-package org-agenda ;; :after evil general :custom (org-id-search-archives nil) (org-modules '(org-habit org-id)) (org-agenda-tags-column -100) (org-extend-today-until 2) ;; the day ends at 2am (org-habit-graph-column (if is-android 35 58)) (org-habit-show-all-today nil) (org-habit-preceding-days 17) (org-habit-following-days 5) (org-agenda-prefix-format '((agenda . " %i %-16:c%?-12t% s") ;(agenda . " %i %-23b %-16:c%?-12t% s") (todo . " %i %-16:c") (tags . " %i %-16:c") (search . " %i %-16:c"))) (org-stuck-projects '("+project" ("TODO" "IN-PROGRESS") nil "")) ;default ;'("+LEVEL=2/-DONE" ("TODO" "NEXT" "NEXTACTION") nil "")) (org-deadline-warning-days 7) (org-agenda-breadcrumbs-separator " ❱ ") (org-agenda-log-mode-items '(state) ;; '(closed state) ) ;;(setq org-ellipsis "…") (org-agenda-skip-scheduled-delay-if-deadline t) (org-agenda-skip-scheduled-if-deadline-is-shown t) (org-agenda-skip-deadline-prewarning-if-scheduled t) (org-agenda-block-separator (string-to-char " ")) (org-agenda-compact-blocks t) ;; makes everything much more compact, makes above option redundant as there are no separators ;; doesn't really work for todo/tags ;; (org-agenda-sorting-strategy ;; '((agenda habit-down time-up priority-down category-keep) ;; (todo priority-down category-keep) ;; (tags priority-down category-keep) ;; (search category-keep)) ;; ) (org-agenda-entry-text-maxlines 20) (org-agenda-entry-text-leaders " ") :config (require 'org) (require 'org-habit) (org-id-update-id-locations nil t) (evil-set-initial-state 'org-agenda-mode 'motion) (require 'org-clock-budget) (require 'bookmark) (bookmark-maybe-load-default-file) ;; this is for agenda hook below (add-to-list 'display-buffer-alist '("*Org Agenda*" (display-buffer-reuse-window display-buffer-in-direction ;; side-window is problematic e.g. when trying to delete-other-windows or using org-agenda-todo ;;display-buffer-in-side-window ) (direction . right) (side . right) (slot . -1) (window-width . 0.5) (reusable-frames . nil))) ;; like it (general-def '(normal insert motion) org-agenda-mode-map "<backtab>" 'org-agenda-entry-text-mode) :hook (org-agenda-mode . org-agenda-entry-text-mode) (org-agenda-mode . (lambda () ;; to make agenda buffer part of org directory project (setq default-directory org-directory))) )
10.7. org-agenda custom commands
(defun agenda-tags-todo-with-goals (title todo-keyword query) `(tags-todo ,query ((org-agenda-overriding-header ,title) (org-agenda-todo-keyword-format ,todo-keyword) (org-agenda-remove-tags t) (org-agenda-prefix-format (if is-android "%?-12t% s" ;; " %-3i %12c %-17(concat \"❱ \" (my/org-get-parent-goal)) " " %i %t %s " )) (org-agenda-todo-keyword-format "%9s")))) (defun agenda-schedule (&optional priority) (let* ((skip-func (if priority `(and (not (or (not (equal "habit" (org-entry-get nil "STYLE"))) ; skip not-<priority> habits, leave scheduled/deadlines (equal ,priority (org-entry-get nil "PRIORITY")))) (point-at-eol)) nil)) (log-mode (if (not (string= priority "A")) 't 'nil))) `(agenda "" ((org-agenda-span 5) (org-agenda-skip-function ',skip-func) (org-agenda-show-log ,log-mode) (org-agenda-todo-keyword-format " 🔨") ;; (org-agenda-skip-scheduled-if-done t) ;; (org-agenda-skip-timestamp-if-done t) ;; (org-agenda-skip-deadline-if-done t) (org-agenda-remove-tags t) ;; (org-agenda-start-day "+0d") ;; (org-agenda-repeating-timestamp-show-all nil) (org-agenda-current-time-string "⮜┈┈┈┈┈┈┈ now") (org-agenda-scheduled-leaders '("⏰" "⏰.%2dx: ")) (org-agenda-deadline-leaders '("☠" "In %3d d.: " "%2d d. ago: ")) (org-agenda-time-grid (quote ((today require-timed remove-match) (0900 2100) " " "┈┈┈┈┈┈┈┈┈┈┈┈┈"))) (org-agenda-overriding-header "⚡ Schedule:") (org-agenda-prefix-format (if is-android " %?-12t% s" ;; " %-3i %12c %-17(concat \"❱ \" (my/org-get-parent-goal)) %?-12t% s" " %i %t %s " )) )))) ;; custom agendas ;; (with-eval-after-load 'org-agenda (setq org-agenda-custom-commands `(("c" . "Custom Agendas") ("cB" "Blocking others" ((tags "+blocking/!")) nil nil) ("ct" "Today" ((agenda "" ((org-agenda-span 1))) nil) nil) ("cT" "All Todo" ((tags-todo "-project-book/!-GOAL-VISION-MODE-FOCUS-SOMEDAY-MAYBE-DRAFT-IDEA-TOREAD-READING")) nil nil) ("cA" "Appointments" agenda* nil nil) ("cW" "Waiting for" ((todo "+WAITING")) nil nil) ("cd" "Delegated" ((tags-todo "+delegated/!+DELEGATED")) nil nil) ("cD" "Done" ((todo "DONE|CANCELLED|CLOSED|SKIPPED")) nil nil) ("cu" "Unscheduled" ((tags-todo "-project-book/!-GOAL-MODE-FOCUS-VISION-SOMEDAY-MAYBE-DRAFT-IDEA-TOREAD-READING" ((org-agenda-overriding-header "\nUnscheduled TODO") (org-agenda-skip-function '(org-agenda-skip-entry-if 'timestamp))))) nil nil) ("cI" "All A-B Todo" ((tags-todo "-project+PRIORITY={A\\|B}/!-GOAL-VISION-MODE-FOCUS-SOMEDAY-MAYBE-DRAFT-IDEA-TOREAD-READING")) ((org-agenda-overriding-header "All A-B Todo")) nil) ("ci" "All In Progress" ((todo "IN-PROGRESS|PROCESS")) ((org-agenda-max-entries 25)) nil) ("cp" "Projects" ((tags-todo "+project")) nil nil) ("cg" "Goals" ((todo "GOAL")) nil nil) ("cG" "Current Goals" ((tags-todo "+current+goal/!-MODE")) nil nil) ("cv" "Vision" ((todo "VISION")) nil nil) ("cS" "Someday/Maybe" ((todo "SOMEDAY|MAYBE")) nil nil) ("cs" "Stuck Projects" ((stuck "")) nil nil) ("ca" "Areas" ((tags "+area")) nil nil) ("cb" "Buylist" ((tags "+buy")) nil nil) ("co" "Books" ((tags-todo "+book")) nil nil) ;("cD" "Deep" ((tags-todo "+deep")) nil nil) ;("ck" "Deep work" ((tags-todo "+deep+work")) nil nil) ;("c," "Process" ((tags-todo "-deep-project")) nil nil) ("ch" "Habits" ((tags "STYLE=\"habit\"")) ((org-agenda-overriding-header "Habits") (org-agenda-sorting-stragety '(todo-state-down effort-up category-keep))) nil) ("cz" "All TODOs groups by category" alltodo "" ((org-super-agenda-groups '((:auto-category t))))) ("a" "Action" (,(agenda-tags-todo-with-goals "⚡ Goals:" " 🟍" "+current+goal") ,(agenda-tags-todo-with-goals "⚡ Doing:" " 🔨" "+TODO={IN-PROGRESS\\|DELEGATED}") ,(agenda-tags-todo-with-goals "⚡ Process:" " 🔨" "+TODO={PROCESS}") ,(agenda-tags-todo-with-goals "⚡ Next:" " ↷" "-project+PRIORITY={A\\|B}+TODO={TODO\\|WAITING}") ;;ON-HOLD\\| ;; ,(agenda-tags-todo-with-goals "⚡ Projects:" " 🔨" "/!PROJECT") ;; for '!' see https://orgmode.org/manual/Matching-tags-and-properties.html ,(agenda-tags-todo-with-goals "⚡ Ideas:" " 🤔" "+PRIORITY={A\\|B}/!IDEA") ,(agenda-schedule ())) ((ps-number-of-columns 2) (ps-landscape-mode t) (org-agenda-prefix-format " %-3i %12c %?-12t% s") ) ("agenda.html")) ("A" "Action #A" (,(agenda-tags-todo-with-goals "⚡ Doing[A]:" " 🔨" "+TODO={IN-PROGRESS\\|PROCESS\\|WAITING\\|DELEGATED}+PRIORITY={A}") ,(agenda-tags-todo-with-goals "⚡ Next[A]:" " ↷" "-project+PRIORITY={A}+TODO={TODO\\|WAITING}") ;;ON-HOLD\\| ,(agenda-tags-todo-with-goals "⚡ Projects[A]:" " 🔨" "+PRIORITY={A}/!PROJECT") ;; ,(agenda-in-progress "A") ;;,(agenda-next "A") ,(agenda-schedule "A"))) ("R" "Week review" agenda "" ((org-agenda-span 'week) (org-agenda-start-on-weekday 1) (org-habit-show-all-today t) (org-agenda-overriding-header "Week in Review") (org-agenda-show-all-dates t) (org-agenda-start-with-log-mode t) (org-agenda-log-mode-items '(closed state)) (org-agenda-start-with-clockreport-mode t) (org-agenda-archives-mode t) (org-agenda-hide-tags-regexp (concat org-agenda-hide-tags-regexp "\\|ARCHIVE")))) ("r" "All Review" ((tags "+blocking/!" ((org-agenda-overriding-header "Blocking others"))) (tags-todo "+delegated/!+DELEGATED" ((org-agenda-overriding-header "Delegated"))) (todo "WAITING" ((org-agenda-overriding-header "Waiting for"))) ;;(tags-todo "+current+goal/!-MODE" ((org-agenda-overriding-header "⚡ Current goals:"))) ;;(tags-todo "+current/!+MODE" ((org-agenda-overriding-header "⚡ Current mode:"))) (todo "IN-PROGRESS" ((org-agenda-overriding-header "In progress"))) (tags-todo "-project+PRIORITY={A\\|B}+TODO={ON-HOLD\\|TODO\\|WAITING}" ((org-agenda-overriding-header "Most important to do"))) (tags-todo "+project+PRIORITY={A\\|B}" ((org-agenda-overriding-header "A-B Projects"))) (tags-todo "+project+PRIORITY={C\\|D}" ((org-agenda-overriding-header "Other Projects"))) (todo "SOMEDAY|MAYBE" ((org-agenda-overriding-header "Someday/Maybe"))) (tags-todo "-project+PRIORITY={C\\|D}+TODO={ON-HOLD\\|TODO\\|WAITING}" ((org-agenda-overriding-header "Other to do [Scheduled]") (org-agenda-skip-function '(org-agenda-skip-entry-if 'nottimestamp)))) (tags-todo "-project+PRIORITY={C\\|D}+TODO={ON-HOLD\\|TODO\\|WAITING}+CREATED>\"<-4m>\"" ((org-agenda-overriding-header "Other to do [Unscheduled]") (org-agenda-skip-function '(org-agenda-skip-entry-if 'timestamp)))) (tags-todo "-project+PRIORITY={C\\|D}+TODO={ON-HOLD\\|TODO\\|WAITING}-CREATED>\"<-4m>\"" ((org-agenda-overriding-header "Other to do [Unscheduled, Old]") (org-agenda-skip-function '(org-agenda-skip-entry-if 'timestamp)))) (tags "STYLE=\"habit\"" ((org-agenda-overriding-header "Habits") (org-agenda-sorting-stragety '(todo-state-down effort-up category-keep))) nil) (tags "+tech+priorities+current" ((org-agenda-overriding-header "⚡ Current tech priorities:")) ((concat org-directory "consume.org"))) (tags-todo "+reading" ((org-agenda-overriding-header "⚡ Books:")) ((concat org-directory "consume.org"))) )) )) ) ;; agenda icons ;; (setq org-agenda-category-icon-alist `( ;; ;("personal" ,(list (all-the-icons-material "check_box" :height 1.2)) nil nil :ascent center) ;; ("personal" ,(list (all-the-icons-faicon "home")) nil nil :ascent center) ;; ("work" ,(list (all-the-icons-material "work")) nil nil :ascent center) ;; ("content" ,(list (all-the-icons-fileicon "video")) nil nil :ascent center) ;; ("blog" ,(list (all-the-icons-octicon "book")) nil nil :ascent center) ;; ("employment" ,(list (all-the-icons-material "people")) nil nil :ascent center) ;; ("finance" ,(list (all-the-icons-faicon "money")) nil nil :ascent center) ;; ; todo ;; ("rivne" ,(list (all-the-icons-faicon "sun-o")) nil nil :ascent center) ;; ("bigtrip" ,(list (all-the-icons-faicon "sun-o")) nil nil :ascent center) ;; ("emacs" ,(list (all-the-icons-faicon "sun-o")) nil nil :ascent center) ;; ("software" ,(list (all-the-icons-faicon "sun-o")) nil nil :ascent center) ;; ("holiday" ,(list (all-the-icons-faicon "sun-o")) nil nil :ascent center) ;; ("health" ,(list (all-the-icons-faicon "sun-o")) nil nil :ascent center) ;; ("consume" ,(list (all-the-icons-faicon "sun-o")) nil nil :ascent center) ;; ("org" ,(list (all-the-icons-faicon "sun-o")) nil nil :ascent center) ;; )) ;; (setq org-agenda-category-icon-alist nil)
10.8. org-agenda colorize clocks
Experimental.
(defun org-agenda-log-mode-colorize-block () "Set different line spacing based on clock time duration." (save-excursion (let* ((colors (cl-case (alist-get 'background-mode (frame-parameters)) ((quote light) (list "#F6B1C3" "#FFFF9D" "#BEEB9F" "#ADD5F7")) ((quote dark) (list "#aa557f" "DarkGreen" "DarkSlateGray" "DarkSlateBlue")))) pos duration) (nconc colors colors) (goto-char (point-min)) (while (setq pos (next-single-property-change (point) 'duration)) (goto-char pos) (when (and (not (equal pos (point-at-eol))) (setq duration (org-get-at-bol 'duration))) ;; larger duration bar height (let ((line-height (if (< duration 15) 1.0 (+ 0.5 (/ duration 30)))) (ov (make-overlay (point-at-bol) (1+ (point-at-eol))))) (overlay-put ov 'face `(:background ,(car colors) :foreground "black")) (setq colors (cdr colors)) (overlay-put ov 'line-height line-height) (overlay-put ov 'line-spacing (1- line-height)))))))) ;;(add-hook 'org-agenda-finalize-hook #'org-agenda-log-mode-colorize-block) [/sourcecode] </div> </div> <div id="outline-container-org9ab206a" class="outline-3"> <h3 id="org9ab206a">clock & notify</h3> <div class="outline-text-3" id="text-org9ab206a"> (use-package org-clock :preface (declare-function org-clocking-buffer "org-clock") (declare-function org-pomodoro-reset "org-pomodoro") :after org evil :init (evil-define-key 'motion global-map (kbd "<leader>c") 'hydra-org-clock/body) (defun my/run-not-clocking-timer () (run-with-timer 0 (* 5 60) #'(lambda () (when (equal (org-clocking-buffer) nil) (progn (alert "din din" :severity 'low :title "clock in" :category "clock")))))) :config (org-clock-persistence-insinuate) ;;(my/run-not-clocking-timer) :custom ((org-clock-persist 'history) (org-clock-idle-time 90) (org-clock-mode-line-total 'today) (visible-bell t) (org-clock-sound "/usr/share/sounds/custom/bell_small.wav") (org-clock-continuously t) (org-agenda-clockreport-parameter-plist '(:maxlevel 4 :scope agenda :emphasize t :fileskip0 t :stepskip0 t :compact t :hidefiles t :formula % ;; :sort (3 . ?n) ))) :pretty-hydra (hydra-org-clock (:hint nil :color blue :quit-key "C-g" :exit t :title (with-faicon "clock-o" "Clock")) ("Clock" (("i" org-mru-clock-in "pick in") ("I" org-clock-in "in") ("o" org-clock-out "out") ("r" org-resolve-clocks "resolve") ("c" org-clock-in-last "in last") ("j" org-mru-clock-select-recent-task "select recent") ("J" org-clock-goto "goto") ("e" org-clock-modify-effort-estimate "edit") ("q" org-clock-cancel "quit") ("?" (org-info "Clocking commands") "info")) "Clock report" (("d" org-clock-display "display") ("R" org-clock-report "report")) "Pomodoro" (("pp" (org-pomodoro '(16)) "start") ;; (4) - will ask for task interactively ("pr" (org-pomodoro-reset) "reset")) "Timer" (("ts" org-timer-start "start") ("tt" org-timer-set-timer "set") ("tp" org-timer-pause-or-continue "pause") ("tq" org-timer-stop "stop") ("t?" (org-info "Timers") "info")) "Timer insert" (("tm" org-timer "time") ("ti" org-timer-item "item"))))) (use-package org-mru-clock :ensure :after org :custom ((org-mru-clock-how-many 40) (org-mru-clock-completing-read #'ivy-completing-read))) (use-package org-clock-budget :after org evil-collection :quelpa (org-clock-budget :repo "Fuco1/org-clock-budget" :fetcher "github") :preface (defun org-clock-budget-interval-today () "Return the interval representing today." (cons (format-time-string "%Y-%m-%d 00:00:00") (format-time-string "%Y-%m-%d 23:59:59"))) :config (evil-collection-define-key 'normal 'org-clock-budget-report-mode-map (kbd "gr") 'org-clock-budget-report) (evil-collection-define-key 'normal 'org-clock-budget-report-mode-map (kbd "zs") 'org-clock-budget-report-sort) :custom (org-clock-budget-default-sort-column '("BUDGET_WEEK" ratio asc)) (org-clock-budget-intervals '( ("BUDGET_WEEK" org-clock-budget-interval-this-week) ;; ("BUDGET_TODAY" org-clock-budget-interval-today) ))) (use-package alert :ensure :custom (alert-fade-time 36000) ;; todo - cannot remove fade-away for org-alert (alert-default-style 'libnotify)) (use-package alert-toast :if (eq system-type 'windows-nt) :demand :after alert :quelpa (alert-toast :repo "gkowzan/alert-toast" :fetcher "github") :custom (alert-default-style 'toast)) ;; bad performance ;; (use-package org-alert ;; :functions (org-alert-enable) ;; :custom (org-alert-interval (* 12 (* 60 60))) ; every 12 hours ;; :config (org-alert-enable)) ;; doesn't work ;; (use-package org-wild-notifier ;; :config ;; (with-eval-after-load 'org ;; (require 'async) ;; (org-wild-notifier--start) ;; (org-wild-notifier--stop) ;; (org-wild-notifier-mode 1))) ;; (use-package org-notifications ;; :after org ;; :config ;; (org-notifications-start)) (use-package org-pomodoro :ensure :commands (org-pomodoro) :after (alert org) :custom (org-pomodoro-length 50) (org-pomodoro-short-break-length 10) (org-pomodoro-format "%s") (org-pomodoro-short-break-format "%s") (org-pomodoro-long-break-format "~~%s~~") (org-pomodoro-audio-player "mplayer") ; sound-wav cannot play oga - pure noise (org-pomodoro-long-break-sound "/usr/share/sounds/custom/bell_small.wav") ;"/usr/share/sounds/freedesktop/stereo/window-attention.oga") (org-pomodoro-long-break-sound-args "-af volume=5") (org-pomodoro-short-break-sound "/usr/share/sounds/custom/bell_small.wav") ;"/usr/share/sounds/freedesktop/stereo/window-attention.oga") (org-pomodoro-short-break-sound-args "-af volume=5") (org-pomodoro-finished-sound "/usr/share/sounds/custom/bell_small.wav") ;/usr/share/sounds/freedesktop/stereo/complete.oga") (org-pomodoro-finished-sound-args "-af volume=5") (org-pomodoro-start-sound "/usr/share/sounds/custom/bell_small.wav") ;"/usr/share/sounds/freedesktop/stereo/complete.oga") (org-pomodoro-start-sound-args "-af volume=5") :hook (org-pomodoro-break-finished . (lambda () (interactive) (org-pomodoro '(16)))) (org-pomodoro-finished . (lambda () (interactive) (shell-command "~/bin/lock.sh")))) ;; this cannot create alarm for tommorrow (use-package alarm-clock :disabled :ensure :config ;;(alarm-clock-set "06:34" "Wake up!") :custom (alarm-clock-sound-file "/usr/share/sounds/custom/Freshstart.mp3")) ;; testing ;; (notifications-notify :title "Achtung!" ;; :body (format "You have an appointment in %d minutes" 10) ;; :app-name "Emacs: Org" ;; :sound-file "/usr/share/sounds/custom/bell_small.wav")
10.9. org-journal
(use-package org-journal :ensure :disabled :bind (("C-c j j" . org-journal-new-entry)) :custom (org-journal-dir "~/Dropbox/org/journal/") (org-journal-date-format "%A, %d %B %Y") (org-journal-file-type 'weekly) (org-journal-enable-agenda-integration t) )
10.10. org-gcal
(use-package org-gcal :disabled :ensure :after org org-agenda :custom ((org-gcal-down-days 7) (org-gcal-up-days 7) (org-gcal-notify-p nil)) ;;(org-gcal-local-timezone "America/Mexico_City") :config (require 'auth-source-pass) (let ((gcal-auth (nth 0 (auth-source-search :host "api.google.com" :requires '(:login :password))))) (let ((gcal-secret (plist-get gcal-auth :secret))) (setq org-gcal-client-id (plist-get gcal-auth :user) org-gcal-client-secret (if (functionp gcal-secret) (funcall gcal-secret) gcal-secret)))) (setq org-gcal-file-alist '( ("twist.522@gmail.com" . "~/Dropbox/org/gcal/personal.org") ("3fq436g1h8aigd0k0k5jtrv4po@group.calendar.google.com" . "~/Dropbox/org/gcal/sport.org") ("0saojhu0tmsuhvii1vccddgvvk@group.calendar.google.com" . "~/Dropbox/org/gcal/routine.org") ("d9tv5thudt39po9amct0m1jrag@group.calendar.google.com" . "~/Dropbox/org/gcal/nutrition.org") ("family07835897960350574739@group.calendar.google.com" . "~/Dropbox/org/gcal/family.org") ("e7rucoek6h9bu30j8eggn0fdhk@group.calendar.google.com" . "~/Dropbox/org/gcal/trading.org") )) (with-eval-after-load 'org-agenda (defvar my/agenda-gcal-sync-date nil) (defvar my/gcal-sync-date-file (concat user-emacs-directory "persist/agenda-gcal-sync-date")) (defun dump-gcal-sync-date-to-file () (my/dump-vars-to-file '(my/agenda-gcal-sync-date) my/gcal-sync-date-file)) (when (and (not my/agenda-gcal-sync-date) (file-exists-p my/gcal-sync-date-file)) (load-file my/gcal-sync-date-file)) (when (not my/agenda-gcal-sync-date) (setq my/agenda-gcal-sync-date (format-time-string "%d.%m.%Y")) (dump-gcal-sync-date-to-file)) (when (not is-android) ;;(executable-find "pass") (add-hook 'org-agenda-mode-hook (lambda() (let ((current-date (format-time-string "%d.%m.%Y"))) (when (not (string= current-date my/agenda-gcal-sync-date)) (org-gcal-sync) ;; TODO - stick this one here for a moment ;;(org-store-agenda-views) (setq my/agenda-gcal-sync-date current-date) (dump-gcal-sync-date-to-file) ) )) )) ) ) ;; org-timeline ;; ;;(use-package org-timeline) ;;(require 'org-timeline) ;;(add-hook 'org-agenda-finalize-hook 'org-timeline-insert-timeline :append)
10.11. jira
(use-package org-jira :ensure :disabled :config (setq jiralib-url "http://.atlassian.net" jiralib-user-login-name "yuri" org-jira-custom-jqls '( (:jql "project = \"..\" and sprint = \"Sprint 39\" and resolution = Unresolved order by rank asc" :limit 20 :filename "sprint-board") (:jql "project = \"..\" and sprint = \"backlog\" and resolution = Unresolved order by rank asc" :limit 20 :filename "tim-data-backlog") ) ) ) ;; confluence support ;; (require 'ox-confluence)
10.12. presentations
(use-package org-tree-slide :ensure :bind (:map org-mode-map ( ("C-c t t" . org-tree-slide-mode) ("C-c t T d" . org-tree-slide-skip-done-toggle) ("C-c t T h" . org-tree-slide-display-header-toggle) ("C-c t P s" . org-tree-slide-simple-profile) ("C-c t P p" . org-tree-slide-presentation-profile) ("C-c t P n" . org-tree-slide-narrowing-control-profile) ))) (use-package ox-reveal :ensure :init (defun my/create-talk-file() "Create an org file for a new talk" (interactive) (let ((name (read-string "Filename: "))) (expand-file-name (format "%s.org" name) "~/Dropbox/org/talks/"))) :custom (org-reveal-root "/home/twist/.local/src/reveal.js") (org-reveal-reveal-js-version 4) (org-reveal-highlight-css "%r/plugin/highlight/zenburn.css")) :config ;this works fine but no speaker notes and highlight plugins ;(setq org-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js") (add-to-list 'org-capture-templates '("T" "Talk" plain (file my/create-talk-file) "\ #+OPTIONS: reveal_global_footer:t\n\ #+REVEAL_THEME: beige\n\ #+REVEAL_PLUGINS: (highlight notes)\n\ #+REVEAL_INIT_OPTIONS: slideNumber:true\n\ #+REVEAL_HLEVEL: 1\n\ #+TITLE: %^{Title}\n\ #+AUTHOR: https://git.io/Jvd9c\n\ #+EMAIL: twist522@gmail.com\n\ #+OPTIONS: reveal_title_slide:\"<h2>\\%t</h2><h4>%^{Sub Title}</h4>\"\n\ #+OPTIONS: toc:nil\n\ #+OPTIONS: num:0\n\ \n* Plan\n\ :PROPERTIES:\n\ :UNNUMBERED: t\n\ :END:\n\ - %^{point1}\n\ - %^{point2}\n\ - %^{point3}\n\ - %^{point4}\n* Problem\n* Solution\n* Call to Action\n\ - %^{action1}\n\ - %^{action2}\n* \n\ :PROPERTIES:\n\ :UNNUMBERED: t\n\ :END:\n\ #+REVEAL_HTML: <h1>😃</h1>") t)
10.13. calfw & calendar
;; example - https://cestlaz.github.io/posts/using-emacs-26-gcal/#.WIqBud9vGAk ;; should use ical link - it works only if calendar is public (use-package calfw-org :ensure) (use-package calfw :ensure :commands cfw:open-calendar-buffer cfw:open-org-calendar :config (require 'calfw) (require 'calfw-org) (setq cfw:org-overwrite-default-keybinding t)) ;;; local additional holidays to diplay through org-calendar-holiday func ;;; This snippet is taken from https://github.com/abo-abo/ukrainian-holidays ;;; Author: Oleh Krehel <ohwoeowho@gmail.com> (defvar displayed-year nil "It's bound in `calendar-generate'.") (defun holiday-eastern-etc (&optional n string) "Date of Nth day after Orthodox Easter (named STRING), if visible in calendar window. Negative values of N are interpreted as days before Easter. STRING is used purely for display purposes. The return value has the form ((MONTH DAY YEAR) STRING), where the date is that of the Nth day before or after Easter." (list (list (if (= n 0) (easter-eastern displayed-year) (calendar-gregorian-from-absolute (+ n (calendar-absolute-from-gregorian (easter-eastern displayed-year))))) string))) (defun easter-eastern (year) (let* ((x (% (+ (* (% year 19) 19) 15) 30)) (day (- (+ x 10) (% (+ (/ (* year 5) 4) x) 7)))) (if (< day 31) (list 4 day year) (list 5 (- day 30) year)))) (setq holiday-local-holidays '( (holiday-fixed 5 22 "День вишиванки") (holiday-eastern-etc 0 "Воскресіння Христове") ;; Дванадесяті свята (holiday-fixed 1 7 "Різдво") (holiday-fixed 1 19 "Водохреща") (holiday-fixed 2 15 "Стрітення") (holiday-fixed 4 7 "Благовіщення") (holiday-eastern-etc -7 "Вербна неділя") (holiday-eastern-etc 39 "Вознесіння Господнє") (holiday-eastern-etc 49 "Святої трійці (П'ятидесятниця)") (holiday-fixed 8 19 "Преображення Господнє (Яблучний Спас)") (holiday-fixed 8 28 "Успіння Пресвятої Богородиці") (holiday-fixed 9 21 "Різдво Пресвятої Богородиці") (holiday-fixed 9 27 "Воздвиження Хреста Господнього") (holiday-fixed 12 4 "Уведення в храм Пресвятої Богородиці") ;; Інші релігійні свята (holiday-fixed 1 6 "Святий Вечір") (holiday-eastern-etc -3 "Великий четвер") (holiday-eastern-etc -2 "Велика пятниця") (holiday-eastern-etc -1 "Велика субота") (holiday-eastern-etc 1 "Світлий Понеділок") (holiday-eastern-etc 2 "Світлий Вівторок") (holiday-eastern-etc 7 "Провідна неділя") (holiday-eastern-etc 50 "Святого духа") (holiday-fixed 8 14 "Маковея (Медовий Спас)") (holiday-fixed 10 14 "Покрова Пресвятої Богородиці") ;; Державні свята (holiday-fixed 1 1 "Новий рік") (holiday-fixed 3 8 "Міжнародний жіночий день") (holiday-fixed 5 1 "День Праці") (holiday-fixed 5 2 "День Праці") (holiday-fixed 5 9 "День Перемоги") (holiday-fixed 6 28 "День Конституції України") (holiday-fixed 8 24 "День Незалежності України") ;; решта свят (holiday-fixed 1 13 "Старий Новий рік") (holiday-fixed 1 22 "День Соборності та Свободи України") (holiday-fixed 2 14 "День святого Валентина") (holiday-fixed 2 21 "Міжнародний день рідної мови") (holiday-fixed 10 14 "День захисника Вітчизни") (holiday-fixed 4 1 "День сміху") )) (setq calendar-christian-all-holidays-flag t) ;(with-eval-after-load 'org-agenda ; (error "test")) ;; I'm using the list above ;; (with-eval-after-load 'org-agenda ;; (load-library "ukrainian-holidays")) [/sourcecode] </div> </div> <div id="outline-container-orgf5195b6" class="outline-3"> <h3 id="orgf5195b6">org-download</h3> <div class="outline-text-3" id="text-orgf5195b6"> (use-package org-download :ensure :commands (org-download-screenshot) :after org ;:init (with-eval-after-load 'org ; (require 'org-download) ; (org-download-enable)) :bind ("C-S-y" . org-download-screenshot) :config (org-download-enable) ;(setq org-download-screenshot-method "gnome-screenshot -a -f %s") (setq org-download-screenshot-method "scrot -s %s") ;;(setq org-download-screenshot-method "sleep 0.2; scrot -s --line mode=edge 'Y-m-d-s_screenshot_$wx$h.jpg' -e 'mv $f ~/Documents/screenshots/; xclip -selection clipboard -t image/png < $f'") (when (eq system-type 'windows-nt) (setq org-download-screenshot-method "magick convert clipboard: %s") (setq org-download-screenshot-file "C:\\Users\\Admin\\Pictures\\screenshot.png")) ;(setq org-download-heading-lvl nil) ;; Drag and drop to Dired (?) (add-hook 'dired-mode-hook 'org-download-enable) (add-hook 'org-mode-hook 'org-download-enable) :custom (org-download-image-dir "~/Dropbox/org/data") (org-image-actual-width '(400)) (org-download-method 'attach) (org-startup-with-inline-images t) ) [/sourcecode] </div> </div> <div id="outline-container-org2578f96" class="outline-3"> <h3 id="org2578f96">org-images</h3> <div class="outline-text-3" id="text-org2578f96"> (use-package org-inline-image-fix :after org :quelpa (org-http-inline-image :fetcher github :repo "misohena/org-inline-image-fix" :files ("org-http-inline-image.el" "org-better-inline-images.el")) :config (require 'org-better-inline-images) (require 'org-http-inline-image) (org-http-inline-image-activate) )
10.14. easydraw
(use-package el-easydraw :ensure :after org :quelpa (edraw-org :fetcher github :repo "misohena/el-easydraw") :config (require 'edraw-org) (edraw-org-setup-default) )
10.14.1. test
10.15. utilities
(defun change-tag (old new) (when (member old (org-get-tags)) (org-toggle-tag new 'on) (org-toggle-tag old 'off))) (defun org-rename-tag (old new) (interactive "scurrent tag: \nsnew name: ") (org-map-entries (lambda () (change-tag old new)) (format "+%s" old) 'agenda-with-archives)) ;; (defun my/org-ql-parents () ;; (interactive) ;; (org-ql-search (org-agenda-files) '(todo) :super-groups '((:auto-parent t)))) (defun my/org-get-parent-goal () (interactive) (-when-let* ((goal-link (org-entry-get (point) "GOAL" t))) (org-link-display-format goal-link) ;; (save-window-excursion ;; (org-link-open-from-string goal-link) ;; (org-get-heading 'notags 'notodo)) )) (defun my/org-set-goal () (interactive) (ivy-read "Goal: " (org-map-entries (lambda () (org-element-property :title (org-element-at-point))) "+goal+current+TODO=\"GOAL\"" (list (concat org-directory "goals.org"))) :action (lambda (goal) (with-ivy-window (when goal (let ((goal-link (format "[[file:%sgoals.org::*%s][%s]]" org-directory goal goal))) (if (string= (buffer-name) "*Org Agenda*") ;; below taken from org-agenda-set-property (let* ((marker (org-get-at-bol 'org-hd-marker)) (buffer (marker-buffer marker)) (pos (marker-position marker))) (org-with-remote-undo buffer (with-current-buffer buffer (widen) (goto-char pos) (org-show-context 'agenda) (org-set-property "GOAL" goal-link) )) (org-agenda-redo t) ) (org-set-property "GOAL" goal-link) ) ) ))))) (use-package orgtbl-join :ensure)
10.16. plantuml
(use-package plantuml-mode :ensure :after org :mode "\\.plantuml\\'" :custom (plantuml-default-exec-mode 'jar) (plantuml-jar-path org-plantuml-jar-path))
10.17. gnuplot
(use-package gnuplot :ensure :config (setq gnuplot-program-version "5.4") ;; auto-determine version within gnuplot.el doesn't work (autoload 'gnuplot-mode "gnuplot" "gnuplot major mode" t) (autoload 'gnuplot-make-buffer "gnuplot" "open a buffer in gnuplot mode" t) ;; this line automatically causes all files with the .gp extension to be loaded into gnuplot mode (setq auto-mode-alist (append '(("\\.gp$" . gnuplot-mode)) auto-mode-alist)) ;; This line binds the function-9 key so that it opens a buffer into gnuplot mode (global-set-key [(f9)] 'gnuplot-make-buffer) )
10.18. prettify
;; prettify ;; todo - this destroys some of the org-mode and evil bindings for some reason (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 '("#+begin_src" . "➤") prettify-symbols-alist) ;; ➤ 🖝 ➟ ➤ ✎ (push '("#+END_SRC" . "⏹") prettify-symbols-alist) ;; ⏹ □ (push '("#+end_src" . "⏹") prettify-symbols-alist) ;; ⏹ □ ;(push '("[#A]" . "❗" ) prettify-symbols-alist) ;(push '("[#B]" . "⬆" ) prettify-symbols-alist) ;(push '("[#C]" . "❖" ) prettify-symbols-alist) ;(push '("[#D]" . "⬇" ) prettify-symbols-alist) (push '("<=" . "≤") prettify-symbols-alist) (push '("part_d" . "∂") prettify-symbols-alist) (push '("Gamma" . "Γ") prettify-symbols-alist) (push '("sigmoid" . "σ") prettify-symbols-alist) (prettify-symbols-mode))) (defun yant/str-to-glyph (str) "Transform string into glyph, displayed correctly." (let ((composition nil)) (dolist (char (string-to-list str) (nreverse (cdr composition))) (push char composition) (push '(Br . Bl) composition)))) ;(?▤ org-specific ":LOGBOOK:" (org-mode)) ;(?⚙ org-specific ":PROPERTIES:" (org-mode)) ;(?⏏ org-specific ":END:" (org-mode)) ;((yant/str-to-glyph "⚑") org-specific "\\(?:^*+ +\\)\\(\\<WAITING\\>\\)" (org-mode) 1) ;((yant/str-to-glyph "♲") org-specific "\\(?:^*+ +\\)\\(\\<HOLD\\>\\)" (org-mode) 1) ;((yant/str-to-glyph "☠D") org-specific "\\<DEADLINE:" (org-mode)) ;((yant/str-to-glyph "◴S") org-specific "\\<SCHEDULED:" (org-mode)))))) (use-package org-bullets :disabled :ensure :hook (org-mode . (lambda() (org-bullets-mode 1)))) (use-package org-superstar :ensure :hook (org-mode . (lambda () (org-superstar-mode 1)))) [/sourcecode] </div> </div> <div id="outline-container-orge2683d9" class="outline-3"> <h3 id="orge2683d9">others</h3> <div class="outline-text-3" id="text-orge2683d9"> (use-package org-sidebar :ensure :disabled) (use-package org-ql :disabled :ensure) ;(use-package org-super-agenda ; :config ; ;; (setq org-super-agenda-header-map (copy-keymap evil-org-agenda-mode-map)) ; ) (use-package org-roam :disabled :ensure :init (setq org-roam-v2-ack t) ;; I want to silence bytecompiler :custom (org-roam-directory "~/Dropbox/org/") :bind (:map org-roam-mode-map (("C-c n l" . org-roam) ("C-c n f" . org-roam-find-file) ("C-c n g" . org-roam-graph)) :map org-mode-map (("C-c n i" . org-roam-insert)) (("C-c n I" . org-roam-insert-immediate)))) ;; feed (experiment) ;(setq org-feed-alist ; '(("Slashdot" ; "http://rss.slashdot.org/Slashdot/slashdot" ; "~/Dropbox/org/feeds.org" "Slashdot Entries"))) ;; experimenting (use-package outshine :quelpa (outshine :fetcher github :repo "alphapapa/outshine"))
10.19. individual visibility
Choosing initial visibility per src block (for now disabled, using STARTUP:hideblocks per file)
(defun individual-visibility-source-blocks () "Fold some blocks in the current buffer." (interactive) (org-show-block-all) (org-block-map (lambda () (let ((case-fold-search t)) (when (and (save-excursion (beginning-of-line 1) (looking-at org-block-regexp)) (cl-assoc ':hidden (cl-third (org-babel-get-src-block-info)))) (org-hide-block-toggle)))))) (add-hook 'org-mode-hook (function individual-visibility-source-blocks))
10.20. personal configs
(with-eval-after-load 'org (load-file (concat org-directory "config.el")))
11. prog
11.1. git
(use-package magit :ensure :ensure-system-package git ;;:custom (magit-credential-cache-daemon-socket "/home/twist/.git-credential-cache/socket") ;;:config ;;(require 'magit-gh-pulls) ;;(add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh) :after evil general :general (magit-mode-map "SPC" nil) (normal magit-mode-map "?" 'magit-dispatch) (magit-section-mode-map "M-1" nil "M-2" nil "M-3" nil "M-4" nil) ;; free for tab-bar (:modes '(normal motion) :keymaps 'global-map (kbd "<leader>g") 'hydra-git/body) :commands (hydra-git/body) :custom ((vc-follow-symlinks t) ;; this will prevent asking when visiting git-controlled symlink (magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1)) :pretty-hydra (hydra-git (:hint nil :color teal :quit-key "q" :title (with-alltheicon "git" "Git" 1 -0.05)) ("Action" (("b" magit-blame-addition "blame") ("c" magit-clone "clone") ("i" magit-init "init") ("t" git-timemachine "time machine") ("l" magit-log-buffer-file "commit log (current file)") ("L" magit-log-current "commit log (project)") ("g" magit-status "status"))))) (use-package magithub :ensure) (use-package git-timemachine :ensure :after evil :config (evil-make-overriding-map git-timemachine-mode-map 'normal) ;; force update evil keymaps after git-timemachine-mode loaded (add-hook 'git-timemachine-mode-hook #'evil-normalize-keymaps)) (use-package gh :ensure) (use-package git-modes :ensure) (use-package magit-todos :ensure :after magit :hook (magit-mode . magit-todos-mode) :unless (eq system-type 'windows-nt)) (use-package magit-delta :ensure :disabled ;; ugly,buggy :after magit :hook (magit-mode . magit-delta-mode)) ;; increase performance (on windows especially) ;; (use-package magit-libgit :ensure :demand :after magit ;; :unless (eq system-type 'windows-nt)) (use-package magit-gh-pulls :disabled :ensure :functions (gh-profile-current-profile gh-auth-remember) ;; actually coming from gh :after magit ;;:hook ((magit-mode . magit-gh-pulls-mode) ;; ;;(magit-mode . magit-gh-pulls-reload) ;; ) :config (gh-auth-remember (gh-profile-current-profile) :token (auth-source-pass-get "oauth-token" "github.com/thatwist")) (gh-auth-remember (gh-profile-current-profile) :username "thatwist")) ; don't need as it is in evil-collection ;(use-package evil-magit ; :after evil magit ; :config ; (setq evil-magit-state 'motion)) (use-package ediff :preface (defun my/ediff-prepare () "To make proper load order and turn off unnecessary stuff for ediff" (require 'evil-collection) (require 'ediff) (require 'ediff-util) (eval-after-load 'golden-ratio (golden-ratio-mode -1)) (eval-after-load 'tab-line (global-tab-line-mode -1))) (defun my/ediff-diff (a b) "To be run as eval param from external process for diff" (my/ediff-prepare) (ediff a b)) (defun my/ediff-merge (a b c) "To be run as eval param from external process for merge" (my/ediff-prepare) (ediff-merge-files-with-ancestor a b c)) (defun my/ediff-copy-both-to-C () "Copy both A then B into merge buffer." (interactive) (ediff-copy-diff ediff-current-difference nil 'C nil (concat (ediff-get-region-contents ediff-current-difference 'A ediff-control-buffer) (ediff-get-region-contents ediff-current-difference 'B ediff-control-buffer)))) :commands (ediff) :after evil-collection :config (message "ediff config") (evil-collection-ediff-setup) (add-hook 'ediff-keymap-setup-hook ;; todo - move it to evil-collection/leader configuration (lambda () (general-def 'normal ediff-mode-map "SPC" (general-simulate-key "<leader>")))) (setq ediff-control-frame-parameters (cons '(tab-bar-lines . 0) ediff-control-frame-parameters)) (when (eq system-type 'windows-nt) (setq ediff-diff-program "C:\\Program Files\\Git\\usr\\bin\\diff.exe") (setq diff-command "\"C:\\Program Files\\Git\\usr\\bin\\diff.exe\"")) :hook (ediff-keymap-setup . (lambda () (define-key ediff-mode-map "c" 'my/ediff-copy-both-to-C))) :custom (ediff-window-setup-function 'ediff-setup-windows-default) ;'ediff-setup-windows-plain ; ediff use same frame (ediff-merge-split-window-function 'split-window-vertically) ;; maybe one day I will turn off tab-line-mode locally just in ediff control window ;; :hook (ediff-startup-hook . (lambda () ;; (make-local-variable 'tab-line-mode) ;; ())) ) ;; diff-hl requires this (use-package smartrep) (use-package diff-hl :ensure :after smartrep :hook (prog-mode . diff-hl-mode) (vc-dir-mode-hook . diff-hl-mode) ;;:custom-face ;; (diff-hl-change ((t (:background "#333355" :foreground "blue3" :width extra-expanded)))) ;; (diff-hl-delete ((t (:inherit diff-removed :foreground "red3" :width extra-expanded)))) ;; (diff-hl-insert ((t (:inherit diff-added)))) ) ;; github gist integration ;;(use-package gist)
11.2. smerge hydra
(use-package smerge-mode :after evil :init (evil-define-key 'motion global-map (kbd "<leader>M-m") 'hydra-smerge/body) :pretty-hydra (hydra-smerge (:quit-key "q" :exit nil :color blue :hint nil :pre (smerge-mode 1)) ("Move" (("n" smerge-next) ("p" smerge-prev)) "Keep" (("a" smerge-keep-all) ("b" smerge-keep-base) ("u" smerge-keep-upper) ("l" smerge-keep-lower) ("RET" smerge-keep-current)) "Diff" (("C" smerge-combine-with-next) ("E" smerge-ediff) ("R" smerge-refine) ("r" smerge-resolve)) "Pair" (("<" smerge-diff-base-upper) ("=" smerge-diff-upper-lower) (">" smerge-diff-base-lower)))))
11.3. flycheck
(use-package flycheck-projectile :ensure :demand :after (flycheck projectile)) (use-package flycheck :ensure :after evil general :hook (prog-mode . flycheck-mode) :diminish ;; " F" ;; prog-mode in this list doesn't work against child modes ;;(cutsomize-set-variable 'flycheck-global-modes '(prog-mode markdown-mode))) :custom (flycheck-error-message-buffer " *Flycheck error messages*") :general (:modes 'motion "<leader>f" 'hydra-flycheck/body) :pretty-hydra (hydra-flycheck (:hint nil :color teal :quit-key "q" :title (with-faicon "plane" "Flycheck" 1 -0.05)) ("Checker" (("?" flycheck-describe-checker "describe") ("d" flycheck-disable-checker "disable") ("m" flycheck-mode "mode") ("s" flycheck-select-checker "select")) "Errors" (("k" flycheck-previous-error "previous" :color pink) ("j" flycheck-next-error "next" :color pink) ("f" flycheck-buffer "check") ("l" flycheck-list-errors "list") ("L" flycheck-projectile-list-errors "list project")) "Other" (("M" flycheck-manual "manual") ("v" flycheck-verify-setup "verify setup")))))
11.4. next-error hydra
Disabling this one as flycheck hydra is enough
(defhydra hydra-next-error (:hint nil) " Compilation errors: _j_: next error _h_: first error _q_uit _k_: previous error _l_: last error " ("`" next-error nil) ("j" next-error nil :bind nil) ("k" previous-error nil :bind nil) ("h" first-error nil :bind nil) ("l" (condition-case err (while t (next-error)) (user-error nil)) nil :bind nil) ("q" nil nil :color blue))
11.5. jump-to
(use-package dumb-jump :functions xref-show-definitions-completing-read :ensure :init (setq xref-show-definitions-function #'xref-show-definitions-completing-read) :config (add-hook 'xref-backend-functions #'dumb-jump-xref-activate))
11.6. elisp
11.6.1. elisp cheatsheet
car/cdr reminder
(cdr '(1 . 2)) ;2 (cdr '(1 2)) ;(2) ; equivalent (cdr '(1 . (2 . nil))) ;(2)
11.6.2. editing
(use-package paredit :ensure :diminish "()" :hook (emacs-lisp-mode . enable-paredit-mode) (lisp-interaction-mode . (lambda() (enable-paredit-mode) (define-key paredit-mode-map (kbd "C-j") nil))) :config (with-eval-after-load 'evil (evil-define-key 'normal 'lisp-interaction-mode (kbd "C-j") 'eval-print-last-sexp)) ) (use-package evil-paredit :ensure :hook (emacs-lisp-mode . evil-paredit-mode)) ;; can use '(' to navigate up sexp (use-package evil-cleverparens :ensure :diminish " {}" :hook (paredit-mode . evil-cleverparens-mode) :general ((normal visual motion) evil-cleverparens-mode-map ;; free up for my buffer/window movements "M-y" nil "M-H" nil "M-L" nil "M-k" nil "M-j" nil "M-h" nil "M-o" nil "M-i" nil "M-l" nil "M-m" nil) :custom (evil-cleverparens-move-skip-delimiters t) (evil-cleverparens-swap-move-by-word-and-symbol nil) ;; this will swap bewBEW movements - I don't like it as I use subword mode (evil-cleverparens-use-additional-movement-keys t)) ;; didn't like it ;;(use-package lispy ;; :init ;; (add-hook 'emacs-lisp-mode-hook (lambda () (lispy-mode 1))) ;; :config (require 'evil-lispy)) ;; ;;(use-package evil-lispy) (unless (eq system-type 'windows-nt) (use-package elisp-autofmt :ensure :config :hook (lisp-interaction-mode . (lambda () "Makes it possible to use evil's '==' for fmt." (setq indent-line-function 'elisp-autofmt-region-dwim)))))
11.6.3. edebug
hydra came from here
(use-package edebug :after evil :init (evil-define-key 'motion emacs-lisp-mode-map (kbd "<leader>e") 'hydra-edebug/body) :commands (hydra-edebug/body) :bind (:map edebug-mode-map ("?" . hydra-edebug/body)) :config ;; use <normal> 's' instead (define-key edebug-mode-map (kbd "<SPC>") nil) :pretty-hydra (hydra-edebug (:color amaranth :hint none :quit-key "q" :title (with-faicon "wrench" "Edebug" 1 -0.05)) ("" (("<SPC>" edebug-step-mode) ("n" edebug-next-mode) ("g" edebug-go-mode) ("G" edebug-Go-nonstop-mode) ("t" edebug-trace-mode) ("T" edebug-Trace-fast-mode) ("c" edebug-continue-mode) ("C" edebug-Continue-fast-mode) ("f" edebug-forward-sexp) ("h" edebug-goto-here) ("I" edebug-instrument-callee) ("i" edebug-step-in) ("o" edebug-step-out)) "breakpoints" (("b" edebug-set-breakpoint) ("u" edebug-unset-breakpoint) ("B" edebug-next-breakpoint) ("x" edebug-set-conditional-breakpoint) ("X" edebug-set-global-break-condition)) "evaluation" (("r" edebug-previous-result) ("e" edebug-eval-expression) ("l" edebug-eval-last-sexp) ("E" edebug-visit-eval-list)) "views" (("w" edebug-where) ("d" edebug-pop-to-backtrace) ("p" edebug-bounce-point) ("v" edebug-view-outside) ; maybe obsolete?? ("P" edebug-view-outside) ; same as v ("W" edebug-toggle-save-windows)) "quitting and stopping" (("q" top-level :color blue) ("Q" edebug-top-level-nonstop :color blue) ("a" abort-recursive-edit :color blue) ("U" edebug-remove-instrumentation :color blue) ("S" edebug-stop :color blue)))))
11.6.4. elisp-hydra
(use-package elisp-mode :mode-hydra (emacs-lisp-mode nil ("Eval" (("b" eval-buffer "buffer") ("e" eval-defun "defun") ("r" eval-region "region")) "Debug" (("E" hydra-edebug/body "edebug")) "REPL" (("I" ielm "ielm")) "Test" (("t" ert "prompt") ("T" (ert t) "all") ("F" (ert :failed) "failed")) "Doc" (("f" describe-function "function") ("v" describe-variable "variable") ("i" info-lookup-symbol "info lookup")))))
11.7. completion
(use-package company-prescient :ensure :after (prescient company) :config (company-prescient-mode 1)) (use-package company :ensure ;;:defer 1 ;; going minimal on startup :diminish :custom (tab-always-indent 'complete) ;; (tab-first-completion 'word-or-paren-or-punct) ;;(company-dabbrev-ignore-case nil) (company-dabbrev-code-ignore-case nil) ;;(company-dabbrev-downcase nil) (company-idle-delay 0.3) (company-minimum-prefix-length 2) (company-require-match 'company-explicit-action-p) (company-selection-wrap-around t) :config (global-company-mode 1) ;; testing this one (add-to-list 'company-backends '(company-capf :with company-dabbrev company-yasnippet)) ;; reserve TAB in normal for evil-toggle-fold ;; (general-def 'insert company-mode-map [remap indent-for-tab-command] 'company-complete-common-or-cycle) (general-def 'insert company-mode-map [remap indent-for-tab-command] 'company-indent-or-complete-common) ;; tab-and-go (company-tng-mode) (define-key company-active-map (kbd "RET") #'company-complete-selection) ;; :functions (company-complete-common company-complete) ) (use-package company-quickhelp :ensure :after company :hook (company-mode . company-quickhelp-mode)) (use-package company-box :disabled :ensure :diminish :demand :after company :hook (company-mode . company-box-mode)) (use-package company-emoji :ensure :after company :config (add-to-list 'company-backends 'company-emoji)) ;; experimental (use-package company-posframe :ensure) (use-package smart-tab :ensure :disabled ;; hm, what I have right now is actually better: 'company-indent-or-complete-common + yas-expand that somehow works :config (global-smart-tab-mode 1) :custom (smart-tab-user-provided-completion-function #'company-complete-common) (smart-tab-using-hippie-expand t))
11.8. yasnippet
(use-package yasnippet :ensure :after evil :diminish (yas-minor-mode . "") ;; " Y" :config ;;(yas-reload-all) ;; default dir is ~/.emacs.d/snippets, others are somehow loaded from yasnippet-snippets ;; (yas-global-mode 1) ;;:bind ("<tab>" . yas-expand) :init (evil-define-key 'motion global-map (kbd "<leader>y") 'hydra-yas/body) :commands hydra-yas/body yas-global-mode :pretty-hydra (hydra-yas (:color blue :quit-key "q" :hint nil :title (with-faicon "code" "Yas" 1 -0.05)) ("Modes" (("g" yas-global-mode "global") ("m" yas-minor-mode "minor") ("e" yas-activate-extra-mode "extra")) "Load/Visit" (("d" yas-load-directory "directory") ("f" yas-visit-snippet-file "file" :color blue) ("l" yas-describe-tables "list") ("a" yas-reload-all "all")) "Actions" (("i" yas-insert-snippet "insert") ("t" yas-tryout-snippet "tryout") ("n" yas-new-snippet "new")))) ) (use-package yasnippet-snippets :ensure :demand :after yasnippet) (use-package ivy-yasnippet :demand :after yasnippet :pretty-hydra (hydra-yas ("Actions" (("i" ivy-yasnippet "insert"))))) ;; very slow load ;;(use-package aws-snippets ;; :after yasnippet)
11.9. lsp
(use-package lsp-mode :ensure :pin melpa ; ok I can afford it :after general :general (:modes 'motion "<leader>l" 'hydra-lsp/body) :hook ( ;; disable automatic lsp start to save resources ;;(scala-mode . lsp-deferred) ;;(java-mode . lsp-deferred) (haskell-mode . lsp-deferred) (lsp-mode . lsp-lens-mode) (lsp-mode . (lambda () (eldoc-mode -1)))) ;; waits too long when typing ;;:config (add-hook 'lsp-mode-hook #'lsp-enable-which-key-integration) :custom (lsp-keymap-prefix "C-l") (lsp-idle-delay 0.500) (lsp-progress-prefix "") ;; rendering issues with icon and tab-bar ;;(lsp-log-io nil) (lsp-completion-provider :capf) (lsp-signature-auto-activate nil) :init ;; WIP (defadvice lsp--help-open-link (after lsp-help-link-browse last disable) "LSP oens 'file://' links locally (and fails with # suffixes in the url). This advice opens url externally." (message "buf=%s file=%s" (window-buffer) (buffer-file-name)) ;; (browse-url-of-buffer) ;; (quit-window t) ) ;; kill :config ;;(lsp-register-custom-settings ;; '(("pyls.plugins.pyls_mypy.enabled" t t) ;; ("pyls.plugins.pyls_mypy.live_mode" nil t) ;; ("pyls.plugins.pyls_black.enabled" t t) ;; ("pyls.plugins.pyls_isort.enabled" t t))) ;; Uncomment following few lines if you would like to tune lsp-mode performance according to ;; https://emacs-lsp.github.io/lsp-mode/page/performance/ ;(setq gc-cons-threshold 100000000) ;; 100mb (setq read-process-output-max (* 1024 1024)) ;; 1mb (require 'lsp-protocol) ;; ain't have any space (diminish 'lsp-mode "") ;; " LSP" (diminish 'lsp-lens-mode " Lens") :commands (lsp lsp-deferred hydra-lsp/body) :pretty-hydra (hydra-lsp (:hint nil :color teal :quit-key "q" :exit t :title (with-faicon "rocket" "Lsp")) ("Find" (("D" lsp-find-declaration "declaration") ("d" lsp-find-definition "definition") ("R" lsp-find-references "references") ("i" lsp-find-implementation "implementation") ("gt" lsp-find-type-definition "type") ("f" lsp-ivy-workspace-symbol "symbol") ("F" lsp-ivy-global-workspace-symbol "global symbol") ("uf" lsp-ui-find-workspace-symbol "ui symbol") ("pd" lsp-ui-peek-find-definitions "peek def") ("pr" lsp-ui-peek-find-references "peek refs") ("pf" lsp-ui-peek-find-workspace-symbol "peek symb") ("pi" lsp-ui-peek-find-implementation "peek impl")) "Toggle" (("Td" lsp-ui-doc-mode "doc" :toggle t :exit nil) ("TS" lsp-ui-sideline-mode "sideline" :toggle t :exit nil) ("Ts" lsp-ui-sideline-toggle-symbols-info "side symb" :toggle lsp-ui-sideline-show-hover :exit nil) ("Tl" lsp-lens-mode "lens" :toggle t :exit nil) ("Ti" lsp-toggle-trace-io "trace-io" :toggle lsp-log-io :exit nil) ("Th" lsp-toggle-symbol-highlight "symb highlight" :toggle lsp-enable-symbol-highlighting :exit nil) ("Tf" lsp-toggle-on-type-formatting "format" :toggle lsp-enable-on-type-formatting :exit nil) ("TT" lsp-treemacs-sync-mode "treemacs sync" :toggle t :exit nil) ("TD" lsp-modeline-diagnostics-mode "diag line" :toggle t :exit nil) ("Tnf" lsp-signature-toggle-full-docs "sign docs full") ("Tna" lsp-signature-activate "sign activate help") ("Tns" lsp-toggle-signature-auto-activate "sign auto activate")) "Code" (("=f" lsp-format-buffer "format") ("=r" lsp-format-region "region") ("r" lsp-rename "rename") ("o" lsp-organize-imports "org imports") ("m" lsp-ui-imenu "imenu") ("x" lsp-execute-code-action "action") ("hd" lsp-ui-doc-glance "doc glance") ("hh" lsp-describe-thing-at-point "describe") ("l" lsp-avy-lens "avy lens") ("gc" lsp-treemacs-call-hierarchy "call hierarchy") ("gt" lsp-treemacs-type-hierarchy "type hierarchy") ("ge" lsp-treemacs-errors-list "errors") ("gf" lsp-ui-flycheck-list "diagnostics") ("gs" lsp-treemacs-symbols "symbols") ("gi" lsp-treemacs-implementations "implementations") ("gr" lsp-treemacs-references "references") ("ga" xref-find-apropos "xref-apropos")) "Metals" (("Mb" lsp-metals-build-import "build import") ("Ms" lsp-metals-sources-scan "sources rescan") ("Mr" lsp-metals-build-connect "bloop reconnect")) "Session" (("s?" lsp-describe-session "describe") ("ss" lsp "start") ("sd" lsp-disconnect "disconnect") ("sr" lsp-workspace-restart "restart") ("sq" lsp-workspace-shutdown "shutdown") ("sl" lsp-workspace-show-log "log") ("sfa" lsp-workspace-folders-add "folders +") ("sfo" lsp-workspace-folders-open "folder") ("sfr" lsp-workspace-folders-remove "folders -") ("sfb" lsp-workspace-blacklist-remove "blacklist -"))))) (use-package lsp-ui :ensure :pin melpa :custom ;; (lsp-ui-doc-enable t) ;; (lsp-ui-doc-use-childframe t) ;; (lsp-ui-doc-position 'top) (lsp-ui-doc-include-signature t) (lsp-ui-peek-always-show t) (lsp-eldoc-enable-hover nil) ;; (lsp-eldoc-render-all nil) ;;(lsp-ui-doc-use-webkit t) ;; buggy as of 2021 (lsp-ui-flycheck-enable t) (lsp-ui-flycheck-list-position 'bottom) (lsp-ui-sideline-enable t) ;; (lsp-ui-sideline-ignore-duplicate t) (lsp-ui-sideline-show-symbol nil) (lsp-ui-sideline-show-hover t) (lsp-ui-sideline-show-diagnostics t) (lsp-ui-sideline-show-code-actions t) (lsp-ui-sideline-delay 0.8) (lsp-ui-sideline-diagnostic-max-lines 2) (lsp-ui-sideline-code-actions-prefix "* ") ;; unfortunately such unicode icon changes text height a little, which is annoying (lsp-ui-peek-enable t) (lsp-ui-peek-list-width 60) (lsp-ui-peek-peek-height 25) (lsp-ui-imenu-enable t) (lsp-ui-imenu-kind-position 'top) (lsp-headerline-breadcrumb-icons-enable nil) ;; ugly (lsp-modeline-code-actions-segments '(count name)) ;; problem with formatting tab-bar-mode and light-bulb icon :custom-face (lsp-ui-sideline-symbol-info ((t (:family "Hack")))) ;; problems with slight text height change I don't want to debug (lsp-ui-sideline-code-action ((t (:family "Hack")))) ;; this font doesn't have this effect fortunately :bind (:map lsp-mode-map ("C-l m" . lsp-ui-imenu)) :config :hook (lsp-mode . lsp-ui-mode) :commands (lsp-ui-mode) :after lsp-mode) (use-package lsp-ivy :ensure :pin melpa :demand :after lsp-mode :commands lsp-ivy-workspace-symbol) (use-package lsp-treemacs :ensure :pin melpa :demand :after lsp treemacs :config (lsp-treemacs-sync-mode 1) :custom (lsp-treemacs-error-list-severity 4) :general (evil-treemacs-state-map "M-k" 'quit-window-kill-buffer "M-j" 'quit-window) :commands (lsp-treemacs-errors-list lsp-treemacs-references)) (use-package dap-mode :ensure :after lsp-mode :config (dap-auto-configure-mode) (dap-ui-mode) (dap-ui-controls-mode 1) (when (executable-find "lldb-mi") ;; rust stuff (require 'dap-lldb) (require 'dap-gdb-lldb) ;; installs .extension/vscode (dap-gdb-lldb-setup) (dap-register-debug-template "Rust::LLDB Run Configuration" (list :type "lldb" :request "launch" :name "LLDB::Run" :gdbpath "rust-lldb" ;; uncomment if lldb-mi is not in PATH ;; :lldbmipath "path/to/lldb-mi" ))) :hook (dap-stopped . (lambda (arg) (call-interactively #'dap-hydra))) ;; performance-wise ;;(lsp-mode . dap-mode) ;;(lsp-mode . dap-ui-mode) ) (use-package company-lsp :ensure :disabled ;; lsp-capf is used? :after lsp-mode company :custom (company-lsp-cache-candidates t) ;; auto, t(always using a cache), or nil (company-lsp-async t) (company-lsp-enable-snippet t) (company-lsp-enable-recompletion t) :commands company-lsp)
11.10. c++/c
(use-package ccls :ensure :config (setq ccls-executable "ccls") (setq lsp-prefer-flymake nil) (setq-default flycheck-disabled-checkers '(c/c++-clang c/c++-cppcheck c/c++-gcc)) ;:hook ((c-mode c++-mode objc-mode) . ; (lambda () (require 'ccls) (lsp)))) )
11.11. scala
(use-package lsp-metals :ensure :after lsp :config (with-eval-after-load 'treemacs (setq lsp-metals-treeview-show-when-views-received t) (lsp-metals-treeview-enable t) (lsp-metals-treeview-theme 'Metals-dark))) (use-package scala-mode :ensure :mode "\\.s\\(cala\\|bt\\|c\\)$" :interpreter ("scala" . scala-mode) :config (require 'smartparens) (require 'smartparens-scala) (defun sp-restrict-c (sym) "Smartparens restriction on `SYM' for C-derived parenthesis." (sp-restrict-to-pairs-interactive "{([" sym)) (bind-key "C-S-<tab>" 'dabbrev-expand scala-mode-map) (bind-key "s-<delete>" (sp-restrict-c 'sp-kill-sexp) scala-mode-map) (bind-key "s-<backspace>" (sp-restrict-c 'sp-backward-kill-sexp) scala-mode-map) (bind-key "s-<home>" (sp-restrict-c 'sp-beginning-of-sexp) scala-mode-map) (bind-key "s-<end>" (sp-restrict-c 'sp-end-of-sexp) scala-mode-map) :hook (scala-mode . (lambda() ;;indentation and asterisk-insertion within multi-line comments. ;; An alternative is the 'reindent-then-newline-and-indent' command. (local-set-key (kbd "RET") '(lambda () (interactive) (newline-and-indent) (scala-indent:insert-asterisk-on-multiline-comment))) (local-set-key (kbd "<backtab>") 'scala-indent:indent-with-reluctant-strategy) ;; clean-up whitespace at save (make-local-variable 'before-save-hook) (add-hook 'before-save-hook 'whitespace-cleanup) (setq comment-start "/* " comment-end " */" comment-style 'multi-line comment-empty-lines t) (smartparens-mode) (scala-mode:goto-start-of-code)))) (use-package play-routes-mode :ensure :disabled :hook (play-routes-mode . (lambda () (font-lock-add-keywords nil '(("\\<\\(FIXME\\|TODO\\|fixme\\|todo\\):" 1 font-lock-warning-face t)))))) (use-package sbt-mode :ensure :after evil :init (evil-define-key 'motion global-map (kbd "<leader>S") 'sbt-hydra) ;:config ;; sbt-supershell kills sbt-mode: https://github.com/hvesalai/emacs-sbt-mode/issues/152 ; (setq sbt:program-options '("-Dsbt.supershell=false")) )
11.12. python
(use-package elpy :ensure :config (setq elpy-modules (delq 'elpy-module-flymake elpy-modules)) (add-hook 'elpy-mode-hook 'flycheck-mode) (add-hook 'elpy-mode-hook 'py-autopep8-enable-on-save) ) (use-package py-autopep8 :ensure) (use-package blacken :ensure) (use-package auto-virtualenv :ensure :config (add-hook 'python-mode-hook 'auto-virtualenv-set-virtualenv))
11.13. java
;; java config taken from https://blog.jmibanez.com/2019/03/31/emacs-as-java-ide-revisited.html (use-package lsp-java :disabled :ensure :pin melpa :init (defun java-mode-config () (toggle-truncate-lines 1) (setq-local tab-width 4) (setq-local c-basic-offset 4)) :config ;; Enable dap-java (require 'dap-java) (setq lombok-jar (expand-file-name "/usr/lib/lombok-common/lombok.jar")) ;;(setq my/java-format-settings-file (expand-file-name "~/projects/defaultFormatterProfile.xml")) (setq lsp-java-vmargs (list "-noverify" "-Xmx2G" "-XX:+UseG1GC" "-XX:+UseStringDeduplication" (concat "-javaagent:" lombok-jar) (concat "-Xbootclasspath/a:" lombok-jar)) lsp-java-import-order '["" "java" "javax" "#"] ;; Don't organize imports on save lsp-java-save-action-organize-imports nil ;; Formatter profile lsp-java-format-settings-url "https://raw.githubusercontent.com/google/styleguide/gh-pages/eclipse-java-google-style.xml") :hook (java-mode . java-mode-config) :after (lsp-mode dap-mode))
11.14. sql
11.14.1. ejc
(use-package ejc-sql :ensure :disabled ;;:after company-quickhelp - this makes it loading realy after explicit quickhelp load :config ;;(require 'ejc-sql) ;;(require 'ejc-autocomplete) (require 'ejc-company) (push 'ejc-company-backend company-backends) (add-hook 'ejc-sql-minor-mode-hook (lambda () ;;(auto-complete-mode t) ;;(ejc-ac-setup) (ejc-eldoc-setup) (company-mode t))) (add-hook 'ejc-sql-connected-hook (lambda () (ejc-set-fetch-size 200) (ejc-set-max-rows 200) ;(ejc-set-show-too-many-rows-message t) (ejc-set-column-width-limit 100) ;(ejc-set-use-unicode t) )) ;(setq ejc-result-table-impl 'ejc-result-mode) (setq ejc-result-table-impl 'orgtbl-mode) ;; this will change begin_example to lines starting with : (setq org-babel-min-lines-for-block-output 1000) ;; sets timeout for long queries, otherwise nrepl will fail (default is 10) (setq nrepl-sync-request-timeout 600) (global-set-key (kbd "C-c eb") 'ejc-get-temp-editor-buffer) (require 'company-quickhelp) (company-quickhelp-mode) (ejc-create-connection "presto" :subprotocol "presto" :dependencies [[com.facebook.presto/presto-jdbc "0.232"]] ;;:classpath (concat "~/.m2/repository/com/facebook/presto/presto-jdbc/0.232/" "presto-jdbc-0.232.jar") :connection-uri (concat "jdbc:presto://presto-db.thetimmedia.site:8889/hive/default?" "user=hadoop")) (ejc-create-connection "conf-db" :subprotocol "mysql" ;;:dependencies [[mysql/mysql-connector-java "6.0.5"]] :dependencies [[org.mariadb.jdbc/mariadb-java-client "2.6.2"]] ;;:classname "com.mysql.cj.jdbc.Driver" :classname "org.mariadb.jdbc.Driver" :connection-uri "jdbc:mariadb://conf-db.site:3306/data" :user "app" :password (funcall (plist-get (nth 0 (auth-source-search :host "conf-db.site" :require '(:user :secret))) :secret))) (ejc-create-connection "content-db" :subprotocol "mysql" :dependencies [[org.mariadb.jdbc/mariadb-java-client "2.6.2"]] :classname "org.mariadb.jdbc.Driver" :connection-uri "jdbc:mariadb://content-db.site:3306/data" :user "admin" :password (funcall (plist-get (nth 0 (auth-source-search :host "content-db.site" :require '(:user :secret))) :secret))) (ejc-create-connection "reporting-db" :subprotocol "postgresql" :classname "org.postgresql.Driver" :classpath "~/.m2/repository/postgresql/postgresql/9.3.1102.jdbc41/postgresql-9.3-1102.jdbc41.jar" :connection-uri "jdbc:postgresql://reporting-db.site:3306/postgres" :user "postgres" :password (funcall (plist-get (nth 0 (auth-source-search :host "reporting-db.site" :require '(:user :secret))) :secret))) (ejc-create-connection "redshift" :subprotocol "postgres" ;;:dependencies [[com.amazon.redshift/redshift-jdbc42 "1.2.37.1061"]] :classpath "/home/twist/.m2/repository/com/amazon/redshift/redshift-jdbc42/jar/redshift-jdbc42-jar.1.2.37.1061" :classname "com.amazon.redshift.jdbc42.Driver" :connection-uri "jdbc:redshift://redshift-db.site:5439/dev" :user "adminelad" :password (funcall (plist-get (nth 0 (auth-source-search :host "redshift-db.site" :require '(:user :secret))) :secret))) (ejc-create-connection "hive" :subprotocol "hive" ;;:dependencies [[org.apache.hive/hive-jdbc "2.3.6"]] ;;:classpath "/home/twist/.m2/repository/org/apache/hive/hive-jdbc/2.3.6/hive-jdbc-2.3.6.jar" ;;:classname "org.apache.hive.jdbc.HiveDriver" ;;in fact this path is not valid maven path, but for valid clomacs fails as it tries to resolve artifact in some remote inaccessible repo :classpath "/home/twist/.m2/repository/org/amazon/hive/hive-jdbc41-amazon/jar/hive-jdbc41-amazon-jar.2.6.2" :classname "com.amazon.hive.jdbc41.HS2Driver" :connection-uri "jdbc:hive2://presto-db.site:10000/default" :user "hadoop") (ejc-create-connection "spark-test" :subprotocol "spark-sql" :classpath ["/home/twist/.m2/repository/org/amazon/spark/spark-jdbc41-amazon/alljars/hive-jdbc-1.2.1-spark2-amzn-1.jar" "/home/twist/.m2/repository/org/amazon/spark/spark-jdbc41-amazon/alljars/libthrift-0.9.3.jar" "/home/twist/.m2/repository/org/amazon/spark/spark-jdbc41-amazon/alljars/hadoop-common-2.8.5-amzn-5.jar" "/home/twist/.m2/repository/org/amazon/spark/spark-jdbc41-amazon/alljars/hive-metastore-1.2.1-spark2-amzn-1.jar" "/home/twist/.m2/repository/org/amazon/spark/spark-jdbc41-amazon/alljars/hive-exec-1.2.1-spark2-amzn-1.jar" "/home/twist/.m2/repository/org/amazon/spark/spark-jdbc41-amazon/alljars/spark-hive-thriftserver_2.11-2.4.4.jar"] :classname "org.apache.hive.jdbc.HiveDriver" :connection-uri "jdbc:hive2://spark2.site:10001" :user "hadoop") )
11.14.2. sql.el & tools
(use-package sql-presto :ensure :disabled ;:custom ;(sql-presto-options ("--output-format" "CSV_HEADER" )) ) (use-package sqlformat :ensure :commands (sqlformat sqlformat-buffer sqlformat-region) ;:hook (sql-mode . sqlformat-on-save-mode) ;:init ;(setq sqlformat-command 'pgformatter ; sqlformat-args '("-s2" "-g" "-u1")) ) (use-package sql :init (defun my-sql-login-hook () "Custom SQL log-in behaviours. See `sql-login-hook'." (when (eq sql-product 'postgres) (let ((proc (get-buffer-process (current-buffer)))) ;; Output each query before executing it. (n.b. this also avoids ;; the psql prompt breaking the alignment of query results.) (comint-send-string proc "\\set ECHO queries\n") (comint-send-string proc "\\pset null '<null>'\n")))) :hook ;;(sql-mode . company-mode) (sql-interactive-mode . (lambda () (toggle-truncate-lines 1))) (sql-login . my-sql-login-hook) :custom (comint-move-point-for-output 'this) (comint-scroll-to-bottom-on-input 'all) (sql-connection-alist '((mysql-local (sql-product 'mysql) (sql-server "127.0.0.1") (sql-user "root") (sql-password "root") (sql-database "db") (sql-port 3306)) (postgres-local (sql-product 'postgres) (sql-server "localhost") (sql-port 5432) (sql-user "postgres") (sql-password "postgres") (sql-database "postgres")) (sqlite (sql-product 'sqlite) (sql-database "e:\\Documents\\work\\sql\\tmp\\tmp.db")))) :config (add-to-list 'display-buffer-alist '("*sql" (display-buffer-reuse-window display-buffer-in-side-window) (side . right) (slot . -1) (window-width . 0.5) (reusable-frames . nil))) ;; this makes connection list in .dir-locals.el safe (put 'sql-connection-alist 'safe-local-variable #'listp) ;; trying to friend sql and pass ;;(setq sql-postgres-options "-w") ;;(setq sql-password-search-wallet-function #'sql-pass-search-wallet) ;;(defun sql-pass-search-wallet (wallet product user server database port) ;; (auth-source-pass-get 'secret wallet)) ;; it's so annoying (evil-collection-define-key '(insert replace) 'sql-interactive-mode (kbd "C-a") 'beginning-of-line) )
11.14.3. ob-sql-mode
(use-package ob-sql-mode :ensure :after (org ob sql))
11.14.4. lsp-sqls
(use-package lsp-sqls :after lsp :custom (lsp-sqls-connections '(((driver . "mysql") (dataSourceName . "local:local@tcp(localhost:3306)/testdb")) ((driver . "postgresql") (dataSourceName . "host=127.0.0.1 port=5433 user=postgres dbname=postgres sslmode=disable")))) :config ;; this makes connection list in .dir-locals.el safe (put 'lsp-sqls-connections 'safe-local-variable #'listp) :pretty-hydra (hydra-lsp ( "SQL" (("Sl" lsp-sql-show-schemas "show schemas") ("Sq" lsp-sql-execute-query "exec query") ("Ss" lsp-sql-execute-paragraph "exec paragraph") ("Sd" lsp-sql-show-databases "show databases") ("SD" lsp-sql-switch-database "switch database") ("Sc" lsp-sql-show-connections "show conns") ("SC" lsp-sql-switch-connection "switch conn")))))
11.15. haskell
(use-package haskell-mode :ensure :custom (haskell-process-type 'stack-ghci) (haskell-process-log t) :hook (haskell-mode . haskell-indent-mode) :general ('insert 'haskell-indent-map "<backtab>" 'haskell-indent-cycle) :config ;; (diminish 'interactive-haskell-mode "IHs") (major-mode-hydra-define haskell-mode (:hint nil :color teal :quit-key "q" :exit t :title (with-alltheicon "haskell" "Haskell")) ("REPL" (("i" haskell-interactive-bring "repl") ("f" run-haskell "inferior") ))) ;; Experiment: copy of haskell-interactive-mode-handle-h (defun haskell-interactive-mode-handle-r () "Handle ^M in output." (let ((bound (point-min)) (inhibit-read-only t)) (save-excursion (while (search-backward "\r" bound t 1) (save-excursion (forward-char) (let ((end (point))) (if (search-backward-regexp "[^\r]" bound t 1) (forward-char) (goto-char (point-min))) (let ((start (point))) (delete-region (max (- (point) (- end start)) (point-min)) end)))))))) ;; (advice-add 'haskell-interactive-mode-handle-h :after #'haskell-interactive-mode-handle-r) ) (unless (eq system-type 'windows-nt) (use-package lsp-haskell :ensure :after lsp)) (use-package flycheck-haskell :ensure)
11.16. other
(use-package json :ensure :custom (json-reformat:indent-width 2)) (add-to-list 'auto-mode-alist '("\\.avsc$" . json-mode)) (add-to-list 'auto-mode-alist '("\\.hql$" . sql-mode)) (use-package csv-mode :ensure) (use-package yaml-mode :ensure :bind (:map yaml-mode-map ("C-m" . newline-and-indent))) (use-package htmlize :ensure) ;(require 'ob-clojure) (use-package cider :disabled :ensure :custom (org-babel-clojure-backend 'cider)) ;(use-package awscli-capf ; :commands (awscli-add-to-capf) ; :hook (shell-mode . awscli-add-to-capf)) (use-package electric-operator :ensure) ;; jupyter ;(use-package ein ; :config ; (require 'ein-jupyterhub)) (use-package conda :ensure :config (conda-env-initialize-eshell) (conda-env-initialize-interactive-shells) :custom ((conda-anaconda-home (expand-file-name "/opt/miniconda3/")) (conda-env-home-directory (expand-file-name "/opt/miniconda3/")))) (use-package go-mode :ensure) (use-package gradle-mode :ensure) (use-package groovy-mode :ensure) ;; a couple of interactive commands (use-package know-your-http-well :ensure) (use-package restclient :ensure) ;; very nice (use-package color-identifiers-mode :ensure :diminish ;; " #id" :pretty-hydra (toggle-hydra ("Prog" (("I" color-identifiers-mode "color identifiers" :toggle t)))) :hook (prog-mode . color-identifiers-mode-maybe)) ; omit annoying echo - use 'maybe' function here (use-package nix-mode :ensure) (use-package kotlin-mode :ensure) (use-package flycheck-kotlin :ensure ;; :if (executable-find "yay") :ensure-system-package "yay -S --noconfirm ktlint" :demand :after kotlin-mode :config (flycheck-kotlin-setup)) (unless (eq system-type 'windows-nt) (use-package kotlin-ts-mode :ensure ;; :if (executable-find "yay") :ensure-system-package "yay -S tree-sitter-kotlin-git" )) (use-package apache-mode :ensure)
11.17. web
(use-package add-node-modules-path :ensure) (use-package prettier-js :ensure) (use-package typescript-mode :ensure) (use-package php-mode :ensure) (use-package js :ensure :custom (js-indent-level 2)) (use-package tide :ensure :disabled) (use-package emmet-mode :ensure :diminish " EM" :hook (sgml-mode . emmet-mode) ;; Auto-start on any markup modes (html-mode . emmet-mode) (css-mode . emmet-mode)) (use-package web-mode :ensure :mode "\\.jsx?$\\|\\.html?$" :after flycheck :config ;;disable default checker (setq-default flycheck-disabled-checkers (append flycheck-disabled-checkers '(javascript-jshint json-jsonlist))) ;; Enable eslint checker for web-mode (flycheck-add-mode 'javascript-eslint 'web-mode) ;; Enable flycheck globally (add-hook 'after-init-hook #'global-flycheck-mode) ;; for eslint and other stuff too (add-hook 'web-mode-hook 'add-node-modules-path) (add-hook 'web-mode-hook 'emmet-mode) ;; Using a local eslint from node_modules (add-hook 'flycheck-mode-hook 'add-node-modules-path) :custom (web-mode-code-indent-offset 2) (web-mode-content-types-alist '(("jsx" . "\\.js[x]?\\'"))) (web-mode-markup-indent-offset 2) )
11.18. mobile
;; Assuming usage with dart-mode (use-package dart-mode :ensure :hook (dart-mode . flutter-test-mode) :custom (dart-sdk-path "/opt/flutter/bin/cache/dark-sdk/" dart-format-on-save t)) (use-package flutter :ensure :after dart-mode :bind (:map dart-mode-map ("C-M-x" . #'flutter-run-or-hot-reload)) :custom (flutter-sdk-path "/opt/flutter/")) (use-package hover :ensure :after dart-mode :bind (:map hover-minor-mode-map ("C-M-z" . #'hover-run-or-hot-reload) ("C-M-x" . #'hover-run-or-hot-restart) ("C-M-p" . #'hover-take-screenshot)) :init (setq ;;hover-flutter-sdk-path "/opt/flutter" ; remove if `flutter` is already in $PATH ;;hover-command-path (concat (getenv "GOPATH") "/bin/hover") ; remove if `hover` is already in $PATH hover-hot-reload-on-save t hover-screenshot-path (concat (getenv "HOME") "/screenshots") hover-screenshot-prefix "hover-screenshot-" hover-observatory-uri "http://localhost:50300" hover-clear-buffer-on-hot-restart t) (hover-minor-mode 1)) (use-package lsp-dart :ensure)
11.19. rust
;; https://robert.kra.hn/posts/rust-emacs-setup ;; rustic = basic rust-mode + additions (use-package rustic :ensure :ensure-system-package lsp-rust-analyzer :bind (:map rustic-mode-map ;;("C-c C-c s" . lsp-rust-analyzer-status) ;;("C-c C-c e" . lsp-rust-analyzer-expand-macro) ;;("C-c C-c d" . dap-hydra) ;;("C-c C-c h" . lsp-ui-doc-glance) ) :custom ;; This controls the overlays that display type and other hints inline. Enable ;; / disable as you prefer. Well require a `lsp-workspace-restart' to have an ;; effect on open projects. (lsp-rust-analyzer-server-display-inlay-hints t) (lsp-rust-analyzer-cargo-watch-command "clippy") (lsp-rust-analyzer-display-lifetime-elision-hints-enable "skip_trivial") (lsp-rust-analyzer-display-chaining-hints t) (lsp-rust-analyzer-display-lifetime-elision-hints-use-parameter-names nil) (lsp-rust-analyzer-display-closure-return-type-hints t) (lsp-rust-analyzer-display-parameter-hints nil) (lsp-rust-analyzer-display-reborrow-hints nil) :init (defun rk/rustic-mode-hook () ;; so that run C-c C-c C-r works without having to confirm, but don't try to ;; save rust buffers that are not file visiting. Once ;; https://github.com/brotzeit/rustic/issues/253 has been resolved this should ;; no longer be necessary. (when buffer-file-name (setq-local buffer-save-without-query t)) (add-hook 'before-save-hook 'lsp-format-buffer nil t)) :hook (rustic-mode . rk/rustic-mode-hook)) ;; unused for now (defun company-yasnippet-or-completion () (interactive) (or (do-yas-expand) (company-complete-common))) (defun check-expansion () (save-excursion (if (looking-at "\\_>") t (backward-char 1) (if (looking-at "\\.") t (backward-char 1) (if (looking-at "::") t nil))))) (defun do-yas-expand () (let ((yas/fallback-behavior 'return-nil)) (yas/expand))) (defun tab-indent-or-complete () (interactive) (if (minibufferp) (minibuffer-complete) (if (or (not yas/minor-mode) (null (do-yas-expand))) (if (check-expansion) (company-complete-common) (indent-for-tab-command))))) (use-package rust-playground :ensure) (use-package toml-mode :ensure) (use-package exec-path-from-shell :unless (eq system-type 'windows-nt) :ensure :init (exec-path-from-shell-initialize)) (use-package pest-mode :ensure) (use-package flycheck-pest :ensure :after flycheck :config (flycheck-pest-setup)) (use-package just-mode :ensure) (unless (eq system-type 'windows-nt) (use-package cmake-mode :ensure)) (use-package ninja-mode :ensure) (use-package cargo :ensure :hook (rust-mode . cargo-minor-mode))
11.20. smartparens
; if M-<backspace> annoys - see this - https://github.com/Fuco1/smartparens/pull/861/files (use-package smartparens :ensure :diminish ;; " sp" :after evil :init (evil-define-key 'motion global-map (kbd "<leader>[") 'hydra-sp/body) :hook (prog-mode . show-smartparens-mode) :functions (sp-pair sp-restrict-to-pairs-interactive) :config (require 'smartparens-config) (sp-use-smartparens-bindings) (smartparens-global-mode 1) ;; to be protected from introducing unbalanced pairs by editing commands which delete regions, what you want is smartparens-strict-mode ;;(smartparens-strict-mode) (sp-pair "(" ")" :wrap "C-(") ;; how do people live without this? (sp-pair "[" "]" :wrap "s-[") ;; C-[ sends ESC (sp-pair "{" "}" :wrap "C-{") (bind-key "C-S-<left>" nil smartparens-mode-map) (bind-key "C-S-<right>" nil smartparens-mode-map) (bind-key "s-<delete>" 'sp-kill-sexp smartparens-mode-map) (bind-key "s-<backspace>" 'sp-backward-kill-sexp smartparens-mode-map) (bind-key "s-{" 'sp-rewrap-sexp smartparens-mode-map) ;; unbind the annoying one (unbind-key "M-<backspace>" smartparens-mode-map) :pretty-hydra (hydra-sp (:hint nil :title "Smartparens") ( "Moving" ( ("a" sp-beginning-of-sexp) ("e" sp-end-of-sexp) ("f" sp-forward-sexp) ("b" sp-backward-sexp) ("n" sp-down-sexp) ("N" sp-backward-down-sexp) ("p" sp-up-sexp) ("P" sp-backward-up-sexp)) "Slurp & Barf" ;; Slurping & barfing ( ("h" sp-backward-slurp-sexp) ("H" sp-backward-barf-sexp) ("l" sp-forward-slurp-sexp) ("L" sp-forward-barf-sexp)) ;; Wrapping "Sexp juggling" ( ("R" sp-rewrap-sexp) ("u" sp-unwrap-sexp) ("U" sp-backward-unwrap-sexp) ("(" sp-wrap-round) ("{" sp-wrap-curly) ("[" sp-wrap-square)) ;; Sexp juggling "Destructive" ( ("S" sp-split-sexp) ("s" sp-splice-sexp) ("r" sp-raise-sexp) ("j" sp-join-sexp) ("t" sp-transpose-sexp) ("A" sp-absorb-sexp) ("E" sp-emit-sexp) ("o" sp-convolute-sexp)) "Destructive" ( ("c" sp-change-inner :exit t) ("C" sp-change-enclosing :exit t) ("k" sp-kill-sexp) ("K" sp-backward-kill-sexp) ("w" sp-copy-sexp) ("q" nil) ("g" nil)))) ) (use-package evil-smartparens :ensure :hook (emacs-lisp . evil-smartparens-mode))
11.21. code comments
(use-package evil-nerd-commenter :disabled ;; newcomment handles it :ensure :config (evilnc-default-hotkeys nil t) (evil-define-key 'motion 'global (kbd "<leader>;i") 'evilnc-comment-or-uncomment-lines) )
11.22. code nav
(use-package prog-mode :hook ;; navigate snakeCase (prog-mode . subword-mode))
11.23. code highlights
(use-package rainbow-delimiters :ensure :hook (prog-mode . rainbow-delimiters-mode))
(use-package prog-mode :hook ;; do not wrap in prog-modes ((prog-mode . (lambda () (toggle-truncate-lines 1))) ;; ..and special-modes (special-mode . (lambda () (toggle-truncate-lines 1)))))
(use-package whitespace :ensure :defer 0.7 :diminish (global-whitespace-mode . "") ;; " $" :custom (whitespace-line-column 210) ;; limit line length (whitespace-style '(face tabs ;; spaces trailing lines space-before-tab newline indentation empty space-after-tab ;; space-mark tab-mark newline-mark)) (whitespace-global-modes '(prog-mode)) ;;:hook (prog-mode . whitespace-mode) ;; this caused problems in sql-mode (dunno why), global mode + list of modes to enable works better :config (global-whitespace-mode) )
(use-package highlight-symbol :ensure :diminish " hls" :commands highlight-symbol :bind ("C-c h" . highlight-symbol))
(use-package hl-todo :ensure :config (setq hl-todo-keyword-faces '(("TODO" . "#FF0000") ("todo" . "#FF0000") ("FIXME" . "#FF0000") ("fixme" . "#FF0000") ("DEBUG" . "#A020F0") ("GOTCHA" . "#FF4500") ("why" . "#FF4500") ("STUB" . "#1E90FF"))) (define-key hl-todo-mode-map (kbd "C-c H p") 'hl-todo-previous) (define-key hl-todo-mode-map (kbd "C-c H n") 'hl-todo-next) (define-key hl-todo-mode-map (kbd "C-c H o") 'hl-todo-occur) (define-key hl-todo-mode-map (kbd "C-c H i") 'hl-todo-insert) (add-hook 'prog-mode-hook 'hl-todo-mode) )
display colors visually
(use-package rainbow-mode :ensure :diminish " #")
Prism – experimenting
(use-package prism :disabled :quelpa (prism :fetcher github :repo "alphapapa/prism.el") ;;:hook ;;(emacs-lisp-mode . prism-mode) ;;(java-mode . prism-mode) ;;(scala-mode . prism-mode) ;;(javascript-mode . prism-mode) ;;(sh-mode . prism-whitespace-mode) ;;(python-mode . prism-whitespace-mode) )
11.24. code folding
;; integrates with evil-fold z-.. awesome! (use-package origami :ensure :after evil :diminish " O" :general ;; amazing - aka org-mode TAB everywhere ('normal [remap indent-for-tab-command] 'evil-toggle-fold) ('normal "<backtab>" 'evil-open-folds) ('motion global-map (kbd "<leader>O") 'hydra-folding/body) :commands (hydra-folding/body) ;; I'm actually may use evil-fold-.. stuff.. :pretty-hydra (hydra-folding (:color red :title "Folding") ("" (("o" origami-open-node) ("c" origami-close-node) ("n" origami-next-fold) ("p" origami-previous-fold) ("f" origami-forward-toggle-node) ("a" origami-toggle-all-nodes) ("s" origami-show-only-node))))) (use-package hs-minor-mode :hook ;; use origami only for lsp (prog-mode . hs-minor-mode)) ;; warn - this package depends on lsp-mode not from melpa-stable (use-package lsp-origami :ensure :after lsp origami :hook (lsp-mode . (lambda () (hs-minor-mode -1) (lsp-origami-mode 1))) :bind ("C-S-t" . origami-toggle-node) ("C-S-c" . origami-toggle-all-nodes))
11.25. docker
(use-package dockerfile-mode :ensure) (use-package docker-compose-mode :ensure) (use-package docker :ensure :bind ("C-c d" . docker))
11.26. markdown
(use-package markdown-mode :ensure :commands (markdown-mode gfm-mode) :mode (("README\\.md\\'" . gfm-mode) ("\\.md\\'" . markdown-mode) ("\\.markdown\\'" . markdown-mode)) :init (setq markdown-command "multimarkdown") :custom-face (markdown-code-face ((t (:inherit fixed-pitch :background "gray25")))) )
11.27. log-files
;; aka tail -f for log files (doesn't really work) (add-to-list 'auto-mode-alist '("\\.log\\'" . auto-revert-mode)) (use-package logview :ensure :mode "\\.log\\(?:\\.[0-9]+\\)?\\'")
12. system
12.1. emacs tools
(use-package request :ensure :custom (request-log-level 'debug)) (use-package restart-emacs :ensure)
12.2. multimedia & files
12.2.1. image scroll
; not using for now - it actually overrides good-scroll ;(add-hook 'after-init-hook ; #'(lambda() (load-library "iscroll")))
12.2.2. emms
(use-package emms :ensure :disabled :config (emms-all) (emms-default-players) (define-emms-simple-player mplayer '(file url) (regexp-opt '(".ogg" ".mp3" ".wav" ".mpg" ".mpeg" ".wmv" ".wma" ".mov" ".avi" ".divx" ".ogm" ".asf" ".mkv" "http://" "mms://" ".rm" ".rmvb" ".mp4" ".flac" ".vob" ".m4a" ".flv" ".ogv" ".pls")) "mplayer" "-slave" "-quiet" "-really-quiet" "-fullscreen") ;; (define-emms-simple-player afplay '(file) ;; (regexp-opt '(".mp3" ".m4a" ".aac")) ;; "afplay") ;; (setq emms-player-list `(,emms-player-afplay)) ) ;; todo - xterm colors for shell ;;https://github.com/atomontage/xterm-color
12.2.3. doc
(use-package pdf-tools :ensure) (use-package djvu :ensure) (use-package doc-view ;; :mode ("\\.odt\\'" . doc-view-mode) ) (use-package nov :ensure :mode ("\\.epub\\'" . nov-mode))
12.3. shell, eshell, term
(use-package eshell :functions (eshell-smart-initialize) :after evil :init (defun eshell-new() "Open a new instance of eshell." (interactive) (eshell 'N)) (evil-define-key 'motion global-map (kbd "<leader>e") 'eshell-new) :custom (eshell-history-size 12800) (eshell-where-to-jump 'begin) :hook (eshell-mode . (lambda () (setq-local global-hl-line-mode nil) ;; disable global mode (eshell-smart-initialize) (remove-hook 'window-scroll-functions 'eshell-smart-scroll-window) ;; (bind-key "M-n" #'next-buffer 'eshell-hist-mode-map) ;; (bind-key "M-p" #'previous-buffer 'eshell-hist-mode-map) ;; (evil-collection-define-key 'insert 'eshell-mode-map ;; (kbd "C-n") 'eshell-next-matching-input-from-input ;; (kbd "C-p") 'eshell-previous-matching-input-from-input) )) :config (require 'eshell-syntax-highlighting) (require 'eshell-git-prompt) (require 'em-smart) ; smart eshell features (require 'conda)) (use-package eshell-git-prompt :ensure :config (eshell-git-prompt-use-theme 'default)) (use-package eshell-syntax-highlighting :ensure :after eshell :config ;;(setq eshell-highlight-prompt nil) ;; Enable in all Eshell buffers. (eshell-syntax-highlighting-global-mode 1)) ;; looks poor ;(use-package eshell-prompt-extras ; :init ; (with-eval-after-load "esh-opt" ; (autoload 'epe-theme-pipeline "eshell-prompt-extras") ; (autoload 'epe-theme-dakrone "eshell-prompt-extras") ; (autoload 'epe-theme-lambda "eshell-prompt-extras") ; (autoload 'epe-theme-multiline-with-status "eshell-prompt-extras") ; (setq eshell-highlight-prompt t ;nil ; eshell-prompt-function 'epe-theme-multiline-with-status))) (use-package term :preface (defun term-zsh () (interactive) (term "/usr/bin/zsh")) (defun ansi-term-zsh () (interactive) (ansi-term "/usr/bin/zsh")) :hook (term-mode . (lambda () (setq-local global-hl-line-mode nil) ;; disable global mode in term ;; (bind-key "M-n" #'next-buffer 'term-mode-map) ;; (bind-key "M-p" #'previous-buffer 'term-mode-map) ;; (bind-key "M-n" #'next-buffer 'term-raw-map) ;; (bind-key "M-p" #'previous-buffer 'term-raw-map) )) :custom (term-scroll-to-bottom-on-output t)) (use-package multi-term :ensure :after evil :init (defun my/open-term () (interactive) (tab-new) (multi-term) (set-window-dedicated-p (get-buffer-window (current-buffer)) t)) (evil-define-key 'motion global-map (kbd "<leader>r") 'multi-term) (evil-define-key 'motion global-map (kbd "<leader>R") 'multi-term-dedicated-open) :config (setq multi-term-program "/usr/bin/zsh") :custom (multi-term-dedicated-select-after-open-p t) (multi-term-scroll-to-bottom-on-output t)) (use-package ansi-color :init (defun ansi-colorize-buffer () (interactive) (ansi-color-apply-on-region (point-min) (point-max))) ;; ansi coloring in compilation-mode buffers (e.g. for dap-java-run-test-class) (defun colorize-compilation-buffer () (read-only-mode t) (ansi-color-apply-on-region compilation-filter-start (point)) (read-only-mode nil)) :custom (ansi-color-names-vector ["#3c3836" "#fb4934" "#b8bb26" "#fabd2f" "#83a598" "#d3869b" "#8ec07c" "#ebdbb2"]) :hook (compilation-filter . colorize-compilation-buffer)) ;; testing this (use-package shell-switcher :ensure :config (setq shell-switcher-mode t) (setq-default shell-switcher-new-shell-function 'eshell-new)) ;; trying to solve coloring problems in 'shell' ;; do not change terminfo - this will break comints like sql.el etc ;; use term "zsh" instead ;;(setq comint-terminfo-terminal "dumb-emacs-ansi") ;;(setq comint-terminfo-terminal "dumb") ;; default ;dunno what it does ;(with-eval-after-load 'shell (set-face-attribute 'comint-highlight-prompt nil :inherit nil)) ;; todo - group this bindings under some 'buffer' namespace with :after (use-package comint :after evil ;; :bind (:map comint-mode-map ("M-n" . next-buffer) ("M-p" . previous-buffer)) ;; :config ;; (evil-collection-define-key 'insert 'comint-mode-map ;; (kbd "C-n") 'comint-next-input ;; (kbd "C-p") 'comint-previous-input) ) (use-package powershell :config ;; Change default compile command for powershell (add-hook 'powershell-mode-hook (lambda () (set (make-local-variable 'compile-command) (format "powershell.exe -NoLogo -NonInteractive -Command \"& '%s'\"" (buffer-file-name))))) )
12.4. vterm
(use-package vterm :ensure :disabled :unless (eq system-type 'windows-nt))
12.5. powershell
(use-package powershell :ensure)
12.6. system
12.6.1. systemd
;; systemd-mode (use-package systemd :ensure) ;; evil in terminal - cursor shapes (doesn't work in gui) ;(add-hook 'evil-insert-state-entry-hook (lambda () (send-string-to-terminal "\033[5 q"))) ;(add-hook 'evil-normal-state-entry-hook (lambda () (send-string-to-terminal "\033[0 q")))
12.6.2. terminal cursor
(if (eq system-type 'windows-nt) nil ;; terminal cursor (e.g. for evil) ;(quelpa '(term-cursor :repo "h0d/term-cursor.el" :fetcher github)) ;;(global-term-cursor-mode) ) (use-package evil-terminal-cursor-changer :ensure :demand :after evil :unless (display-graphic-p) :config (evil-terminal-cursor-changer-activate))
12.6.3. sudo edit
;; to sudo-edit files (use-package sudo-edit :ensure :general (motion "<leader> M-s" 'sudo-edit) :custom (sudo-edit-user user-login-name)) (use-package auto-sudoedit ;; no sudo on my android :unless (or (eq system-type 'windows-nt) is-android) :diminish :ensure ;; :demand ;; going minimal on startup :after ivy :config (auto-sudoedit-mode)) ; testing sudo ;(defun sudired () ; (interactive) ; (require 'tramp) ; (let ((dir (expand-file-name default-directory))) ; (if (string-match "^/sudo:" dir) ; (user-error "Already in sudo") ; (dired (concat "/sudo::" dir))))) ;(define-key dired-mode-map "!" 'sudired)
12.6.4. docop
;;(use-package docopt)
12.6.5. i3wm
;; i3wm (use-package i3wm-config-mode :ensure :hook (i3wm-config-mode . rainbow-mode))
12.6.6. exwm
(use-package exwm :ensure :disabled :unless (eq system-type 'windows-nt) :config (require 'exwm-config) (setq exwm-input-global-keys `(,(kbd "s-&") . (lambda (command) (interactive (list (read-shell-command "$ "))) (start-process-shell-command command nil command)))) (require 'exwm-systemtray) ;; didn't work ;;(exwm-systemtray-enable) ;; uncomment to start exwm ;;(exwm-config-default) )
12.6.7. other
(use-package ovpn-mode :ensure :mode ("\\.ovpn$" . conf-mode) :config ;;(evil-set-initial-state 'ovpn-mode 'emacs) (add-to-list 'evil-snipe-disabled-modes 'ovpn-mode) (evil-collection-define-key 'normal 'ovpn-mode-map "s" 'ovpn-mode-start-vpn "r" 'ovpn-mode-restart-vpn "q" 'ovpn-mode-stop-vpn "Q" 'ovpn-mode-stop-all "i" 'ovpn-mode-info-vpn "B" 'ovpn-mode-buffer-vpn "E" 'ovpn-mode-edit-vpn "d" 'ovpn-mode-dir-set "~" 'ovpn-mode-dir-filter "n" 'ovpn-mode-start-vpn-with-namespace "t" 'ovpn-mode-spawn-term-in-namespace "W" 'ovpn-mode-spawn-browser-in-namespace "a" 'ovpn-mode-active "6" (struct-ovpn-mode-platform-specific-ipv6-toggle ovpn-mode-platform-specific) "H" 'describe-mode) :custom (ovpn-mode-base-directory "~/vpn")) (use-package arch-packer :ensure) ;; manage external services (use-package prodigy :ensure :disabled) (use-package proced :hook (proced-mode . (lambda () (proced-toggle-auto-update 1))) :custom (proced-auto-update-interval (if (eq system-type 'windows-nt) 15 5))) (use-package vimrc-mode :ensure)
12.7. tramp
(use-package tramp :pin gnu :config ; not sure what it highlights ;(require 'tramp-theme) ;(load-theme 'tramp) (setq remote-file-name-inhibit-cache nil) ;; set if editing outside of tramp as well (setq vc-ignore-dir-regexp (format "%s\\|%s" vc-ignore-dir-regexp tramp-file-name-regexp)) (setq tramp-verbose 4) ;; raise if debug tramp errors ;(setq tramp-connection-timeout 3) ; for debug ;(setq-default tramp-default-method "ssh") ;(setq-default tramp-default-method "scp") ;(setq tramp-default-user "twist") ;deprecated ;(setq tramp-default-host "localhost") ;(add-to-list 'tramp-default-user-alist '("\\`\\(?:doas\\|sudoedit\\|ksu\\|su\\(?:do\\)?\\)\\'" "localhost" "twist")) ;(setq tramp-syntax 'default) ; simplified | default | separate ) (use-package counsel-tramp :ensure :after (counsel tramp) ;; this is to speed up tramp :hook (counsel-tramp-pre-command-hook . (lambda () (global-aggressive-indent-mode 0) (projectile-mode 0) (editorconfig-mode 0))) (counsel-tramp-quit-hook . (lambda () (global-aggressive-indent-mode 1) (projectile-mode 1) (editorconfig-mode 1)))) (use-package tramp-theme :ensure)
12.8. sauron
(use-package sauron :demand :after mu4e :ensure :config ;;(add-to-list 'evil-emacs-state-modes 'sauron-mode) ;; (setq sauron-hide-mode-line t) ;; (setq sauron-column-alist '((timestamp . 8) ;; (origin . 7) ;; (message))) ;; (setq sauron-timestamp-format "%H:%M:%S") (global-set-key (kbd "C-c s s") 'sauron-toggle-hide-show) (global-set-key (kbd "C-c s c") 'sauron-clear) (setq sauron-modules '(sauron-org sauron-notifications sauron-mu4e sauron-elfeed) sauron-max-line-length 120 sauron-separate-frame nil sauron-dbus-cookie t sauron-min-priority 1 ;; you probably want to add your own nickname to the these patterns sauron-watch-patterns '("emacs-fu" "emacsfu" "wombat" "capybara" "yak" "gnu" "\\bmu\\b") ;; you probably want to add you own nick here as well sauron-watch-nicks '("Tom" "Dick" "Harry")) ;; some sound/light effects for certain events (add-hook 'sauron-event-added-functions (lambda (origin prio msg &optional props) (sauron-fx-aplay "/usr/share/sounds/custom/bell_small.wav") ;; (if (string-match "ping" msg) ;; (sauron-fx-sox "/usr/share/sounds/custom/bell_small.wav")) ;; (cond ;; ((= prio 3) (sauron-fx-sox "/usr/share/sounds/pling.wav")) ;; ((= prio 4) (sauron-fx-sox "/usr/share/sounds/plong.wav")) ;; ((= prio 5) ;; ;;(sauron-fx-sox "/usr/share/sounds/alarm.wav") ;; ;;(sauron-fx-gnome-osd (format "%S: %s" origin msg) 5) ;; )) )) ;; events to ignore (add-hook 'sauron-event-block-functions (lambda (origin prio msg &optional props) (or (string-match "^*** Users" msg)))) ;; filter out IRC spam (add-hook 'sauron-event-added-functions 'sauron-alert-el-adapter) (sauron-start-hidden) ;;(require 'sauron-mu4e) ;;(sauron-mu4e-start) (sauron-org-start) ;;(elfeed-update-background-start) ;;(sauron-elfeed-start) (sauron-add-event 'kitchen ;; origin 2 ;; priority "Coffee is ready!" '(lambda () ;; function called when activated (message "Coffee's ready, get it while it's hot!")) '(:temperature 80)) ;; arbitrary props passed to ;; hook functions ) ;; dbus-send --session \ ;; --dest="org.gnu.Emacs" \ ;; --type=method_call \ ;; "/org/gnu/Emacs/Sauron" \ ;; "org.gnu.Emacs.Sauron.AddMsgEvent" \ ;; string:shell uint32:3 string:"Hello, world!"
13. user
13.1. games & fun
(use-package 2048-game :ensure) (use-package fireplace :ensure)
13.2. accessibility
(pretty-hydra-define hydra-accessibility (:hint nil :color teal :quit-key "q" :title (with-faicon "universal-access" "Accessibility" 1 -0.05)) ("TTS" ( ("b" festival-say-buffer "festival bufer") ("r" festival-say-region "festival region") ("k" festival-kill-process "festival kill"))))
13.3. hugo
(use-package ox-hugo :ensure :after ox org-capture :pin melpa :config ;; Populates only the EXPORT_FILE_NAME property in the inserted headline. (defun org-hugo-new-subtree-post-capture-template () "Returns `org-capture' template string for new Hugo post. See `org-capture-templates' for more information." (let* ((title (read-from-minibuffer "Post Title: ")) ; Prompt to enter the post title (fname (org-hugo-slug title))) (mapconcat #'identity `( ,(concat "* TODO " title) ":PROPERTIES:" ,(concat ":EXPORT_FILE_NAME: " fname) ":END:" "%?\n") ;Place the cursor here finally "\n"))) (add-to-list 'org-capture-templates '("h" ;`org-capture' binding + h "Hugo post" entry ;; It is assumed that below file is present in `org-directory' ;; and that it has a "Blog Ideas" heading. It can even be a ;; symlink pointing to the actual location of all-posts.org! (file+olp "blog.org" "Blog Ideas") (function org-hugo-new-subtree-post-capture-template))))
13.4. wordpress
(use-package org2blog :ensure :config ;;(org2blog-structure-template-add) ;;(add-to-list 'org-structure-template-alist '("wp" "@@wp:?@@")) :custom (org-export-preserve-breaks t) (org2blog/wp-use-sourcecode-shortcode t) (org2blog/wp-image-upload t) (org2blog/wp-image-thumbnails t) (org2blog/wp-track-posts nil) ;; (list "content.org" "org2blog-ostapchuk-posts") ;; pretty much useless (org2blog/wp-blog-alist `(("ostapchuk.xyz" :url "https://ostapchuk.xyz/xmlrpc.php" :username "twist522" :password ,(auth-source-pass-get 'secret "ostapchuk.xyz/twist522") ) ("codefastdieyoung.com" :url "https://codefastdieyoung.com/xmlrpc.php" :username "twist522@gmail.com" :password ,(auth-source-pass-get 'secret "codefastdieyoung.com/twist522@gmail.com") ) )) )
13.5. ledger
(use-package ledger-mode :ensure :config ;(require 'flycheck-ledger) (add-to-list 'org-capture-templates '("l" "Ledger") t) (add-to-list 'org-capture-templates '("lb" "Bank" plain (file "~/Dropbox/org/ledger/journal.dat") "%(org-read-date) %^{Payee}\n\tExpenses:%^{Account} %^{Ammount} UAH\n\tKredo" :empty-lines 1 :immediate-finish t)) (add-to-list 'org-capture-templates ' ("lc" "Cash" plain (file "~/Dropbox/org/ledger/journal.dat") "%(org-read-date) * %^{Payee}\n\tExpenses:%^{Account} %^{Amount} UAH\n\tCash" :empty-lines 1 :immediate-finish t)) :bind ;;(:map ledger-mode-map ("M-n" . next-buffer) ("M-p" . previous-buffer)) :hook (ledger-mode . (lambda () (setq-local indent-line-function #'ledger-indent-line) (setq-local indent-region-function 'ledger-post-align-postings) )) :custom ;;(ledger-binary-path "hledger") (ledger-reconcile-default-commodity nil) (ledger-reports '(("this month budget" "ledger budget expenses -p \"this month\" -X UAH") ("last-month-balance" "ledger [[ledger-mode-flags]] -f ~/Dropbox/org/ledger/ledger.dat --monthly bal ^expenses -X UAH -p \"last month\"") ("last-month-expenses" "ledger [[ledger-mode-flags]] -f ~/Dropbox/org/ledger/ledger.dat reg ^expenses -X UAH -p \"last month\" --monthly") ("bal" "%(binary) -f %(ledger-file) bal") ("reg" "%(binary) -f %(ledger-file) reg") ("payee" "%(binary) -f %(ledger-file) reg @%(payee)") ("account" "%(binary) -f %(ledger-file) reg %(account)") )) ) (use-package flycheck-ledger :ensure :demand :after ledger-mode) (use-package hledger-mode :commands (hledger-run-command) :ensure :hook (hledger-mode . (lambda () (make-local-variable 'company-backends) (add-to-list 'company-backends 'hledger-company))) :config (evil-collection-define-key 'normal 'hledger-view-mode-map "gr" 'hledger-redo) ;; why should I define both for map and mode? (evil-collection-define-key 'normal 'hledger-view-mode "gr" 'hledger-redo) (evil-collection-define-key 'normal 'hledger-view-mode-map (kbd "<") 'hledger-prev-report) (evil-collection-define-key 'normal 'hledger-view-mode-map (kbd ">") 'hledger-next-report) (evil-collection-define-key 'normal 'hledger-view-mode "<" 'hledger-prev-report) (evil-collection-define-key 'normal 'hledger-view-mode ">" 'hledger-next-report) :custom ;;(hledger-date-regex "[0-9]\\{2\\}[-/][0-9]\\{2\\}") (hledger-jfile (concat org-directory "ledger/ledger.dat")) (hledger-currency-string "USD") (hledger-running-report-months 12) (hledger-extra-args " -X USD --infer-market-prices -S") (hledger-top-asset-account "Assets") (hledger-top-expense-account "Expenses") (hledger-top-income-account "Income") (hledger-ratios-income-accounts "Income") (hledger-ratios-assets-accounts "Assets") (hledger-ratios-debt-accounts "Liabilities") (hledger-ratios-liquid-asset-accounts "Assets") (hledger-reporting-day 1) (hledger-daily-report-accounts "Expenses") (hledger-show-only-unstarred-p nil) ) (use-package flycheck-hledger :ensure :demand :after hledger-mode) (use-package evil-ledger :demand :after evil ledger-mode) (fset 'euro (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([24 56 return 35 120 50 48 65 67 return] 0 "%d")) arg)))
13.6. beancount
(use-package beancount :disabled :mode "\\.beancount\\'" :quelpa (beancount :repo "beancount/beancount-mode" :fetcher github) :hook (beancount-mode . (lambda () (setq-local electric-indent-chars nil))) (beancount-mode . outline-minor-mode) :bind (:map beancount-mode-map (("C-c C-n" . outline-next-visible-heading) ("C-c C-p" . outline-previous-visible-heading))))
13.7. google-translate
; doesn't work ;(use-package go-translate ; :config ; (setq go-translate-local-language "en") ; (setq go-translate-target-language "uk") ; (setq go-translate-extra-directions '(("uk" . "ru") ("ru" . "en"))) ; (setq go-translate-buffer-follow-p t) ; focus the result window ; (setq go-translate-buffer-source-fold-p t) ; fold the source text in the result window ; (setq go-translate-buffer-window-config nil) ; config the result window as your wish ; (setq go-translate-debug-p t) ; (global-set-key "\C-ct" 'go-translate) ; (global-set-key "\C-cT" 'go-translate-popup)) ; crazy, finally it works (use-package google-translate :disabled :ensure ;:init ;(require 'google-translate) ;(require 'google-translate-smooth-ui) ;(defun google-translate--search-tkk () "Search TKK." (list 430675 2721866130)) :functions (google-translate--search-tkk) :config (require 'google-translate-smooth-ui) (defun google-translate--search-tkk () "Search TKK." (list 430675 2721866130)) ;todo - fix minibuffer keymap with evil for directions ;(evil-define-key '(motion normal insert) minibuffer-local-map) :custom (google-translate-input-method-auto-toggling t) (google-translate-preferable-input-methods-alist '((nil . ("en")) (ukrainian-computer . ("ru" "uk")))) (google-translate-translation-directions-alist '(("uk" . "en") ("ru" . "en") ("en" . "uk"))) ;(google-translate--tkk-url "http://translate.google.com/") ;(google-translate-base-url "http://translate.google.com/") ;(google-translate-backend-debug t) (google-translate-backend-method 'curl) (google-translate-show-phonetic t) :bind ("C-c C-t t" . google-translate-smooth-translate) ("C-c C-t p" . google-translate-at-point) ("C-c C-t q" . google-translate-query-translate) ("C-c C-t d" . google-translate-query-translate-using-directions) )
13.8. elfeed
(use-package elfeed :disabled :ensure :bind ("C-c f" . elfeed) :config (elfeed-update) :custom (elfeed-search-filter "@6-months-ago +unread -ARCHIVE")) (use-package elfeed-org :disabled :ensure :demand :after elfeed :custom (rmh-elfeed-org-files (list (concat org-directory "elfeed/feeds.org"))) :config (defadvice elfeed (after elfeed-update-each-time activate) "Update each time" (elfeed-update)) (elfeed-org) (elfeed-update)) (use-package elfeed-goodies :disabled :ensure :demand :after elfeed :config (elfeed-goodies/setup)) ; this is for scoring entries, not using it now (use-package elfeed-score :disabled :ensure :disabled :after evil :config ;;(elfeed-score-enable) (evil-define-key 'normal elfeed-search-mode-map "=" elfeed-score-map))
13.9. mail
(use-package message :init (when (not (eq system-type 'windows-nt)) (progn (setq message-directory "~/.mail/") (setq gnus-directory "~/.config/emacs/news/"))) :custom ;; smtp mail setting; these are the same that `gnus' uses. (message-send-mail-function 'smtpmail-send-it) (smtpmail-smtp-server "smtp.gmail.com") (smtpmail-smtp-service 587) (smtpmail-stream-type 'starttls) ;;smtpmail-default-smtp-server "smtp.example.com" ;;smtpmail-local-domain "example.com" ;;smtp-queue-dir "~/.mail/gmail/sent wd/" ) (use-package gnus :disabled :custom (gnus-select-method `(nnimap "gmail.com" (nnimap-user "twist522") (nnimap-address "imap.gmail.com") (nnimap-server-port 993) (nnmail-expiry-wait immediate))) (gnus-message-archive-group "gmail/[Gmail]/Sent Mail") ;gnus-interactive-exit nil ;gnus-novice-user nil ;gnus-expert-user t (gnus-secondary-select-methods '((nntp "news.gmane.io")))) ;(bind-key "<delete" 'gnus-summary-delete-article gnus-summary-mode-map) (use-package mu4e :disabled :unless (eq system-type 'windows-nt) :after evil :init (evil-define-key 'motion global-map (kbd "<leader>M") 'mu4e) ;;:preface :defines (mu4e~context-current mu4e~main-buffer-name) :functions (mu4e-update-mail-and-index) :commands (mu4e) ;;:config ;;(mu4e-update-mail-and-index t) ;; (add-to-list 'mu4e-view-actions ;; type ‘aV’, and the message opens inside a browse-url-generic-program ;; '("ViewInBrowser" . mu4e-action-view-in-browser) t) ;:hook (mu4e-index-updated . (lambda () (shel-command "aplay /usr/share/sounds/custom/bell_small.wav&"))) :custom (mail-user-agent 'mu4e-user-agent) (mu4e-display-update-status-in-modeline t) (mu4e-change-filenames-when-moving t) (message-kill-buffer-on-exit t) (shr-color-visible-luminance-min 80) ;; this helps a lot in dark theme (mu4e-bookmarks '((:name "Unread messages" :query "flag:unread AND NOT maildir:/Trash/" :key ?u) ;; AND NOT flag:trashed (:name "Today's messages" :query "date:today..now AND NOT maildir:/Trash/" :key ?t) (:name "Last 7 days" :query "date:7d..now AND NOT maildir:/Trash/" :hide-unread t :key ?w) (:name "All inboxes" :query "m:/twist/Inbox or m:/yuri/Inbox or m:/work/Inbox" :key ?i) ;;(:name "Messages with images" :query "mime:image/*" :key ?p) )) (mu4e-get-mail-command "mbsync -a") ;; set it to "true" will not run mbsync within emacs (mu4e-compose-signature (concat "Yuri Ostapchuk\n" "https://codefastdieyoung.xyz\n")) (mu4e-sent-messages-behavior 'delete) ;; gmail takes care of saving it (mu4e-view-show-images t) ;; seems this var is not defined? ;;(mu4e-use-fancy-chars t) (mu4e-update-interval 180) ;; update in background each 5min (mu4e-index-update-in-background t) ;; t is default, but I like it explicit (mu4e-maildir-shortcuts '((:maildir "/twist/Inbox" :key ?i) (:maildir "/yuri/Inbox" :key ?y) (:maildir "/work/Inbox" :key ?w) (:maildir "/twist/band" :key ?B) (:maildir "/twist/biz" :key ?b) (:maildir "/twist/jobs" :key ?j) (:maildir "/twist/relationships" :key ?r) (:maildir "/twist/[Gmail]/Trash" :key ?t) )) (mu4e-icalendar-trash-after-reply t) :config (require 'shr) (require 'shr-color) (require 'mu4e-icalendar) (mu4e-icalendar-setup) (setq mu4e-main-buffer-name "*mu4e-main*") (defun mu4e-fast-update-mail-and-index (run-in-background) "Update only INBOX folder of the current context (fast update)." (interactive "P") (let ((mu4e-get-mail-command (concat "mbsync " (mu4e-context-name (mu4e-context-current)) ":INBOX"))) (mu4e-update-mail-and-index run-in-background))) (evil-collection-define-key 'motion 'mu4e-main-mode-map "U" 'mu4e-fast-update-mail-and-index) ;; trash vs expunge see https://github.com/djcb/mu/issues/1136 (setf (alist-get 'trash mu4e-marks) (list :char '("d" . "▼") :prompt "dtrash" :dyn-target (lambda (target msg) (mu4e-get-trash-folder msg)) :action (lambda (docid msg target) ;; Here's the main difference to the regular trash mark, ;; no +T before -N so the message is not marked as ;; IMAP-deleted: (mu4e--server-move docid (mu4e~mark-check-target target) "-N")))) (setq mu4e-contexts `( ,(make-mu4e-context :name "twist" :enter-func (lambda () (mu4e-message "Entering Personal context")) :leave-func (lambda () (mu4e-message "Leaving Personal context")) ;; we match based on the contact-fields of the message :match-func (lambda (msg) (when msg (mu4e-message-contact-field-matches msg :to "twist522@gmail.com"))) :vars '((user-mail-address . "twist522@gmail.com") (user-full-name . "Yuri Ostapchuk") (smtpmail-smtp-user . "twist522@gmail.com") (mu4e-drafts-folder . "/twist/[Gmail]/Drafts") ;;mu4e-refile-folder "/archive" (mu4e-sent-folder . "/twist/[Gmail]/Sent Mail") (mu4e-trash-folder . "/twist/[Gmail]/Trash") (mu4e-compose-signature . (concat "Yuri Ostapchuk\n" "https://codefastdieyoung.xyz\n")) )) ,(make-mu4e-context :name "yuri" :enter-func (lambda () (mu4e-message "Switch to the Yuri context")) ;; no leave-func ;; we match based on the maildir of the message; assume all ;; cycling-related messages go into the /cycling maildir :match-func (lambda (msg) (when msg (string= (mu4e-message-field msg :maildir) "/yuri"))) :vars '((user-mail-address . "yuri.ostapchuk@gmail.com") (user-full-name . "Yuri Ostapchuk") ; (smtpmail-smtp-user . "yuri.ostapchuk@gmail.com") (mu4e-drafts-folder . "/yuri/[Gmail]/Drafts") (mu4e-sent-folder . "/yuri/[Gmail]/Sent Mail") (mu4e-trash-folder . "/yuri/[Gmail]/Trash") (mu4e-compose-signature . (concat "Yuri Ostapchuk\n" "https://codefastdieyoung.xyz\n")))) ,(make-mu4e-context :name "work" :enter-func (lambda () (mu4e-message "Switch to the Work context")) ;; this matches maildir /Work and its sub-directories :match-func (lambda (msg) (when msg (string-match-p "^/work" (mu4e-message-field msg :maildir)))) :vars `((user-mail-address . ,(auth-source-pass-get "Username" "dk/google.com")) (user-full-name . "Yuri Ostapchuk") (smtpmail-smtp-user . ,(auth-source-pass-get "Username" "dk/google.com")) (mu4e-drafts-folder . "/work/[Gmail]/Drafts") (mu4e-sent-folder . "/work/[Gmail]/Sent Mail") (mu4e-trash-folder . "/work/[Gmail]/Trash") (mu4e-compose-signature . (concat "Yuri Ostapchuk\n" "DataOps\n")))) )) ) (use-package mu4e-marker-icons :disabled :init (mu4e-marker-icons-mode 1)) ;; (use-package sauron-mu4e ;; :demand :after sauron mu4e) (use-package mu4e-alert :disabled :ensure :demand :after mu4e sauron :init (setq ;; these stuff here is because of old mu4e-alert depending on older mu4e mu4e~main-buffer-name mu4e-main-buffer-name) :custom (mu4e-alert-notify-repeated-mails nil) (mu4e-alert-email-notification-types '(subjects)) (mu4e-alert-interesting-mail-query "flag:unread AND NOT maildir:/Trash/") :config ;; todo - save/restore into file (with desktop?) ;;(ht->alist mu4e-alert-repeated-mails) ;;my/dump-vars-to-file (require 'sauron-mu4e) (setq sauron-mu4e-priority 3) (setq mu4e~context-current mu4e--context-current) (defun my/mu4e-alert-filter-repeated-mails (mails) "Filters the MAILS that have been seen already." (cl-remove-if (lambda (mail) (prog1 (and (not mu4e-alert-notify-repeated-mails) (ht-get mu4e-alert-repeated-mails (plist-get mail :message-id))) (ht-set! mu4e-alert-repeated-mails (plist-get mail :message-id) t))) mails)) (defun my/sauron-mu4e-uread-messages (mails) "Add each email to the log. Takes a list of mu4e mails as MAILS." (dolist (mail mails) (let ((log-message (funcall sauron-mu4e-formatter-function mail)) (callback (my/sauron-mu4e-make-link mail))) (sauron-add-event 'mu4e sauron-mu4e-priority log-message callback)))) (defun my/mu4e-alert-notify-unread-mail-async () "Send a desktop notification about currently unread email." (mu4e-alert--get-mu-unread-mails (lambda (mails) (let ((new-mails (my/mu4e-alert-filter-repeated-mails mails))) (when (memql 'count mu4e-alert-email-notification-types) (mu4e-alert-notify-unread-messages-count (length new-mails))) (when (memql 'subjects mu4e-alert-email-notification-types) (progn (my/mu4e-alert-notify-unread-messages new-mails) ;;(my/sauron-mu4e-uread-messages new-mails) ) ))))) (defun my/mu4e-alert-notify-unread-messages (mails) "Display desktop notification for given MAILS." (let* ((mail-groups (funcall mu4e-alert-mail-grouper mails)) (sorted-mail-groups (sort mail-groups mu4e-alert-grouped-mail-sorter)) (notifications (mapcar (lambda (group) (funcall mu4e-alert-grouped-mail-notification-formatter group mails)) sorted-mail-groups))) (dolist (notification (cl-subseq notifications 0 (min 5 (length notifications)))) (alert (plist-get notification :body) :title (plist-get notification :title) :category "mu4e-alert" :icon mu4e-alert-icon)) (dolist (mail mails) (with-temp-buffer (insert (format "%s" mail)) (write-region (point-min) (point-max) "~/test.mails" t)) ) (when notifications (mu4e-alert-set-window-urgency-maybe)))) ;;(setq mu4e-view-message-with-msgid 'mu4e-view-message-with-message-id) (defun my/sauron-mu4e-make-link (mail) "Make the callback link. Takes a single mu4e mail as MAIL." (lambda () (message "this feature was disabled")) ;; this lexical-let just doesn't work ;; (lexical-let ;; ((message-id (plist-get mail :message-id))) ;; (lambda () ;; (switch-to-buffer "*mu4e-headers*") ;; (mu4e-view-message-with-message-id message-id))) ) ;;(advice-add 'sauron-mu4e-make-link :override #'my/sauron-mu4e-make-link) (mu4e-alert-set-default-style 'libnotify) ;;(mu4e-alert-enable-notifications) (my/mu4e-alert-notify-unread-mail-async) (mu4e-alert-enable-mode-line-display) (add-hook 'mu4e-index-updated-hook #'my/mu4e-alert-notify-unread-mail-async) ;;(advice-add 'mu4e-alert-filter-repeated-mails :override #'my/mu4e-alert-filter-repeated-mails) ;;(mu4e-alert-enable-mode-line-display) ) ;; (mu4e-alert-notify-unread-messages-count 10) ;; (defun mu4e-alert-notify-unread-mail-async () ;; "Send a desktop notification about currently unread email." ;; (mu4e-alert--get-mu-unread-mails (lambda (mails) ;; (let ((new-mails (mu4e-alert-filter-repeated-mails mails))) ;; (when (memql 'count mu4e-alert-email-notification-types) ;; (mu4e-alert-notify-unread-messages-count (length new-mails))) ;; (when (memql 'subjects mu4e-alert-email-notification-types) ;; (mu4e-alert-notify-unread-messages new-mails)))))) (use-package mu4e-dashboard :disabled :quelpa (mu4e-dashboard :fetcher "github" :repo "rougier/mu4e-dashboard"))
13.10. web
(use-package eww :disabled :ensure :custom (eww-search-prefix "https://www.google.com/search?q=") )
13.11. msgs
13.11.1. telega
(use-package telega :disabled :ensure :config (telega-notifications-mode))
13.11.2. slack
(use-package emojify :disabled :ensure) (use-package slack :disabled :after emojify :ensure :commands (slack-start) :init (setq slack-buffer-emojify t) ;; if you want to enable emoji, default nil (setq slack-prefer-current-team t) :hook (slack-mode . emojify-mode) :config (slack-register-team :name (auth-source-pass-get "name" "slack.com/work1") :default t :token (auth-source-pass-get 'secret "slack.com/work1") :cookie (auth-source-pass-get "cookie" "slack.com/work1") :subscribed-channels '(general) :full-and-display-names t) (evil-define-key 'normal slack-info-mode-map ",u" 'slack-room-update-messages) (evil-define-key 'normal slack-mode-map ",c" 'slack-buffer-kill ",ra" 'slack-message-add-reaction ",rr" 'slack-message-remove-reaction ",rs" 'slack-message-show-reaction-users ",pl" 'slack-room-pins-list ",pa" 'slack-message-pins-add ",pr" 'slack-message-pins-remove ",mm" 'slack-message-write-another-buffer ",me" 'slack-message-edit ",md" 'slack-message-delete ",u" 'slack-room-update-messages ",2" 'slack-message-embed-mention ",3" 'slack-message-embed-channel "\C-n" 'slack-buffer-goto-next-message "\C-p" 'slack-buffer-goto-prev-message) (evil-define-key 'normal slack-edit-message-mode-map ",k" 'slack-message-cancel-edit ",s" 'slack-message-send-from-buffer ",2" 'slack-message-embed-mention ",3" 'slack-message-embed-channel))
13.12. matrix
(use-package matrix-client :disabled t ;; this is an older client, ement.el is the new one :after bufler :quelpa (matrix-client :fetcher github :repo "alphapapa/matrix-client.el" :files (:defaults "logo.png" "matrix-client-standalone.el.sh"))) (use-package plz :disabled :quelpa (plz :fetcher github :repo "alphapapa/plz.el")) ;; Install Ement. (use-package ement :disabled :quelpa (ement :fetcher github :repo "alphapapa/ement.el"))
13.13. other
(use-package google-maps :disabled :ensure)
13.14. dropbox
Simple helper for dropbox – I’m using it only for org files anyway and
I don’t want to bloat performance on windows with dropbox client app.
I don’t want to bloat performance on windows with dropbox client app.
(defun rclone-dropbox-bisync () "Dropbox sync helper using rclone." (interactive) (let ((buf "rclone-dropbox-bisync")) (switch-to-buffer buf) (erase-buffer) (call-process "rclone" nil buf t "bisync" "--verbose" "dropbox:" (concat (getenv "HOME") "/Dropbox")) (run-with-idle-timer 3 nil `(lambda () (kill-buffer ,buf))))) (add-hook 'kill-emacs-hook #'rclone-dropbox-bisync) (add-hook 'after-init-hook #'rclone-dropbox-bisync) (with-eval-after-load 'pretty-hydra (pretty-hydra-define+ utils-hydra () ("User" (("ud" rclone-dropbox-bisync "dropbox sync")))))
14. custom
;;I'm not using custom, but have to keep this file writable - some functions fail otherwise (customize-set-variable 'custom-file ;'null-device "not storing" (expand-file-name "custom.el" user-emacs-directory) "keep customize settings in their own file") ;;(load custom-file)
15. simple.el
This is a WIP test simplified emacs configuration
(setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/") ;;("org" . "https://orgmode.org/elpa/") ("nongnu" . "https://elpa.nongnu.org/nongnu/") ("melpa" . "https://melpa.org/packages/") ("melpa-stable" . "http://stable.melpa.org/packages/") ) package-archive-priorities '( ("melpa-stable" . 5) ("nongnu" . 20) ("gnu" . 10) ("melpa" . 25))) ;; started using melpa first (require 'package) (package-initialize) (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (require 'use-package) (setq ;; Enable ensure by default for use-package ;;use-package-always-ensure ;; actually, when using this + ensure-nil, macro still generates code - when using byte-compilation there will be warnings use-package-always-defer t use-package-compute-statistics t use-package-verbose 'debug use-package-minimum-reported-time 0 ;; I want to see order and timing ) (use-package use-package-ensure-system-package :ensure) (use-package system-packages :ensure) (setq is-android (string= "Android" (string-trim (shell-command-to-string "uname -o")))) (use-package diminish :ensure :demand) ;; TODO - sort this (use-package emacs :demand :custom (user-full-name "Yuri Ostapchuk") (user-mail-address "twist522@gmail.com") ;; startup (inhibit-startup-message t) (initial-scratch-message "") (initial-buffer-choice nil) ;;(initial-major-mode 'fundamental-mode) ; I don't want to load prog-mode hooks ;;(setq debug-on-error t) (create-lockfiles nil) (make-backup-files nil) ;; editing ;;(show-paren-delay 0.5) (sentence-end-double-space nil) (save-interprogram-paste-before-kill t) ;; (mouse-yank-at-point t) (mouse-drag-copy-region t) ;; ui (global-hl-line-mode 1) ; highlight current line (fringe-mode 16) (size-indication-mode 1) ;; interaction (scroll-error-top-bottom t) (enable-recursive-minibuffers t) ;; experimental - minibuffer within minibuffer (browse-url-browser-function 'browse-url-default-browser) (eww-search-prefix "https://google.com/search?q=") :config ;; ui (menu-bar-mode -1) (tool-bar-mode -1) ;; for windows - easier integration with Dropbox/org paths (when (eq system-type 'window-nt) (setenv "HOME" "C:\\Users\\Admin")) ;; When running from containers I have annoyances with symbolic links ;; (when (eq system-type 'gnu/linux) (setenv "HOME" "/home/twist")) ;; for mac ;;(setq mac-option-modifier 'meta) ;;(setq mac-command-modifier 'super) (with-eval-after-load 'eldoc (diminish 'eldoc-mode "")) :hook (after-init . (lambda () ;; these stuff gets overwritten if run during init (tooltip-mode -1) (save-place-mode 1) ; remember file position in the visited previously file ;; ui (when (display-graphic-p) ;; (display-battery-mode 1) (set-scroll-bar-mode nil)) ;; interaction (auto-insert-mode t) ;; editing ;;(electric-indent-mode 0) ;; it makes indentations messy in org, I'm using org-indent-mode (delete-selection-mode 1) ;; omg how could I live without this - to remove selection (if active) when inserting text (global-so-long-mode 1) (eval-after-load 'prog-mode (show-paren-mode 1)) ;; todo - local? ))) ;; set default (if (eq system-type 'windows-nt) (set-face-attribute 'default nil :font "Fira Mono" :height 114) ;; defaults to 139 (set-face-attribute 'default nil :font "Input Mono Narrow" :height 112)) ;; (if (eq system-type 'windows-nt) ;; (set-face-attribute 'default nil :font "Fira Mono" :height 114) ;; defaults to 139 ;; (set-face-attribute 'default nil :font "Fira Mono" :height 114) ;; defaults to 139 ;; ;; ;; ;;(set-face-attribute 'default nil :font "Source Code Pro-11") ;; ;; equivalent ;; ;;(add-to-list 'default-frame-alist '(font . "Input Mono Narrow-9")) ;; ;;(add-to-list 'default-frame-alist '(font . "Source Code Pro-10")) ;; ) ;(set-face-attribute 'bold nil :height 95) ;; good way to emphasize ;(set-face-attribute 'default nil :font "Input Mono Narrow" :height 95) ;;(set-face-attribute 'default nil :font "Source Code Pro" :height 150) ;; defaults to 139 ;;(set-face-attribute 'default nil :font "Source Code Pro Medium") ;; equivalent of ;;(set-frame-font "Source Code Pro Medium" nil t) ;; or use M-x menu-set-font, or use M-x set-frame-font ;; testing ;;(set-fontset-font t 'latin "Noto Sans") ;; something for icons? (setq inhibit-compacting-font-caches t) (use-package gruvbox-theme :ensure :defer 0.1 :init (defvar my/toggle-dark t) (defun my/tab-line--set-faces () (custom-set-faces `(tab-line-tab-inactive ((t (:background ,gruvbox-bg :foreground ,gruvbox-light0)))) `(tab-line-tab ((t (:background ,gruvbox-dark2 :foreground ,gruvbox-light0)))) `(tab-line ((t (:background ,gruvbox-bg :foreground ,gruvbox-light0)))) `(tab-line-highlight ((t (:inherit (tab-line-tab))))) ;; mouseover `(tab-line-tab-current ((t (:extend t :background ,gruvbox-dark2 :foreground ,gruvbox-light0 :weight bold ;;:underline t :box '(:line-width (1 . 1) :style released-button))))))) (defun my/load-dark-theme () (mapc #'disable-theme custom-enabled-themes) (load-theme 'gruvbox-dark-hard t) ;; can't find a way to get those colors from the theme def itself (let* ((gruvbox-dark0_hard "#1d2021") (gruvbox-dark2 "#504945") (gruvbox-light0 "#fdf4c1") (gruvbox-bg gruvbox-dark0_hard)) (my/tab-line--set-faces))) (defun my/load-light-theme () (mapc #'disable-theme custom-enabled-themes) (load-theme 'gruvbox-light-soft t) (let* ((gruvbox-dark0_soft "#f2e5bc") (gruvbox-dark2 "#d5c4a1") (gruvbox-light0 "#282828") (gruvbox-bg gruvbox-dark0_soft)) (my/tab-line--set-faces))) (defun my/toggle-light-dark () (interactive) (if (eq (car custom-enabled-themes) 'gruvbox-light-soft) (progn (my/load-dark-theme) (setq my/toggle-dark t)) (progn (my/load-light-theme) (setq my/toggle-dark nil)))) :config ;;(load-theme 'gruvbox-dark-medium t) (my/load-dark-theme) ) (use-package doom-themes :ensure :init (defun my/restore-mode-line () "Restore modeline after doom-themes ding, sometimes it gets stuck into doom-modeline-error state" (interactive) (setq face-remapping-alist (delete (assq 'mode-line face-remapping-alist) face-remapping-alist))) :defer 0.1 :config ;(load-theme 'doom-one t) ;(load-theme 'doom-gruvbox t) (doom-themes-visual-bell-config) ;(doom-themes-neotree-config) ;(doom-themes-treemacs-config) (doom-themes-org-config) :custom (doom-themes-enable-bold t) (doom-themes-enable-italic t)) ;; (nerd-icons-install-fonts) (use-package doom-modeline :ensure :defer 0.1 :config (doom-modeline-mode) :custom ((column-number-mode t) ;; these will hardcode height and zoom-frm will not work for mode-line ;;(set-face-attribute 'mode-line nil :height 90) ;;(set-face-attribute 'mode-line-inactive nil :height 50) (doom-modeline-height 25) (doom-modeline-bar-width 6) (doom-modeline-workspace-name nil) ;; tab-bar-mode displays this in the top (doom-modeline-indent-info t) (doom-modeline-window-width-limit 140) ; works for: ;(window-font-width nil 'mode-line) ; 20 ;(window-font-height nil 'mode-line) ; 42 ;; scala projects may have very long file paths, in that case doommodeline doesn't truncate it ;;:custom (doom-modeline-buffer-file-name-style 'truncate-with-project) (doom-modeline-minor-modes t) (doom-modeline-modal-icon t) ;; its better with nerd-icons now (doom-modeline-major-mode-icon t) (doom-modeline-buffer-state-icon t) )) ;; nice (use-package minions :ensure :defer 1 :config (global-set-key [S-down-mouse-3] 'minions-minor-modes-menu)) ;; some problem with use-package and \" probably (with-eval-after-load 'general (general-define-key :states '(normal visual motion) :keymaps 'override "C-\"" (general-simulate-key "<leader>"))) (use-package general :ensure :demand :after evil :config (general-evil-setup) (general-imap "k" (general-key-dispatch 'self-insert-command :timeout 0.1 "j" 'evil-escape "m" (general-simulate-key "RET"))) (general-imap "л" (general-key-dispatch 'self-insert-command :timeout 0.05 ;; "о" 'evil-escape ;; cyrillic "j" 'evil-escape ;; when it dispatches it actually handles 'j' (as "о" translates into it) ;; "ь" (general-simulate-key "RET") "m" (general-simulate-key "RET") )) ;; ;; todo - try for 'override keymap to make it generic? (advice-add 'evil-collection-ivy-setup :after #'(lambda (&rest r) (general-nmap :keymaps 'ivy-minibuffer-map "k" (general-key-dispatch 'ivy-previous-line :timeout 0.1 "j" 'evil-escape "m" 'ivy-done)) )) ;; trick to exit from god-mode using kj same way (general-def god-local-mode-map "k" (general-key-dispatch (general-simulate-key "C-k") :timeout 0.1 "j" 'keyboard-quit)) ;;evil-normal-state (general-imap "M-," 'god-execute-with-current-bindings) ;; todo - cannot make this work (dispatches ',m' as two keys so god exits on ','?) ;; (general-imap "," ;; (general-key-dispatch 'self-insert-command ;; :timeout 0.1 ;; "m" 'god-execute-with-current-bindings)) ) (use-package god-mode :after general evil :ensure :demand :diminish god-local-mode :config (with-eval-after-load 'which-key (which-key-enable-god-mode-support)) ;; (defun my-god-mode-update-cursor-type () ;; (setq cursor-type (if (or god-local-mode buffer-read-only) 'hollow 'box))) ;; (add-hook 'post-command-hook #'my-god-mode-update-cursor-type) :general (:states '(visual normal motion) "," 'god-execute-with-current-bindings) (:keymaps 'god-local-mode-map "i" #'god-local-mode) (:keymaps 'god-local-mode-map "," #'keyboard-quit) ) (use-package ivy :ensure :after evil-collection :diminish :bind (("C-c C-r" . ivy-resume) ("C-x b" . ivy-switch-buffer) ("C-x B" . ivy-switch-buffer-other-window) ("C-c v" . ivy-push-view) ("C-c V" . ivy-pop-view) ("<s-up>" . ivy-push-view) ("<s-S-up>" . ivy-pop-view) ("<s-down>" . ivy-switch-view) (:map ivy-minibuffer-map ("C-c C-c" . hydra-ivy/body))) :custom (ivy-extra-directories '("../" "./")) (ivy-count-format "(%d/%d) ") (ivy-use-virtual-buffers t) :config (ivy-mode) (setq ivy-re-builders-alist '( (ivy-switch-buffer . ivy--regex-fuzzy) ;; be careful with fuzzy - grep command doesn't like the transformed query (counsel-projectile-grep . ivy--regex-plus) (counsel-projectile-ag . ivy--regex-plus) (counsel-projectile-rg . ivy--regex-plus) (counsel-rg . ivy--regex-plus) (counsel-ag . ivy--regex-plus) (counsel-git-grep . ivy--regex-plus) (swiper . ivy--regex-plus) (swiper-isearch . ivy--regex-plus) (t . ivy--regex-fuzzy))) (with-eval-after-load 'evil-collection ;; all fuzzy init ;;(setq ivy-initial-inputs-alist nil) (evil-collection-ivy-setup) ;; todo - <spc> is not a prefix key ;;(evil-collection-define-key 'normal 'ivy-minibuffer-map (kbd "<SPC> <SPC>") 'ivy-done) (evil-collection-define-key 'normal 'ivy-minibuffer-map (kbd "C-f") 'ivy-scroll-up-command) ; this is very missing in evil-collection (evil-collection-define-key 'normal 'ivy-minibuffer-map (kbd "C-b") 'ivy-scroll-down-command)) ) (use-package find-file-in-project :ensure) ;;required by ivy? (use-package counsel :pin melpa :ensure :demand :after ivy :functions counsel-mode :diminish :config (counsel-mode) (with-eval-after-load 'ivy ;; some stupid order of init? (run-with-idle-timer 1 nil #'(lambda () (diminish 'counsel-mode nil)))) :custom (counsel-mode-override-describe-bindings nil) :bind (("M-y" . counsel-yank-pop) ("M-Y" . counsel-evil-registers))) (global-set-key (kbd "M-x") 'counsel-M-x) (global-set-key (kbd "C-x C-f") 'counsel-find-file) (use-package evil :ensure :defer 0.2 :init (setq evil-want-C-i-jump nil) ;; these 2 are for evil-collection (setq evil-want-integration t) ;; This is optional since it's already set to t by default. (setq evil-want-keybinding nil) (global-unset-key (kbd "C-z")) :config (evil-mode) (evil-set-leader 'motion (kbd "<SPC>")) (evil-set-leader 'insert (kbd "s-,")) (add-to-list 'evil-emacs-state-modes 'debugger-mode) (define-key prog-mode-map [(double-mouse-1)] 'evil-goto-definition) ;; amazing (when (display-graphic-p) (define-key input-decode-map [(control ?i)] [control-i]) (define-key input-decode-map [(control ?I)] [(shift control-i)]) (define-key evil-motion-state-map [tab] nil) (define-key evil-motion-state-map [control-i] 'evil-jump-forward)) ;; ;; annoying - when I select and paste it puts selected into register ;; (defun evil-paste-after-from-0 () ;; (interactive) ;; (let ((evil-this-register ?0)) ;; (call-interactively 'evil-paste-after))) ;; (define-key evil-visual-state-map "p" 'evil-paste-after-from-0) ;; (define-key evil-visual-state-map "p" 'evil-paste-after) ;; These are the keybindings evil makes in insert state by default: ;; +-----+----------------------------+----------------------+ ;; |key |command |emacs | ;; | | |default | ;; +-----+----------------------------+----------------------+ ;; |C-v |quoted-insert |scroll-up-command | ;; +-----+----------------------------+----------------------+ ;; |C-k |evil-insert-digraph |kill-line | ;; +-----+----------------------------+----------------------+ ;; |C-o |evil-execute-in-normal-state|open-line | ;; +-----+----------------------------+----------------------+ ;; |C-r |evil-paste-from-register |isearch-backward | ;; +-----+----------------------------+----------------------+ ;; |C-y |evil-copy-from-above |yank | ;; +-----+----------------------------+----------------------+ ;; |C-e |evil-copy-from-below |move-end-of-line | ;; +-----+----------------------------+----------------------+ ;; |C-n |evil-complete-next |next-line | ;; +-----+----------------------------+----------------------+ ;; |C-p |evil-complete-previous |previous-line | ;; +-----+----------------------------+----------------------+ ;; |C-x |evil-complete-next-line |set-goal-column | ;; |C-n | | | ;; +-----+----------------------------+----------------------+ ;; |C-x |evil-complete-previous-line |mark-page | ;; |C-p | | | ;; +-----+----------------------------+----------------------+ ;; |C-t |evil-shift-right-line |transpose-chars | ;; +-----+----------------------------+----------------------+ ;; |C-d |evil-shift-left-line |delete-char | ;; +-----+----------------------------+----------------------+ ;; |C-a |evil-paste-last-insertion |move-beginning-of-line| ;; +-----+----------------------------+----------------------+ ;; |C-w |evil-delete-backward-word or|kill-region | ;; | |evil-window-map | | ;; +-----+----------------------------+----------------------+ (with-eval-after-load "evil-maps" ;; these are absolutely useless for me (evil-global-set-key 'insert "\C-y" nil) (evil-global-set-key 'insert "\C-e" nil) (evil-global-set-key 'insert "\C-a" nil)) :custom ;; this is required even by evil-collection-ivy (evil-want-minibuffer t) (evil-want-Y-yank-to-eol t) ;; experimenting (evil-cross-lines t) ;; experimenting (evil-want-fine-undo t) ;; experimenting (evil-want-visual-char-semi-exclusive t) ;; makes v$ not select newline (annoying) (evil-undo-system 'undo-redo)) (use-package evil-escape :ensure :demand :after evil ;; :config ;; I'm using general to handle actual keypress ;; (evil-escape-mode) ;; (setq-default evil-escape-key-sequence "kj") ;; (setq evil-escape-delay 0.1) ) (use-package tab-line ;;:defer 0.5 :bind ("M-l" . tab-line-next-tab-cycle) ("M-h" . tab-line-prev-tab-cycle) ;; I want to hide window if this is the last tab shown (see set-last-tab-window-quit-restore) ("M-j" . quit-window) ("M-k" . quit-window-kill-buffer) ;; todo - this fails here cause term is not loaded yet ;;(global-set-key (kbd "<s-left>") 'tab-bar-history-back) ;;(global-set-key (kbd "<s-right>") 'tab-bar-history-forward) :bind* ("M-<left>" . tab-line-prev-tab-cycle) ;; using this with libinput-gestures ("M-<right>" . tab-line-next-tab-cycle) :init (global-tab-line-mode) (defun quit-window-kill-buffer () "Simply quit-window with killing current buffer" (interactive) (quit-window t)) (defun tab-line-next-tab-cycle () "Fixing original tab-line-switch-to-next-tab to properly work cycling and preserving order of tabs. This implementation would cycle through tabs visible in the window currently, without switching to buried/other tabs." (interactive) (let* ((tabs (funcall tab-line-tabs-function)) (pos (seq-position tabs (current-buffer) (lambda (tab buffer) (if (bufferp tab) (eq buffer tab) (eq buffer (cdr (assq 'buffer tab))))))) (new-pos (if pos (if (<= (length tabs) (1+ pos)) 0 ;; cycle to the first tab (1+ pos)))) (tab (if (= new-pos 0) (car tabs) (nth new-pos tabs))) (buffer (if (bufferp tab) tab (cdr (assq 'buffer tab))))) (when (bufferp buffer) (if (= new-pos 0) (switch-to-buffer buffer) (switch-to-next-buffer))))) (defun tab-line-prev-tab-cycle () "See `tab-line-next-tab-cycle'." (interactive) (let* ((tabs (funcall tab-line-tabs-function)) (pos (seq-position tabs (current-buffer) (lambda (tab buffer) (if (bufferp tab) (eq buffer tab) (eq buffer (cdr (assq 'buffer tab))))))) (last-pos (1- (length tabs))) (new-pos (if pos (if (<= pos 0) last-pos;; cycle to the last tab (1- pos)))) (tab (nth new-pos tabs)) (buffer (if (bufferp tab) tab (cdr (assq 'buffer tab))))) (when (bufferp buffer) (if (= new-pos last-pos) (switch-to-buffer buffer) (switch-to-prev-buffer))))) ;; :custom-face ;; (tab-line-highlight ((t (:inherit (tab-line-tab))))) ;; mouseover ;; (tab-line-tab-current ;; active tab in current window ;; ((t (:extend t :background "#504945" :foreground "#fdf4c1" :weight bold :underline t ;:box '(:line-width (1 . 1) :color "grey75" :style released-button) ;; )))) ;; (tab-line-tab-inactive ;; inactive tab ;; ((t (:foreground "#fdf4c1" :background "#1d2021")))) ;; (tab-line-tab ((t (:extend t :background "#504945" :foreground "#fdf4c1")))) ;; active tab in another window ;; (tab-line ((t (:foreground "#fdf4c1" :background "#1d2021" :distant-foreground "gray20")))) ;; background behind tabs ;; WIP - trying to colorize tabs (defface tab-line-tab-non-file '((t :inherit tab-line-tab-inactive :foreground "grey65")) "face for non-file tabs") (defface tab-line-tab-org-mode '((t :inherit tab-line-tab-inactive :foreground "LightGoldenrod1")) "face for org-mode tabs") (defface tab-line-tab-term-mode '((t :inherit tab-line-tab-inactive :foreground "LightSlateBlue")) "face for term-mode tabs") (defface tab-line-tab-prog-mode '((t :inherit tab-line-tab-inactive :foreground "CadetBlue1")) "face for prog-mode tabs") (defface tab-line-tab-inactive-dired '((t :inherit tab-line-tab-inactive :foreground "DarkOrange")) "face for dired tab-line tabs") (defface tab-line-tab-inactive-agenda '((t :inherit tab-line-tab-inactive :foreground "PaleVioletRed1")) "face for org agenda tab-line tabs") (defun my/tab-line-colorize (tab _tabs face buffer-p _selected-p) ;; TODO - use some 'case' syntax here (when (not (buffer-file-name tab)) (setf face `(:inherit (tab-line-tab-non-file ,face)))) (when (and buffer-p (eq (buffer-local-value 'major-mode tab) 'term-mode)) (setf face `(:inherit (tab-line-tab-term-mode ,face)))) (when (and buffer-p (eq (buffer-local-value 'major-mode tab) 'dired-mode)) (setf face `(:inherit (tab-line-tab-inactive-dired ,face)))) (when (and buffer-p (provided-mode-derived-p (buffer-local-value 'major-mode tab) 'prog-mode)) (setf face `(:inherit (tab-line-tab-prog-mode ,face)))) (when (and buffer-p (eq (buffer-local-value 'major-mode tab) 'org-mode)) (setf face `(:inherit (tab-line-tab-org-mode ,face)))) (when (and buffer-p (eq (buffer-local-value 'major-mode tab) 'org-agenda-mode)) (setf face `(:inherit (tab-line-tab-inactive-agenda ,face)))) face) :config ;; no idea - it doesn't work when set right away (when is-android (run-with-idle-timer 1 nil #'(lambda () (custom-set-faces (backquote (tab-line-tab-current ((t (:background "#504945" :underline '(:color foreground-color :style line))))))) ))) ;; https://amitp.blogspot.com/2020/06/emacs-prettier-tab-line.html ;; WIP (defun tab-line-wave () (interactive) (require 'powerline) (defvar my/tab-height 36) (defvar my/tab-left (powerline-wave-right 'tab-line nil my/tab-height)) (defvar my/tab-right (powerline-wave-left nil 'tab-line my/tab-height)) (defun my/tab-line-tab-name-buffer (buffer &optional _buffers) (powerline-render (list my/tab-left ;; (format " %s " (buffer-name buffer)) (tab-line-tab-name-truncated-buffer buffer _buffers) my/tab-right))) (setq tab-line-tab-name-function #'my/tab-line-tab-name-buffer) (set-face-attribute 'tab-line nil ;; background behind tabs :foreground "#fdf4c1" :background "#1d2021" ;; :distant-foreground "#fdf4c1" ;; :distant-foreground 'unspecified ;; :family "Fira Sans Condensed" :box nil) (set-face-attribute 'tab-line-tab nil ;; active tab in another window :inherit 'tab-line :background "#1d2021") (set-face-attribute 'tab-line-tab-current nil ;; active tab in current window :inverse-video t :box nil) (set-face-attribute 'tab-line-tab-inactive nil ;; inactive tab :background "#3c3836") (set-face-attribute 'tab-line-highlight nil ;; mouseover :background "#4c4846" :foreground 'unspecified)) ;; hmmm (run-with-idle-timer 1 nil #'tab-line-wave) :custom ((tab-line-new-button-show nil) (tab-line-close-button-show nil) (tab-line-tab-name-function #'tab-line-tab-name-truncated-buffer) (tab-line-tab-name-truncated-max 30) ;; there is a problem with cycling logic because of internal switch-to-buffer vs switch-to-next-buffer and ordering of buffers being changed ;; (tab-line-tabs-function #'(lambda () (tab-line-tabs-window-buffers))) ;; experimenting - M-h/M-l would cycle ;; (tab-line-switch-cycling t) (tab-line-tabs-function #'tab-line-tabs-window-buffers) ;;(tab-line-tabs-function #'tab-line-tabs-buffer-groups) (tab-line-tab-face-functions '(my/tab-line-colorize tab-line-tab-face-modified tab-line-tab-face-special)))) ;;tab-line-tab-face-group tab-line-tab-face-inactive-alternating) [/sourcecode] </div> </div> <div id="outline-container-org3df45fe" class="outline-2"> <h2 id="org3df45fe">provide</h2> <div class="outline-text-2" id="text-org3df45fe"> (provide 'config)