(require 'use-package) (use-package emacs :init ;; package management (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (unless (package-installed-p 'quelpa) (with-temp-buffer (url-insert-file-contents "https://raw.githubusercontent.com/quelpa/quelpa/master/quelpa.el") (eval-buffer) (quelpa-self-upgrade))) (quelpa '(quelpa-use-package :fetcher git :url "https://github.com/quelpa/quelpa-use-package.git")) (require 'quelpa-use-package) ;; basic cfg (tool-bar-mode -1) (require 'server) (unless (server-running-p) (server-start)) (setq gc-cons-threshold 100000000 read-process-output-max (* 1024 1024) custom-file (concat user-emacs-directory "custom.el") create-lockfiles nil tab-always-indent 'complete mac-command-modifier 'super backup-directory-alist `((".*" . ,(concat user-emacs-directory "backup"))) delete-old-versions t kept-new-versions 20 kept-old-versions 2 version-control t delete-old-versions t backup-by-copying t focus-follows-mouse t mouse-autoselect-window t enable-recursive-minibuffers t warning-minimum-level :emergency inhibit-startup-screen t completion-cycle-threshold 3 text-mode-ispell-word-completion nil lsp-file-watch-threshold 3000 read-extended-command-predicate #'command-completion-default-include-p minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt)) (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) (put 'upcase-region 'disabled nil) (put 'erase-buffer 'disabled nil) (when (file-exists-p custom-file) (load custom-file)) ;;(load-theme 'doom-one) (load-theme 'misterioso) (add-hook 'eshell-mode-hook (lambda () (setq-local corfu-auto nil) (corfu-mode))) (with-eval-after-load 'lsp-mode (add-hook 'lsp-mode-hook #'lsp-enable-which-key-integration) (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]plz-out\\'")) (add-to-list 'auto-mode-alist '("BUILD\\'" . python-mode)) (global-set-key (kbd "C-c C-r") 'replace-regexp) (global-set-key (kbd "C-c C-R") 'replace-string) (global-set-key (kbd "C-=") 'multi-vterm-dedicated-toggle) (global-set-key (kbd "C-") 'speedbar)) (global-set-key (kbd "S-") #'lsp-find-definition) (use-package async :ensure t) (use-package async-status :ensure t) (use-package dash :ensure t :defer t) (use-package multiple-cursors :ensure t :defer t :init (multiple-cursors-mode 1) :bind (("C-S-c C-S-c" . 'mc/edit-lines) ("C->" . 'mc/mark-next-like-this) ("C-<" . 'mc/mark-previous-like-this) ("C-c C->" . 'mc/mark-all-like-this))) ;; minibuffer ;; === (use-package embark :ensure t :defer t) (use-package vertico :ensure t :defer t :init (vertico-mode)) (use-package which-key :ensure t :defer t :init (which-key-mode)) ;; mass editing ;; === (use-package multifiles :ensure t :defer t) (use-package wgrep :ensure t :defer t) ;; eye candy ;; === (use-package doom-modeline :ensure t :init (doom-modeline-mode 1)) (use-package nerd-icons :ensure t :defer t) (use-package nerd-icons-corfu :ensure t :defer t) (use-package nerd-icons-dired :ensure t :defer t :hook (dired-mode . nerd-icons-dired-mode)) (use-package nerd-icons-completion :ensure t :defer t) (use-package nerd-icons-ibuffer :ensure t :defer t) (use-package unicode-fonts :ensure t :defer t) ;; scratch buffers ;; === (use-package go-scratch :ensure t :defer t) ;; multimedia ;; === ;;(use-package mingus :ensure t :defer t) (use-package emms :ensure t :defer t :config (setq emms-player-list '(emms-player-mpv) emms-info-functions '(emms-info-native))) ;; terminal / shell ;; === (use-package multishell :ensure t :defer t) (use-package vterm-toggle :ensure t :bind (("C-x C-1 C-t C-v" . #'multi-vterm) ("C-x C-1 C-t C-n" . #'multi-vterm-next) ("C-x C-1 C-t C-p" . #'multi-vterm-prev))) (use-package eshell-toggle :ensure t :defer t :bind (("C-x C-1 C-t C-e" . #'eshell-toggle))) (use-package eshell-vterm :ensure t :defer t :init (eshell-vterm-mode 1)) (use-package multi-vterm :ensure t :defer t) ;; org-mode ;; === (use-package org :ensure t :mode (("\\.org$" . org-mode)) :bind (("C-x O a" . org-agenda) ("C-x O c" . org-capture) ("C-x O k a" . kill-all-org-agenda-buffers)) :config (defun kill-all-org-agenda-buffers () "Close all org-agenda-related buffers." (interactive) (dolist (buffer (buffer-list)) (with-current-buffer buffer (when (or (derived-mode-p 'org-agenda-mode) (and (buffer-file-name) (member (buffer-file-name) (org-agenda-files)))) (kill-buffer buffer)))) (message "Closed all org-agenda-related buffers.")) (defun my/org-config () (setq org-agenda-inhibit-startup t) (setq org-todo-keywords '((sequence "HOLD(h)" "TODO(t)" "|" "DONE(d)" "CNCL(x)"))) (setq org-todo-keyword-faces '(("HOLD" . (:foreground "orange" :weight bold)) ("TODO" . (:foreground "red" :weight bold)) ("DONE" . (:foreground "green" :weight bold)) ("CNCL" . (:foreground "gray" :weight bold)))) (setq org-agenda-files (append (list "~/TODO.org") (directory-files-recursively "~/notes" "\\.org$"))) (setq org-agenda-prefix-format '((agenda . " %i ") (todo . " %i ") (tags . " %i ") (search . " %i "))) (setq org-agenda-hide-tags-regexp ".") (setq org-agenda-todo-keyword-format "%s") (defun my-org-agenda-format-item (item) "Format an agenda or TODO item without the filename, but keep the keyword." (let* ((marker (or (get-text-property 0 'org-marker item) (get-text-property 0 'org-hd-marker item))) (line (when marker (org-with-point-at marker (buffer-substring (line-beginning-position) (line-end-position))))) (todo-keyword (when marker (org-with-point-at marker (org-get-todo-state)))) (truncated-line (when line (replace-regexp-in-string "^\\[#[A-Z]\\] " "" line)))) (if truncated-line (let ((clean-item (replace-regexp-in-string "^\\(\\*+ \\)" "" truncated-line))) (if todo-keyword (concat todo-keyword " " (replace-regexp-in-string (concat "^" todo-keyword " ?") "" clean-item)) clean-item)) item))) (advice-add 'org-agenda-format-item-line :filter-return #'my-org-agenda-format-item) (advice-add 'org-agenda-format-item :filter-return #'my-org-agenda-format-item)) (defun my/org-refile-config () (setq org-refile-targets '((nil :maxlevel . 9) ("~/TODO.org" :maxlevel . 9))) (setq org-refile-use-outline-path 'file) (setq org-outline-path-complete-in-steps nil) (setq org-refile-allow-creating-parent-nodes 'confirm)) (defun my/org-capture-config () (setq org-capture-templates '(("t" "TODO" entry (file "~/TODO.org") "* TODO %?\n %i\n %a" :prepend t)))) (defun refresh-org-agenda-files () (interactive) (setq org-agenda-files (append (list "~/TODO.org") (directory-files-recursively "~/notes" "\\.org$")))) (my/org-config) (my/org-refile-config) (my/org-capture-config) (run-with-idle-timer 300 t 'refresh-org-agenda-files)) (use-package ob-go :ensure t :defer t) (use-package ox-hugo :ensure t :defer t) ;; gitlab uses goldmark (with-eval-after-load 'ox (require 'ox-hugo)) (setq org-hugo-base-dir "~/tmp") (use-package org-context :ensure t :defer t :after (:all org)) ;; knowledge management ;; === (use-package denote :ensure t :config (setq denote-directory (expand-file-name "~/notes/")) (setq denote-save-buffers nil) (setq denote-known-keywords '("emacs" "pascom" "golang" "dev")) (setq denote-infer-keywords t) (setq denote-sort-keywords t) (setq denote-file-type nil) ; Org is the default, set others here (setq denote-prompts '(title keywords)) (setq denote-excluded-directories-regexp nil) (setq denote-excluded-keywords-regexp nil) (setq denote-rename-confirmations '(rewrite-front-matter modify-file-name)) (setq denote-date-prompt-use-org-read-date t) ; use org date interface (setq denote-date-format nil) ; read doc string (setq denote-backlinks-show-context t) (denote-rename-buffer-mode 1) ;; denote key bindings (global-unset-key (kbd "C-x C-n")) (let ((map global-map)) (define-key map (kbd "C-x C-n C-n") #'denote) (define-key map (kbd "C-x C-n C-c") #'denote-region) ; "contents" mnemonic (define-key map (kbd "C-x C-n C-S-n") #'denote-type) (define-key map (kbd "C-x C-n !") #'denote-date) (define-key map (kbd "C-x C-n C-z") #'denote-signature) ; "zettelkasten" mnemonic (define-key map (kbd "C-x C-n C-s") #'denote-subdirectory) (define-key map (kbd "C-x C-n C-t") #'denote-template) ;; If you intend to use Denote with a variety of file types, it is ;; easier to bind the link-related commands to the `global-map', as ;; shown here. Otherwise follow the same pattern for `org-mode-map', ;; `markdown-mode-map', and/or `text-mode-map'. (define-key map (kbd "C-x C-n C-i") #'denote-link) ; "insert" mnemonic (define-key map (kbd "C-x C-n C-I") #'denote-add-links) (define-key map (kbd "C-x C-n C-S-b") #'denote-backlinks) (define-key map (kbd "C-x C-n C-l C-f") #'denote-find-link) (define-key map (kbd "C-x C-n C-l C-b") #'denote-find-backlink) ;; Note that `denote-rename-file' can work from any context, not just ;; Dired bufffers. That is why we bind it here to the `global-map'. (define-key map (kbd "C-x C-n C-r") #'denote-rename-file) (define-key map (kbd "C-x C-n C-S-r") #'denote-rename-file-using-front-matter)) (global-set-key (kbd "C-x C-n C-f") #'denote-open-or-create) ;; Key bindings specifically for Dired. (let ((map dired-mode-map)) (define-key map (kbd "C-x C-n C-d") #'denote-dired-mode) (define-key map (kbd "C-x C-n C-i") #'denote-link-dired-marked-notes) (define-key map (kbd "C-x C-n C-r") #'denote-dired-rename-files) (define-key map (kbd "C-x C-n C-k") #'denote-dired-rename-marked-files-with-keywords) (define-key map (kbd "C-x C-n C-S-r") #'denote-dired-rename-marked-files-using-front-matter)) (with-eval-after-load 'org-capture (setq denote-org-capture-specifiers "%l\n%i\n%?") (add-to-list 'org-capture-templates '("n" "New note (with denote.el)" plain (file denote-last-path) #'denote-org-capture :no-save t :immediate-finish nil :kill-buffer t :jump-to-captured t))) ) ;; projects ;; === (use-package projectile :ensure t :defer t :bind (:map projectile-mode-map ("C-c C-p" . projectile-command-map) ("C-c C-p C-f" . #'projectile-find-file) ("C-c C-p C-p" . #'projectile-switch-project) ("C-c C-p C-/" . #'projectile-ripgrep) ("C-c C-p C-b" . #'projectile-switch-to-buffer) ("C-c C-p C-4 C-b" . #'projectile-switch-to-buffer-other-window) ("C-c C-p C-5 C-b" . #'projectile-switch-to-buffer-other-frame) ("C-c C-p C-d" . #'projectile-dired) ("C-c C-p C-4 C-d" . #'projectile-dired-other-window) ("C-c C-p C-4 C-d" . #'projectile-dired-other-frame) ("C-c C-p C-v" . #'multi-vterm-project)) :diminish projectile-mode :init (projectile-mode)) (use-package denote-explore :ensure t) (use-package go-projectile :ensure t :defer t) (use-package projectile-ripgrep :ensure t :defer t :after (projectile)) (use-package project-explorer :ensure t :defer t) ;; version control ;; === (use-package magit :ensure t :defer t :bind ("C-c C-g" . magit-status) :commands (magit-status-here magit-get-current-branch) :custom (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)) (use-package dired-git :ensure t :defer t) (use-package dired-git-info :ensure t :defer t) (use-package git-link :ensure t :defer t) (use-package git-lens :ensure t :defer t) ;; auto completion ;; === (use-package corfu :ensure t :defer t :bind (:map corfu-map ("C-n" . corfu-next) ("C-p" . corfu-previous) ("SPC" . corfu-insert-separator)) :custom (corfu-cycle t) (corfu-auto nil) (corfu-separator ?\s) (corfu-preselect 'prompt) (corfu-quit-at-boundary t) (corfu-quit-no-match 'separator) (corfu-scroll-margin 5) :hook ((prog-mode . corfu-mode) (shell-mode . corfu-mode) (eshell-mode . corfu-mode)) :init (global-corfu-mode) :config (defun corfu-send-shell (&rest _) "Send completion candidate when inside comint/eshell." (cond ((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input)) (eshell-send-input)) ((and (derived-mode-p 'comint-mode) (fboundp 'comint-send-input)) (comint-send-input)))) (advice-add #'corfu-insert :after #'corfu-send-shell) (global-set-key [remap dabbrev-expand] 'hippie-expand) (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) (use-package dabbrev :ensure t :defer t :bind (("M-/" . dabbrev-completion) ("C-M-/" . dabbrev-expand)) :config (add-to-list 'dabbrev-ignored-buffer-regexps "\\` ") (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode) (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode) (add-to-list 'dabbrev-ignored-buffer-modes 'tags-table-mode)) (use-package orderless :ensure t :defer t :init (setq completion-styles '(orderless partial-completion basic) completion-category-defaults nil completion-category-overrides nil)) (setq text-mode-ispell-word-completion nil) (setq read-extended-command-predicate #'command-completion-default-include-p) (defun crm-indicator (args) (cons (format "[CRM%s] %s" (replace-regexp-in-string "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" "" crm-separator) (car args)) (cdr args))) (advice-add #'completing-read-multiple :filter-args #'crm-indicator) (setq read-extended-command-predicate #'command-completion-default-include-p) ;; Add extensions (use-package cape :ensure t :defer t ;; Bind dedicated completion commands ;; Alternative prefix keys: C-c p, M-p, M-+, ... :bind (("C-c / p" . completion-at-point) ;; capf ("C-c / t" . complete-tag) ;; etags ("C-c / d" . cape-dabbrev) ;; or dabbrev-completion ("C-c / h" . cape-history) ("C-c / f" . cape-file) ("C-c / k" . cape-keyword) ("C-c / s" . cape-elisp-symbol) ("C-c / e" . cape-elisp-block) ("C-c / a" . cape-abbrev) ("C-c / l" . cape-line) ("C-c / w" . cape-dict) ("C-c / :" . cape-emoji) ("C-c / \\" . cape-tex) ("C-c / _" . cape-tex) ("C-c / ^" . cape-tex) ("C-c / &" . cape-sgml) ("C-c / r" . cape-rfc1345)) :init ;; Add to the global default value of `completion-at-point-functions' which is ;; used by `completion-at-point'. The order of the functions matters, the ;; first function returning a result wins. Note that the list of buffer-local ;; completion functions takes precedence over the global list. (add-hook 'completion-at-point-functions #'cape-dabbrev) (add-hook 'completion-at-point-functions #'cape-file) (add-hook 'completion-at-point-functions #'cape-elisp-block) (add-hook 'completion-at-point-functions #'cape-history) (add-hook 'completion-at-point-functions #'cape-keyword)) ;;(add-hook 'completion-at-point-functions #'cape-tex) ;;(add-hook 'completion-at-point-functions #'cape-sgml) ;;(add-hook 'completion-at-point-functions #'cape-rfc1345) ;;(add-hook 'completion-at-point-functions #'cape-abbrev) ;;(add-hook 'completion-at-point-functions #'cape-dict) ;;(add-hook 'completion-at-point-functions #'cape-elisp-symbol) ;;(add-hook 'completion-at-point-functions #'cape-line)) ;; coding ;; === (use-package fic-mode :ensure t :defer t) (use-package lsp-mode :ensure t :commands lsp :custom (lsp-completion-provider :none) ;; we use Corfu! :init (defun my/lsp-mode-setup-completion () (lsp-enable-which-key-integration) (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults)) '(orderless))) :config (setq lsp-prefer-flymake nil) :hook (lsp-completion-mode . my/lsp-mode-setup-completion)) (use-package flycheck :ensure t :defer t) (use-package go-mode :ensure t :defer t :mode (("\\.go$" . go-mode)) :hook ((go-mode . lsp-deferred) (before-save . lsp-format-buffer) (before-save . lsp-organize-imports))) (use-package yaml-mode :ensure t :defer t :mode (("\\.yml$" . yaml-mode))) (use-package json-mode :ensure t :defer t :mode (("\\.json$" . json-mode))) (use-package php-mode :ensure t :defer t :mode (("\\.php$" . php-mode))) (use-package mmm-mode :ensure t :defer t) (use-package multi-web-mode :ensure t :defer t) (use-package graphviz-dot-mode :ensure t :defer t) (use-package protobuf-mode :ensure t :defer t) (use-package rego-mode :ensure t :defer t) (use-package plantuml-mode :ensure t :config (setq plantuml-default-exec-mode 'jar plantuml-jar-path "/usr/share/plantuml/plantuml.jar" org-plantuml-jar-path (expand-file-name "/usr/share/plantuml/plantuml.jar")) (org-babel-do-load-languages 'org-babel-load-languages '( (plantuml . t)))) (use-package kotlin-mode :ensure t :defer t) (use-package flycheck-projectile :ensure t) ;; search & narrow ;; === (use-package prescient :ensure t :defer t) ;; navigation ;; === (use-package ace-jump-mode :ensure t :defer t :bind (("C-c SPC" . 'ace-jump-mode) ("C-x SPC" . 'ace-jump-mode-pop-mark))) (with-eval-after-load 'org (org-babel-do-load-languages 'org-babel-load-languages '((go . t) (dot . t) (plantuml . t) ))) ;; api testing ;; === (use-package plz :ensure t) (add-hook 'prog-mode-hook 'lsp-deferred) ;; Less chatty for unsupported modes (setq lsp-warn-no-matched-clients nil) (defun reload-init-file () "Reload the Emacs init file." (interactive) (load-file user-init-file)) (defun reload-org-config () "Reload the org configuration." (interactive) (my/org-config) (message "Org configuration reloaded")) (global-set-key (kbd "C-x c O") 'reload-org-config) (global-set-key (kbd "C-x c r") #'reload-init-file) (setq hippie-expand-try-functions-list '(try-expand-dabbrev try-expand-dabbrev-all-buffers try-expand-dabbrev-from-kill cape-file cape-keyword cape-elisp-symbol cape-elisp-block cape-abbrev cape-line cape-dict cape-emoji cape-tex cape-sgml cape-rfc1345 try-complete-file-name-partially try-complete-file-name try-expand-all-abbrevs try-expand-list try-expand-line try-complete-lisp-symbol-partially try-complete-lisp-symbol)) (global-set-key (kbd "M-/") 'hippie-expand)