;;; emacs.el --- 10sr emacs initialization ;;; Code: ;; SETUP_LOAD: (load "bytecomp") ;; Required for WSL environment ;; SETUP_LOAD: (let ((file "DOTFILES_DIR/emacs.el")) ;; SETUP_LOAD: (and (file-readable-p file) ;; SETUP_LOAD: (byte-recompile-file file nil 0 t))) ;; TODO: Use custom-set-variables in place of set-variable (setq debug-on-error t) ;; make directories (unless (file-directory-p (expand-file-name user-emacs-directory)) (make-directory (expand-file-name user-emacs-directory))) (require 'cl-lib) (require 'simple) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Some macros for internals (defvar after-first-visit-hook nil "Run only once at the first visit of file.") (defvar after-first-visit-hook--done nil "Non-nil when `after-first-visit-hook' has already been called.") (defun after-first-visit-hook-run () "Run `after-first-visit-hook' and clear its config." (when (not after-first-visit-hook--done) (run-hooks 'after-first-visit-hook)) (setq after-first-visit-hook--done t) (remove-hook 'find-file-hook 'after-first-visit-hook-run)) (add-hook 'find-file-hook 'after-first-visit-hook-run) (defmacro eval-after-init (&rest body) "If `after-init-hook' has been run, run BODY immediately. Otherwize hook it." (declare (indent 0) (debug t)) `(if after-init-time ;; Currently after-init-hook is run just after setting after-init-hook (progn ,@body) (add-hook 'after-init-hook (lambda () ,@body)))) ;; (defmacro safe-require-or-eval (feature) ;; "Require FEATURE if available. ;; At compile time the feature will be loaded immediately." ;; `(eval-and-compile ;; (message "safe-require-or-eval: Trying to require %s" ,feature) ;; (require ,feature nil t))) ;; (defmacro autoload-eval-lazily (feature &optional functions &rest body) ;; "Define autoloading FEATURE that defines FUNCTIONS. ;; FEATURE is a symbol. FUNCTIONS is a list of symbols. If FUNCTIONS is nil, ;; the function same as FEATURE is defined as autoloaded function. BODY is passed ;; to `eval-after-load'. ;; After this macro is expanded, this returns the path to library if FEATURE ;; found, otherwise returns nil." ;; (declare (indent 2) (debug t)) ;; (let* ((libname (symbol-name (eval feature))) ;; (libpath (locate-library libname))) ;; `(progn ;; (when (locate-library ,libname) ;; ,@(mapcar (lambda (f) ;; `(unless (fboundp ',f) ;; (progn ;; (message "Autoloaded function `%S' defined (%s)" ;; (quote ,f) ;; ,libpath) ;; (autoload (quote ,f) ;; ,libname ;; ,(concat "Autoloaded function defined in \"" ;; libpath ;; "\".") ;; t)))) ;; (or (eval functions) ;; `(,(eval feature))))) ;; (eval-after-load ,feature ;; (quote (progn ;; ,@body))) ;; (locate-library ,libname)))) ;; (when (autoload-eval-lazily 'tetris nil ;; (message "Tetris loaded!")) ;; (message "Tetris found!")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; package (set (defvar 10sr-package-list) '( vimrc-mode markdown-mode yaml-mode gnuplot-mode php-mode erlang js2-mode js-doc git-commit gitignore-mode adoc-mode go-mode ;; It seems malabar has been merged into jdee and this package ;; already removed ;; malabar-mode gosh-mode scala-mode web-mode toml-mode json-mode color-moccur ggtags flycheck auto-highlight-symbol hl-todo ;; Currently not available ;; pp-c-l xclip foreign-regexp multi-term term-run editorconfig git-ps1-mode restart-emacs fill-column-indicator pkgbuild-mode minibuffer-line which-key ;; I think this works in place of my autosave lib super-save pipenv imenu-list page-break-lines aggressive-indent dired-filter wgrep magit git-gutter end-mark sl ;; TODO: Configure pony-tpl-mode pony-mode gited highlight-indentation diminish fzf fic-mode term-cursor pydoc swoop color-identifiers-mode dired-k blacken editorconfig editorconfig-custom-majormode git-command prompt-text ;; 10sr repository ;; 10sr-extras terminal-title dired-list-all-mode pack set-modeline-color read-only-only-mode smart-revert autosave ;;window-organizer ilookup pasteboard awk-preview recently )) (require 'package) (set-variable 'package-archives `(,@package-archives ("melpa" . "https://melpa.org/packages/") ;; Somehow fails to download via https ("10sr-el" . "http://10sr.github.io/emacs-lisp/elpa/"))) (package-initialize) (defun my-auto-install-package () "Install packages semi-automatically." (interactive) (package-refresh-contents) (mapc (lambda (pkg) (or (package-installed-p pkg) (package-install pkg))) 10sr-package-list)) ;; (lazy-load-eval 'sudoku) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; my-idle-hook (defvar my-idle-hook nil "Hook run when idle for several secs.") (defvar my-idle-hook-sec 5 "Second to run `my-idle-hook'.") (run-with-idle-timer my-idle-hook-sec t (lambda () (run-hooks 'my-idle-hook))) ;; (add-hook 'my-idle-hook ;; (lambda () ;; (message "idle hook message"))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; start and quit (setq inhibit-startup-message t) (setq initial-buffer-choice 'messages-buffer) (setq confirm-kill-emacs 'y-or-n-p) (setq gc-cons-threshold (* 1024 1024 16)) (setq garbage-collection-messages nil) (when window-system (add-to-list 'default-frame-alist '(cursor-type . box)) (add-to-list 'default-frame-alist '(background-color . "white")) (add-to-list 'default-frame-alist '(foreground-color . "gray10")) ;; (add-to-list 'default-frame-alist '(alpha . (80 100 100 100))) ;; does not work? ) ;; (add-to-list 'default-frame-alist '(cursor-type . box)) (menu-bar-mode 1) (define-key ctl-x-map "M" 'menu-bar-open) (defalias 'menu 'menu-bar-open) (and (fboundp 'tool-bar-mode) (tool-bar-mode 0)) (and (fboundp 'set-scroll-bar-mode) (set-scroll-bar-mode nil)) ?\C-h (eval-after-init (message "%s %s" invocation-name emacs-version) (message "Invocation directory: %s" default-directory) (message "%s was taken to initialize emacs." (emacs-init-time)) ;; (view-echo-area-messages) ;; (view-emacs-news) ) (with-current-buffer "*Messages*" (emacs-lock-mode 'kill)) (cd ".") ; when using windows use / instead of \ in `default-directory' ;; locale (set-language-environment "Japanese") (set-default-coding-systems 'utf-8-unix) (prefer-coding-system 'utf-8-unix) (setq system-time-locale "C") ;; my prefix map (defvar my-prefix-map nil "My prefix map.") (define-prefix-command 'my-prefix-map) (global-set-key (kbd "C-^") 'my-prefix-map) ;; (define-key my-prefix-map (kbd "C-q") 'quoted-insert) ;; (define-key my-prefix-map (kbd "C-z") 'suspend-frame) ;; (comint-show-maximum-output) ;; kill scratch (eval-after-init (let ((buf (get-buffer "*scratch*"))) (when buf (kill-buffer buf)))) ;; modifier keys ;; (setq mac-option-modifier 'control) ;; display (setq visible-bell t) (setq ring-bell-function 'ignore) (mouse-avoidance-mode 'banish) (setq echo-keystrokes 0.1) (defun reload-init-file () "Reload Emacs init file." (interactive) (when (and user-init-file (file-readable-p user-init-file)) (load-file user-init-file))) (require 'session nil t) ;; server (set-variable 'server-name (concat "server" (number-to-string (emacs-pid)))) ;; In Cygwin Environment `server-runnning-p' stops when server-use-tcp is nil ;; In Darwin environment, init fails with message like 'Service name too long' ;; when server-use-tcp is nil (when (or (eq system-type 'cygwin) (eq system-type 'darwin)) (set-variable 'server-use-tcp t)) ;; MSYS2 fix (when (eq system-type 'windows-nt) (setq shell-file-name (executable-find "bash")) '(setq function-key-map `(,@function-key-map ([pause] . [?\C-c]) )) (define-key key-translation-map (kbd "") (kbd "C-c")) '(keyboard-translate [pause] (kbd "C-c")p) ;; TODO: move to other place later (when (not window-system) (setq interprogram-paste-function nil) (setq interprogram-cut-function nil))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; global keys (global-set-key (kbd "") 'scroll-down-line) (global-set-key (kbd "") 'scroll-up-line) (global-set-key (kbd "") 'scroll-down) (global-set-key (kbd "") 'scroll-up) ;; (define-key my-prefix-map (kbd "C-h") help-map) (global-set-key (kbd "C-\\") help-map) (define-key ctl-x-map (kbd "DEL") help-map) (define-key ctl-x-map (kbd "C-h") help-map) (define-key help-map "a" 'apropos) ;; disable annoying keys (global-set-key [prior] 'ignore) (global-set-key (kbd "") 'ignore) (global-set-key [menu] 'ignore) (global-set-key [down-mouse-1] 'ignore) (global-set-key [down-mouse-2] 'ignore) (global-set-key [down-mouse-3] 'ignore) (global-set-key [mouse-1] 'ignore) (global-set-key [mouse-2] 'ignore) (global-set-key [mouse-3] 'ignore) (global-set-key (kbd "") 'ignore) (global-set-key (kbd "C-") 'ignore) ;; Interactively evaluate Emacs Lisp expressions (define-key ctl-x-map "i" 'ielm) (when (fboundp 'which-key-mode) (which-key-mode)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; editor ;; Basically it should not set globally (instead use something like file local ;; variables or editorconfig), but for most cases I just need this... (defun my-set-require-final-newline () "Set `require-final-newline'." (set (make-local-variable 'require-final-newline) mode-require-final-newline)) (add-hook 'prog-mode-hook 'my-set-require-final-newline) (add-hook 'text-mode-hook 'my-set-require-final-newline) (add-hook 'conf-mode-hook 'my-set-require-final-newline) ;; Used from term-cursor ;; hbar is too hard to find... (defun my-cursor-type-change (&rest args) "ARGS are discarded." ;; TODO: Support wdired and wgrep (if buffer-read-only (setq cursor-type 'hbar) (setq cursor-type 'box))) ;; (add-hook 'switch-buffer-functions ;; 'my-cursor-type-change) ;; (add-hook 'read-only-mode-hook ;; 'my-cursor-type-change) ;; (when (fboundp 'global-term-cursor-mode) ;; (global-term-cursor-mode 1)) ;; ;; (term-cursor--eval) (setq kill-whole-line t) (setq scroll-conservatively 35 scroll-margin 2) (setq-default major-mode 'text-mode) (setq next-line-add-newlines nil) (setq kill-read-only-ok t) (setq truncate-partial-width-windows nil) ; when splitted horizontally ;; (setq-default line-spacing 0.2) (setq-default indicate-empty-lines t) ; when using x indicate empty line ;; (setq-default tab-width 4) (setq-default indent-tabs-mode nil) (setq-default indent-line-function 'indent-to-left-margin) ;; (setq-default indent-line-function nil) (setq-default truncate-lines nil) ;; (pc-selection-mode 1) ; make some already defined keybind back to default (delete-selection-mode 1) (cua-mode 0) (setq line-move-visual nil) (setq create-lockfiles nil) (setq set-mark-command-repeat-pop t) (add-hook 'before-save-hook 'time-stamp) ;; Add Time-stamp: <> to insert timestamp there (set-variable 'time-stamp-format "%:y-%02m-%02d %02H:%02M:%02S %Z 10sr") ;; key bindings ;; moving around ;;(keyboard-translate ?\M-j ?\C-j) ;; (global-set-key (kbd "M-p") 'backward-paragraph) (define-key esc-map "p" 'backward-paragraph) ;; (global-set-key (kbd "M-n") 'forward-paragraph) (define-key esc-map "n" 'forward-paragraph) (global-set-key (kbd "C-") 'scroll-down-line) (global-set-key (kbd "C-") 'scroll-up-line) (global-set-key (kbd "C-") 'scroll-down) (global-set-key (kbd "C-") 'scroll-up) (global-set-key (kbd "