;; -*- lexical-binding: t; -*- (add-to-list 'custom-theme-load-path "~/.workspace/elisp-themes/") (let ((home (getenv "HOME"))) ;; 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) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) ;;(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t) (add-to-list 'package-archives '("gnu" . "https://elpa.gnu.org/packages/")) ;; Where custom config values should be saved (setq custom-file (concat home "/.custom.el")) (load custom-file)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;; GLOBAL MODES ;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;; (require 'flyspell) (add-hook 'prog-mode-hook 'flyspell-prog-mode) (add-hook 'prog-mode-hook 'linum-mode) (add-hook 'prog-mode-hook 'show-paren-mode) (add-hook 'prog-mode-hook 'display-fill-column-indicator-mode) (defun hugot-delete-trailing-whitespace-hook () "Add buffer-local book to delete trailing white space." (make-variable-buffer-local 'before-save-hook) (add-hook 'before-save-hook 'delete-trailing-whitespace)) (add-hook 'prog-mode-hook 'hugot-delete-trailing-whitespace-hook) (add-hook 'yaml-mode 'hugot-delete-trailing-whitespace-hook) (yas-global-mode) ;; Switch between tabs with C-number (setq-default tab-bar-select-tab-modifiers '(control)) ;; Add a tab bar up top (tab-bar-mode) ;; enable flycheck everywhere (global-flycheck-mode) ;; Save minibuffer history between sessions (savehist-mode 1) ;; Show the current time in the modeline (display-time-mode 1) (add-hook 'prog-mode-hook 'abbrev-mode) ;; minimal gui (when (eq window-system "x") (require 'emojify) (global-emojify-mode 1) (scroll-bar-mode -1)) (tool-bar-mode -1) (add-hook 'after-init-hook 'global-company-mode) (xclip-mode 1) (setq-default fill-column 80) (setq mouse-wheel-progressive-speed nil) ;; don't accelerate scrolling (setq epa-pinentry-mode 'loopback) ;; Disable GUI prompt for GPG (defadvice epg--start (around advice-epg-disable-agent activate) (let ((agent (getenv "GPG_AGENT_INFO"))) (setenv "GPG_AGENT_INFO" nil) ad-do-it (setenv "GPG_AGENT_INFO" agent))) ;; Disable all colours when rendering HTML using shr by replacing its ;; colourize function with a stub. (advice-add 'shr-colorize-region :around (defun shr-no-colourize-region (&rest ignore))) ;; Let's make sure that lanuage settings are not dependent on the ;; environment ;;(set-language-environment "English") (setq system-time-locale "en_US.UTF-8") (setq calendar-week-start-day 1 calendar-day-name-array ["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"] calendar-month-name-array ["January" "February" "March" "April" "May" "June" "Juli" "August" "Septembre" "October" "November" "December"]) ;; Don't ask wether to save abbrevs (setq save-abbrevs 'silent) ;; ;;Don't auto-save files in the same directory as the file itself ;; (setq auto-save-file-name-transforms ;; `((".*" "~/.emacs-saves/" t))) (setq show-paren-delay 0) (fset 'yes-or-no-p 'y-or-n-p) (setq inhibit-startup-message t inhibit-startup-echo-area-message t) (setq-default indent-tabs-mode nil) (setq-default tab-width 4) (setq-default tab-bar-tab-hints t) ;; This is very php-specific, it would be nice if this could be ;; modularized more per filetype (setq grep-find-ignored-directories '(".cache" "vendor" ".git" ".idea" "vendor" "var" "web" "node_modules" "httpconf")) ;; Disable request to save open files (because it is annoying) (setq grep-save-buffers nil) ;; Disable annoying sounds (setq ring-bell-function 'ignore) ;; Always follow symlinks (setq vc-follow-symlinks t) (setq auth-sources '("~/.authinfo.gpg")) (put 'erase-buffer 'disabled nil) (setq flycheck-emacs-lisp-load-path 'inherit) (add-to-list 'load-path "~/projects/phpinspect.el") (add-to-list 'load-path "~/projects/qtoot") (when (require 'qtoot nil 'noerror) (setq qtoot-enable-drafts t)) ;; END GLOBAL MODES ;;;;;;;;;;;;;;;;;;;;; ;;;;; POWERLINE ;;;;; ;;;;;;;;;;;;;;;;;;;;; (powerline-default-theme) (setq powerline-display-buffer-size nil) (setq display-time-default-load-average nil) ;; END POWERLINE ;;;;;;;;;;;;;;;;;;;; ;;;;; WEB MODE ;;;;; ;;;;;;;;;;;;;;;;;;;; (add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)) (add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode)) ;; When web-mode should be active (add-to-list 'auto-mode-alist '("\\.cshtml" . web-mode)) (add-to-list 'auto-mode-alist '("\\.twig" . web-mode)) (add-to-list 'auto-mode-alist '("\\.svelte" . web-mode)) (add-to-list 'auto-mode-alist '("\\.java" . java-mode)) ;; END WEB MODE ;;;;;;;;;;;;;;;; ;;;;; JAVA ;;;;; ;;;;;;;;;;;;;;;; (when (require 'lsp-java nil t) (setq lsp-java-import-gradle-version "7.4.2") (setq lsp-java-import-gradle-wrapper-enabled nil)) (add-hook 'java-mode-hook 'lsp) (defun hugot-java-indent-setup () (setq c-default-style "java") (c-set-offset 'arglist-intro '+) (c-set-offset 'arglist-close '0) (c-set-offset 'case-label '+)) (add-hook 'java-mode-hook 'hugot-java-indent-setup) ;; END JAVA ;;;;;;;;;;;;;;;;;;;;;; ;;;;; JAVASCRIPT ;;;;; ;;;;;;;;;;;;;;;;;;;;;; (require 'flycheck) (add-to-list 'auto-mode-alist '("\\.jsx?$" . web-mode)) (setq web-mode-content-types-alist '(("jsx" . "\\.js[x]?\\'"))) (add-to-list 'flycheck-disabled-checkers 'javascript-jshint) (add-to-list 'flycheck-disabled-checkers 'json-jsonlist) (flycheck-add-mode 'javascript-eslint 'web-mode) (defun hugot-javascript-web-mode-hook () (when (or (string-match "\\.svelte$" (buffer-name)) (string-match "\\.js$" (buffer-name))) (setq tab-width 2) (setq web-mode-markup-indent-offset 2) (setq web-mode-code-indent-offset 2) (setq js2-basic-offset 2) (setq web-mode-script-padding 2) (setq web-mode-script-padding 2) (setq web-mode-block-padding 2))) (add-hook 'web-mode-hook 'hugot-javascript-web-mode-hook) ;; END JAVASCRIPT ;;;;;;;;;;;;;;; ;;;;; PHP ;;;;; ;;;;;;;;;;;;;;; (defvar hugot-php-mode-expand-list nil "PHP mode expansions.") (setq hugot-php-mode-expand-list '(("pun" "public function (): \n{\n\n}\n" (17 18 21 24)) ("prn" "private function (): \n{\n\n}\n" (18 19 22 25)) ("fn" "function ():\n{\n\n}" (10 11 15)) ("pr" "private " ()) ("pu" "public " ()))) (add-to-list 'auto-mode-alist `("\\.php$" . php-mode)) (defun hugot-php-personal-hook () (require 'expand) (expand-add-abbrevs php-mode-abbrev-table hugot-php-mode-expand-list) (abbrev-mode 1) (set (make-local-variable 'company-minimum-prefix-length) 0) (set (make-local-variable 'company-tooltip-align-annotations) t) (set (make-local-variable 'company-idle-delay) 0.1) (set (make-local-variable 'company-backends) '(phpinspect-company-backend)) ;; Handy namespace stuff (define-key php-mode-map (kbd "C-c u") 'phpinspect-fix-uses-interactive) (define-key php-mode-map (kbd "C-c t t") 'phptest-run-test-for-current-buffer) (define-key php-mode-map (kbd "C-c t p") 'phptest-run-tests-for-current-buffer-project) (define-key php-mode-map (kbd "C-c t o") 'phptest-open-test-for-current-buffer) (phpinspect-mode)) (when (require 'phpinspect nil t) (add-hook 'php-mode-hook #'hugot-php-personal-hook)) ;; END PHP ;;;;;;;;;;;;;;; ;;;;; CSS ;;;;; ;;;;;;;;;;;;;;; (defun hugot-css-mode-hook () "Custom actions to execute when initializing css-mode" (setq-local company-minimum-prefix-length 1) (setq-local company-idle-delay 0)) (add-hook 'css-mode-hook 'hugot-css-mode-hook) ;; END CSS ;;;;;;;;;;;;;;;;;;;;;;;; ;;;;; COMPANY MODE ;;;;; ;;;;;;;;;;;;;;;;;;;;;;;; (with-eval-after-load 'company (dolist (map (list company-active-map company-search-map)) (define-key map (kbd "C-n") nil) (define-key map (kbd "C-p") nil) (define-key map (kbd "M-n") #'company-select-next) (define-key map (kbd "M-p") #'company-select-previous)) (setq company-auto-complete t) (setq company-idle-delay 1) (setq company-auto-complete 'company-explicit-action-p) (global-set-key (kbd "M-p") 'company-select-previous) (global-set-key (kbd "M-n") 'company-select-next) (add-to-list 'company-backends 'company-shell t) (add-to-list 'company-backends 'company-dabbrev-code t) (add-to-list 'company-backends 'company-capf)) (defun hugot-make-capf-dominant-company-backend () (interactive) (setq company-backends `(company-capf ,@(seq-filter (lambda (elt) (not (eq 'company-capf elt))) company-backends)))) ;; END COMPANY MODE ;;;;;;;;;;;;;; ;;;;; GO ;;;;; ;;;;;;;;;;;;;; (require 'go-mode) (require 'company-go) (require 'go-eldoc) (require 'flycheck) (defvar hugot-go-mode-expand-list '(("ern" "if err != nil {\n\n}\n" (17)) ("die" "log.Fatal()" (11)) ("ernd" "if err!= nil {\nlog.Fatal(err)\n}\n" ()) ("fn" "func () {\n}\n" (6)) ("prnl" "fmt.Prinln()" (12)) ("prnf" "fmt.Printf()" (12)) ("sprn" "fmt.Sprintf()" (13))) "Alist with golang expand snippets for use with ABBREV-MODE.") ;;;###autoload (defun hugot-go-mode-hook () "Personal go-mode hook." (require 'lsp-mode) (require 'lsp-ui) (require 'expand) (expand-add-abbrevs go-mode-abbrev-table hugot-go-mode-expand-list) (abbrev-mode 1) (lsp) (lsp-deferred) (lsp-ui-mode) (lsp-ui-sideline-mode) (add-hook 'before-save-hook 'gofmt-before-save) ; gofmt before every save (flymake-mode 1) (local-set-key (kbd "M-.") 'godef-jump) ; Godef jump key binding (local-set-key (kbd "M-*") 'pop-tag-mark) (local-set-key (kbd "M-p") 'compile) ; Invoke compiler (local-set-key (kbd "M-P") 'recompile) ; Redo most recent compile cmd (local-set-key (kbd "M-]") 'next-error) ; Go to next error (or msg) (local-set-key (kbd "M-[") 'previous-error) ; Go to previous error or msg (local-set-key (kbd "C-c g") 'hugot-go-run) (setq gofmt-command "goimports") (hugot-make-capf-dominant-company-backend)) (add-hook 'go-mode-hook 'hugot-go-mode-hook) (defun hugot-go-run () (interactive) (let ((project-dir (lsp--suggest-project-root)) (start-buffer (current-buffer))) (with-current-buffer (get-buffer-create "GO-RUN") (display-buffer (current-buffer)) (let ((default-directory project-dir)) (make-process :name "GO-RUN OUTPUT" :command `("go" "run" "main.go") :buffer (current-buffer) :stderr (current-buffer)))))) ;; END GO ;;;;;;;;;;;;;;;;;;; ;;;;; SH MODE ;;;;; ;;;;;;;;;;;;;;;;;;; (declare-function 'sh-electric-here-document-mode "sh-script") ;; Disable automatic expansion of << to <")) t) (funcall old-function)) (advice-add #'eww-update-header-line-format :around #'hugot-eww-title) ;; END EWW MODE ;;;;;;;;;;;;;;; ;;;;; IDO ;;;;; ;;;;;;;;;;;;;;; (require 'ido) (setq ido-enable-flex-matching t) (ido-everywhere 1) ;;(ido-vertical-mode 1) ;;; This is from ido-completing-read+ which made function/command completion garbage slow. ;;(ido-ubiquitous-mode 1) (ido-mode 1) (defun hugot-completing-read (prompt coll pred &rest args) "`completing-read-default' wrapper to use as `completing-read-function'. Enables ido for M-x and describe-function/describe-variable." (let ((cr-args `(,prompt ,coll ,pred ,@args)) (cr-function #'completing-read-default)) ;; When the collection is a list, ido knows what to do with it (cond ((and (listp coll) (stringp (car coll))) (setq cr-function #'ido-completing-read)) ((and (listp coll) (consp (car coll))) (setq cr-function #'ido-completing-read) (setq coll (mapcar 'car coll)) (setq cr-args `(,prompt ,coll ,pred ,@args))) ;; Collection is a function, ido can't deal with those, so for some cases we ;; force the function to return all matches that contain "empty string", which ;; (usually) results in them returning every possible value. ((functionp coll) ;; Used for `describe-function' (if (or (eq #'help--symbol-completion-table coll) ;; Should match the prompt of `project-find-file' (string-match "^Find file in" prompt)) (setq cr-function #'ido-completing-read cr-args `(,prompt ,(funcall coll "" pred t) ,pred ,@args)) (pcase pred ;; Used for M-x (`read-extended-command') ('commandp (setq cr-function #'ido-completing-read cr-args `(,prompt ,(funcall coll "" pred t) ,pred ,@args))))))) (apply cr-function cr-args))) (setq completing-read-function #'hugot-completing-read) ;; Use IDO for M-x ;;(smex-initialize) ;; (global-set-key (kbd "M-x") 'smex) ;; (global-set-key (kbd "M-X") 'smex-major-mode-commands) ;; This is your old M-x. (global-set-key (kbd "C-c C-c M-x") 'execute-extended-command) (defvar hugot-kr-cr-corpse-length 20) (defun hugot-kr-cr () "Completing read for the `kill-ring'. Returns the kill-ring index of the selected item, for use as argument to `yank' and the like." (interactive) (let* ((body-count 0) (alist (mapcar (lambda (corpse) (cons (replace-regexp-in-string "[[:blank:]]+" " " (truncate-string-to-width corpse hugot-kr-cr-corpse-length)) (setq body-count (+ body-count 1)))) kill-ring-yank-pointer)) (corpse (completing-read "Kill ring: " alist))) (alist-get corpse alist 0 nil #'string=))) (defun hugot-kr-cr-yank (&optional arg) "Yank from the kill-ring, seleting which string to yank using `completing-read'. See `yank' for documentation of ARG." (interactive (list (hugot-kr-cr))) (let ((yank-function #'yank) ;; The yank pointer should stay the same, but there's no way to pass DO-NOT-MOVE ;; to `current-kill' when calling the yank function, so it's stored here to ;; recover it's state after yanking. The yank function appropriate for the current ;; mode needs to be called in stead of just using `insert', because using `insert' ;; in kotl-mode (for example) breaks it. (stored-yank-pointer (cl-copy-list kill-ring-yank-pointer))) (cond ((eq major-mode 'kotl-mode) (setq yank-function #'kotl-mode:yank))) (funcall yank-function arg) ;; Restore yank-pointer (setq kill-ring-yank-pointer stored-yank-pointer))) ;; END IDO (require 'hyperbole) (eval-after-load 'kotl-mode '(require 'hugot-kotl-mode)) ;; Emoji support (set-fontset-font t 'symbol "Apple Color Emoji") (set-fontset-font t 'symbol "Noto Color Emoji" nil 'append) (set-fontset-font t 'symbol "Segoe UI Emoji" nil 'append) (set-fontset-font t 'symbol "Symbola" nil 'append) (setq server-socket-dir (concat (getenv "HOME") "/.cache/emacs")) (defun hugot-set-appearance () "Set appearance settings." (interactive) (load-theme 'epaper) (enable-theme 'epaper) (fringe-mode (alist-get "right-only" fringe-styles nil nil 'string=)) (window-divider-mode) (scroll-bar-mode -1) (menu-bar-mode -1) (set-frame-font "Hack 11" nil t) (set-face-attribute 'default nil :height 110) (setq linum-format "%d ")) (hugot-set-appearance) (put 'downcase-region 'disabled nil) ;;;;;;;;;;;;;;;;;;;; ;;;;; COMMANDS ;;;;; ;;;;;;;;;;;;;;;;;;;; (defun insert-date () (interactive) (insert (format-time-string "%Y-%m-%d %H:%M"))) (defun hugot-list-project-buffers () (let ((project-dir (cdr (project-current))) (buffers)) (dolist (buffer (buffer-list)) (when (and (buffer-file-name buffer) (file-in-directory-p (buffer-file-name buffer) project-dir) (push buffer buffers)))) buffers)) (defun hugot-project-switch-to-buffer (buffer) (interactive (list (completing-read "Buffer: " (mapcar #'buffer-name (hugot-list-project-buffers))))) (switch-to-buffer buffer)) (defun hugot-cp-rsa () (interactive) (with-temp-buffer (insert-file-contents-literally "~/.ssh/id_rsa.pub") (copy-region-as-kill (point-min) (point-max)) (message "~/.ssh/id_rsa.pub contents added to kill-ring"))) ;; END COMMANDS