(custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(ansi-color-faces-vector [default default default italic underline success warning error]) '(blink-cursor-mode nil) '(custom-enabled-themes '(abyss)) '(dired-hide-details-hide-information-lines t) '(dired-hide-details-hide-symlink-targets nil) '(grep-use-null-device nil) '(inhibit-startup-screen t) '(menu-bar-mode nil) '(message-default-mail-headers "Cc: Bcc: ") '(package-archives '(("gnu" . "http://elpa.gnu.org/packages/") ("melpa" . "https://melpa.org/packages/") ("marmalade" . "http://marmalade-repo.org/packages/"))) '(scroll-bar-mode nil) '(send-mail-function 'smtpmail-send-it) '(tool-bar-mode nil)) (custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. ) ;;;;;;;;;;; ;; BASIC ;; ;;;;;;;;;;; (load "~/.emacs.d/init-basic") ;;;;;;;;;;;;;; ;; PACKAGES ;; ;;;;;;;;;;;;;; ;; Added by Package.el. This must come before configurations of ;; installed packages. Don't delete this line. If you don't want it, ;; just comment it out by adding a semicolon to the start of the line. ;; You may delete these explanatory comments. (package-initialize) (require 'bind-key) (eval-when-compile ;; Following line is not needed if use-package.el is in ~/.emacs.d (add-to-list 'load-path (emacs-root-join "custom" "use-package")) (require 'use-package)) (require 'subr-x) ;; for "string-trim" and other string operations (require 'face-remap) ;; for custom face mode ;; reopen last session buffers ;; (desktop-save-mode 1) ;; ;; save buffer on emacs lost focus (not buffer lost focus) ;; (defun save-buffer-on-lost () ;; (interactive) ;; (if (or (null buffer-file-name) (not (file-writable-p buffer-file-name))) ;; () ;; not writable ;; (save-buffer))) ;; (add-hook 'focus-out-hook 'save-buffer-on-lost) ;; current emacs session env variable (defconst MY-EMACS-SERVER-NAME (or (getenv "EMACS_SERVER_NAME") (concat "emacs-server-" (number-to-string (random))))) (setenv "EMACS_SERVER_NAME" MY-EMACS-SERVER-NAME) (setq server-name MY-EMACS-SERVER-NAME) (defvar MY-EMACS-SERVER-STARTED nil) (unless MY-EMACS-SERVER-STARTED (setq MY-EMACS-SERVER-STARTED t) (server-start)) ;;;;;;;;;; ;; MAIL ;; ;;;;;;;;;; ; Outgoing email (msmtp + msmtpq) (setq send-mail-function 'sendmail-send-it sendmail-program "msmtp" mail-specify-envelope-from t message-sendmail-envelope-from 'header mail-envelope-from 'header) (defun my-message-setup-hook () (gnus-alias-determine-identity) ;; (define-key message-mode-map (kbd "C-c f") ;; (lambda () ;; (interactive) ;; (message-remove-header "Fcc") ;; (message-remove-header "Organization") ;; ;; (gnus-alias-select-identity) ;; (notmuch-fcc-header-setup))) (flyspell-mode)) (add-hook 'message-setup-hook 'my-message-setup-hook) (setq gnus-button-url 'browse-url-generic browse-url-generic-program "my-browser-open-link" browse-url-browser-function gnus-button-url) ;;;;;;;;;; ;; TERM ;; ;;;;;;;;;; (require 'term) ;; add my window map to term raw mode as well (define-key term-raw-map (kbd "M-o") my-window-map) (define-key term-raw-map (kbd "C-c C-y") 'term-paste) (defconst my-term-prefix "my-term-mt") (defun my-term-base (bufname &rest arguments) (set-buffer (apply #'make-term (append (list bufname (car arguments) nil) (cdr arguments)))) (term-mode) (term-char-mode) (switch-to-buffer (concat "*" bufname "*"))) (defun my-term-sentinel-advice (orig-fun &rest args) "Kill buffer on terminal close" (apply orig-fun args) (let* ((proc (car args)) (buffer (process-buffer proc))) (unless (eq 0 my-term-self-id) (my-term-put-unique my-term-self-id) (kill-buffer buffer)))) (advice-add 'term-sentinel :around #'my-term-sentinel-advice) (defvar my-term-shell-program (or (getenv "SHELL") (program-resolve-path "fish") (program-resolve-path "bash"))) (defun my-term-taged (name) "Start a terminal-emulator in a new buffer named `name' The buffer is in Term mode;" (interactive (list (read-from-minibuffer "tag: "))) (my-term-base name my-term-shell-program)) (defvar my-term-unique-free (list 1 2 3 4 5 6 7 8 9)) (defvar my-term-unique-max (car (last my-term-unique-free))) (defvar my-term-self-id 0) (defun my-term-get-unique () (when (null my-term-unique-free) (setq my-term-unique-max (1+ my-term-unique-max)) (push my-term-unique-max my-term-unique-free)) (pop my-term-unique-free)) (defun my-term-put-unique (i) "Say that index `i' is free for use This is optimized for `get-` not `put-` because noone cares how long does the terminal take to close " (if (null my-term-unique-free) (push i my-term-unique-free) (let ((lst my-term-unique-free) (going t)) (while going (let ((cur (car lst))) (if (<= i cur) (progn (setcar lst i) (setcdr lst (cons cur (cdr lst))) (setq going nil)) (if (null (cdr lst)) (progn (setcdr lst (list i)) (setq going nil)) (setq lst (cdr lst))))))))) (defun my-term-unsafe (self-id) "Unsafely start or open a term indexed by self-id" (let* ((name (number-to-string self-id)) (bufname (concat my-term-prefix name))) (my-term-taged bufname) (setq-local my-term-self-id self-id))) (defun my-term-indexed (self-id) "Start or open a term indexed by self-id" (delete self-id my-term-unique-free) (my-term-unsafe self-id)) (defun my-term () "Start a new term indexed by unique index" (interactive) (my-term-unsafe (my-term-get-unique))) (defvar my-term-exe-unique-counter 0) (defun my-term-exe (cmd) "Start a terminal-emulator in a new buffer named `program' The buffer is in Term mode;" (interactive (list (read-from-minibuffer "cmd: "))) (setq my-term-exe-unique-counter (+ 1 my-term-exe-unique-counter)) (my-term-base (format "exe-%d" my-term-exe-unique-counter) "/bin/sh" "-c" cmd)) ;;;;;;;;;;;;;;;;;;;;; ;; CYRILLIC LAYOUT ;; ;;;;;;;;;;;;;;;;;;;;; (defun support-cyrillic-layout () "Make emacs output english characters, regardless whether the OS keyboard is english or russian" ;; ;; Uncomment below if want to disable all cyrillic and use latin instead ;; (defun literal-insert () ;; (interactive) ;; (insert-char last-input-event 1)) ;; (define-minor-mode literal-insert-mode ;; "Make emacs output characters corresponging to the OS keyboard, ;; ignoring the key-translation-map" ;; :keymap (let ((new-map (make-sparse-keymap)) ;; (english-chars "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#")) ;; (mapc (lambda (char) ;; (define-key new-map (string char) ;; 'literal-insert)) ;; english-chars) ;; new-map)) ;; (defun run-literal-mode () ;; (literal-insert-mode 1)) ;; (add-hook 'text-mode-hook 'run-literal-mode) (defun translate-keystrokes-ru->en () "Make emacs output english characters, regardless whether the OS keyboard is english or russian" (let ((make-key-stroke (lambda (prefix char) (eval `(kbd ,(if (and (string-match "^C-" prefix) (string-match "[A-Z]" (string char))) (concat "S-" prefix (string (downcase char))) (concat prefix (string char))))))) (case-fold-search nil) (keys-pairs (zip-with 'cons "йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖ\ЭЯЧСМИТЬБЮ№" "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#")) ;; (prefixes '("" "s-" "M-" "M-s-" ;; "C-" "C-s-" "C-M-" "C-M-s-"))) (prefixes '( "s-" "M-" "M-s-" "C-" "C-s-" "C-M-" "C-M-s-"))) (mapc (lambda (prefix) (mapc (lambda (pair) (define-key key-translation-map (funcall make-key-stroke prefix (car pair)) (funcall make-key-stroke prefix (cdr pair)))) keys-pairs)) prefixes))) (translate-keystrokes-ru->en)) (support-cyrillic-layout) ;;;;;;;;;;;;;;;;;;;;;;; ;; LOOK/TRANSPARENCY ;; ;;;;;;;;;;;;;;;;;;;;;;; (defconst MY-DEFAULT-TRANSPARENCY 100) (set-in-alist! default-frame-alist 'alpha MY-DEFAULT-TRANSPARENCY) (defun my-set-transparency (value) "Sets the transparency of the frame window. 0=transparent/100=opaque" (interactive "nTransparency Value 0 - 100 opaque: ") (set-frame-parameter (selected-frame) 'alpha value)) (defun my-toggle-transparency () (interactive) (let ((alpha (frame-parameter nil 'alpha))) (if (eql (cond ((numberp alpha) alpha) ((numberp (cdr alpha)) (cdr alpha)) ;; Also handle undocumented ( ) form. ((numberp (cadr alpha)) (cadr alpha))) 100) (my-set-transparency MY-DEFAULT-TRANSPARENCY) (my-set-transparency 100)))) ;;;;;;;;;;;;;; ;; PACKAGES ;; ;;;;;;;;;;;;;; (use-package buffer-flip :ensure nil) (defun my-elfeed-update () (interactive) (elfeed-update) (elfeed-search--update-list)) (use-package elfeed :bind (:map elfeed-search-mode-map ("g" . 'my-elfeed-update)) :config ;; Save elfeed db automatically, because if Emacs crashes or is killed (which happens to me ;; occasionally, especially since I develop packages in a single instance), we'd lose the db ;; updates not saved. (unless (cl-loop for timer in timer-idle-list thereis (equal (aref timer 5) #'elfeed-db-save)) (run-with-idle-timer 10000 'repeat #'elfeed-db-save))) ;; don't skip same buffer (defun my-buffer-flip-skip-buffer-advice (orig-fun buf) (or (= ? (elt (buffer-name buf) 0)) ; internal? (eq (get-buffer-window buf) (get-buffer-window (current-buffer))))) (advice-add 'buffer-flip-skip-buffer :around #'my-buffer-flip-skip-buffer-advice) (defun agda-mode-exists? () (= 0 (car (list (call-process "which" nil nil nil "agda-mode"))))) (if (agda-mode-exists?) (condition-case nil (load-file (let ((coding-system-for-read 'utf-8)) (shell-command-to-string "agda-mode locate"))) (error (message "could not load agda-mode"))) (print "agda-mode is not installed")) (with-eval-after-load 'company (let ((m company-active-map)) (define-key m [return] nil) (define-key m (kbd "RET") nil) (define-key m [tab] 'company-complete-selection) (define-key m (kbd "TAB") 'company-complete-selection) (define-key m (kbd "C-n") 'company-select-next) (define-key m (kbd "C-p") 'company-select-previous) ;; ;; optionaly don't use same keys as for movement ;; (define-key m (kbd "C-n") nil) ;; (define-key m (kbd "C-p") nil) ; optionaly don't use same keys as for movement ;; (define-key m [backtab] 'company-select-next) ;; (define-key m (kbd "S-TAB") 'company-select-next) ) ) (use-package company :ensure nil :config (setq company-minimum-prefix-length 1) (setq company-idle-delay 0)) (add-hook 'after-init-hook 'global-company-mode) (use-package company-tabnine :ensure nil) (defvar company-tabnine-restart-enabled nil) (defun company-tabnine-toggle () (interactive) (setq company-tabnine-restart-enabled (not company-tabnine-restart-enabled)) (company-tabnine-kill-process) (company-tabnine-restart-server) (if company-tabnine-restart-enabled (progn (add-to-list 'company-backends #'company-tabnine) (message "tabnine was turned on")) (progn (setq company-backends (delete #'company-tabnine company-backends)) (message "tabnine was turned off")))) (defun company-tabnine-start-process-wrapper (orig-fun &rest args) (if company-tabnine-restart-enabled (apply orig-fun args))) (advice-add 'company-tabnine-start-process :around #'company-tabnine-start-process-wrapper) (haskell-tab-indent-mode 1) (use-package projectile :ensure nil :init (projectile-mode)) (use-package markdown-mode)