;; Requires: ;; aspell ;; Optional: ;; clang ;; TODO ;; Look up authors of projects. See what other useful things they make. ;; ----------- Default Variables ----------- ;; Global variables (defvar backup-directory (concat user-emacs-directory "backups")) (unless (file-exists-p backup-directory) (make-directory backup-directory)) (setq-default inhibit-startup-screen t column-number-mode t scroll-error-top-bottom t show-paren-delay 0.25 tab-width 4 indent-tabs-mode nil ;x-select-enable-clipboard t ;interprogram-paste-function 'x-cut-buffer-or-selection-value backup-directory-alist `(("." . ,backup-directory)) delete-old-versions t) ;; (global-linum-mode) ;; Delete selected text when typing (normal editor behavior) (delete-selection-mode t) ;; ------------- Keybindings ------------- (defun smart-beginning-of-line () "Move point to first non-whitespace character or beginning-of-line. Move point to the first non-whitespace character on this line. If point was already at that position, move point to beginning of line." (interactive "^") ;(if (version< "22" emacs-version) (interactive "^") (interactive)) (let ((oldpos (point))) (beginning-of-line-text); goes to first significant character ;(back-to-indentation); goes to first non-whitespace (and (= oldpos (point)) (beginning-of-line)))) (global-set-key [home] 'smart-beginning-of-line) (global-set-key (kbd "C-c /") 'comment-or-uncomment-region) (global-set-key (kbd "C-c C-k") 'compile) (global-set-key (kbd "M-") 'backward-list) (global-set-key (kbd "M-") 'forward-list) (global-set-key (kbd "M-") 'racket-backward-up-list) ;; Can't seem to find forward-down-list. ;; Not very important since I would rarely use it anyway ;;(global-set-key (kbd "M-") '?) (global-set-key (kbd "M-") 'kill-sexp) ;; ----------- Package Managing ----------- ;; The package manager (require 'package) ;; Add package sources (setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/") ("melpa" . "https://melpa.org/packages/") ("melpa-stable" . "https://stable.melpa.org/packages/") ("org" . "https://orgmode.org/elpa/")) package-archive-priorities '(("melpa" . 1))) (package-initialize) (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (require 'use-package) (setq use-package-always-ensure t) (use-package auto-package-update :config (add-hook 'auto-package-update-before-hook (lambda () (package-refresh-contents))) (setq auto-package-update-delete-old-versions t auto-package-update-interval 4 auto-package-update-prompt-before-update t auto-package-update-hide-results t) (auto-package-update-maybe)) ;; ---------- Color Themes ---------- ;; TODO: Fix warning underline to always be orange/yellow ;; Update: Seems it always takes the color of the foreground. ;; Also seems to ignore most properties. (e.g. overline, underline, ;; strike-though, etc.) Maybe it's an xterm problem? (use-package color-theme :config (color-theme-initialize) (load-theme 'Thomas-Experiement t)) ;; ---------- Use X11 clipboard ----------- (use-package xclip :if (executable-find "xclip") :config (add-to-list 'load-path "~/.emacs.d/elpa/xclip-1.4/") (xclip-mode 1)) ;; --------- Parentheses Matching --------- (show-paren-mode) (use-package highlight-parentheses :config (define-globalized-minor-mode global-highlight-parentheses-mode highlight-parentheses-mode (lambda () (highlight-parentheses-mode t))) (global-highlight-parentheses-mode t)) (if (version<= "24.4" emacs-version) (electric-pair-mode) (use-package autopair :config (autopair-global-mode))) ;; ------------ xTerm Mouse ------------ ;; Disable because it became annoying, sounds cool though. (use-package mouse :disabled :config (xterm-mouse-mode t)) ;; ----------- Ensime ----------- ;; Java/Scala featues. Includes: ;; * Inferred types ;; * Autocomplete ;; * Syntax highlighting ;; * Jump to source/docs ;; * Refactoring ;; * Error detection (use-package company) (if (version<= "24.4" emacs-version) (use-package ensime :requires company :hook (scala-mode java-mode) :config (setq ensime-startup-notification nil) (eval-after-load 'ensime-mode '(define-key ensime-mode-map (kbd "C-c i") (lambda () "Generate ensime.sbt file" (interactive) (write-region "ensimeScalaVersion in ThisBuild := \"2.11.8\"" nil (concat (read-directory-name "SBT Root:") "ensime.sbt")))))) (use-package scala-mode :commands (scala-mode))) ;; --------- C Syntax checker --------- ;; TODO: C autocomplete. Both with clang integration and backup naive method ;; (use-package irony ;; ;;:hook (c-mode c++-mode objc-mode) ;; :init ;; (add-hook 'c++-mode-hook 'irony-mode) ;; (add-hook 'c-mode-hook 'irony-mode) ;; (add-hook 'objc-mode-hook 'irony-mode) ;; :commands (irony-mode irony-version) ;; :config ;; (defun my-irony-mode-hook () ;; (define-key irony-mode-map [remap completion-at-point] ;; 'irony-completion-at-point-async) ;; (define-key irony-mode-map [remap complete-symbol] ;; 'irony-completion-at-point-async)) ;; (add-hook 'irony-mode-hook 'my-irony-mode-hook) ;; (add-hook 'irony-mode-hook irony-cdb-autosetup-compile-options) ;; ) ;; (use-package company ;; :init (add-hook 'after-init-hook 'global-company-mode) ;; :config ;; (setq company-idle-delay nil ;; company-minimum-prefix-length 2 ;; company-show-numbers t ;; company-tooltip-limit 20 ;; company-dabbrev-downcase nil ;; company-backends '((company-irony company-gtags)) ;; ) ;; :bind ("C-;" . company-complete-common) ;; ) ;; (use-package company-irony ;; :requires company) ;; (use-package flycheck-irony ;; :hook c-mode) ;; ; :mode ("\\.c\\'" "\\.h\\'") ;; ------------ Web Mode ------------ (defun my-sgml-insert-gt () "Inserts a `>' character and calls `my-sgml-close-tag-if-necessary', leaving point where it is." (interactive) (insert ">") (save-excursion (my-sgml-close-tag-if-necessary))) (defun my-sgml-close-tag-if-necessary () "Calls sgml-close-tag if the tag immediately before point is an opening tag that is not followed by a matching closing tag." (when (looking-back "<\\s-*\\([^ \t\r\n]+\\)[^]*>") (let ((tag (match-string 1))) (unless (and (not (sgml-unclosed-tag-p tag)) (looking-at (concat "\\s-*<\\s-*/\\s-*" tag "\\s-*>"))) (sgml-close-tag))))) ;; TODO: Disable autopair in HTML. Interferes with autoclose tab. (use-package multi-web-mode :init (setq mweb-default-major-mode 'html-mode mweb-tags '((php-mode "<\\?php\\|<\\? \\|<\\?=" "\\?>") (js-mode "]*>" "") (css-mode "]*>" "")) mweb-filename-extensions '("php" "htm" "html" "ctp" "phtml" "php4" "php5")) :config (multi-web-global-mode 1) (eval-after-load "sgml-mode" '(define-key sgml-mode-map ">" 'my-sgml-insert-gt))) ;; ------------ Git Mode ------------ ;; TODO: make resolving merge conflicts hotkeys not use "^" ;; TODO: Conflict resolution theme is unreadable (when (version<= "24.4" emacs-version) (use-package magit :bind ("C-x g" . magit-status))) ;; ----------- Rust Mode ------------ (use-package rust-mode) (use-package rust-playground :requires rust-mode) (use-package cargo :after rust-mode) (use-package flycheck-rust :after rust-mode) ;; ----------- i3 Support ---------- (use-package i3wm :disabled :if (equal (getenv "DESKTOP_SESSION") "i3")) ;; --------- Racket Mode ---------- (use-package racket-mode) ;; ---------- C# Mode ------------- (use-package csharp-mode :if (version<= "24.4" emacs-version)) ;; ------- Markdown Mode ---------- (when (version<= "24.4" emacs-version) (use-package markdown-mode)) ;; ---- StackOverflow Client ------ (use-package sx ;; TODO: More keybindings if useful :bind (("C-c C-q" . sx-search)) :config (defvar sx-dir (concat user-emacs-directory ".sx")) (if (file-exists-p sx-dir) (and (shell-command (concat "chmod 700 " sx-dir)) (shell-command (concat "chmod 600 " sx-dir "/*.el"))) ) :commands (sx-accept sx-answer sx-ask sx-authenticate sx-bug-report sx-button-copy sx-button-edit-this sx-button-follow-link sx-cache-invalidate-all sx-comment sx-compose-insert-tags sx-compose-mode sx-compose-quit sx-compose-send sx-delete sx-display sx-display-question sx-downvote sx-edit sx-favorite sx-inbox sx-inbox-mode sx-inbox-notifications sx-open-link sx-question-list-hide sx-question-list-mark-read sx-question-list-mode sx-question-list-next sx-question-list-next-far sx-question-list-next-page sx-question-list-order-by sx-question-list-previous sx-question-list-previous-far sx-question-list-refresh sx-question-list-switch-site sx-question-list-view-next sx-question-list-view-previous sx-question-mode sx-question-mode-hide-show-section sx-question-mode-next-section sx-question-mode-order-by sx-question-mode-previous-section sx-question-mode-refresh sx-search sx-search-tag-at-point sx-star sx-tab-all-questions sx-tab-featured sx-tab-frontpage sx-tab-hot sx-tab-month sx-tab-newest sx-tab-starred sx-tab-topvoted sx-tab-unanswered sx-tab-unanswered-my-tags sx-tab-week sx-upvote sx-version sx-visit-externally)) ;; -------- Spellcheck ------------ (defun flyspell-detect-ispell-args (&optional run-together) (cond ((string-match "aspell$" ispell-program-name) (append (list "--sug-mode=ultra" "--lang=en_US") (if run-together '("--run-together" "--run-together-limit=5" "--run-together-min=2")))) ((string-match "hunspell$" ispell-program-name) "-d en_US"))) (use-package flyspell-correct-popup :bind ("M-s" . ispell-word) :hook ((text-mode . flyspell-mode) (prog-mode . flyspell-prog-mode) ((flyspell-mode flyspell-prog-mode) . flyspell-buffer)) :config (cond ((executable-find "aspell") (setq ispell-program-name "aspell")) ((executable-find "hunspell") (setq ispell-program-name "hunspell") (setq ispell-local-dictionary "en_US") (setq ispell-local-dictionary-alist '(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_US") nil utf-8)))) (t (setq ispell-program-name nil))) (setq-default ispell-extra-args (flyspell-detect-ispell-args t)) (setq-default flyspell-issue-message-flag nil)) ;; -------- REST Client --------- (use-package restclient :commands (restclient-copy-curl-command restclient-http-send-current restclient-http-send-current-raw restclient-http-send-current-stay-in-window restclient-jump-next restclient-jump-prev restclient-mark-current restclient-mode restclient-narrow-to-current restclient-outline-mode restclient-toggle-body-visibility restclient-toggle-body-visibility-or-indent)) ;; ------- Highlight TODO ------- ;; Remove transpose bindings. I don't have any reasonable use for them ;; and would much rather use them for navigating TODO's. (let ((trans-chars "\C-t");; Transpose (swap) adjacent characters ) (global-unset-key trans-chars)) (use-package hl-todo :commands (hl-todo-mode hl-todo-next hl-todo-occur hl-todo-previous) :hook (prog-mode . hl-todo-mode) :bind (("C-t n" . hl-todo-next) ("C-t p" . hl-todo-previous))) ;; ---- Printer Integration ----- (use-package printing :bind ("M-p" . print-buffer) :commands (print-buffer print-region lpr-buffer lpr-customize lpr-region) :config (pr-update-menus t))