Конфигурация GNU Emacs
Emacs – текстовый редактор от сообщества GNU. Он расширяется при помощи языка Emacs Lisp и является одним из старейших текстовых редакторов, который используется многими и по сей день. Далее идёт моя конфигурация этого редактора.
Исходный код
;; -- lexical-binding: t -- (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
;; Optimize Emacs (setq-default bidi-display-reordering 'left-to-right bidi-paragraph-direction 'left-to-right) (setq bidi-inhibit-bpa t)
(setq redisplay-skip-fontification-on-input t) (setq read-process-output-max (* 4 1024 1024)) (setq kill-do-not-save-duplicates t) (setq help-window-select t)
;; (use-package exwm ;; :config ;; ;; Set the initial workspace number. ;; (unless (get 'exwm-workspace-number 'saved-value) ;; (setq exwm-workspace-number 4)) ;; ;; Make class name the buffer name ;; (add-hook 'exwm-update-class-hook ;; (lambda () ;; (exwm-workspace-rename-buffer exwm-class-name))) ;; ;; Global keybindings. ;; (unless (get 'exwm-input-global-keys 'saved-value) ;; (setq exwm-input-global-keys ;; `( ;; ;; 's-r': Reset (to line-mode). ;; ([?\s-r] . exwm-reset) ;; ;; 's-w': Switch workspace. ;; ([?\s-w] . exwm-workspace-switch) ;; ;; 's-&': Launch application. ;; ([?\s-&] . (lambda (command) ;; (interactive (list (read-shell-command "$ "))) ;; (start-process-shell-command command nil command))) ;; ;; 's-N': Switch to certain workspace. ;; ,@(mapcar (lambda (i) ;; `(,(kbd (format "s-%d" i)) . ;; (lambda () ;; (interactive) ;; (exwm-workspace-switch-create ,i)))) ;; (number-sequence 0 9))))) ;; ;; Line-editing shortcuts ;; (unless (get 'exwm-input-simulation-keys 'saved-value) ;; (setq exwm-input-simulation-keys ;; '(([?\C-b] . [left]) ;; ([?\C-f] . [right]) ;; ([?\C-p] . [up]) ;; ([?\C-n] . [down]) ;; ([?\C-a] . [home]) ;; ([?\C-e] . [end]) ;; ([?\M-v] . [prior]) ;; ([?\C-v] . [next]) ;; ([?\C-d] . [delete]) ;; ([?\C-k] . [S-end delete])))) ;; ;; Enable EXWM ;; (exwm-enable) ;; ;; Configure Ido ;; ;; (require 'exwm-config) ;; ;; (add-hook 'exwm-init-hook #'exwm-config–fix/ido-buffer-window-other-frame) ;; )
(use-package emacs :bind ("s-s" . save-buffer) ("s-x" . kill-region) ("s-c" . kill-ring-save) ("s-v" . yank) :config (setq mac-command-modifier 'meta) (setq mac-option-modifier 'super) ;; Dont ask when following symlinks (setq vc-follow-symlinks t) ;; Save session after quitting emacs (desktop-save-mode nil) ;; Load your custom settings (setq custom-file "~/.emacs.d/custom-settings.el") (setq completion-styles '(basic partial-completion emacs22 substring)) (load custom-file t) ;; Timer (add-hook 'emacs-startup-hook (lambda () (message "Emacs ready in %s with %d garbage collections." (format "%.2f seconds" (float-time (time-subtract after-init-time before-init-time))) gcs-done))))
;; Information about me (setq user-full-name "Mikhail Kirillov" user-mail-address "w96k@runbox.com")
(define-key global-map (kbd "<f7>") 'display-line-numbers-mode)
(define-key global-map (kbd "<f6>") 'whitespace-mode)
;; Show files in KiB (setq dired-listing-switches "-hlap" dired-kill-when-opening-new-dired-buffer t)
(customize-set-variable 'global-auto-revert-non-file-buffers t) (global-auto-revert-mode 1)
(use-package imenu-list :bind ("C-x C-d" . imenu-list-smart-toggle) :config (setq imenu-list-focus-after-activation nil imenu-list-auto-resize nil imenu-list-mode-line-format '() imenu-list-size 0.4))
(setq vc-command-messages t)
(use-package magit :defer t :bind (("C-x g" . magit-status)))
(use-package forge :defer t :after magit)
(use-package git-timemachine :defer t)
;; Jumps by highlighting symbols on screen (use-package avy :defer t :bind (("M-s M-s" . avy-goto-char) ("M-s s" . avy-goto-char) ("M-s g" . avy-goto-line) ("M-s l" . avy-goto-char-in-line) ("M-s M-l" . avy-goto-char-in-line)
("M-g g" . avy-goto-line) ("M-s M-g" . avy-goto-line)))
(use-package link-hint :defer t :bind (("M-s j" . link-hint-open-link)))
;; Jumps to last change (use-package goto-chg :defer t :bind (("s-z" . goto-last-change) ("s-Z" . goto-last-change-reverse)))
;; Jumps using grep and similar tools (use-package dumb-jump :defer t :bind (("M-g o" . dumb-jump-go-other-window) ("M-g j" . dumb-jump-go) ("M-g b" . dumb-jump-back) ("M-g q" . dumb-jump-quick-look) ("M-g x" . dumb-jump-go-prefer-external) ("M-g z" . dumb-jump-go-prefer-external-other-window)))
(add-hook 'prog-mode-hook 'display-fill-column-indicator-mode)
;;; Input of pair delimiters (electric-pair-mode) (add-hook 'prog-mode-hook 'electric-pair-mode) (add-hook 'prog-mode-hook 'electric-indent-mode)
(add-to-list 'Info-default-directory-list "~/.local/share/info")
(use-package browse-kill-ring :defer t :bind ("C-M-y" . browse-kill-ring))
(use-package ggtags :defer t :hook (c-mode . ggtags-mode))
;; (use-package undo-tree ;; :defer t ;; :hook ;; (prog-mode . undo-tree-mode) ;; (org-mode . undo-tree-mode))
(use-package jsonrpc :defer t)
(with-eval-after-load 'eglot (add-to-list 'eglot-server-programs '((php-mode phps-mode php-ts-mode) . ("/home/w96k/projects/phpactor/bin/phpactor" "language-server" "-vvv"))))
;; (add-hook 'eglot-managed-mode-hook ;; (lambda () ;; "Make sure Eldoc will show us all of the feedback at point." ;; (setq-local eldoc-documentation-strategy ;; #'eldoc-documentation-compose)))
(use-package phps-mode :ensure t)
;; (with-eval-after-load 'eglot ;; (add-to-list 'eglot-server-programs '((php-mode phps-mode) . ("~/projects/phpactor/bin/phpactor" "language-server" "-vvv"))) ;; (add-to-list 'eglot-server-programs '((php-mode phps-mode) . ("intelephense" "–stdio")))
;; ;; No event buffers, disable providers cause a lot of hover traffic. Shutdown unused servers. ;; (setq eglot-events-buffer-size 0 ;; eglot-ignored-server-capabilities '(:hoverProvider ;; :documentHighlightProvider) ;; eglot-autoshutdown t))
;; Show all of the available eldoc information when we want it. This way Flymake errors ;; don't just get clobbered by docstrings. (add-hook 'eglot-managed-mode-hook (lambda () "Make sure Eldoc will show us all of the feedback at point." (setq-local eldoc-documentation-strategy #'eldoc-documentation-compose)))
(use-package dape :ensure t :preface ;; By default dape shares the same keybinding prefix as `gud' ;; If you do not want to use any prefix, set it to nil. ;; (setq dape-key-prefix "\C-x\C-a")
;; :hook ;; Save breakpoints on quit ;; (kill-emacs . dape-breakpoint-save) ;; Load breakpoints on startup ;; (after-init . dape-breakpoint-load)
:config ;; Turn on global bindings for setting breakpoints with mouse ;; (dape-breakpoint-global-mode)
;; Info buffers to the right (setq dape-buffer-window-arrangement 'right)
;; Info buffers like gud (gdb-mi) ;; (setq dape-buffer-window-arrangement 'gud) ;; (setq dape-info-hide-mode-line nil)
;; Pulse source line (performance hit) ;; (add-hook 'dape-display-source-hook 'pulse-momentary-highlight-one-line)
;; Showing inlay hints (setq dape-inlay-hints t)
;; Save buffers on startup, useful for interpreted languages ;; (add-hook 'dape-start-hook (lambda () (save-some-buffers t t)))
;; Kill compile buffer on build success ;; (add-hook 'dape-compile-hook 'kill-buffer)
(add-to-list 'dape-configs `(go-debug modes (go-mode go-ts-mode) command "dlv" command-args ("dap" "–listen" "127.0.0.1::autoport") command-cwd dape-cwd-fn port :autoport dape "debug" :type "go" :showLog "true" :mode "debug" :request "launch" :name "go-debug" :cwd "." :program "." :args []))
(add-to-list 'dape-configs `(php modes (php-mode php-ts-mode) hostname "localhost" port 4711 :workspaceFolder "home/w96k/projects/lms-app/app" :request "launch" command "node" command-args ("/home/w96k.emacs.d/php/php-debug/extension/out/phpDebug.js" "–server=4711" ) :projectName "php" :pathMappings (:/var/www/localhost/moodle/ "/home/w96k/projects/lms-app/app") :hostname "localhost" :port 9003 :type "php"))
(add-to-list 'dape-configs `(odoo modes (php-mode php-ts-mode) hostname "localhost" port 4711 :workspaceFolder "home/w96k/projects/odoo-client" :request "launch" command "node" command-args ("home/w96k.emacs.d/php/php-debug/extension/out/phpDebug.js" "–server=4711" ) :program "home/w96k/projects/odoo-client/src/wkz/debug.php" :cwd "/home/w96k/projects/odoo-client" :projectName "odoo" ;; :pathMappings (:/var/www/localhost/moodle/ "home/w96k/projects/odoo-client") :hostname "localhost" :port 9003 :type "php")) )
(use-package expand-region :defer t :bind (("s-e" . er/expand-region)))
(use-package ace-window :defer t :bind (("s-w" . ace-window)))
(use-package ace-link :defer t :bind (("s-l" . ace-link)))
(setq scroll-margin 0) (scroll-bar-mode 0) (tool-bar-mode 0) (menu-bar-mode 0)
(context-menu-mode 1) (xterm-mouse-mode 1) ;;(gpm-mouse-mode 1) (mouse-avoidance-mode 'exile)
(set-cursor-color "red")
(with-eval-after-load 'isearch (define-key isearch-mode-map "\C-h" 'isearch-delete-char) (define-key isearch-mode-map "\C-ch" 'isearch-help-for-help))
(use-package anzu :defer t :config (global-anzu-mode t))
(which-function-mode t)
(setq geiser-active-implementations '("guile"))
(unless (package-installed-p 'eglot-java) (package-vc-install "https://github.com/yveszoundi/eglot-java" nil nil 'eglot-java))
(setq composer-executable-bin "~/.bin/composer")
;; (unless (package-installed-p 'pg) ;; (package-vc-install "https://github.com/emarsden/pg-el" nil nil 'pg)) ;; (unless (package-installed-p 'pgmacs) ;; (package-vc-install "https://github.com/emarsden/pgmacs"))
(use-package pgmacs :defer t)
(use-package web-mode :defer t :config (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.twig.html\\'" . web-mode)) (setq web-mode-markup-indent-offset 2) (setq web-mode-enable-auto-pairing t) (setq web-mode-enable-css-colorization t) (setq web-mode-enable-block-face t) (setq web-mode-enable-current-element-highlight t))
(use-package org :defer t :config (org-babel-do-load-languages 'org-babel-load-languages '((R . t) (ditaa . t) (dot . t) ;; (php . t) (emacs-lisp . t) (gnuplot . t) (haskell . nil) (latex . t) ;;(ledger . t) (ocaml . nil) (octave . t) (python . t) (ruby . t) (screen . nil) (shell . t) (sql . t) (js . t))) (setq org-default-notes-file "~/Documents/todo.org" system-time-locale "C" org-use-speed-commands t org-adapt-indentation nil org-return-follows-link t org-agenda-include-diary t org-display-remote-inline-images 'download org-agenda-start-with-log-mode t org-image-actual-width (list 400) org-hide-emphasis-markers t org-outline-path-complete-in-steps nil org-src-tab-acts-natively t org-id-track-globally t org-confirm-babel-evaluate nil) :bind ("C-c l" . org-store-link) ("C-c a" . org-agenda) ("C-c c" . org-capture))
(use-package org-roam :ensure t :vc (:url "https://github.com/org-roam/org-roam" :branch "org-roam") :bind ("C-c n l" . org-roam-node-insert) ("C-c n b" . org-roam-buffer-toggle) ("C-c n f" . org-roam-node-find) ("C-c n t t" . org-roam-tag-add) ("C-c n t r" . org-roam-tag-remove) ("C-c n i" . org-roam-jump-to-index) ("C-c n g" . org-roam-graph) ("C-c n d" . org-roam-db-build-cache) ("C-c n r" . org-roam-node-random) ("C-c n j" . org-roam-dailies-find-date) :config (setq org-roam-directory (file-truename "~/Zettelkasten") org-roam-v2-ack t org-roam-completion-everywhere t org-roam-index-file (concat org-roam-directory "20210409054712-жизнь.org") org-roam-dailies-directory (concat org-roam-directory "journals"))
(org-roam-db-autosync-mode t))
(defun org-roam-jump-to-index () "Stub of recreating the function from V1" (interactive) (let ((org-roam-index org-roam-index-file)) (find-file org-roam-index)))
(use-package org :defer t :config (customize-set-variable 'org-link-descriptive t)
(add-to-list 'org-agenda-files "~/Documents/todo.org")
(setq org-directory "~/Documents" org-default-notes-file (concat org-directory "/todo.org")))
(use-package yaml-mode :defer t)
(use-package yaml-imenu :after yaml-mode :defer t)
(use-package telega :defer t :bind (("C-c t" . telega-prefix-map)) :custom (telega-server-libs-prefix "/usr"))
(if (boundp 'use-short-answers) (setq use-short-answers t) (advice-add 'yes-or-no-p :override #'y-or-n-p))
(icomplete-mode t)
(flyspell-mode t)
(setq-default confirm-nonexistent-file-or-buffer t)
(global-set-key (kbd "M-o") 'mode-line-other-buffer)
;; (setq redisplay-dont-pause t)
(setq select-enable-clipboard t select-enable-primary t)
(setq completions-detailed nil)
(setq kill-buffer-delete-auto-save-files t) (setq next-error-message-highlight t)
(setq mode-line-compact 'long)
(setq completions-group t)
;;(set-frame-parameter nil 'internal-border-width 0)
;; (set-window-buffer nil (current-buffer))
(setq default-directory "~/" custom-safe-themes t delete-old-versions t enable-local-variables t)
(setq ansi-color-for-comint-mode t) (setq shell-command-prompt-show-cwd t)
(column-number-mode)
(setq nobreak-char-display nil)
(defvar backup-dir "~/.emacs.d/backups/")
(setq backup-by-copying t backup-directory-alist '(("~/.emacs.d/backups/")) version-control nil)
(setq calendar-week-start-day 1)
(set-input-method "russian-computer") (toggle-input-method)
(setq require-final-newline t)
(global-subword-mode 1)
;; (use-package geiser-guile :defer t)
;; (use-package guix ;; :defer t ;; :config ;; (setq geiser-guile-binary "guile") ;; (with-eval-after-load 'geiser-guile ;; (progn ;; (add-to-list 'geiser-guile-load-path "~/projects/guix/")))
;; (let ((guix-copyright "~/projects/guix/etc/copyright.el")) ;; (if (file-exists-p guix-copyright) ;; (load-file "~/projects/guix/etc/copyright.el")))
;; (setq copyright-names-regexp ;; (format "%s <%s>" user-full-name user-mail-address)))
(defun delete-file-and-buffer () "Kill the current buffer and deletes the file it is visiting." (interactive) (let ((filename (buffer-file-name))) (if filename (if (y-or-n-p (concat "Do you really want to delete file " filename " ?")) (progn (delete-file filename) (message "Deleted file %s." filename) (kill-buffer))) (message "Not a file visiting buffer!"))))
(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)
(savehist-mode 1)
(setq completion-ignore-case t read-buffer-completion-ignore-case t read-file-name-completion-ignore-case t)
(add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)
(global-set-key (kbd "<f1>") 'shell) (global-set-key (kbd "<f2>") 'rgrep)
(global-set-key [remap dabbrev-expand] 'hippie-expand)
;; let's get encryption established (use-package pinentry :ensure t :config (setenv "GPG_AGENT_INFO" nil) ;; use emacs pinentry (setq auth-source-debug t)
(setq epg-gpg-program "gpg2") ;; not necessary (require 'epa-file) (epa-file-enable) (setq epa-pinentry-mode 'loopback) (setq epg-pinentry-mode 'loopback) (pinentry-start)
(require 'org-crypt) (org-crypt-use-before-save-magic))
(use-package helm :defer t :bind ("s-<tab>" . helm-buffers-list) ("s-SPC" . helm-M-x))
;; Available only in Melpa ;;(use-package docker :defer t :ensure t) ;;(use-package docker-compose-mode :defer t :ensure t)
(use-package visual-fill-column)
;; (use-package telega ;; :vc (:url "https://github.com/zevlg/telega.el" ;; :branch "master") ;; :commands (telega) ;; :defer t)
(use-package sudo-edit :defer t)
(use-package nov :defer t) (put 'narrow-to-region 'disabled nil)
(use-package gptel :bind ("s-g" . gptel-menu) :config (setq gptel-model 'claude-opus-4.7 gptel-backend (gptel-make-anthropic "Claude" :stream t :key "sk-ant-api03-Y7CFoPJkEcCsWSInlaSwv7vXbrvb9DThyzlNGAYiHS_pqsyJoh7rXAIMN7eVQokh2sqcv3f—APtgAJg0hPAg-LHlUzQAA")))