diff --git a/config/home/.bashrc.br b/config/home/.bashrc.br new file mode 100644 index 0000000..2b8eecc --- /dev/null +++ b/config/home/.bashrc.br @@ -0,0 +1,194 @@ +#!/usr/bin/env bash +# +# ~/.bashrc.br - user specific initialization +# +# (C) Bruno Raoult ("br"), 2001-2023 +# Licensed under the GNU General Public License v3.0 or later. +# Some rights reserved. See COPYING. +# +# You should have received a copy of the GNU General Public License along with this +# program. If not, see . +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# Usage: to be invoked from .bashrc. +# i.e., add at the end of .bashrc: +# [ -f "$HOME/.bashrc.$USER" ] && . "$HOME/.bashrc.$USER" + +# _remove $1 from PATH +_path_del() { + local _l=":$PATH:" + while [[ $_l =~ :$1: ]]; do + _l=${_l//:$1:/:} + done + _l=${_l%:} + _l=${_l#:} + PATH="$_l" +} + +# _prepend : prepend $1 to PATH. +_path_prepend() { + _path_del "$1" + PATH="$1:$PATH" +} + +# _append : append $1 to PATH. +_path_append() { + _path_del "$1" + PATH="$PATH:$1" +} + +# adjust PATH. Below paths will be added at beginning. +_lpath=("$HOME/bin/$(uname -s)-$(uname -m)" + "$HOME/bin" + "$HOME/.cargo/bin" + "/usr/local/bin") + +# loop array in reverse order. Note: We do not test for path existence and add it +# unconditionally, to avoid automounter interference. +for (( _i = ${#_lpath[@]} - 1; _i >= 0; --_i )); do + _path_prepend "${_lpath[_i]}" +done +unset _lpath +_path_append /usr/games + +# enable core file +ulimit -Sc 102400 # in 1024 bytes, 100Mb + +# ... and set PAGER to less (for man(1) and others) +if hash less 2>/dev/null; then + export PAGER=less + # do not clear screen after "less", exit immediately if one page only + export LESS="-XFB" + # ... and just alias more... to less ;-) + alias more=less +fi + +# no output split for dc and bc / make bc silent +export DC_LINE_LENGTH=0 +export BC_LINE_LENGTH=0 +export BC_ENV_ARGS=--quiet + +# both ubuntu and debian assume we want colors if TERM contains "color" +# this is surely not true, as TERM is often forced by terminal emulator +# shellcheck disable=SC2154 +PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' +case "$TERM" in + xterm*|rxvt*) + PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" + ;; + *) + ;; +esac + +# trim prompt path +export PROMPT_DIRTRIM=3 + +# find a suitable editor +e() { + $VISUAL "$@" +} +export -f e +if hash emacs 2>/dev/null; then + # uncomment below to use full emacs + #export EDITOR=emacs + # ... OR: uncomment below to use emacsclient + #export ALTERNATE_EDITOR="/usr/bin/emacs" + #export EDITOR="emacs.sh" + #alias emacs="emacs.sh" + export ALTERNATE_EDITOR="" + export VISUAL="emacsclient -c" + alias emacs="emacsclient -c" + #alias crontab="VISUAL=emacsclient crontab -e" + #alias crontab="emacs-crontab.sh" +else + # emacs clones, then vim/vi, then... whatever left. + _VISUALS=(zile jed mg vim vi nano ed) + + for e in "${_VISUALS[@]}"; do + if hash "$e" 2>/dev/null; then + export VISUAL="$e" + break + fi + done + unset _VISUALS +fi +export EDITOR=$VISUAL + +# append to the history file, don't overwrite it +shopt -s histappend +# write history after each command +export PROMPT_COMMAND="history -a" + +# Add timestamp in history +export HISTTIMEFORMAT="%d/%m %H:%M " +# ignore history dups, delete all previous dups +export HISTCONTROL=ignoredups:erasedups +# history size +HISTSIZE=5000 +HISTFILESIZE=5000 + +# remove new stupid Debian "ls" quoting, and colors... +# Many complains, one of them: +# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=813164#226 +export QUOTING_STYLE=literal +[[ -v BASH_ALIASES[ls] ]] && unalias ls + +# avoid these stupid systemd defaults (horizontal scroll and pager) +alias systemctl="systemctl --no-pager --full" + +# aliases for ls and history +alias l='ls -F' +alias ls='ls -F' +alias l1='ls -1F' +alias la='ls -aF' +alias ll='ls -lF' +alias lla='ls -laF' +alias ldl='ls -l | grep ^d' +[[ -v BASH_ALIASES[lrt] ]] && unalias lrt +lrt() { + local -i _l=20 + if (( $# > 0 )) && [[ $1 =~ [[:digit:]]+ ]]; then + _l="$1" + shift + fi + # shellcheck disable=2012 + ls -lrt "${1:-.}" | tail -"$_l" +} +[[ -v BASH_ALIASES[lart] ]] && unalias lart +lart() { + local -i _l=20 + if (( $# > 0 )) && [[ $1 =~ [[:digit:]]+ ]]; then + _l="$1" + shift + fi + # shellcheck disable=2012 + ls -laFrt "${1:-.}" | tail -"$_l" +} + +alias h="history 10" # short +alias hl="history 25" # long +alias hll="history 100" # very long +alias hlll="history" # all history + +# user temp directory +export USERTMP=~/tmp + +# :) +alias fuck='sudo $(history -p \!\!)' + +# french-> english and english->french translation +alias trans="trans.sh" +alias rtrans="trans.sh -fen -tfr" + +# host specific initialization +# shellcheck disable=SC1090 +[ -f "$HOME/.bashrc.$USER.$(hostname)" ] && . "$HOME/.bashrc.$USER.$(hostname)" + +# Indent style for emacs +# Local Variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indentation: 4 +# indent-tabs-mode: nil +# End: diff --git a/config/home/.bashrc.br.lorien b/config/home/.bashrc.br.lorien new file mode 100644 index 0000000..9a4d720 --- /dev/null +++ b/config/home/.bashrc.br.lorien @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# +# ~/.bashrc.br.lorien - host specific initialization +# +# (C) Bruno Raoult ("br"), 2001-2023 +# Licensed under the GNU General Public License v3.0 or later. +# Some rights reserved. See COPYING. +# +# You should have received a copy of the GNU General Public License along with this +# program. If not, see . +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# Usage: to be invoked from .bashrc.$USER +# i.e., add at the end of .bashrc.$USER: +# [ -f "$HOME/.bashrc.$USER.$(hostname)" ] && . "$HOME/.bashrc.$USER.$(hostname)" + +# look for a pdf viewer +hash atril 2> /dev/null && alias acroread=atril + +# mysql aliases. Will match any "[client-XXX]" lines in ~/.my.cnf +# and generate "myXXX" aliases. +if [[ -r ~/.my.cnf ]]; then + mapfile -t MYSQL_ARRAY < ~/.my.cnf + + for line in "${MYSQL_ARRAY[@]}"; do + if [[ $line =~ ^\[client-(.+)\]$ ]]; then + SUFFIX="${BASH_REMATCH[1]}" + # shellcheck disable=SC2139,SC2140 + alias my"$SUFFIX"="mysql --defaults-group-suffix=-$SUFFIX" + fi + done +fi + +# shortcuts to commonly used directories +# alias dev="cd ~/dev/www/cf.bodi" # Clash of Clans +alias eud="cd ~/dev/eudyptula; . ./bin/ENV.sh" # Eudyptula +alias aoc="cd ~/dev/advent-of-code/2022/; . ../env.sh" # Advent of Code +alias wchess="cd ~/dev/www/com.raoult/devs/chess" # raoult.com chess +alias chess="cd ~/dev/brchess; . env.sh" # brchess +alias tools="cd ~/dev/tools" # tools + +# Indent style for emacs +# Local Variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indentation: 4 +# indent-tabs-mode: nil +# End: diff --git a/config/home/.emacs.d/init.el b/config/home/.emacs.d/init.el new file mode 100755 index 0000000..eab6a97 --- /dev/null +++ b/config/home/.emacs.d/init.el @@ -0,0 +1,2444 @@ +;;;; ~/.Emacs.d/init.el +;;;; +;;;; emacs configuration +;;;; br, 2010-2020 +;;;; +;;;; all personal variables/defun are prefixed with "my/". +;; +;; +;; TODO +;; paredit: see https://takeokunn.github.io/.emacs.d/ +;; +;;; Code: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; packages/directories setup +(require 'package) +;; (require 'use-package) +(package-initialize) +(setq use-package-always-ensure t) + +(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) +;;(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/")) +;;(add-to-list 'package-archives '("ox-odt" . "https://kjambunathan.github.io/elpa/")) + +;; set package directory & recompile lisp files in user-emacs-directory +(add-to-list 'load-path (concat user-emacs-directory "lisp/")) +(add-to-list 'load-path "~/data/private/") + +;; (byte-recompile-directory user-emacs-directory 0 t) + +;; need to check +;;(require 'prog-mode) + +;; store backup and auto-saved buffers (file~ and .#file#) in ~/tmp/emacs +(defconst my/emacs-tmpdir "~/tmp/emacs" + "Directory where to store all temp and backup files.") +(setq backup-directory (concat my/emacs-tmpdir "/backups/") + save-directory (concat my/emacs-tmpdir "/autosave/") + auto-save-list-file-prefix (concat my/emacs-tmpdir "/autosave-list/") + ) + +;; create dirs if necessary +(dolist (dir (list backup-directory save-directory auto-save-list-file-prefix)) + (if (not (file-exists-p dir)) + (make-directory dir t))) + +;; backup settings +(setq backup-directory-alist `(("." . ,backup-directory)) + make-backup-file t ; make backup when first saving + delete-old-versions t ; removes old versions silently + kept-old-versions 10 ; how many to keep (oldest) + kept-new-versions 10 ; how many to keep (newest) + backup-by-copying 1 ; to avoid link issues, backups are copied + version-control t ; numbered backups + ) +;; auto-save settings +(setq auto-save-file-name-transforms `((".*" ,save-directory t)) + auto-save-timeout 60 ; seconds idle before auto-save + auto-save-interval 200 ; keystrokes between auto-saves + ) +;; backup tramp files locally +(add-to-list 'backup-directory-alist + (cons tramp-file-name-regexp backup-directory)) + +;; disable lockfiles +(setq create-lockfiles nil) + +;; external editing in firefox +(require 'atomic-chrome) +(atomic-chrome-start-server) + +;; *scratch* & *Messages* are immortal +(add-hook 'kill-buffer-query-functions + (lambda () (not (member (buffer-name) + '("*scratch*" "*Messages*"))))) + +;; allow remembering risky variables +(defun risky-local-variable-p (sym &optional _ignored) "Zoba SYM." nil) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; swap modifier keysyms (japanese keyboard) +;; windows key (super) becomes hyper +;;(setq x-super-keysym 'hyper) +;; alt key (meta) becomes super +;;(setq x-meta-keysym 'super) +;; muhenkan key (hyper) becomes meta +;;(setq x-hyper-keysym 'meta) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; crontabs handling +;; The idea: copy crontab entries to temp buffer, and +;; send back current buffer to "crontab" + +(defun my/edit-root-crontab () + "Edit root crontab." + (interactive) + (with-editor-async-shell-command "crontab -e")) + +(defvar my/crontabs-dir + (concat my/emacs-tmpdir "/crontabs/" (number-to-string (user-uid))) + "The directory in which to place the crontabs.") +;;(format "%s/emacs-cron" (or (getenv "TMPDIR") "/tmp") (user-uid))) + +(defun my/edit-crontab () + "Edit current user crontab." + (interactive) + (setq cronBuf (get-buffer "br-crontab")) + (when (not + (and cronBuf + (buffer-live-p cronBuf))) + ;;(not cronBuf) + ;;() + (message "creating br-crontab") + (setq cronBuf (get-buffer-create "br-crontab")) + (set-buffer cronBuf) + (crontab-mode) + (insert (shell-command-to-string "crontab -l")) + (set-buffer-modified-p nil) + (goto-char (point-min))) + (pop-to-buffer-same-window cronBuf)) + + +(defun my/crontab-e () + "Run `crontab -e' in an Emacs buffer. Use 'kill-buffer' on crontab window to validate." + (interactive) + (with-editor-async-shell-command "crontab -e")) + +(defun my/root-crontab-e () + "Run `crontab -e -u root' in an Emacs buffer. Use 'kill-buffer' on crontab window to validate." + (interactive) + (with-editor-async-shell-command "sudo -E crontab -e -u root")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lisp tools +(defun my/append-to-list (list-var elements) + "Append ELEMENTS to the end of LIST-VAR. Return new LIST-VAR value." + (unless (consp elements) + (error "ELEMENTS must be a list")) + (let ((list (symbol-value list-var))) + (if list + (setcdr (last list) elements) + (set list-var elements))) + (symbol-value list-var)) + + +(defun my/add-to-list (list-var elements &optional uniq) + "Add ELEMENTS to the beginning LIST-VAR, remove duplicates if UNIQ is true. +Return new LIST-VAR value." + (unless (consp elements) + (error "ELEMENTS must be a list")) + (set list-var (append elements (symbol-value list-var))) + (and uniq + (delete-dups (symbol-value list-var))) + (symbol-value list-var)) + +;; don't remember what it was about. Saturday night wine idea ? +(defun my/str-replace-all (str alist) + "Given an ALIST of the form '((a1 . a2)(b1 . b2)), will return a1 or b1 if STR equals a2 or b2." + (if (null alist) + str + (let* ((elem (car alist)) + (lhs (car elem)) + (rhs (cdr elem))) + ;;(message str) + ;;(message lhs) + ;;(message rhs) + ;;(message "+++++++") + (replace-regexp-in-string rhs lhs (my/str-replace-all str (cdr alist)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; buffer names +;; shorten tramp sudo +;;(my/add-to-list +;; 'directory-abbrev-alist +;; '(("^root:/" . "/ssh:arwen:/home/br/www/cf.bodi/seven/") +;; ("arwen:rebels:/" . "/ssh:arwen:/home/br/www/cf.bodi/rebels21/") +;; ("arwen:strats:/" . "/ssh:arwen:/home/br/www/cf.bodi/strat-dom/"))) + +;; Buffer name in status bar +(require 'uniquify) +(setq uniquify-buffer-name-style 'forward ; display finename as dir1/dir2/file + uniquify-min-dir-content 0 ; minimum # of dirs in name + uniquify-strip-common-suffix t ; strip dirs suffixes if conflict + ) + +;; set main frame title +(set-frame-name "GNU Emacs") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ibuffer -- NOT USED: Using Helm +(defun my/ibuffer-hook () + "br ibuffer-hook." + (interactive) + (ibuffer-tramp-set-filter-groups-by-tramp-connection) + (ibuffer-do-sort-by-alphabetic)) + +(define-ibuffer-column dirname + (:name "Directory" + :inline nil) + (message (buffer-file-name buffer)) + (if (buffer-file-name buffer) + (my/str-replace-all + (file-name-directory + (buffer-file-name buffer)) + directory-abbrev-alist) + (or dired-directory + ""))) +;; (global-set-key (kbd "C-x C-b") 'ibuffer) +;; (global-set-key (kbd "C-x b") 'ibuffer) + +;; original value +;; (setq ibuffer-formats +;; '((mark modified read-only " " +;; (name 18 18 :left :elide) +;; " " +;; (size 9 -1 :right) +;; " " +;; (mode 16 16 :left :elide) +;; " " filename-and-process) +;; (mark " " +;; (name 16 -1) +;; " " filename))) + +(setq ibuffer-formats + '((mark modified " " + (name 18 18 :right :elide) + " " + (size 9 -1 :right) + " " + (mode 16 16 :left :elide) + " " filename-and-process) + (mark " " + (name 16 -1) + " " filename + ) + (mark modified read-only " " + (name 30 30 :left :elide) + " " + (size 9 -1 :right) + " " dirname) + )) + +(add-hook 'ibuffer-hook 'my/ibuffer-hook) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; package auto update +(use-package auto-package-update + :if (not (daemonp)) + :custom + (auto-package-update-interval 7) ; in days + (auto-package-update-prompt-before-update t) + (auto-package-update-delete-old-versions t) + (auto-package-update-hide-results t) + :config + (auto-package-update-maybe)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; command-log-mode +;;(use-package command-log-mode +;; :straight t +;; :defer t) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ggtags +(use-package ggtags + :ensure t + :diminish ggtags-mode + :disabled t + :defer t + :init + (setq ggtags-global-window-height 28 + ggtags-enable-navigation-keys nil) + + (after cc-mode (add-hook 'c-mode-common-hook #'ggtags-mode)) + + :config + (bind-keys :map ggtags-mode-map + ("C-c g s" . ggtags-find-other-symbol) + ("C-c g h" . ggtags-view-tag-history) + ("C-c g r" . ggtags-find-reference) + ("C-c g f" . ggtags-find-file) + ("C-c g c" . ggtags-create-tags) + ("C-c g u" . ggtags-update-tags) + ("M-," 'pop-tag-mark))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; projectile +;; default config from developer +(use-package projectile + ;;:diminish projectile-mode + :diminish " prj" + :ensure t + :config + ;;(define-key projectile-mode-map (kbd "s-p") 'projectile-command-map) + ;;(define-key projectile-mode-map (kbd "s-p") 'projectile-command-map) + (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map) + (setq projectile-enable-caching t + ;;projectile-indexing-method 'alien ;; does not use ".projectile" + projectile-indexing-method 'hybrid + ;;projectile-indexing-method 'native + projectile-completion-system 'default) + (add-to-list 'projectile-globally-ignored-files "*.png") + (projectile-mode +1)) + +;; (add-to-list 'projectile-globally-ignored-files "node-modules") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; git +;; (use-package forge +;; :after magit) +(use-package magit + :ensure t + :config + (setq magit-delete-by-moving-to-trash nil + magit-clone-default-directory "~/dev/") + (magit-auto-revert-mode -1)) + + +(use-package git-gutter + :diminish + :config + (global-git-gutter-mode +1)) + +;; (use-package magithub +;; :after magit +;; ;;:ensure t +;; :config +;; (progn +;; (magithub-feature-autoinject t) +;; ;; (magithub-feature-autoinject '(commit-browse completion)) +;; (setq +;; magithub-clone-default-directory "~/dev"))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; delight +(use-package autorevert + :delight auto-revert-mode) +(use-package whole-line-or-region + :delight whole-line-or-region-local-mode) +;;(use-package abbrev +;; :delight abbrev-mode) +(use-package emacs + :delight + ;; (auto-fill-function " AF") + (auto-fill-function) + (abbrev-mode) + (visual-line-mode)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; tramp +(setq tramp-default-method "ssh" ; faster than default scp + enable-remote-dir-locals t + tramp-verbose 1) +;; (customize-set-variable 'tramp-syntax 'simplified) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; conf mode +;; strangely ".cnf" is not here... +(use-package conf-mode + :hook + (conf-mode . my/conf-mode-hook) + :mode + (("\\.cnf\\'" . conf-mode) + ("/auto\\." . conf-mode)) + :config + (defun my/conf-mode-hook () + (message "calling my/conf-mode-hook") + (setq-local comment-column 50))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ssh config +(use-package ssh-config-mode + :ensure t + :init + (autoload 'ssh-config-mode "ssh-config-mode" t) + :mode + (("/\\.ssh/config\\'" . ssh-config-mode) + ("/sshd?_config\\'" . ssh-config-mode) + ("/known_hosts\\'" . ssh-known-hosts-mode) + ("/authorized_keys2?\\'" . ssh-authorized-keys-mode)) + :hook + (ssh-config-mode . turn-on-font-lock)) + +;; (autoload 'ssh-config-mode "ssh-config-mode" t) +;; (add-to-list 'auto-mode-alist +;; '("/\\.ssh/config\\'" . ssh-config-mode)) +;; (add-to-list 'auto-mode-alist +;; '("/sshd?_config\\'" . ssh-config-mode)) +;; (add-to-list 'auto-mode-alist +;; '("/knownhosts\\'" . ssh-known-hosts-mode)) +;; (add-to-list 'auto-mode-alist +;; '("/authorized_keys2?\\'" . ssh-authorized-keys-mode)) +;; (add-hook 'ssh-config-mode-hook 'turn-on-font-lock) + +;; following does not work +;;(set-default 'tramp-default-proxies-alist +;; '("arwen" "root" "/ssh:arwen:")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; which-key +(use-package which-key + :diminish which-key-mode + :init + (which-key-mode) + :config + (which-key-setup-side-window-right-bottom) + (setq which-key-sort-order 'which-key-key-order-alpha + which-key-side-window-max-width 0.33 + which-key-idle-delay 1)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; flycheck +(use-package flycheck + :ensure t + :init + (require 'projectile) + (global-flycheck-mode) + :config + (setq-default flycheck-sh-bash-args '("-O" "extglob") + flycheck-disabled-checkers '(c/c++-clang c/c++-cppcheck c/c++-gcc)) + ;;(flycheck-add-mode 'sh-shellcheck 'bats-mode) + + :bind + (("H-n" . flycheck-next-error) + ("H-p" . flycheck-previous-error) + ("H-l" . flycheck-list-errors) + ("M-n" . flycheck-next-error) + ("M-p" . flycheck-previous-error))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; subversion +;;(require 'psvn) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Japanese/iBus: works out of the box now +;; ibus-mode +;;(require 'ibus) +;; Turn on ibus-mode automatically after loading .emacs +;;(add-hook 'after-init-hook 'ibus-mode-on) +;; Use C-SPC for Set Mark command +;;(ibus-define-common-key ?\C-\s nil) +;; Use C-/ for Undo command +;;(ibus-define-common-key ?\C-/ nil) +;; Change cursor color depending on IBus status +;;(setq ibus-cursor-color '("red" "blue" "limegreen")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Some useful setups +;; mouse +;; does not change point when getting focus - DOES NOT WORK +;;x-mouse-click-focus-ignore-position t +;;focus-follows-mouse nil ; must reflect WM settings +;;mouse-autoselect-window nil ; pointer does not select window + +(global-set-key (kbd "C-h c") 'describe-char) +(global-set-key (kbd "C-x 4 C-b") 'switch-to-buffer-other-window) + +;; next example maps C-x C-x to the same as C-c +;; (global-set-key (kbd "C-x C-x") (lookup-key global-map (kbd "C-c"))) + +(setq inhibit-splash-screen t ; no spash screen + column-number-mode t ; displays line/column positions + kill-whole-line t ; C-k kills whole line + + ;; tab indents first, if indented, tries to autocomplete + ;; TOO DANGEROUS (it completes without asking!)... + ;; tab-always-indent t ; TAB always indent + tab-always-indent 'complete + completions-format 'vertical ; sort completions vertically + + ;; Removed: Use smartparens instead. + ;; show matching brace/paren + ;;show-paren-mode t + ;; style: parenthesis, expression, mixed + ;;show-paren-style 'parenthesis + + sentence-end-double-space nil ; who decided sentences should + ; end with two spaces ?? + ;; global-hl-line-sticky-flag t ; highlight line + tab-width 2 ; default tab width + ) + +(setq-default indent-tabs-mode nil) + +(icomplete-mode 0) ; minibuffer completion + ; soooo sloooow + +;; (global-hl-line-mode) ; line highlight + +(delete-selection-mode 1) ; replace region when inserting text + +;; fix mess with bidirectional (arabic/hebrew) +(setq-default bidi-display-reordering nil + bidi-paragraph-direction 'left-to-right) + +(setq display-time-24hr-format t) ; time format +(display-time-mode 0) ; disable time in the mode-line + +(defalias 'yes-or-no-p 'y-or-n-p) ; just 'y' or 'n' instead of yes/no + +(mouse-avoidance-mode 'exile) ; Avoid collision of mouse with point + +;;(menu-bar-mode 0) ; Disable the menu bar +;;(put 'downcase-region 'disabled nil) ; Enable downcase-region +;;(put 'upcase-region 'disabled nil) ; Enable upcase-region +;;(global-subword-mode 1) ; Iterate through CamelCase words +;;(fringe-mode 0) ; Disable fringes +(set-default-coding-systems 'utf-8) ; default encoding - obviously utf-8 + +;; enable recursive minibuffer +(minibuffer-depth-indicate-mode) +(setq enable-recursive-minibuffers t) + +;; copy from point to end of line (including '\n') +(defun my/mark-from-point-to-end-of-line () + "Copy text from point to end of line." + (interactive) + (set-mark (+ (line-end-position) 1)) + (kill-ring-save nil nil t)) + +(global-set-key (kbd "M-k") 'my/mark-from-point-to-end-of-line) +;; (global-set-key (kbd "C-k") 'kill-line) + + +;; minions: minor modes menu instead of (long) list on modeline +;;(use-package minions +;; :config (minions-mode 1)) + +;;(defun caadr (a) +;; (car(car(cdr a)))) +;;(defun mouse-set-point-2 (event) +;; (interactive "e") +;; (mouse-minibuffer-check event) +;; (let ((event-target-window (caadr event))) +;; (if (eql event-target-window (frame-selected-window)) +;; (posn-set-point (event-end event)) +;; (set-frame-selected-window nil event-target-window)))) +;; +;;(global-set-key [mouse-1] 'mouse-set-point-2) +;; +;;(global-unset-key [down-mouse-1]) + +;;(defadvice mouse-set-point (around cv/mouse-set-point (event) activate) +;; (let ((event-name (car event)) +;; (event-target-window (posn-window (event-start event)))) +;; (if (and (eql 'down-mouse-1 event-name) +;; (eql event-target-window (selected-window))) +;; ad-do-it +;; (select-window event-target-window)))) + +;; (defadvice mouse-drag-region (around cv/mouse-drag-region (event) activate) +;; (let ((event-target-window (posn-window (event-start event)))) +;; ; (if (eql event-target-window (selected-window)) +;; ; ad-do-it +;; ; (select-window event-target-window)))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; local functions +(defun my/indent-whole-buffer () + "Indent whole buffer. TODO: indent comments." + (interactive) + ;; (delete-trailing-whitespace) + ;; (untabify (point-min) (point-max)) + (indent-region (point-min) (point-max) nil)) + +(global-set-key (kbd "H-;") 'my/indent-whole-buffer) +(global-set-key (kbd "H-\\") 'my/indent-whole-buffer) + +(defvar my/temp-buffer-count 0) + +(defun my/make-temp-buffer (&optional mode) + "Create new temporary buffer named '*temp-digit*' with MODE mode (default: text)." + (interactive) + (let ((tmp (format "*temp-%d*" my/temp-buffer-count)) + (dir (concat my/emacs-tmpdir "/tmpbufs/"))) + (switch-to-buffer tmp) + (cd dir) + (if mode + (mode) + (text-mode)) + (message "New temp buffer (%s) created." tmp)) + (setq my/temp-buffer-count (1+ my/temp-buffer-count))) + +(global-set-key (kbd "C-c t") 'my/make-temp-buffer) + +(defun my/write-visit-file () + "Write current buffer/region to file, and visit it." + (interactive) + (let ((thefile (read-file-name + "Copy/visit file: " nil nil nil))) + (if (use-region-p) + (write-region (region-beginning) (region-end) thefile nil nil nil t) + (save-restriction + (widen) + (write-region (point-min) (point-max) thefile nil nil nil t))) + (find-file-noselect thefile))) + +(global-set-key (kbd "C-c w") 'my/write-visit-file) + +(defun my/before-save () + "Remove trailing spaces, remove 'org-mode' results blocks." + (delete-trailing-whitespace) + (when (derived-mode-p 'org-mode) + (org-babel-map-src-blocks nil (org-babel-remove-result)))) + +(add-hook 'before-save-hook 'my/before-save) +;;(global-set-key (kbd "C-c w") 'my/write-visit-file) + +;;; from https://github.com/zilongshanren/prelude/blob/master/core/prelude-core.el +(defun my/delete-buffer-and-file () + "Kill the current buffer and deletes the file it is visiting." + (interactive) + (let ((filename (buffer-file-name))) + (when filename + (if (vc-backend filename) + (vc-delete-file filename) + (when (y-or-n-p (format "Are you sure you want to delete %s? " filename)) + (delete-file filename) + (message "Deleted file %s" filename) + (kill-buffer)))))) + +(global-set-key (kbd "s-d") 'my/delete-buffer-and-file) + +;; from https://pages.sachachua.com/.emacs.d/Sacha.html +(defun my/smarter-move-beginning-of-line (arg) + "Move point back to indentation of beginning of line. + +Move point to the first non-whitespace character on this line. +If point is already there, move to the beginning of the line. +Effectively toggle between the first non-whitespace character and +the beginning of the line. + +If ARG is not nil or 1, move forward ARG - 1 lines first. If +point reaches the beginning or end of the buffer, stop there." + (interactive "^p") + (setq arg (or arg 1)) + + ;; Move lines first + (when (/= arg 1) + (let ((line-move-visual nil)) + (forward-line (1- arg)))) + + (let ((orig-point (point))) + (back-to-indentation) + (when (= orig-point (point)) + (move-beginning-of-line 1)))) + +;; remap C-a to `smarter-move-beginning-of-line' +(global-set-key [remap move-beginning-of-line] + 'my/smarter-move-beginning-of-line) + +;;(defun my/upcase-word() +;; "Upcase current word." +;; (interactive) +;; (save-excursion +;; (let* ((bounds (bounds-of-thing-at-point 'word)) +;; (beg (car bounds)) +;; (end (cdr bounds))) +;; (upcase-region beg end)))) + +;; redefine upcase/downcase-word to really do it. +(defun my/upcase-word() + "Upcase current word." + (interactive) + (save-excursion + (beginning-of-thing 'word) + (upcase-word 1))) + +(defun my/downcase-word() + "Downcase current word." + (interactive) + (save-excursion + (beginning-of-thing 'word) + (downcase-word 1))) + +(global-set-key (kbd "M-u") 'my/upcase-word) +(global-set-key (kbd "M-l") 'my/downcase-word) + +;; rewrite comment-kill to avoid filling kill-ring +;; From: https://emacs.stackexchange.com/a/5445/23591 +;; https://emacs.stackexchange.com/questions/5441/function-to-delete-all-comments-from-a-buffer-without-moving-them-to-kill-ring +(defun my/comment-delete (arg) + "Delete the first comment on this line, if any. Don't touch the kill ring. +With prefix ARG, delete comments on that many lines starting with this one." + (interactive "P") + (comment-normalize-vars) + (dotimes (_i (prefix-numeric-value arg)) + (save-excursion + (beginning-of-line) + (let ((cs (comment-search-forward (line-end-position) t))) + (when cs + (goto-char cs) + (skip-syntax-backward " ") + (setq cs (point)) + (comment-forward) + ;; (kill-region cs (if (bolp) (1- (point)) (point))) ; original + (delete-region cs (if (bolp) (1- (point)) (point))) ; change to delete-region + (indent-according-to-mode)))) + (if arg (forward-line 1)))) + +(defun my/comment-delete-dwim (beg end arg) + "Delete comments without touching the kill ring. +With active region, delete comments in region. With prefix, delete comments +in whole buffer. With neither, delete comments on current line." + (interactive "r\nP") + (let ((lines (cond (arg + (count-lines (point-min) (point-max))) + ((region-active-p) + (count-lines beg end))))) + + (save-excursion + (when lines + (goto-char (if arg (point-min) beg))) + (my/comment-delete (or lines 1))))) + +;; kill remove all consecutive blank lines (keep one only). +(defun my/single-blank-lines () + "Keep only one blank lines in buffer, keep one when multiple ones." + (interactive) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "\\(^[[:space:]\n]+\\)\n" nil t) + (replace-match "\n")))) + +(defun my/collapse-blank-lines (beg end) + "Delete all consecutive `blank' lines in region or buffer, keeping one only." + (interactive "r") + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "\\(^[[:space:]\n]+\\)\n" nil t) + (replace-match "\n")))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; shell, eshell modes +;; will tell e-shell to run in visual mode +'(eshell-visual-commands + (quote + ("vi" "screen" "top" "less" "more"))) + +;; ignore duplicate input in shell-mode +(use-package shell + :config + (progn + (setq comint-input-ignoredups t))) + +;; https://www.emacswiki.org/emacs/SwitchingBuffers +(defun my/switch-buffers () + "Switch the buffers between the two last frames." + (interactive) + (let ((this-frame-buffer nil) + (other-frame-buffer nil)) + (setq this-frame-buffer (car (frame-parameter nil 'buffer-list))) + (other-frame 1) + (setq other-frame-buffer (car (frame-parameter nil 'buffer-list))) + (switch-to-buffer this-frame-buffer) + (other-frame 1) + (switch-to-buffer other-frame-buffer))) + +(defun my/switch-upper-window () + "Switch main window and upper one." + (interactive) + (window-swap-states my/main-window my/upper-window)) +(defun my/switch-lower-window () + "Switch main window and lower one." + (interactive) + (window-swap-states my/main-window my/below-window)) + +(global-set-key (kbd "C-c u") 'my/switch-upper-window) +(global-set-key (kbd "C-c l") 'my/switch-lower-window) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; recent files +(require 'recentf) +(setq recentf-max-saved-items 20 + recentf-max-menu-items 10) +(recentf-mode) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vc-mode modeline +;; inspired from: +;; https://emacs.stackexchange.com/questions/10955 +(advice-add #'vc-git-mode-line-string :filter-return #'my-replace-git-status) +(defun my-replace-git-status (tstr) + "Replace git `variable:vc-mode' string, for a modified icon followed by TSTR without \"git\"." + (let* ((tstr (replace-regexp-in-string "Git" "" tstr)) + (first-char (substring tstr 0 1)) + (rest-chars (substring tstr 1))) + (cond + ((string= ":" first-char) ; Modified + (replace-regexp-in-string "^:" "⚡️" tstr)) + ((string= "-" first-char) ; No change + (replace-regexp-in-string "^-" "✔️" tstr)) + ((string= "@" first-char) ; Added + (replace-regexp-in-string "^@" "️✑" tstr)) + (t tstr)))) + +(setf mode-line-modes + (mapcar (lambda (item) + (if (and (listp item) + (eq :propertize (car item)) + (listp (cdr item)) + (string= "" (car (cadr item))) + (eq 'mode-name (cadr (cadr item)))) + (cl-list* (car item) + '(:eval (if (eq 'sh-mode major-mode) + '("" sh-shell) + '("" mode-name))) + (cddr item)) + item)) + mode-line-modes)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hippie +;; (setq hippie-expand-try-functions-list +;; '(yas-hippie-try-expand +;; try-expand-all-abbrevs +;; try-complete-file-name-partially +;; try-complete-file-name +;; try-expand-dabbrev +;; try-expand-dabbrev-from-kill +;; try-expand-dabbrev-all-buffers +;; try-expand-list +;; try-expand-line +;; try-complete-lisp-symbol-partially +;; try-complete-lisp-symbol)) + +;; (use-package yasnippet +;; :diminish yas-minor-mode +;; :init (yas-global-mode) +;; :config +;; (progn +;; (yas-global-mode) +;; (add-hook 'hippie-expand-try-functions-list 'yas-hippie-try-expand) +;; (setq yas-key-syntaxes '("w_" "w_." "^ ")) +;; ;;(setq yas-installed-snippets-dir (concat user-emacs-directory "yassnippet")) +;; (setq yas-expand-only-for-last-commands nil) +;; (yas-global-mode 1) +;; (bind-key "\t" 'hippie-expand yas-minor-mode-map) +;; (add-to-list 'yas-prompt-functions 'shk-yas/helm-prompt))) + +;; (use-package yasnippet-snippets +;; :after (yasnippet) +;; :defer t +;; :config +;; (yas-global-mode 1)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; key Bindings +(global-set-key (kbd "") 'my/indent-whole-buffer) +;;(global-set-key (kbd "C-a") 'back-to-indentation) + +;; https://github.com/technomancy/better-defaults/blob/master/better-defaults.el#L78 +(global-set-key (kbd "M-/") 'hippie-expand) +(global-set-key (kbd "M-z") 'zap-up-to-char) +(global-set-key (kbd "C-s") 'isearch-forward-regexp) +(global-set-key (kbd "C-r") 'isearch-backward-regexp) +;; (global-set-key (kbd "C-M-s") 'isearch-forward) ; conflict with org +;; (global-set-key (kbd "C-M-r") 'isearch-backward) + +;; goto-line/goto-char +;; (global-set-key (kbd "C-c g") 'goto-line) +;; (global-set-key (kbd "C-c c") 'goto-char) +(global-set-key (kbd "s-g g") 'goto-line) +(global-set-key (kbd "s-g c") 'goto-char) +(global-set-key (kbd "s-g s-g") 'goto-line) +(global-set-key (kbd "s-g s-c") 'goto-char) + +(global-set-key (kbd "C-x w") 'compare-windows) + +;; multiple cursors +(global-set-key (kbd "C->") 'mc/mark-next-like-this) +(global-set-key (kbd "C-<") 'mc/mark-previous-like-this) +(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this) +(global-set-key (kbd "C-S-") 'mc/add-cursor-on-click) +(global-set-key (kbd "C-M-m") 'mc/mark-all-dwim) + +(global-set-key (kbd "C-x g") 'magit-status) + +;; (global-set-key (kbd "s-SPC") 'delete-blank-lines) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; define my own keymap (s-c) +;; first, define a keymap, with Super-c as prefix. +(defvar my/keys-mode-map (make-sparse-keymap) + "Keymap for my/keys-mode.") + +(defvar my/keys-mode-prefix-map (lookup-key global-map (kbd "s-c")) + "Keymap for custom key bindings starting with s-c prefix.") + +;; (define-key my/keys-mode-map (kbd "s-c") my/keys-mode-prefix-map) + +(define-minor-mode my/keys-mode + "A minor mode for custom key bindings." + :lighter "s-c" + :keymap 'my/keys-mode-map + :global t) + +(defun my/prioritize-keys + (file &optional noerror nomessage nosuffix must-suffix) + "Try to ensure that custom key bindings always have priority." + (unless (eq (caar minor-mode-map-alist) 'my/keys-mode) + (let ((my/keys-mode-map (assq 'my/keys-mode minor-mode-map-alist))) + (assq-delete-all 'my/keys-mode minor-mode-map-alist) + (add-to-list 'minor-mode-map-alist my/keys-mode-map)))) + +(advice-add 'load :after #'my/prioritize-keys) + +;;(global-set-key (kbd "C-c t") #'make-temp-buffer) +;;(define-key my/keys-mode-prefix-map (kbd "r b") #'revert-buffer) +;;(define-key my/keys-mode-prefix-map (kbd "r b") 'revert-buffer) + +;;(define-key ctl-x-map ";" 'indent-region) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; helm +;; Partially from http://pages.sachachua.com/.emacs.d/Sacha.html#org480d137 +;; and http://tuhdo.github.io/helm-intro.html +(use-package helm + :diminish helm-mode + :init + ;;(progn + ;;(require 'helm-config) + ;;(require 'helm-autoloads) + (require 'pcomplete) + (require 'helm-projectile) + (setq + helm-candidate-number-limit 100 + ;; From https://gist.github.com/antifuchs/9238468 + helm-split-window-inside-p t ; open helm buffer in current window + + helm-idle-delay 0.0 ; update fast sources immediately (doesn't). + helm-input-idle-delay 0.01 ; this actually updates things + ; reeeelatively quickly. + helm-yas-display-key-on-candidate t + helm-quick-update t + helm-M-x-requires-pattern nil + helm-ff-skip-boring-files t + helm-ff-guess-fap-urls nil ; do not use ffap for URL at point + + helm-projectile-fuzzy-match nil + + helm-buffers-truncate-lines nil ; truncate lines in buffers list + helm-buffer-max-length nil ; buffer name length is longest one + helm-prevent-escaping-from-minibuffer nil ; allow escaping from minibuffer (C-o) + helm-scroll-amount 8 ; scroll 8 lines other window M- + + helm-ff-file-name-history-use-recentf t + helm-echo-input-in-header-line t) ; ?? + ;;) + (helm-mode) + (helm-projectile-on) + ;;) + :bind + (("C-c h" . helm-mini) + ("C-h a" . helm-apropos) + ("C-x C-b" . helm-buffers-list) + ("C-x C-f" . helm-find-files) + ("C-x b" . helm-buffers-list) + ("M-y" . helm-show-kill-ring) + ("M-x" . helm-M-x) + ("C-x c o" . helm-occur) + ("C-x c s" . helm-swoop) + ("C-x c y" . helm-yas-complete) + ("C-x c Y" . helm-yas-create-snippet-on-region) + ;;("C-x c b" . my/helm-do-grep-book-notes) + ("C-x c SPC" . helm-all-mark-rings) + :map helm-map + ;; rebind tab/C-i to run persistent action + ("" . helm-execute-persistent-action) + ("C-i" . helm-execute-persistent-action) ; make TAB works in terminal + ("C-z" . helm-select-action) ; list actions using C-z + + ;; bookmarks + + )) + +(use-package helm-swoop + :bind + (("M-i" . helm-swoop) + ("M-I" . helm-swoop-back-to-last-point) + ("C-c M-i" . helm-multi-swoop) + ("C-x M-i" . helm-multi-swoop-all) + ) + :config + (progn + (define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch) + (define-key helm-swoop-map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop))) + +(use-package helm-flycheck + :requires (helm)) + +;; Turn off ido mode in case I enabled it accidentally +;; (ido-mode -1) + +;; helm will be used to describe bindings +(use-package helm-descbinds + :defer t + :bind (("C-h b" . helm-descbinds) + ("C-h w" . helm-descbinds))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wc-mode +;;(require 'wc-mode) +;;(global-set-key (kbd "C-c C-w") 'wc-mode) +;;(setq wc-modeline-format "WC[%C/%tc]") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; kill/copy line if no region +(use-package whole-line-or-region + :delight whole-line-or-region-local-mode + ;;:diminish whole-line-or-region-local-mode + :commands + (whole-line-or-region-global-mode) + :init + (whole-line-or-region-global-mode 1) + ;; remove comment remaps + (define-key whole-line-or-region-local-mode-map [remap comment-dwim] nil) + (define-key whole-line-or-region-local-mode-map [remap comment-region] nil) + (define-key whole-line-or-region-local-mode-map [remap uncomment-region] nil) + :config + ;;(whole-line-or-region-global-mode 1) + ;; remove comment remaps + ;;(define-key whole-line-or-region-local-mode-map [remap comment-dwim] nil) + ;;(define-key whole-line-or-region-local-mode-map [remap comment-region] nil) + ;;(define-key whole-line-or-region-local-mode-map [remap uncomment-region] nil) + ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; undo tree +(use-package undo-tree + :diminish undo-tree-mode + :defer t + :init + (progn + (defalias 'redo 'undo-tree-redo) + (defalias 'undo 'undo-tree-undo) + (global-undo-tree-mode 1)) + :config + (progn + (setq undo-tree-visualizer-timestamps t + undo-tree-visualizer-diff t + undo-tree-enable-undo-in-region t + ;;undo-tree-auto-save-history t + ) + (let ((undo-dir (concat my/emacs-tmpdir "/undo-tree/"))) + (setq undo-tree-history-directory-alist + `(("." . ,undo-dir))) + (unless (file-exists-p undo-dir) + (make-directory undo-dir t))))) + +;; useful to come back to working window after a buffer has popped up +;; C-c to come back +(use-package winner + :init (winner-mode 1)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; windows navigation +(use-package windmove + :bind (("H-" . windmove-right) + ("H-" . windmove-left) + ("H-" . windmove-up) + ("H-" . windmove-down) + )) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; auto completion +(use-package company + :diminish "Co" + :defer t + :bind + (:map company-active-map + ("RET" . nil) + ;; ([return] . nil) + ("TAB" . company-complete-selection) + ;; ([tab] . company-complete-selection) + ("" . company-complete-common)) + :config + ;; Too slow ! + ;; (global-company-mode 1) + (setq-default + company-idle-delay .2 + company-minimum-prefix-length 3 + company-require-match nil + company-tooltip-align-annotations t) + :hook + (('prog-mode . 'company-mode))) + +;;(add-to-list 'company-backends 'company-shell) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dot-mode (vi-like redo) +;; repo: https://github.com/wyrickre/dot-mode +(use-package dot-mode + :diminish + :bind (("" . dot-mode-execute) + ("C-M-" . dot-mode-override) ; store next keystroke + ("C-c " . dot-mode-copy-to-last-kbd-macro) + + ("C-." . dot-mode-execute) ; default bindings below + ("C-M-." . dot-mode-override) + ("C-c ." . dot-mode-copy-to-last-kbd-macro)) + + :init + (global-dot-mode 1) ; enabled in all buffers + (setq dot-mode-verbose nil + dot-mode-ignore-undo t ; don't consider undos + dot-mode-global-mode t)) ; can redo in different buffer + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; change copy/kill region +;; from sacha +(defadvice kill-region (before slick-cut activate compile) + "When called interactively with no active region, kill a single line instead." + (interactive + (if mark-active (list (region-beginning) (region-end)) + (list (line-beginning-position) + (line-beginning-position 2))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; browse-url / webpaste (pastebin) +(use-package browse-url + :ensure t + :defer t + :bind (( "C-c b" . browse-url ))) + +(use-package webpaste + :ensure t + + :bind (("C-c P b" . webpaste-paste-buffer) + ("C-c P r" . webpaste-paste-region)) + + :hook (webpaste-return-url . my/webpaste-return-url-hook) + + :config + (progn + (setq webpaste-provider-priority '("dpaste.org" "gist.github.com" "paste.mozilla.org" + "dpaste.org" "ix.io") + webpaste-paste-confirmation t ; prompts before sending + ;; nothing below: We do in webpaste-return-url hook + webpaste-open-in-browser nil ; do not open in browser + webpaste-add-to-killring nil ; do not add url to killring + webpaste-paste-raw-text nil ; try to detect language + )) + (defun my/webpaste-return-url-hook (url) + (message "Webpaste: %S" url) + (browse-url-xdg-open url))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; markdown mode +;; https://github.com/jrblevin/markdown-mode/issues/578 +(setq native-comp-deferred-compilation-deny-list '("markdown-mode\\.el$")) +;; inspired from: https://github.com/zaeph/.emacs.d/blob/master/init.el +;; doc: https://leanpub.com/markdown-mode/read +(use-package markdown-mode + :ensure t + :init + ;;(setq markdown-command "pandoc" + ;; markdown-command-needs-filename t) + ;; for pandoc: + (setq markdown-command + (concat "pandoc" + " --quiet" + " --from=markdown --to=html" + " --standalone --mathjax --highlight-style=pygments")) + ;; https://github.com/jrblevin/markdown-mode/issues/578 + ;; (setq markdown-nested-imenu-heading-index nil) + :mode + (("\\.md\\'" . gfm-mode) + ("\\.markdown\\'" . gfm-mode)) + :hook + ((markdown-mode . visual-line-mode) + (markdown-mode . flyspell-mode))) + +;; markdown-toc mode +;; (require 'dash) +;; drop all H1 titles +(custom-set-variables + '(markdown-toc-user-toc-structure-manipulation-fn + (lambda (toc-structure) + (--map (-let (((level . label) it)) + (cons (- level 1) label)) + (cdr toc-structure))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; text mode +;; for some reason, I was not able to "use-package". +;;(use-package text-mode +;; :preface (provide 'text-mode) +;; :ensure nil +;; :mode +;; (("\\.txt\\'" . text-mode) +;; ("\\.text\\'" . text-mode)) +;; :config +;; (progn +;; (message "I am in text-mode- use-package") +;; (setq visual-line-fringe-indicators '(nil right-curly-arrow)) +;; (turn-on-visual-line-mode) ; enable visual-line +;; (auto-fill-mode -1)) ; disable auto-fill +;; ) + +(defun my/text-mode-hook () + "X br text mode hook." + (setq visual-line-fringe-indicators '(nil right-curly-arrow)) + (turn-on-visual-line-mode) ; enable visual-line + (auto-fill-mode -1)) ; disable auto-fill + +(add-hook 'text-mode-hook 'my/text-mode-hook) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; makefile mode +(defun my/makefile-mode-hook () + "X br text mode hook." + (message "entering Makefile-mode") + (setq indent-tabs-mode t + tab-width 4 + comment-column 60)) + +(add-hook 'text-mode-hook 'my/text-mode-hook) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org mode +;; mediawiki export +(require 'ox-mediawiki) +(require 'org-tempo) +;;(require 'ox-extra) + +(defun my/org-mode-hook () + "X br org-mode-hook." + (interactive) + (setq fill-column 78 + ;; show structure at startup + org-startup-folded 'content + truncate-lines nil + org-src-fontify-natively t ; nil: disable coloring in code blocks + org-src-preserve-indentation t + org-src-tab-acts-natively t + org-src-window-setup 'current-window + org-src-block-faces nil + ;; org-descriptive-links nil + org-link-descriptive nil + ;; no TOC by default in export + ;; org-export-with-toc nil + ;;org-html-head-include-default-style nil + ;;org-src-block-faces '(("emacs-lisp" (:background "#EEE2FF")) + ;; ("python" (:background "#E5FFB8"))) + org-todo-keywords '((sequence "TODO" "STARTED" "WAITING" + ;; "REVIEW(r)" "SUBMIT(m)" + "|" "DONE" "CANCELED")) + ;;org-todo-keyword-faces '(("TODO" :foreground "red" :weight bold) + ;; ("STARTED" :foreground "cyan" :weight bold) + ;; ("WAITING" :foreground "gold" :weight bold) + ;; ("DONE" :foreground "sea green" :weight bold) + ;; ("LATER" :foreground "dark red" :weight bold) + ;; ("CANCELED" :foreground "dark red" :weight bold)) + + org-support-shift-select t + org-indent-mode-turns-on-hiding-stars nil + org-export-allow-bind-keywords t + visual-line-fringe-indicators '(nil right-curly-arrow) + ) + ;; change "=" (verbatim) to be different from "~" (code) + (push '(verbatim . "%s") org-html-text-markup-alist) + ;; to allow hiding a headline with :ignore: tag + ;;(ox-extras-activate '(ignore-headlines)) + ;; visual-line mode + (org-indent-mode) + (visual-line-mode) + ;;(setq visual-line-fringe-indicators '(nil right-curly-arrow)) + (auto-fill-mode 1) + (define-key org-mode-map + (kbd "C-c l") 'my/org-toggle-link-display) + (define-key org-mode-map + (kbd "C-c x") 'org-mw-export-as-mediawiki)) + +(defun my/org-toggle-link-display () + "Toggle the literal or descriptive display of links." + (interactive) + (if org-link-descriptive + (progn (remove-from-invisibility-spec '(org-link)) + (org-restart-font-lock) + (setq org-link-descriptive nil)) + (progn (add-to-invisibility-spec '(org-link)) + (org-restart-font-lock) + (setq org-link-descriptive t)))) + +(add-hook 'org-mode-hook 'my/org-mode-hook) + +;; inspired from https://orgmode.org/guide/Introduction.html +(global-set-key (kbd "H-c l") 'org-store-link) +(global-set-key (kbd "H-c a") 'org-agenda) +(global-set-key (kbd "H-c c") 'org-capture) + +;; babel languages +(org-babel-do-load-languages + 'org-babel-load-languages + '((calc . t) + (emacs-lisp . t) + (sql . t) + (perl . t) + (shell . t))) + +;; (plantuml . t) +;; (python . t) +;; (ruby . t) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vimrc mode +(add-hook + 'vimrc-mode-hook + (lambda () + (setq indent-tabs-mode nil ; do not use tabs + comment-column 50))) + +(require 'vimrc-mode) +(add-to-list 'auto-mode-alist '("\\.vim\\(rc\\)?\\'" . vimrc-mode)) +;;(add-to-list 'auto-mode-alikst '(".vim\\(rc\\)?$" . vimrc-mode)) +;;(add-to-list 'auto-mode-alist '(".vim\\(rc\\)?" . vimrc-mode)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; perl (cperl) mode +(defalias 'perl-mode 'cperl-mode) +(add-hook + 'perl-lisp-mode-hook + (lambda () + (setq indent-tabs-mode nil ; do not use tabs + tab-width 2))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Cobol mode +(setq auto-mode-alist + (append + '(("\\.cob\\'" . cobol-mode) + ("\\.cbl\\'" . cobol-mode) + ("\\.cpy\\'" . cobol-mode)) + auto-mode-alist)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; C mode +(defun my/indent-maybe-cpp-directive () + "Indent c pre-processor line according to my own standard." + (interactive) + (save-excursion + (back-to-indentation) + (when (looking-at "#") + (delete-char 1) + (indent-according-to-mode) + (beginning-of-line) + (when (looking-at " ") + (delete-char 1)) + (insert "#") + (beginning-of-line)))) + +(defun my/c-style () + "Some general C setup." + (interactive) + (c-set-style "k&r") + (c-set-offset 'knr-argdecl-intro '+) + (c-set-offset 'case-label '+) + (bind-keys :map c-mode-map + ("s-;" . my/indent-maybe-cpp-directive) + ("" . projectile-compile-project) + ("F" . self-insert-command)) + + (auto-complete-mode 0) + ;;(yas-minor-mode 1) + (flycheck-mode 1) + ;;(ggtags-mode 1) + (show-smartparens-mode 1) + (company-mode 1) + (auto-fill-mode 1) + (setq company-backends '((company-dabbrev-code company-gtags)) + c-basic-offset 4 + comment-column 50 + fill-column 100 + c-ignore-auto-fill '(string cpp) + comment-auto-fill-only-comments nil + comment-style 'extra-line)) + +(add-hook 'c-mode-hook 'my/c-style) + +;;;;;;;;;;;;; linux kernel style +(defun c-lineup-arglist-tabs-only (ignored) + "Line up argument lists by tabs, not spaces. fuck flycheck IGNORED." + (let* ((anchor (c-langelem-pos c-syntactic-element)) + (column (c-langelem-2nd-pos c-syntactic-element)) + (offset (- (1+ column) anchor)) + (steps (floor offset c-basic-offset))) + (* (max steps 1) + c-basic-offset))) + +;; Eudyptula challenge +(defvar my/eudyptula-dir + (expand-file-name "~/dev/eudyptula") + "Eudyptula challenge directory.") +(defvar my/kernel-dir + (concat my/eudyptula-dir "/linux") + "Kernel tree within Eudyptula challenge.") +(defvar my/kernel-scripts-dir + (concat my/kernel-dir "/scripts") + "Scripts dir within Eudyptula challenge's kernel directory.") +(defvar my/kernel-include-dirs + (list (concat my/kernel-dir "/include") + (concat my/kernel-dir "/arch/x86/include") + (concat my/kernel-dir "/arch/x86/include/generated")) + "Kernel include directory.") +(defvar my/running-kernel-include-dirs + (let ((kernel (concat "/lib/modules/" + (string-trim (shell-command-to-string "uname -r")) + "/build"))) + (list (concat kernel "/include") + (concat kernel "/arch/x86/include"))) + "Running kernel include directory.") + +;; https://stackoverflow.com/questions/29709967/using-flycheck-flymake-on-kernel-source-tree +(flycheck-define-checker my/flycheck-kernel-checker + "Linux source checker" + :command + ( + "make" "C=1" "-C" (eval my/kernel-dir) + (eval (concat "M=" + (file-name-directory buffer-file-name))) + (eval (concat (file-name-sans-extension (file-name-nondirectory buffer-file-name)) + ".o")) + ) + :error-patterns + ((error line-start + (message "In file included from") " " (file-name) ":" line ":" + column ":" + line-end) + (info line-start (file-name) ":" line ":" column + ": note: " (message) line-end) + (warning line-start (file-name) ":" line ":" column + ": warning: " (message) line-end) + (error line-start (file-name) ":" line ":" column + ": " (or "fatal error" "error") ": " (message) line-end)) + :modes (c-mode c++-mode)) +;; :error-filter +;; (lambda (errors) +;; (let ((errors (flycheck-sanitize-errors errors))) +;; (dolist (err errors) +;; (let* ((fn (flycheck-error-filename err)) +;; ;; flycheck-fix-error-filename converted to absolute, revert +;; (rn0 (file-relative-name fn default-directory)) +;; ;; make absolute relative to "make -C dir" +;; (rn1 (expand-file-name rn0 my/kernel-dir)) +;; ;; relative to source +;; (ef (file-relative-name rn1 default-directory)) +;; ) +;; (setf (flycheck-error-filename err) ef) +;; ))) +;; errors) + +;; (defun my/flycheck-mode-hook () +;; "Flycheck mode hook." +;; (setq flycheck-linux-makefile my/kernel-dir) +;; (flycheck-select-checker 'my/flycheck-kernel-checker) +;; ) + +(dir-locals-set-class-variables + 'linux-kernel + '((c-mode + . ((c-basic-offset . 8) + (c-label-minimum-indentation . 0) + (c-offsets-alist + . ((arglist-close . c-lineup-arglist) + (arglist-cont-nonempty . (c-lineup-gcc-asm-reg c-lineup-arglist)) + (arglist-intro . +) + (brace-list-intro . +) + (c . c-lineup-C-comments) + (case-label . 0) + (comment-intro . c-lineup-comment) + (cpp-define-intro . +) + (cpp-macro . -1000) + (cpp-macro-cont . +) + (defun-block-intro . +) + (else-clause . 0) + (func-decl-cont . +) + (inclass . +) + (inher-cont . c-lineup-multi-inher) + (knr-argdecl-intro . 0) + (label . -1000) + (statement . 0) + (statement-block-intro . +) + (statement-case-intro . +) + (statement-cont . +) + (substatement . +))) + (indent-tabs-mode . t) + (show-trailing-whitespace . t) + (eval . (flycheck-select-checker 'my/flycheck-kernel-checker) + ;; (setq flycheck-gcc-include-path my/kernel-include-dirs) + ) + )))) + +;; (setq flycheck-checkers (delete 'c/c++-clang flycheck-checkers)) + +;; linux kernel style +(defun my/maybe-linux-style () + "Apply linux kernel style when buffer path contain 'eudyptula'." + (interactive) + (when (and buffer-file-name + (string-match "eudyptula" buffer-file-name)) + (setq flycheck-checkers (delete '(c/c++-clang c/c++-cppcheck) flycheck-checkers) + flycheck-gcc-include-path my/kernel-include-dirs + flycheck-clang-include-path my/kernel-include-dirs))) + +;; (add-hook 'c-mode-hook 'my/maybe-linux-style) + +(dir-locals-set-directory-class my/eudyptula-dir 'linux-kernel) + +;; (add-hook 'flycheck-mode-hook 'my/flycheck-mode-hook) + +(defun my/checkpatch (file &optional nointree noterse nofilemode) + "Run checkpatch on FILE, or current buffer if FILE is nil. + +If NOTERSE is t, a full report will be done. If NOFILEMODE is t, FILE +is supposed to be a patchfile (otherwise a regular source file). +If NOINTREE is t, check will be done on file outside `my/kernel-dir'" + ;;(interactive) + (interactive "FFile name (default: current buffer): ") + (let* ((ckp (concat my/kernel-scripts-dir "checkpatch.pl ")) + (fn (or file (buffer-file-name))) + (terse (if noterse "" "--terse ")) + (tree (if nointree "--notree " "")) + (fm (if nofilemode "" "--file ")) + (opt (concat "--emacs --color=never " terse tree fm))) + (setq my/compile (concat ckp opt fn)) + (compile (concat ckp opt fn)))) + +(defun my/checkstaging () + "Zobi." + (interactive) + (my/checkpatch "drivers/staging/*/*.[ch]")) + +;; add kernel includes +;;(string-trim (shell-command-to-string "uname -r")) + +;; to avoid "free variable" warnings at compile +;; (eval-when-compile +;; (require 'cc-defs)) + +;; (add-hook 'c-mode-common-hook +;; (lambda () +;; ;; Add kernel style +;; (c-add-style +;; "linux-tabs-only" +;; '("linux" (c-offsets-alist +;; (arglist-cont-nonempty +;; c-lineup-gcc-asm-reg +;; c-lineup-arglist-tabs-only)))))) + +;; linux kernel style +;; (defun maybe-linux-style () +;; "Apply linux kernel style when buffer path contains 'linux'." +;; (interactive) +;; (when (and buffer-file-name +;; (string-match "linux" buffer-file-name)) +;; (c-set-style "linux"))) + +;; (add-hook 'c-mode-hook 'maybe-linux-style) + +;; ;; (defun br-linux-style () +;; ;; "Line up argument lists by tabs, not spaces" +;; ;; (interactive) +;; ;; (setq indent-tabs-mode t) +;; ;; (setq show-trailing-whitespace t) +;; ;; (c-set-style "linux-tabs-only")) + +;; (add-hook 'c-mode-hook +;; (lambda () +;; (let ((filename (buffer-file-name))) +;; ;; Enable kernel mode for the appropriate files +;; (when (and filename +;; (or (string-match "dev/eudyptula" filename) +;; (string-match "dev/kernel" filename))) +;; ;;(string-match (expand-file-name "~/dev/Eudyptula") +;; ;; (string-match "Eudyptula" buffer-file-name)) +;; ;;(cl-search "eudyptula" buffer-file-name)) +;; ;;(setq indent-tabs-mode t) +;; (setq show-trailing-whitespace t) +;; (c-set-style "linux-tabs-only"))))) + +;; exercism C style +(defvar my/exercism-dir + (expand-file-name "~/dev/exercism-tracks/") + "Exercism challenge directory.") + +(dir-locals-set-class-variables + 'exercism-style + '((c-mode + . ((c-basic-offset . 3) + (c-label-minimum-indentation . 0) + (c-offsets-alist + . ((arglist-close . c-lineup-arglist) + (arglist-cont-nonempty . (c-lineup-gcc-asm-reg c-lineup-arglist)) + (arglist-intro . +) + (brace-list-intro . +) + (c . c-lineup-C-comments) + (case-label . 0) + (comment-intro . c-lineup-comment) + (cpp-define-intro . +) + (cpp-macro . -1000) + (cpp-macro-cont . +) + (defun-block-intro . +) + (else-clause . 0) + (func-decl-cont . +) + (inclass . +) + (inher-cont . c-lineup-multi-inher) + (knr-argdecl-intro . 0) + (label . -1000) + (statement . 0) + (statement-block-intro . +) + (statement-case-intro . +) + (statement-cont . +) + (substatement . +))) + (indent-tabs-mode . nil) + (fill-column . 80) + (show-trailing-whitespace . t) + (comment-column . 33) + ;;(eval . (flycheck-select-checker 'my/flycheck-kernel-checker) + ;; (setq flycheck-gcc-include-path my/kernel-include-dirs) + ;;) + )))) + +(dir-locals-set-directory-class my/exercism-dir 'exercism-style) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; emacs lisp mode +(defun my/emacs-lisp-mode-hook () + "My Emacs Lisp mode hook." + (interactive) + (setq + indent-tabs-mode nil + tab-width 2 + lisp-body-indent 2 + ;; lisp-indent-offset 2 + + comment-column 50 + fill-column 128 + comment-auto-fill-only-comments t + auto-fill-mode t) + + (define-key emacs-lisp-mode-map + (kbd "") 'reindent-then-newline-and-indent)) + +(add-hook + 'lisp-interaction-mode-hook + (lambda () + (define-key lisp-interaction-mode-map + (kbd "") 'eval-last-sexp))) + +(add-hook + 'lisp-mode-hook + (lambda () + (outline-minor-mode) + (make-local-variable 'outline-regexp) + (setq outline-regexp "^(.*") + (ignore-errors (semantic-default-elisp-setup)) + (set (make-local-variable lisp-indent-function) + 'common-lisp-indent-function))) + +(add-hook 'emacs-lisp-mode-hook 'my/emacs-lisp-mode-hook) + + +;; eldoc - provides minibuffer hints when working in elisp +(use-package "eldoc" + :diminish eldoc-mode + :commands turn-on-eldoc-mode + :defer t + :init + (progn + (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode) + (add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode) + (add-hook 'ielm-mode-hook 'turn-on-eldoc-mode))) + +;; aggressive indent +;; (add-hook 'emacs-lisp-mode-hook #'aggressive-indent-mode) +;; (add-hook 'css-mode-hook #'aggressive-indent-mode) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lisp interaction mode + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; php mode +;;TODO (use-package php +;; +;; ) +(defun my/php-send-buffer () + "Send current buffer to PHP for execution. +The output will appear in the buffer *PHP*." + (interactive) + (php-send-region (if (string-match "\\(^#!.*$\\)" (buffer-string) nil) + (+ 1 (point-min) (match-end 1)) + (point-min)) + (point-max))) + +(defun my/php-mode-hook () + "Hook for php-mode." + (interactive) + (setq indent-tabs-mode nil + c-basic-offset 4 + comment-column 50 + fill-column 128 + comment-auto-fill-only-comments t + auto-fill-mode t + php-mode-template-compatibility nil) + ;;php-executable "php -f") + (paren-toggle-open-paren-context 1) + (php-enable-default-coding-style) + (c-set-offset 'case-label '+) + (define-key php-mode-map + (kbd "C-c f") 'php-search-documentation) + (define-key php-mode-map + (kbd "C-c r") 'my/php-send-buffer) + ;;(auto-complete-mode t) + ;;(require 'ac-php) + ;;(setq ac-sources '(ac-source-php)) + (require 'company-php) + (set (make-local-variable 'company-backends) + '((company-ac-php-backend company-dabbrev-code) + company-capf company-files)) + ) + +(use-package phpactor :ensure t) +(use-package company-phpactor :ensure t) +;;(setq lsp-clients-php-server-command '("phpactor" "language-server")) + +;; Add lsp or lsp-deferred function call to functions for your php-mode customization +;; https://phpactor.readthedocs.io/en/master/lsp/emacs.html +(defun init-php-mode () + "Zobi." + (lsp-deferred)) + +(with-eval-after-load 'php-mode + ;; If phpactor command is not installed as global, write the full path + ;; (custom-set-variables '(lsp-phpactor-path "/path/to/phpactor")) + (add-hook 'php-mode-hook #'init-php-mode)) + +;;(company-mode t) +;;(require 'company-php) +;;(set (make-local-variable 'company-backends) +;; '((company-ac-php-backend company-dabbrev-code) +;; company-capf company-files))) + +;; (add-to-list 'company-backends 'company-ac-php-backend )) + +(add-hook 'php-mode-hook 'my/php-mode-hook) + +;; autoload php-html-helper-mode +;;(autoload 'php-html-helper-mode "html-helper-mode" "html-helper-mode" t) +;;(add-to-list 'auto-mode-alist '("\\.inc\\'" . php-html-helper-mode)) +;;(add-to-list 'auto-mode-alist '("\\.html\\'" . html-mode)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; go mode +(add-hook + 'go-mode-hook + (lambda () + ;; (setq-default) + (setq + indent-tabs-mode nil + tab-width 2 + standard-indent 2))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; js mode +(add-hook + 'js-mode-hook + (lambda () + (setq + indent-tabs-mode nil + js-indent-level 3 + ;; tab-width 3 + c-basic-offset 3 + comment-column 50 + fill-column 128 + comment-auto-fill-only-comments t + auto-fill-mode t) + (define-key js-mode-map + (kbd "") 'reindent-then-newline-and-indent))) + +(use-package json-mode + :defer t + :mode "\\.json\\'" + :config + (setq indent-tabs-mode nil + js-indent-level 2) + ;; https://github.com/joshwnj/json-mode/issues/72 + (setq-default json-mode-syntax-table + (let ((st (make-syntax-table))) + ;; Objects + (modify-syntax-entry ?\{ "(}" st) + (modify-syntax-entry ?\} "){" st) + ;; Arrays + (modify-syntax-entry ?\[ "(]" st) + (modify-syntax-entry ?\] ")[" st) + ;; Strings + (modify-syntax-entry ?\" "\"" st) + ;; Comments + (modify-syntax-entry ?\n ">" st) + st)) + ) +;;(add-hook +;; 'json-mode-hook +;; (lambda () +;; (setq +;; indent-tabs-mode nil +;; js-indent-level 2) +;; )) + +;;(add-to-list 'auto-mode-alist '("\\.js\\'" . my/js-mode-hook)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hideshow mode +(use-package hideshow + :ensure nil + ;;:diminish hideshow + :hook + ((json-mode . hs-minor-mode) + (web-mode . hs-minor-mode) + (php-mode . hs-minor-mode) + (prog-mode . hs-minor-mode) + (lisp-mode . hs-minor-mode)) + :bind + (:map hs-minor-mode-map + ("H-" . hs-toggle-hiding) + ("H-h" . hs-hide-block) + ("H-s" . hs-show-block) + ("H-l" . hs-hide-level) + ("H-a" . hs-show-all) + ("H-t" . hs-hide-all)) + ;; :commands hs-toggle-hiding + ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; handle large buffers +(defun my/dabbrev-friend-buffer (other-buffer) + "Exclude very large buffers from dabbrev." + (< (buffer-size other-buffer) (* 1 1024 1024))) + +(setq dabbrev-friend-buffer-function 'my/dabbrev-friend-buffer) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; multiple cursors +(use-package multiple-cursors + :ensure t + :bind (("C-S-C C-S-C" . mc/edit-lines) + + ("H-SPC" . set-rectangular-region-anchor))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sql mode +;;(use-package sql-indent :defer t) +;;(use-package sqlup-mode :defer t) + +(use-package sql + :ensure t + :init + ;;(setq sql-product 'mysql + ;; sqlup-mode t + ;;(toggle-truncate-lines 1) + + ;; connect to a predefined connection (sql-connection-alist) + (defun my/sql-connect-preset (name) + "Connect to a predefined SQL connection listed in `sql-connection-alist'" + (eval `(let ,(cdr (assoc name sql-connection-alist)) + (flet ((sql-get-login (&rest what))) + (sql-product-interactive sql-product))))) + + (defun my/sql-mode-hook () + "Hook for SQL mode." + (toggle-truncate-lines 1) + (message "br sql hook")) + + (add-hook 'sql-interactive-mode-hook + (lambda () + (toggle-truncate-lines t) + ;;(my/sql-connect-preset) + (setq comint-move-point-for-output "all"))) + ;; (add-hook 'sql-interactive-mode-hook #'my/sql-mode-hook) + (font-lock-add-keywords 'sql-mode '(("greatest" . font-lock-builtin-face) + ("least" . font-lock-builtin-face))) + :config + (toggle-truncate-lines 1) + (sql-set-product-feature 'mysql :prompt-regexp + "^\\(MariaDB\\|MySQL\\) \\[[_a-zA-Z]*\\]> ") + + :hook + ((sql-mode . sqlind-minor-mode) + (sql-mode . sqlup-mode)) + ;;(sql . my/sql-mode-hook) + ;;(sql-interactive-mode . #'my/sql-mode-hook)) + ;;(sql-interactive-mode . (toggle-truncate-lines 1))) + ) + +;;(use-package sqlup-mode +;;:ensure +;;:after sql +;;:init +;;(local-set-key (kbd "C-c u") 'sqlup-capitalize-keywords-in-region) +;;:hook +;;(add-hook 'sql-mode-hook #'sqlup-mode) +;;:config +;;(add-to-list 'sqlup-blacklist "name") ; I use "name" a lot. +;; ) + +;;(use-package sql-indent +;;:after (sql-mode) +;;:after sql +;;:init +;;:hook +;;((sql . sqlind-minor-mode))) + +;; (use-package sql-interactive-mode +;; :ensure +;; :after sql +;; :config +;; (toggle-truncate-lines 0)) + +;;(add-hook 'sql-mode-hook #'my/sql-mode-hook) +;; When connected to a server within Emacs +;;(add-hook 'sql-interactive-mode-hook #'my/sql-mode-hook) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; html/xml mode +(add-hook + 'html-mode-hook + (lambda () + (setq + indent-tabs-mode nil + ;; tab-width 2 + sgml-basic-offset 2))) + +(defun xml-reformat () + "Reformats xml to make it readable (respects current selection)." + (interactive) + (save-excursion + (let ((beg (point-min)) + (end (point-max))) + (if (and mark-active transient-mark-mode) + (progn + (setq beg (min (point) (mark))) + (setq end (max (point) (mark)))) + (widen)) + (setq end (copy-marker end t)) + (goto-char beg) + (while (re-search-forward ">\\s-*<" end t) + (replace-match ">\n<" t t)) + (goto-char beg) + (indent-region beg end nil)))) + +(add-hook + 'nxml-mode-hook + (lambda () + (setq + indent-tabs-mode nil + ;; tab-width 2 + sgml-basic-offset 2))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; web mode +(use-package web-mode + ;;:demand t + :init + (require 'php-mode) + ;; (setq web-mode-enable-current-column-highlight t) + (make-local-variable 'web-mode-code-indent-offset) + (make-local-variable 'web-mode-markup-indent-offset) + (make-local-variable 'web-mode-css-indent-offset) + :mode + ("\\.phtml\\'" "\\.html?\\'") + ;;(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode)) + ;;(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode)) + + :bind + (:map web-mode-map + ("C-c f" . php-search-documentation)) + + ;;:hook + ;; (('web-mode . php-mode)) + + :config + (require 'company-php) + (set (make-local-variable 'company-backends) + '((company-ac-php-backend company-dabbrev-code) + company-capf company-files)) + (setq web-mode-markup-indent-offset 2 + web-mode-enable-auto-pairing nil ; overrides smartparens + web-mode-css-indent-offset 2 + web-mode-code-indent-offset 4 + web-mode-style-padding 1 + web-mode-script-padding 1 + web-mode-block-padding 2 + web-mode-enable-current-element-highlight t + web-mode-enable-current-column-highlight t + web-mode-sql-indent-offset 2 + web-mode-engines-alist '(("php" . "\\.phtml\\'"))) + (setq web-mode-ac-sources-alist + '(("css" . (ac-source-css-property)) + ("html" . (ac-source-words-in-buffer ac-source-abbrev))) + ) + ;;) + ;;(add-hook 'web-mode-hook 'my/web-mode-hook) + ;;(eval-after-load "web-mode" + ;;' + ;;(set-face-background 'web-mode-current-element-highlight-face "red") + (set-face-foreground 'web-mode-current-element-highlight-face "chartreuse") + + ) + +;; (defun my/web-mode-hook () +;; "br web-mode-hook." +;; (interactive) +;; (setq indent-tabs-mode nil +;; tab-width 2 +;; ;; web-mode-attr-indent-offset 2 +;; web-mode-enable-auto-pairing nil +;; web-mode-code-indent-offset 2 ; for php, js, etc... +;; web-mode-css-indent-offset 2 +;; web-mode-markup-indent-offset 2 ; for html +;; web-mode-sql-indent-offset 2 +;; web-mode-enable-current-column-highlight t +;; ) +;; (define-key web-mode-map +;; (kbd "C-c f") 'php-search-documentation) +;; (paren-toggle-open-paren-context 1) +;; (c-set-offset 'case-label '+) +;; (setq web-mode-engines-alist +;; '(("php" . "\\.phtml\\'"))) +;; (sp-local-pair 'web-mode "<" nil :when '(my/sp-web-mode-is-code-context)) +;; ) + +;; (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode)) +;; (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode)) +;; ;; (add-to-list 'auto-mode-alist '("\\.css\\'" . web-mode)) +;; ;; (add-to-list 'auto-mode-alist '("\\.php\\'" . web-mode)) +;; (add-hook 'web-mode-hook 'my/web-mode-hook) + +;; ;; from FAQ at http://web-mode.org/ for smartparens +;; (defun my/sp-web-mode-is-code-context (id action context) +;; (when (and (eq action 'insert) +;; (not (or (get-text-property (point) 'part-side) +;; (get-text-property (point) 'block-side)))) +;; t)) + +;; (use-package web-mode +;; ;;:mode "\\.html?\\'" +;; :init + +;; :hook +;; ((auto-mode-alist .'("\\.php\\'" . web-mode) +;; ) +;; :config +;; (progn +;; (setq web-mode-markup-indent-offset 2) +;; (setq web-mode-code-indent-offset 2) +;; (setq web-mode-css-indent-offset 2) +;; (setq web-mode-enable-current-element-highlight t) +;; (setq web-mode-ac-sources-alist +;; '(("css" . (ac-source-css-property)) +;; ("html" . (ac-source-words-in-buffer ac-source-abbrev))) +;; ))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; smartparens mode +;; inspired from http://pages.sachachua.com/.emacs.d/Sacha.html#org480d137 +(use-package smartparens + :diminish + :ensure t + :config + (progn + (require 'smartparens-config) + (smartparens-global-mode 1) + (show-smartparens-global-mode 1) + ;;(add-hook 'emacs-lisp-mode-hook 'smartparens-mode) + + (add-hook 'emacs-lisp-mode-hook 'show-smartparens-mode) + + (setq sp-navigate-close-if-unbalanced t) + + ;; keybinding management + ;;(define-key smartparens-mode-map (kbd "C-M-k") 'sp-kill-sexp) + ;;(define-key smartparens-mode-map (kbd "C-M-w") 'sp-copy-sexp) + (define-key smartparens-mode-map (kbd "s-k") 'sp-kill-hybridsexp) + (define-key smartparens-mode-map (kbd "s-w") 'sp-copy-sexp) + + (define-key smartparens-mode-map (kbd "C-c s r n") 'sp-narrow-to-sexp) + + ;; (define-key smartparens-mode-map (kbd "C-M-f") 'sp-forward-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-b") 'sp-backward-sexp) + (define-key smartparens-mode-map (kbd "s-f") 'sp-forward-sexp) + (define-key smartparens-mode-map (kbd "s-b") 'sp-backward-sexp) + + ;; (define-key smartparens-mode-map (kbd "C-S-a") 'sp-beginning-of-sexp) + ;; (define-key smartparens-mode-map (kbd "C-S-d") 'sp-end-of-sexp) + ;; (define-key smartparens-mode-map (kbd "C-S-e") 'sp-end-of-sexp) + (define-key smartparens-mode-map (kbd "s-a") 'sp-beginning-of-sexp) + (define-key smartparens-mode-map (kbd "s-e") 'sp-end-of-sexp) + + ;; (define-key smartparens-mode-map (kbd "C-M-n") 'sp-next-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-p") 'sp-previous-sexp) + (define-key smartparens-mode-map (kbd "s-n") 'sp-next-sexp) + (define-key smartparens-mode-map (kbd "s-p") 'sp-previous-sexp) + + ;; (define-key smartparens-mode-map (kbd "C-M-t") 'sp-transpose-sexp) + (define-key smartparens-mode-map (kbd "s-") 'sp-transpose-hybrid-sexp) + (define-key smartparens-mode-map (kbd "s-") 'sp-push-hybrid-sexp) + + ;; (define-key smartparens-mode-map (kbd "M-D") 'sp-splice-sexp) + (define-key smartparens-mode-map (kbd "s-d") 'sp-splice-sexp) + + ;; (define-key smartparens-mode-map (kbd "C-") 'sp-forward-slurp-sexp) + ;; (define-key smartparens-mode-map (kbd "C-") 'sp-forward-barf-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-") 'sp-backward-slurp-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-") 'sp-backward-barf-sexp) + (define-key smartparens-mode-map (kbd "s-") 'sp-slurp-hybrid-sexp) + (define-key smartparens-mode-map (kbd "s-") 'sp-forward-barf-sexp) + (define-key smartparens-mode-map (kbd "s-S-") 'sp-backward-slurp-sexp) + (define-key smartparens-mode-map (kbd "s-S-") 'sp-backward-barf-sexp) + + ;; nearly useless in C + ;; (define-key smartparens-mode-map (kbd "") 'sp-up-sexp) + ;; (define-key emacs-lisp-mode-map (kbd ")") 'sp-up-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-d") 'sp-down-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-e") 'sp-up-sexp) + + (define-key smartparens-mode-map (kbd "C-M-a") 'sp-backward-down-sexp) + (define-key smartparens-mode-map (kbd "C-M-u") 'sp-backward-up-sexp) + + (define-key smartparens-mode-map (kbd "M-") + 'sp-unwrap-sexp) + (define-key smartparens-mode-map (kbd "M-") + 'sp-backward-unwrap-sexp) + + (define-key smartparens-mode-map (kbd "C-M-") + 'sp-splice-sexp-killing-forward) + (define-key smartparens-mode-map (kbd "C-M-") + 'sp-splice-sexp-killing-backward) + (define-key smartparens-mode-map (kbd "C-S-") + 'sp-splice-sexp-killing-around) + + ;;(define-key smartparens-mode-map (kbd "C-]") 'sp-select-next-thing-exchange) + ;;(define-key smartparens-mode-map (kbd "C-") 'sp-select-previous-thing) + ;;(define-key smartparens-mode-map (kbd "C-M-]") 'sp-select-next-thing) + (define-key smartparens-mode-map (kbd "s-]") + 'sp-select-next-thing-exchange) + (define-key smartparens-mode-map (kbd "s-") + 'sp-select-previous-thing-exchange) + + ;;(define-key smartparens-mode-map (kbd "M-F") 'sp-forward-symbol) + ;;(define-key smartparens-mode-map (kbd "M-B") 'sp-backward-symbol) + + (define-key smartparens-mode-map (kbd "C-c s t") 'sp-prefix-tag-object) + (define-key smartparens-mode-map (kbd "C-c s p") 'sp-prefix-pair-object) + (define-key smartparens-mode-map (kbd "C-c s c") 'sp-convolute-sexp) + (define-key smartparens-mode-map (kbd "C-c s a") 'sp-absorb-sexp) + (define-key smartparens-mode-map (kbd "C-c s e") 'sp-emit-sexp) + (define-key smartparens-mode-map (kbd "C-c s p") 'sp-add-to-previous-sexp) + (define-key smartparens-mode-map (kbd "C-c s n") 'sp-add-to-next-sexp) + (define-key smartparens-mode-map (kbd "C-c s j") 'sp-join-sexp) + (define-key smartparens-mode-map (kbd "C-c s s") 'sp-split-sexp) + +;;;;;;;;;;;;;;;;;; + ;; pair management + + (sp-local-pair 'minibuffer-inactive-mode "'" nil :actions nil) + +;;; c-mode + (sp-with-modes '(c-mode c++-mode) + (sp-local-pair "{" nil :post-handlers '(("||\n[i]" "RET"))) + (sp-local-pair "/*" "*/" :post-handlers '((" | " "SPC") + ("* ||\n[i]" "RET")))) +;;; markdown-mode + (sp-with-modes '(markdown-mode gfm-mode rst-mode) + (sp-local-pair "*" "*" :bind "C-*") + (sp-local-tag "2" "**" "**") + (sp-local-tag "s" "```scheme" "```") + (sp-local-tag "<" "<_>" "" :transform 'sp-match-sgml-tags)) + +;;; tex-mode latex-mode + (sp-with-modes '(tex-mode plain-tex-mode latex-mode) + (sp-local-tag "i" "1d5f8e69396c521f645375107197ea4dfbc7b792quot;<" "1d5f8e69396c521f645375107197ea4dfbc7b792quot;>")) + +;;; html-mode + (sp-with-modes '(html-mode sgml-mode web-mode) + (sp-local-pair "<" ">")) + +;;; web-mode + (defun my/sp-web-mode-is-code-context (id action context) + (when (and (eq action 'insert) + (not (or (get-text-property (point) 'part-side) + (get-text-property (point) 'block-side)))) + t)) + (sp-local-pair 'web-mode "<" nil :when '(my/sp-web-mode-is-code-context)) + +;;; lisp modes + (sp-with-modes sp-lisp-modes + (sp-local-pair "(" nil :bind "C-(")))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; shell-script mode +(add-hook + 'sh-mode-hook + (lambda () + (setq indent-tabs-mode nil + tab-width 4 + sh-basic-offset 4 + comment-column 50 + comment-auto-fill-only-comments t + fill-column 128 + auto-fill-mode t + shfmt-command "~/go/bin/shfmt" + shfmt-arguments '("-i" "4" "-ci")) + (sh-electric-here-document-mode) + (define-key sh-mode-map (kbd "C-c f") 'shfmt-buffer))) + +;;(define-key sh-mode-map +;; (kbd "") 'reindent-then-newline-and-indent))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lsp-mode +(use-package lsp-mode + :ensure t + :diminish "LSP" + :commands (lsp lsp-deferred) + :config + (setq lsp-prefer-flymake nil + lsp-semantic-tokens-enable t + ;;lsp-enable-on-type-formatting nil + lsp-enable-snippet nil + lsp-enable-symbol-highlighting t + lsp-lens-enable t + lsp-headerline-breadcrumb-enable t + lsp-enable-indentation nil + lsp-enable-on-type-formatting nil + lsp-eldoc-enable-hover t + lsp-modeline-diagnostics-enable t + lsp-modeline-code-actions-enable t + lsp-modeline-code-actions-segments '(count icon name) + lsp-signature-render-documentation t) + :hook + ((sh-mode . lsp-deferred) + ;;(c-mode-common . lsp-deferred) + (lsp-mode . lsp-enable-which-key-integration))) + +(use-package lsp-ui + :ensure t + ;;:diminish + :config + (setq ; lsp-ui-doc-show-with-cursor t + ; lsp-ui-doc-show-with-mouse t + lsp-ui-sideline-enable t + lsp-ui-sideline-show-code-actions t + lsp-ui-sideline-enable t + lsp-ui-sideline-show-hover t + lsp-ui-sideline-enable t + lsp-ui-doc-enable nil) + + :commands + (lsp-ui-mode) + :bind-keymap + ("s-l" . lsp-command-map)) + +;;(use-package lsp-lens +;; :diminish) + +(use-package helm-lsp + :commands + helm-lsp-workspace-symbol) + +;;(use-package eglot +;; :ensure t +;; :diminish "EG") + +(use-package ccls + :ensure t + :diminish " ccls" + :init + (setq ccls-initialization-options + '(:index (:comments 2) :completion (:detailedLabel t))) + (setq-default flycheck-disabled-checkers '(c/c++-clang c/c++-cppcheck c/c++-gcc)) + (setq ccls-sem-highlight-method 'font-lock) + ;; alternatively, + ;;(setq ccls-sem-highlight-method 'overlay) + ;; For rainbow semantic highlighting + ;;(ccls-use-default-rainbow-sem-highlight) + :config + ;;(setq projectile-project-root (ccls--suggest-project-root)) + :hook + ((c-mode) . (lambda () (require 'ccls) (lsp))) + ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CSS mode +(add-hook + 'css-mode-hook + (lambda() + (setq cssm-indent-level 3 + cssm-newline-before-closing-bracket t + cssm-indent-function #'cssm-c-style-indenter + cssm-mirror-mode t + css-indent-offset 2 + indent-tabs-mode nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; additional files to load +;; load different files if they exist in user-emacs-directory directory: +;; emacs custom file, graphical system, system type, and hostname +;; in this order. + +;; special case for custom file. Need to do something (maybe use an alist below) +(setq custom-file + (concat user-emacs-directory "custom.el")) +(when (file-exists-p custom-file) + (load custom-file)) + +;; secret file: all sensitive data +(setq my/secret-file "~/data/private/secret.el") +(when (file-exists-p my/secret-file) + (load my/secret-file) + (message "+++%s" my/secret-file)) + +;; load graphic/terminal specific file +(let ((filename (concat user-emacs-directory + (if (display-graphic-p) + "graphic" + "term") + ".el"))) + (when (file-exists-p filename) + (load filename) + (message "+++%s" filename))) + +;; host specific file +(let ((filename (concat user-emacs-directory + (system-name) + ".el"))) + (when (file-exists-p filename) + (load filename) + (message "+++%s" filename))) + +;; start server if not running +(require 'server) +(unless (server-running-p) + (server-start) + (message "++++++ emacs server started")) + +;; (dolist +;; (filename +;; (list +;; ;; emacs self-generated - TO IMPROVE +;; ;; "custom" +;; ;; graphical system +;; (if (display-graphic-p) +;; "graphic" +;; "term") +;; ;; system type - we need to replace "/" with "!" here, for "gnu/linux" +;; (replace-regexp-in-string "/" "%" (symbol-name system-type)) +;; ;; hostname +;; (system-name))) +;; (let ((full-filename (concat user-emacs-directory filename ".el"))) +;; ;; load file +;; (message "+++%s" full-filename) +;; (if (file-exists-p full-filename) +;; (load full-filename) +;; ))) + +(message "++++++ init.el end") +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; nothing works in Emacs 25 +(defun my/trim-spaces (beg end) + "Trim all blank characters in region to one space, and remove whitespaces +at beginning and end of lines." + (interactive "r") + (save-excursion + (save-restriction + (narrow-to-region beg end) + ;; replace multiple spaces in one + (goto-char (point-min)) + (while (re-search-forward "[ \t]+" nil t) + (replace-match " ")) + ;; remove spaces at lines beginning + (goto-char (point-min)) + (while (re-search-forward "^[ \t]+" nil t) + (replace-match "")) + ;; remove spaces at line start/end + (delete-trailing-whitespace)))) + +(defun my/align (beg end) + "Align columns with spaces." + (interactive "r") + (save-excursion + (save-restriction + (narrow-to-region beg end) + (my/trim-spaces (point-min) (point-max)) + (align-regexp (point-min) (point-max) "\\(\\s-*\\)\\s-" 1 0 t) + (delete-trailing-whitespace)))) + +(defun align-cols (start end max-cols) + "Align text between point and mark as columns. +Columns are separated by whitespace characters. +Prefix arg means align that many columns. (default is all) +Attribution: ?" + (interactive "r\nP") + (save-excursion + (let ((p start) + pos + end-of-line + word + count + (max-cols (if (numberp max-cols) (max 0 (1- max-cols)) nil)) + (pos-list nil) + (ref-list nil)) + ;; find the positions + (goto-char start) + (while (< p end) + (beginning-of-line) + (setq count 0) + (setq end-of-line (save-excursion (end-of-line) (point))) + (re-search-forward "^\\s-*" end-of-line t) + (setq pos (current-column)) ;start of first word + (if (null (car ref-list)) + (setq pos-list (list pos)) + (setq pos-list (list (max pos (car ref-list)))) + (setq ref-list (cdr ref-list))) + (while (and (if max-cols (< count max-cols) t) + (re-search-forward "\\s-+" end-of-line t)) + (setq count (1+ count)) + (setq word (- (current-column) pos)) + ;; length of next word including following whitespaces + (setq pos (current-column)) + (if (null (car ref-list)) + (setq pos-list (cons word pos-list)) + (setq pos-list (cons (max word (car ref-list)) pos-list)) + (setq ref-list (cdr ref-list)))) + (while ref-list + (setq pos-list (cons (car ref-list) pos-list)) + (setq ref-list (cdr ref-list))) + (setq ref-list (nreverse pos-list)) + (forward-line) + (setq p (point))) + ;; align the cols starting with last row + (setq pos-list (copy-sequence ref-list)) + (setq start + (save-excursion (goto-char start) (beginning-of-line) (point))) + (goto-char end) + (beginning-of-line) + (while (>= p start) + (beginning-of-line) + (setq count 0) + (setq end-of-line (save-excursion (end-of-line) (point))) + (re-search-forward "^\\s-*" end-of-line t) + (goto-char (match-end 0)) + (setq pos (nth count pos-list)) + (while (< (current-column) pos) + (insert-char ?\040 1)) + (setq end-of-line (save-excursion (end-of-line) (point))) + (while (and (if max-cols (< count max-cols) t) + (re-search-forward "\\s-+" end-of-line t)) + (setq count (1+ count)) + (setq pos (+ pos (nth count pos-list))) + (goto-char (match-end 0)) + (while (< (current-column) pos) + (insert-char ?\040 1)) + (setq end-of-line (save-excursion (end-of-line) (point)))) + (forward-line -1) + (if (= p (point-min)) (setq p (1- p)) + (setq p (point))))))) +;;(setq +;;current-language-environment "UTF-8" +;;(prefer-coding-system 'UTF-8) +;;(set-default-coding-systems 'UTF-8) +;;(set-terminal-coding-system 'UTF-8) +;;(setq-default buffer-file-coding-system 'UTF-8) + +;; affichage direct des caractères sur 8 bits +;; (standard-display-european 1) +;; les caractères iso-latin1 qui sont des lettres, des majuscules... +;; (require 'iso-syntax ) + +;; (rplacd fancy-startup-text +;; `("\nZou are running a customized Emacs configuration. See " :link +;; ("here" +;; #[257 "\300\301!\207" +;; [browse-url-default-browser "http://github.com/izahn/dotemacs/"] +;; 3 "\n\n(fn BUTTON)"] +;; "Open the README file") +;; "\nfor information about these customizations.\n" +;; . +;; (cdr fancy-startup-text))) +;; (rplacd add-to-list 'fancy-startup-text +;; '("\nYou are running a customized Emacs configuration. See " :link +;; ("here" +;; #[257 "\300\301!\207" +;; [browse-url-default-browser "http://github.com/izahn/dotemacs/"] +;; 3 "\n\n(fn BUTTON)"] +;; "Open the README file") +;; "\nfor information about these customizations.\n")) + +;; Local Variables: +;; byte-compile-warnings: (not free-vars) +;; End: +(provide 'init) +;;; init.el ends here +(put 'narrow-to-region 'disabled nil) diff --git a/config/home/graphic.el b/config/home/graphic.el new file mode 100755 index 0000000..72bf5d4 --- /dev/null +++ b/config/home/graphic.el @@ -0,0 +1,22 @@ +;; ~/.emacs.d/graphic.el +;; +;; emacs configuration - this file will be loaded only when emacs runs on graphic +;; system. +;; +;; br, 2010-2019 + +;; avoids calling this twice +(when (not (boundp 'my/graphic-loaded)) + ;; disable toolbar + (tool-bar-mode -1) + + ;; initial frame size + (set-frame-size (selected-frame) 180 50) + + (setq + ;; split windows and assign them references + my/upper-window (selected-window) + my/main-window (split-window-right) + my/below-window (split-window-below) + + my/graphic-loaded t)) diff --git a/config/home/init.el b/config/home/init.el new file mode 100755 index 0000000..eab6a97 --- /dev/null +++ b/config/home/init.el @@ -0,0 +1,2444 @@ +;;;; ~/.Emacs.d/init.el +;;;; +;;;; emacs configuration +;;;; br, 2010-2020 +;;;; +;;;; all personal variables/defun are prefixed with "my/". +;; +;; +;; TODO +;; paredit: see https://takeokunn.github.io/.emacs.d/ +;; +;;; Code: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; packages/directories setup +(require 'package) +;; (require 'use-package) +(package-initialize) +(setq use-package-always-ensure t) + +(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) +;;(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/")) +;;(add-to-list 'package-archives '("ox-odt" . "https://kjambunathan.github.io/elpa/")) + +;; set package directory & recompile lisp files in user-emacs-directory +(add-to-list 'load-path (concat user-emacs-directory "lisp/")) +(add-to-list 'load-path "~/data/private/") + +;; (byte-recompile-directory user-emacs-directory 0 t) + +;; need to check +;;(require 'prog-mode) + +;; store backup and auto-saved buffers (file~ and .#file#) in ~/tmp/emacs +(defconst my/emacs-tmpdir "~/tmp/emacs" + "Directory where to store all temp and backup files.") +(setq backup-directory (concat my/emacs-tmpdir "/backups/") + save-directory (concat my/emacs-tmpdir "/autosave/") + auto-save-list-file-prefix (concat my/emacs-tmpdir "/autosave-list/") + ) + +;; create dirs if necessary +(dolist (dir (list backup-directory save-directory auto-save-list-file-prefix)) + (if (not (file-exists-p dir)) + (make-directory dir t))) + +;; backup settings +(setq backup-directory-alist `(("." . ,backup-directory)) + make-backup-file t ; make backup when first saving + delete-old-versions t ; removes old versions silently + kept-old-versions 10 ; how many to keep (oldest) + kept-new-versions 10 ; how many to keep (newest) + backup-by-copying 1 ; to avoid link issues, backups are copied + version-control t ; numbered backups + ) +;; auto-save settings +(setq auto-save-file-name-transforms `((".*" ,save-directory t)) + auto-save-timeout 60 ; seconds idle before auto-save + auto-save-interval 200 ; keystrokes between auto-saves + ) +;; backup tramp files locally +(add-to-list 'backup-directory-alist + (cons tramp-file-name-regexp backup-directory)) + +;; disable lockfiles +(setq create-lockfiles nil) + +;; external editing in firefox +(require 'atomic-chrome) +(atomic-chrome-start-server) + +;; *scratch* & *Messages* are immortal +(add-hook 'kill-buffer-query-functions + (lambda () (not (member (buffer-name) + '("*scratch*" "*Messages*"))))) + +;; allow remembering risky variables +(defun risky-local-variable-p (sym &optional _ignored) "Zoba SYM." nil) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; swap modifier keysyms (japanese keyboard) +;; windows key (super) becomes hyper +;;(setq x-super-keysym 'hyper) +;; alt key (meta) becomes super +;;(setq x-meta-keysym 'super) +;; muhenkan key (hyper) becomes meta +;;(setq x-hyper-keysym 'meta) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; crontabs handling +;; The idea: copy crontab entries to temp buffer, and +;; send back current buffer to "crontab" + +(defun my/edit-root-crontab () + "Edit root crontab." + (interactive) + (with-editor-async-shell-command "crontab -e")) + +(defvar my/crontabs-dir + (concat my/emacs-tmpdir "/crontabs/" (number-to-string (user-uid))) + "The directory in which to place the crontabs.") +;;(format "%s/emacs-cron" (or (getenv "TMPDIR") "/tmp") (user-uid))) + +(defun my/edit-crontab () + "Edit current user crontab." + (interactive) + (setq cronBuf (get-buffer "br-crontab")) + (when (not + (and cronBuf + (buffer-live-p cronBuf))) + ;;(not cronBuf) + ;;() + (message "creating br-crontab") + (setq cronBuf (get-buffer-create "br-crontab")) + (set-buffer cronBuf) + (crontab-mode) + (insert (shell-command-to-string "crontab -l")) + (set-buffer-modified-p nil) + (goto-char (point-min))) + (pop-to-buffer-same-window cronBuf)) + + +(defun my/crontab-e () + "Run `crontab -e' in an Emacs buffer. Use 'kill-buffer' on crontab window to validate." + (interactive) + (with-editor-async-shell-command "crontab -e")) + +(defun my/root-crontab-e () + "Run `crontab -e -u root' in an Emacs buffer. Use 'kill-buffer' on crontab window to validate." + (interactive) + (with-editor-async-shell-command "sudo -E crontab -e -u root")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lisp tools +(defun my/append-to-list (list-var elements) + "Append ELEMENTS to the end of LIST-VAR. Return new LIST-VAR value." + (unless (consp elements) + (error "ELEMENTS must be a list")) + (let ((list (symbol-value list-var))) + (if list + (setcdr (last list) elements) + (set list-var elements))) + (symbol-value list-var)) + + +(defun my/add-to-list (list-var elements &optional uniq) + "Add ELEMENTS to the beginning LIST-VAR, remove duplicates if UNIQ is true. +Return new LIST-VAR value." + (unless (consp elements) + (error "ELEMENTS must be a list")) + (set list-var (append elements (symbol-value list-var))) + (and uniq + (delete-dups (symbol-value list-var))) + (symbol-value list-var)) + +;; don't remember what it was about. Saturday night wine idea ? +(defun my/str-replace-all (str alist) + "Given an ALIST of the form '((a1 . a2)(b1 . b2)), will return a1 or b1 if STR equals a2 or b2." + (if (null alist) + str + (let* ((elem (car alist)) + (lhs (car elem)) + (rhs (cdr elem))) + ;;(message str) + ;;(message lhs) + ;;(message rhs) + ;;(message "+++++++") + (replace-regexp-in-string rhs lhs (my/str-replace-all str (cdr alist)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; buffer names +;; shorten tramp sudo +;;(my/add-to-list +;; 'directory-abbrev-alist +;; '(("^root:/" . "/ssh:arwen:/home/br/www/cf.bodi/seven/") +;; ("arwen:rebels:/" . "/ssh:arwen:/home/br/www/cf.bodi/rebels21/") +;; ("arwen:strats:/" . "/ssh:arwen:/home/br/www/cf.bodi/strat-dom/"))) + +;; Buffer name in status bar +(require 'uniquify) +(setq uniquify-buffer-name-style 'forward ; display finename as dir1/dir2/file + uniquify-min-dir-content 0 ; minimum # of dirs in name + uniquify-strip-common-suffix t ; strip dirs suffixes if conflict + ) + +;; set main frame title +(set-frame-name "GNU Emacs") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ibuffer -- NOT USED: Using Helm +(defun my/ibuffer-hook () + "br ibuffer-hook." + (interactive) + (ibuffer-tramp-set-filter-groups-by-tramp-connection) + (ibuffer-do-sort-by-alphabetic)) + +(define-ibuffer-column dirname + (:name "Directory" + :inline nil) + (message (buffer-file-name buffer)) + (if (buffer-file-name buffer) + (my/str-replace-all + (file-name-directory + (buffer-file-name buffer)) + directory-abbrev-alist) + (or dired-directory + ""))) +;; (global-set-key (kbd "C-x C-b") 'ibuffer) +;; (global-set-key (kbd "C-x b") 'ibuffer) + +;; original value +;; (setq ibuffer-formats +;; '((mark modified read-only " " +;; (name 18 18 :left :elide) +;; " " +;; (size 9 -1 :right) +;; " " +;; (mode 16 16 :left :elide) +;; " " filename-and-process) +;; (mark " " +;; (name 16 -1) +;; " " filename))) + +(setq ibuffer-formats + '((mark modified " " + (name 18 18 :right :elide) + " " + (size 9 -1 :right) + " " + (mode 16 16 :left :elide) + " " filename-and-process) + (mark " " + (name 16 -1) + " " filename + ) + (mark modified read-only " " + (name 30 30 :left :elide) + " " + (size 9 -1 :right) + " " dirname) + )) + +(add-hook 'ibuffer-hook 'my/ibuffer-hook) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; package auto update +(use-package auto-package-update + :if (not (daemonp)) + :custom + (auto-package-update-interval 7) ; in days + (auto-package-update-prompt-before-update t) + (auto-package-update-delete-old-versions t) + (auto-package-update-hide-results t) + :config + (auto-package-update-maybe)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; command-log-mode +;;(use-package command-log-mode +;; :straight t +;; :defer t) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ggtags +(use-package ggtags + :ensure t + :diminish ggtags-mode + :disabled t + :defer t + :init + (setq ggtags-global-window-height 28 + ggtags-enable-navigation-keys nil) + + (after cc-mode (add-hook 'c-mode-common-hook #'ggtags-mode)) + + :config + (bind-keys :map ggtags-mode-map + ("C-c g s" . ggtags-find-other-symbol) + ("C-c g h" . ggtags-view-tag-history) + ("C-c g r" . ggtags-find-reference) + ("C-c g f" . ggtags-find-file) + ("C-c g c" . ggtags-create-tags) + ("C-c g u" . ggtags-update-tags) + ("M-," 'pop-tag-mark))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; projectile +;; default config from developer +(use-package projectile + ;;:diminish projectile-mode + :diminish " prj" + :ensure t + :config + ;;(define-key projectile-mode-map (kbd "s-p") 'projectile-command-map) + ;;(define-key projectile-mode-map (kbd "s-p") 'projectile-command-map) + (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map) + (setq projectile-enable-caching t + ;;projectile-indexing-method 'alien ;; does not use ".projectile" + projectile-indexing-method 'hybrid + ;;projectile-indexing-method 'native + projectile-completion-system 'default) + (add-to-list 'projectile-globally-ignored-files "*.png") + (projectile-mode +1)) + +;; (add-to-list 'projectile-globally-ignored-files "node-modules") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; git +;; (use-package forge +;; :after magit) +(use-package magit + :ensure t + :config + (setq magit-delete-by-moving-to-trash nil + magit-clone-default-directory "~/dev/") + (magit-auto-revert-mode -1)) + + +(use-package git-gutter + :diminish + :config + (global-git-gutter-mode +1)) + +;; (use-package magithub +;; :after magit +;; ;;:ensure t +;; :config +;; (progn +;; (magithub-feature-autoinject t) +;; ;; (magithub-feature-autoinject '(commit-browse completion)) +;; (setq +;; magithub-clone-default-directory "~/dev"))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; delight +(use-package autorevert + :delight auto-revert-mode) +(use-package whole-line-or-region + :delight whole-line-or-region-local-mode) +;;(use-package abbrev +;; :delight abbrev-mode) +(use-package emacs + :delight + ;; (auto-fill-function " AF") + (auto-fill-function) + (abbrev-mode) + (visual-line-mode)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; tramp +(setq tramp-default-method "ssh" ; faster than default scp + enable-remote-dir-locals t + tramp-verbose 1) +;; (customize-set-variable 'tramp-syntax 'simplified) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; conf mode +;; strangely ".cnf" is not here... +(use-package conf-mode + :hook + (conf-mode . my/conf-mode-hook) + :mode + (("\\.cnf\\'" . conf-mode) + ("/auto\\." . conf-mode)) + :config + (defun my/conf-mode-hook () + (message "calling my/conf-mode-hook") + (setq-local comment-column 50))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ssh config +(use-package ssh-config-mode + :ensure t + :init + (autoload 'ssh-config-mode "ssh-config-mode" t) + :mode + (("/\\.ssh/config\\'" . ssh-config-mode) + ("/sshd?_config\\'" . ssh-config-mode) + ("/known_hosts\\'" . ssh-known-hosts-mode) + ("/authorized_keys2?\\'" . ssh-authorized-keys-mode)) + :hook + (ssh-config-mode . turn-on-font-lock)) + +;; (autoload 'ssh-config-mode "ssh-config-mode" t) +;; (add-to-list 'auto-mode-alist +;; '("/\\.ssh/config\\'" . ssh-config-mode)) +;; (add-to-list 'auto-mode-alist +;; '("/sshd?_config\\'" . ssh-config-mode)) +;; (add-to-list 'auto-mode-alist +;; '("/knownhosts\\'" . ssh-known-hosts-mode)) +;; (add-to-list 'auto-mode-alist +;; '("/authorized_keys2?\\'" . ssh-authorized-keys-mode)) +;; (add-hook 'ssh-config-mode-hook 'turn-on-font-lock) + +;; following does not work +;;(set-default 'tramp-default-proxies-alist +;; '("arwen" "root" "/ssh:arwen:")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; which-key +(use-package which-key + :diminish which-key-mode + :init + (which-key-mode) + :config + (which-key-setup-side-window-right-bottom) + (setq which-key-sort-order 'which-key-key-order-alpha + which-key-side-window-max-width 0.33 + which-key-idle-delay 1)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; flycheck +(use-package flycheck + :ensure t + :init + (require 'projectile) + (global-flycheck-mode) + :config + (setq-default flycheck-sh-bash-args '("-O" "extglob") + flycheck-disabled-checkers '(c/c++-clang c/c++-cppcheck c/c++-gcc)) + ;;(flycheck-add-mode 'sh-shellcheck 'bats-mode) + + :bind + (("H-n" . flycheck-next-error) + ("H-p" . flycheck-previous-error) + ("H-l" . flycheck-list-errors) + ("M-n" . flycheck-next-error) + ("M-p" . flycheck-previous-error))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; subversion +;;(require 'psvn) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Japanese/iBus: works out of the box now +;; ibus-mode +;;(require 'ibus) +;; Turn on ibus-mode automatically after loading .emacs +;;(add-hook 'after-init-hook 'ibus-mode-on) +;; Use C-SPC for Set Mark command +;;(ibus-define-common-key ?\C-\s nil) +;; Use C-/ for Undo command +;;(ibus-define-common-key ?\C-/ nil) +;; Change cursor color depending on IBus status +;;(setq ibus-cursor-color '("red" "blue" "limegreen")) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Some useful setups +;; mouse +;; does not change point when getting focus - DOES NOT WORK +;;x-mouse-click-focus-ignore-position t +;;focus-follows-mouse nil ; must reflect WM settings +;;mouse-autoselect-window nil ; pointer does not select window + +(global-set-key (kbd "C-h c") 'describe-char) +(global-set-key (kbd "C-x 4 C-b") 'switch-to-buffer-other-window) + +;; next example maps C-x C-x to the same as C-c +;; (global-set-key (kbd "C-x C-x") (lookup-key global-map (kbd "C-c"))) + +(setq inhibit-splash-screen t ; no spash screen + column-number-mode t ; displays line/column positions + kill-whole-line t ; C-k kills whole line + + ;; tab indents first, if indented, tries to autocomplete + ;; TOO DANGEROUS (it completes without asking!)... + ;; tab-always-indent t ; TAB always indent + tab-always-indent 'complete + completions-format 'vertical ; sort completions vertically + + ;; Removed: Use smartparens instead. + ;; show matching brace/paren + ;;show-paren-mode t + ;; style: parenthesis, expression, mixed + ;;show-paren-style 'parenthesis + + sentence-end-double-space nil ; who decided sentences should + ; end with two spaces ?? + ;; global-hl-line-sticky-flag t ; highlight line + tab-width 2 ; default tab width + ) + +(setq-default indent-tabs-mode nil) + +(icomplete-mode 0) ; minibuffer completion + ; soooo sloooow + +;; (global-hl-line-mode) ; line highlight + +(delete-selection-mode 1) ; replace region when inserting text + +;; fix mess with bidirectional (arabic/hebrew) +(setq-default bidi-display-reordering nil + bidi-paragraph-direction 'left-to-right) + +(setq display-time-24hr-format t) ; time format +(display-time-mode 0) ; disable time in the mode-line + +(defalias 'yes-or-no-p 'y-or-n-p) ; just 'y' or 'n' instead of yes/no + +(mouse-avoidance-mode 'exile) ; Avoid collision of mouse with point + +;;(menu-bar-mode 0) ; Disable the menu bar +;;(put 'downcase-region 'disabled nil) ; Enable downcase-region +;;(put 'upcase-region 'disabled nil) ; Enable upcase-region +;;(global-subword-mode 1) ; Iterate through CamelCase words +;;(fringe-mode 0) ; Disable fringes +(set-default-coding-systems 'utf-8) ; default encoding - obviously utf-8 + +;; enable recursive minibuffer +(minibuffer-depth-indicate-mode) +(setq enable-recursive-minibuffers t) + +;; copy from point to end of line (including '\n') +(defun my/mark-from-point-to-end-of-line () + "Copy text from point to end of line." + (interactive) + (set-mark (+ (line-end-position) 1)) + (kill-ring-save nil nil t)) + +(global-set-key (kbd "M-k") 'my/mark-from-point-to-end-of-line) +;; (global-set-key (kbd "C-k") 'kill-line) + + +;; minions: minor modes menu instead of (long) list on modeline +;;(use-package minions +;; :config (minions-mode 1)) + +;;(defun caadr (a) +;; (car(car(cdr a)))) +;;(defun mouse-set-point-2 (event) +;; (interactive "e") +;; (mouse-minibuffer-check event) +;; (let ((event-target-window (caadr event))) +;; (if (eql event-target-window (frame-selected-window)) +;; (posn-set-point (event-end event)) +;; (set-frame-selected-window nil event-target-window)))) +;; +;;(global-set-key [mouse-1] 'mouse-set-point-2) +;; +;;(global-unset-key [down-mouse-1]) + +;;(defadvice mouse-set-point (around cv/mouse-set-point (event) activate) +;; (let ((event-name (car event)) +;; (event-target-window (posn-window (event-start event)))) +;; (if (and (eql 'down-mouse-1 event-name) +;; (eql event-target-window (selected-window))) +;; ad-do-it +;; (select-window event-target-window)))) + +;; (defadvice mouse-drag-region (around cv/mouse-drag-region (event) activate) +;; (let ((event-target-window (posn-window (event-start event)))) +;; ; (if (eql event-target-window (selected-window)) +;; ; ad-do-it +;; ; (select-window event-target-window)))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; local functions +(defun my/indent-whole-buffer () + "Indent whole buffer. TODO: indent comments." + (interactive) + ;; (delete-trailing-whitespace) + ;; (untabify (point-min) (point-max)) + (indent-region (point-min) (point-max) nil)) + +(global-set-key (kbd "H-;") 'my/indent-whole-buffer) +(global-set-key (kbd "H-\\") 'my/indent-whole-buffer) + +(defvar my/temp-buffer-count 0) + +(defun my/make-temp-buffer (&optional mode) + "Create new temporary buffer named '*temp-digit*' with MODE mode (default: text)." + (interactive) + (let ((tmp (format "*temp-%d*" my/temp-buffer-count)) + (dir (concat my/emacs-tmpdir "/tmpbufs/"))) + (switch-to-buffer tmp) + (cd dir) + (if mode + (mode) + (text-mode)) + (message "New temp buffer (%s) created." tmp)) + (setq my/temp-buffer-count (1+ my/temp-buffer-count))) + +(global-set-key (kbd "C-c t") 'my/make-temp-buffer) + +(defun my/write-visit-file () + "Write current buffer/region to file, and visit it." + (interactive) + (let ((thefile (read-file-name + "Copy/visit file: " nil nil nil))) + (if (use-region-p) + (write-region (region-beginning) (region-end) thefile nil nil nil t) + (save-restriction + (widen) + (write-region (point-min) (point-max) thefile nil nil nil t))) + (find-file-noselect thefile))) + +(global-set-key (kbd "C-c w") 'my/write-visit-file) + +(defun my/before-save () + "Remove trailing spaces, remove 'org-mode' results blocks." + (delete-trailing-whitespace) + (when (derived-mode-p 'org-mode) + (org-babel-map-src-blocks nil (org-babel-remove-result)))) + +(add-hook 'before-save-hook 'my/before-save) +;;(global-set-key (kbd "C-c w") 'my/write-visit-file) + +;;; from https://github.com/zilongshanren/prelude/blob/master/core/prelude-core.el +(defun my/delete-buffer-and-file () + "Kill the current buffer and deletes the file it is visiting." + (interactive) + (let ((filename (buffer-file-name))) + (when filename + (if (vc-backend filename) + (vc-delete-file filename) + (when (y-or-n-p (format "Are you sure you want to delete %s? " filename)) + (delete-file filename) + (message "Deleted file %s" filename) + (kill-buffer)))))) + +(global-set-key (kbd "s-d") 'my/delete-buffer-and-file) + +;; from https://pages.sachachua.com/.emacs.d/Sacha.html +(defun my/smarter-move-beginning-of-line (arg) + "Move point back to indentation of beginning of line. + +Move point to the first non-whitespace character on this line. +If point is already there, move to the beginning of the line. +Effectively toggle between the first non-whitespace character and +the beginning of the line. + +If ARG is not nil or 1, move forward ARG - 1 lines first. If +point reaches the beginning or end of the buffer, stop there." + (interactive "^p") + (setq arg (or arg 1)) + + ;; Move lines first + (when (/= arg 1) + (let ((line-move-visual nil)) + (forward-line (1- arg)))) + + (let ((orig-point (point))) + (back-to-indentation) + (when (= orig-point (point)) + (move-beginning-of-line 1)))) + +;; remap C-a to `smarter-move-beginning-of-line' +(global-set-key [remap move-beginning-of-line] + 'my/smarter-move-beginning-of-line) + +;;(defun my/upcase-word() +;; "Upcase current word." +;; (interactive) +;; (save-excursion +;; (let* ((bounds (bounds-of-thing-at-point 'word)) +;; (beg (car bounds)) +;; (end (cdr bounds))) +;; (upcase-region beg end)))) + +;; redefine upcase/downcase-word to really do it. +(defun my/upcase-word() + "Upcase current word." + (interactive) + (save-excursion + (beginning-of-thing 'word) + (upcase-word 1))) + +(defun my/downcase-word() + "Downcase current word." + (interactive) + (save-excursion + (beginning-of-thing 'word) + (downcase-word 1))) + +(global-set-key (kbd "M-u") 'my/upcase-word) +(global-set-key (kbd "M-l") 'my/downcase-word) + +;; rewrite comment-kill to avoid filling kill-ring +;; From: https://emacs.stackexchange.com/a/5445/23591 +;; https://emacs.stackexchange.com/questions/5441/function-to-delete-all-comments-from-a-buffer-without-moving-them-to-kill-ring +(defun my/comment-delete (arg) + "Delete the first comment on this line, if any. Don't touch the kill ring. +With prefix ARG, delete comments on that many lines starting with this one." + (interactive "P") + (comment-normalize-vars) + (dotimes (_i (prefix-numeric-value arg)) + (save-excursion + (beginning-of-line) + (let ((cs (comment-search-forward (line-end-position) t))) + (when cs + (goto-char cs) + (skip-syntax-backward " ") + (setq cs (point)) + (comment-forward) + ;; (kill-region cs (if (bolp) (1- (point)) (point))) ; original + (delete-region cs (if (bolp) (1- (point)) (point))) ; change to delete-region + (indent-according-to-mode)))) + (if arg (forward-line 1)))) + +(defun my/comment-delete-dwim (beg end arg) + "Delete comments without touching the kill ring. +With active region, delete comments in region. With prefix, delete comments +in whole buffer. With neither, delete comments on current line." + (interactive "r\nP") + (let ((lines (cond (arg + (count-lines (point-min) (point-max))) + ((region-active-p) + (count-lines beg end))))) + + (save-excursion + (when lines + (goto-char (if arg (point-min) beg))) + (my/comment-delete (or lines 1))))) + +;; kill remove all consecutive blank lines (keep one only). +(defun my/single-blank-lines () + "Keep only one blank lines in buffer, keep one when multiple ones." + (interactive) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "\\(^[[:space:]\n]+\\)\n" nil t) + (replace-match "\n")))) + +(defun my/collapse-blank-lines (beg end) + "Delete all consecutive `blank' lines in region or buffer, keeping one only." + (interactive "r") + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "\\(^[[:space:]\n]+\\)\n" nil t) + (replace-match "\n")))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; shell, eshell modes +;; will tell e-shell to run in visual mode +'(eshell-visual-commands + (quote + ("vi" "screen" "top" "less" "more"))) + +;; ignore duplicate input in shell-mode +(use-package shell + :config + (progn + (setq comint-input-ignoredups t))) + +;; https://www.emacswiki.org/emacs/SwitchingBuffers +(defun my/switch-buffers () + "Switch the buffers between the two last frames." + (interactive) + (let ((this-frame-buffer nil) + (other-frame-buffer nil)) + (setq this-frame-buffer (car (frame-parameter nil 'buffer-list))) + (other-frame 1) + (setq other-frame-buffer (car (frame-parameter nil 'buffer-list))) + (switch-to-buffer this-frame-buffer) + (other-frame 1) + (switch-to-buffer other-frame-buffer))) + +(defun my/switch-upper-window () + "Switch main window and upper one." + (interactive) + (window-swap-states my/main-window my/upper-window)) +(defun my/switch-lower-window () + "Switch main window and lower one." + (interactive) + (window-swap-states my/main-window my/below-window)) + +(global-set-key (kbd "C-c u") 'my/switch-upper-window) +(global-set-key (kbd "C-c l") 'my/switch-lower-window) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; recent files +(require 'recentf) +(setq recentf-max-saved-items 20 + recentf-max-menu-items 10) +(recentf-mode) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vc-mode modeline +;; inspired from: +;; https://emacs.stackexchange.com/questions/10955 +(advice-add #'vc-git-mode-line-string :filter-return #'my-replace-git-status) +(defun my-replace-git-status (tstr) + "Replace git `variable:vc-mode' string, for a modified icon followed by TSTR without \"git\"." + (let* ((tstr (replace-regexp-in-string "Git" "" tstr)) + (first-char (substring tstr 0 1)) + (rest-chars (substring tstr 1))) + (cond + ((string= ":" first-char) ; Modified + (replace-regexp-in-string "^:" "⚡️" tstr)) + ((string= "-" first-char) ; No change + (replace-regexp-in-string "^-" "✔️" tstr)) + ((string= "@" first-char) ; Added + (replace-regexp-in-string "^@" "️✑" tstr)) + (t tstr)))) + +(setf mode-line-modes + (mapcar (lambda (item) + (if (and (listp item) + (eq :propertize (car item)) + (listp (cdr item)) + (string= "" (car (cadr item))) + (eq 'mode-name (cadr (cadr item)))) + (cl-list* (car item) + '(:eval (if (eq 'sh-mode major-mode) + '("" sh-shell) + '("" mode-name))) + (cddr item)) + item)) + mode-line-modes)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hippie +;; (setq hippie-expand-try-functions-list +;; '(yas-hippie-try-expand +;; try-expand-all-abbrevs +;; try-complete-file-name-partially +;; try-complete-file-name +;; try-expand-dabbrev +;; try-expand-dabbrev-from-kill +;; try-expand-dabbrev-all-buffers +;; try-expand-list +;; try-expand-line +;; try-complete-lisp-symbol-partially +;; try-complete-lisp-symbol)) + +;; (use-package yasnippet +;; :diminish yas-minor-mode +;; :init (yas-global-mode) +;; :config +;; (progn +;; (yas-global-mode) +;; (add-hook 'hippie-expand-try-functions-list 'yas-hippie-try-expand) +;; (setq yas-key-syntaxes '("w_" "w_." "^ ")) +;; ;;(setq yas-installed-snippets-dir (concat user-emacs-directory "yassnippet")) +;; (setq yas-expand-only-for-last-commands nil) +;; (yas-global-mode 1) +;; (bind-key "\t" 'hippie-expand yas-minor-mode-map) +;; (add-to-list 'yas-prompt-functions 'shk-yas/helm-prompt))) + +;; (use-package yasnippet-snippets +;; :after (yasnippet) +;; :defer t +;; :config +;; (yas-global-mode 1)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; key Bindings +(global-set-key (kbd "") 'my/indent-whole-buffer) +;;(global-set-key (kbd "C-a") 'back-to-indentation) + +;; https://github.com/technomancy/better-defaults/blob/master/better-defaults.el#L78 +(global-set-key (kbd "M-/") 'hippie-expand) +(global-set-key (kbd "M-z") 'zap-up-to-char) +(global-set-key (kbd "C-s") 'isearch-forward-regexp) +(global-set-key (kbd "C-r") 'isearch-backward-regexp) +;; (global-set-key (kbd "C-M-s") 'isearch-forward) ; conflict with org +;; (global-set-key (kbd "C-M-r") 'isearch-backward) + +;; goto-line/goto-char +;; (global-set-key (kbd "C-c g") 'goto-line) +;; (global-set-key (kbd "C-c c") 'goto-char) +(global-set-key (kbd "s-g g") 'goto-line) +(global-set-key (kbd "s-g c") 'goto-char) +(global-set-key (kbd "s-g s-g") 'goto-line) +(global-set-key (kbd "s-g s-c") 'goto-char) + +(global-set-key (kbd "C-x w") 'compare-windows) + +;; multiple cursors +(global-set-key (kbd "C->") 'mc/mark-next-like-this) +(global-set-key (kbd "C-<") 'mc/mark-previous-like-this) +(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this) +(global-set-key (kbd "C-S-") 'mc/add-cursor-on-click) +(global-set-key (kbd "C-M-m") 'mc/mark-all-dwim) + +(global-set-key (kbd "C-x g") 'magit-status) + +;; (global-set-key (kbd "s-SPC") 'delete-blank-lines) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; define my own keymap (s-c) +;; first, define a keymap, with Super-c as prefix. +(defvar my/keys-mode-map (make-sparse-keymap) + "Keymap for my/keys-mode.") + +(defvar my/keys-mode-prefix-map (lookup-key global-map (kbd "s-c")) + "Keymap for custom key bindings starting with s-c prefix.") + +;; (define-key my/keys-mode-map (kbd "s-c") my/keys-mode-prefix-map) + +(define-minor-mode my/keys-mode + "A minor mode for custom key bindings." + :lighter "s-c" + :keymap 'my/keys-mode-map + :global t) + +(defun my/prioritize-keys + (file &optional noerror nomessage nosuffix must-suffix) + "Try to ensure that custom key bindings always have priority." + (unless (eq (caar minor-mode-map-alist) 'my/keys-mode) + (let ((my/keys-mode-map (assq 'my/keys-mode minor-mode-map-alist))) + (assq-delete-all 'my/keys-mode minor-mode-map-alist) + (add-to-list 'minor-mode-map-alist my/keys-mode-map)))) + +(advice-add 'load :after #'my/prioritize-keys) + +;;(global-set-key (kbd "C-c t") #'make-temp-buffer) +;;(define-key my/keys-mode-prefix-map (kbd "r b") #'revert-buffer) +;;(define-key my/keys-mode-prefix-map (kbd "r b") 'revert-buffer) + +;;(define-key ctl-x-map ";" 'indent-region) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; helm +;; Partially from http://pages.sachachua.com/.emacs.d/Sacha.html#org480d137 +;; and http://tuhdo.github.io/helm-intro.html +(use-package helm + :diminish helm-mode + :init + ;;(progn + ;;(require 'helm-config) + ;;(require 'helm-autoloads) + (require 'pcomplete) + (require 'helm-projectile) + (setq + helm-candidate-number-limit 100 + ;; From https://gist.github.com/antifuchs/9238468 + helm-split-window-inside-p t ; open helm buffer in current window + + helm-idle-delay 0.0 ; update fast sources immediately (doesn't). + helm-input-idle-delay 0.01 ; this actually updates things + ; reeeelatively quickly. + helm-yas-display-key-on-candidate t + helm-quick-update t + helm-M-x-requires-pattern nil + helm-ff-skip-boring-files t + helm-ff-guess-fap-urls nil ; do not use ffap for URL at point + + helm-projectile-fuzzy-match nil + + helm-buffers-truncate-lines nil ; truncate lines in buffers list + helm-buffer-max-length nil ; buffer name length is longest one + helm-prevent-escaping-from-minibuffer nil ; allow escaping from minibuffer (C-o) + helm-scroll-amount 8 ; scroll 8 lines other window M- + + helm-ff-file-name-history-use-recentf t + helm-echo-input-in-header-line t) ; ?? + ;;) + (helm-mode) + (helm-projectile-on) + ;;) + :bind + (("C-c h" . helm-mini) + ("C-h a" . helm-apropos) + ("C-x C-b" . helm-buffers-list) + ("C-x C-f" . helm-find-files) + ("C-x b" . helm-buffers-list) + ("M-y" . helm-show-kill-ring) + ("M-x" . helm-M-x) + ("C-x c o" . helm-occur) + ("C-x c s" . helm-swoop) + ("C-x c y" . helm-yas-complete) + ("C-x c Y" . helm-yas-create-snippet-on-region) + ;;("C-x c b" . my/helm-do-grep-book-notes) + ("C-x c SPC" . helm-all-mark-rings) + :map helm-map + ;; rebind tab/C-i to run persistent action + ("" . helm-execute-persistent-action) + ("C-i" . helm-execute-persistent-action) ; make TAB works in terminal + ("C-z" . helm-select-action) ; list actions using C-z + + ;; bookmarks + + )) + +(use-package helm-swoop + :bind + (("M-i" . helm-swoop) + ("M-I" . helm-swoop-back-to-last-point) + ("C-c M-i" . helm-multi-swoop) + ("C-x M-i" . helm-multi-swoop-all) + ) + :config + (progn + (define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch) + (define-key helm-swoop-map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop))) + +(use-package helm-flycheck + :requires (helm)) + +;; Turn off ido mode in case I enabled it accidentally +;; (ido-mode -1) + +;; helm will be used to describe bindings +(use-package helm-descbinds + :defer t + :bind (("C-h b" . helm-descbinds) + ("C-h w" . helm-descbinds))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wc-mode +;;(require 'wc-mode) +;;(global-set-key (kbd "C-c C-w") 'wc-mode) +;;(setq wc-modeline-format "WC[%C/%tc]") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; kill/copy line if no region +(use-package whole-line-or-region + :delight whole-line-or-region-local-mode + ;;:diminish whole-line-or-region-local-mode + :commands + (whole-line-or-region-global-mode) + :init + (whole-line-or-region-global-mode 1) + ;; remove comment remaps + (define-key whole-line-or-region-local-mode-map [remap comment-dwim] nil) + (define-key whole-line-or-region-local-mode-map [remap comment-region] nil) + (define-key whole-line-or-region-local-mode-map [remap uncomment-region] nil) + :config + ;;(whole-line-or-region-global-mode 1) + ;; remove comment remaps + ;;(define-key whole-line-or-region-local-mode-map [remap comment-dwim] nil) + ;;(define-key whole-line-or-region-local-mode-map [remap comment-region] nil) + ;;(define-key whole-line-or-region-local-mode-map [remap uncomment-region] nil) + ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; undo tree +(use-package undo-tree + :diminish undo-tree-mode + :defer t + :init + (progn + (defalias 'redo 'undo-tree-redo) + (defalias 'undo 'undo-tree-undo) + (global-undo-tree-mode 1)) + :config + (progn + (setq undo-tree-visualizer-timestamps t + undo-tree-visualizer-diff t + undo-tree-enable-undo-in-region t + ;;undo-tree-auto-save-history t + ) + (let ((undo-dir (concat my/emacs-tmpdir "/undo-tree/"))) + (setq undo-tree-history-directory-alist + `(("." . ,undo-dir))) + (unless (file-exists-p undo-dir) + (make-directory undo-dir t))))) + +;; useful to come back to working window after a buffer has popped up +;; C-c to come back +(use-package winner + :init (winner-mode 1)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; windows navigation +(use-package windmove + :bind (("H-" . windmove-right) + ("H-" . windmove-left) + ("H-" . windmove-up) + ("H-" . windmove-down) + )) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; auto completion +(use-package company + :diminish "Co" + :defer t + :bind + (:map company-active-map + ("RET" . nil) + ;; ([return] . nil) + ("TAB" . company-complete-selection) + ;; ([tab] . company-complete-selection) + ("" . company-complete-common)) + :config + ;; Too slow ! + ;; (global-company-mode 1) + (setq-default + company-idle-delay .2 + company-minimum-prefix-length 3 + company-require-match nil + company-tooltip-align-annotations t) + :hook + (('prog-mode . 'company-mode))) + +;;(add-to-list 'company-backends 'company-shell) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; dot-mode (vi-like redo) +;; repo: https://github.com/wyrickre/dot-mode +(use-package dot-mode + :diminish + :bind (("" . dot-mode-execute) + ("C-M-" . dot-mode-override) ; store next keystroke + ("C-c " . dot-mode-copy-to-last-kbd-macro) + + ("C-." . dot-mode-execute) ; default bindings below + ("C-M-." . dot-mode-override) + ("C-c ." . dot-mode-copy-to-last-kbd-macro)) + + :init + (global-dot-mode 1) ; enabled in all buffers + (setq dot-mode-verbose nil + dot-mode-ignore-undo t ; don't consider undos + dot-mode-global-mode t)) ; can redo in different buffer + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; change copy/kill region +;; from sacha +(defadvice kill-region (before slick-cut activate compile) + "When called interactively with no active region, kill a single line instead." + (interactive + (if mark-active (list (region-beginning) (region-end)) + (list (line-beginning-position) + (line-beginning-position 2))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; browse-url / webpaste (pastebin) +(use-package browse-url + :ensure t + :defer t + :bind (( "C-c b" . browse-url ))) + +(use-package webpaste + :ensure t + + :bind (("C-c P b" . webpaste-paste-buffer) + ("C-c P r" . webpaste-paste-region)) + + :hook (webpaste-return-url . my/webpaste-return-url-hook) + + :config + (progn + (setq webpaste-provider-priority '("dpaste.org" "gist.github.com" "paste.mozilla.org" + "dpaste.org" "ix.io") + webpaste-paste-confirmation t ; prompts before sending + ;; nothing below: We do in webpaste-return-url hook + webpaste-open-in-browser nil ; do not open in browser + webpaste-add-to-killring nil ; do not add url to killring + webpaste-paste-raw-text nil ; try to detect language + )) + (defun my/webpaste-return-url-hook (url) + (message "Webpaste: %S" url) + (browse-url-xdg-open url))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; markdown mode +;; https://github.com/jrblevin/markdown-mode/issues/578 +(setq native-comp-deferred-compilation-deny-list '("markdown-mode\\.el$")) +;; inspired from: https://github.com/zaeph/.emacs.d/blob/master/init.el +;; doc: https://leanpub.com/markdown-mode/read +(use-package markdown-mode + :ensure t + :init + ;;(setq markdown-command "pandoc" + ;; markdown-command-needs-filename t) + ;; for pandoc: + (setq markdown-command + (concat "pandoc" + " --quiet" + " --from=markdown --to=html" + " --standalone --mathjax --highlight-style=pygments")) + ;; https://github.com/jrblevin/markdown-mode/issues/578 + ;; (setq markdown-nested-imenu-heading-index nil) + :mode + (("\\.md\\'" . gfm-mode) + ("\\.markdown\\'" . gfm-mode)) + :hook + ((markdown-mode . visual-line-mode) + (markdown-mode . flyspell-mode))) + +;; markdown-toc mode +;; (require 'dash) +;; drop all H1 titles +(custom-set-variables + '(markdown-toc-user-toc-structure-manipulation-fn + (lambda (toc-structure) + (--map (-let (((level . label) it)) + (cons (- level 1) label)) + (cdr toc-structure))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; text mode +;; for some reason, I was not able to "use-package". +;;(use-package text-mode +;; :preface (provide 'text-mode) +;; :ensure nil +;; :mode +;; (("\\.txt\\'" . text-mode) +;; ("\\.text\\'" . text-mode)) +;; :config +;; (progn +;; (message "I am in text-mode- use-package") +;; (setq visual-line-fringe-indicators '(nil right-curly-arrow)) +;; (turn-on-visual-line-mode) ; enable visual-line +;; (auto-fill-mode -1)) ; disable auto-fill +;; ) + +(defun my/text-mode-hook () + "X br text mode hook." + (setq visual-line-fringe-indicators '(nil right-curly-arrow)) + (turn-on-visual-line-mode) ; enable visual-line + (auto-fill-mode -1)) ; disable auto-fill + +(add-hook 'text-mode-hook 'my/text-mode-hook) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; makefile mode +(defun my/makefile-mode-hook () + "X br text mode hook." + (message "entering Makefile-mode") + (setq indent-tabs-mode t + tab-width 4 + comment-column 60)) + +(add-hook 'text-mode-hook 'my/text-mode-hook) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org mode +;; mediawiki export +(require 'ox-mediawiki) +(require 'org-tempo) +;;(require 'ox-extra) + +(defun my/org-mode-hook () + "X br org-mode-hook." + (interactive) + (setq fill-column 78 + ;; show structure at startup + org-startup-folded 'content + truncate-lines nil + org-src-fontify-natively t ; nil: disable coloring in code blocks + org-src-preserve-indentation t + org-src-tab-acts-natively t + org-src-window-setup 'current-window + org-src-block-faces nil + ;; org-descriptive-links nil + org-link-descriptive nil + ;; no TOC by default in export + ;; org-export-with-toc nil + ;;org-html-head-include-default-style nil + ;;org-src-block-faces '(("emacs-lisp" (:background "#EEE2FF")) + ;; ("python" (:background "#E5FFB8"))) + org-todo-keywords '((sequence "TODO" "STARTED" "WAITING" + ;; "REVIEW(r)" "SUBMIT(m)" + "|" "DONE" "CANCELED")) + ;;org-todo-keyword-faces '(("TODO" :foreground "red" :weight bold) + ;; ("STARTED" :foreground "cyan" :weight bold) + ;; ("WAITING" :foreground "gold" :weight bold) + ;; ("DONE" :foreground "sea green" :weight bold) + ;; ("LATER" :foreground "dark red" :weight bold) + ;; ("CANCELED" :foreground "dark red" :weight bold)) + + org-support-shift-select t + org-indent-mode-turns-on-hiding-stars nil + org-export-allow-bind-keywords t + visual-line-fringe-indicators '(nil right-curly-arrow) + ) + ;; change "=" (verbatim) to be different from "~" (code) + (push '(verbatim . "%s") org-html-text-markup-alist) + ;; to allow hiding a headline with :ignore: tag + ;;(ox-extras-activate '(ignore-headlines)) + ;; visual-line mode + (org-indent-mode) + (visual-line-mode) + ;;(setq visual-line-fringe-indicators '(nil right-curly-arrow)) + (auto-fill-mode 1) + (define-key org-mode-map + (kbd "C-c l") 'my/org-toggle-link-display) + (define-key org-mode-map + (kbd "C-c x") 'org-mw-export-as-mediawiki)) + +(defun my/org-toggle-link-display () + "Toggle the literal or descriptive display of links." + (interactive) + (if org-link-descriptive + (progn (remove-from-invisibility-spec '(org-link)) + (org-restart-font-lock) + (setq org-link-descriptive nil)) + (progn (add-to-invisibility-spec '(org-link)) + (org-restart-font-lock) + (setq org-link-descriptive t)))) + +(add-hook 'org-mode-hook 'my/org-mode-hook) + +;; inspired from https://orgmode.org/guide/Introduction.html +(global-set-key (kbd "H-c l") 'org-store-link) +(global-set-key (kbd "H-c a") 'org-agenda) +(global-set-key (kbd "H-c c") 'org-capture) + +;; babel languages +(org-babel-do-load-languages + 'org-babel-load-languages + '((calc . t) + (emacs-lisp . t) + (sql . t) + (perl . t) + (shell . t))) + +;; (plantuml . t) +;; (python . t) +;; (ruby . t) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vimrc mode +(add-hook + 'vimrc-mode-hook + (lambda () + (setq indent-tabs-mode nil ; do not use tabs + comment-column 50))) + +(require 'vimrc-mode) +(add-to-list 'auto-mode-alist '("\\.vim\\(rc\\)?\\'" . vimrc-mode)) +;;(add-to-list 'auto-mode-alikst '(".vim\\(rc\\)?$" . vimrc-mode)) +;;(add-to-list 'auto-mode-alist '(".vim\\(rc\\)?" . vimrc-mode)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; perl (cperl) mode +(defalias 'perl-mode 'cperl-mode) +(add-hook + 'perl-lisp-mode-hook + (lambda () + (setq indent-tabs-mode nil ; do not use tabs + tab-width 2))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Cobol mode +(setq auto-mode-alist + (append + '(("\\.cob\\'" . cobol-mode) + ("\\.cbl\\'" . cobol-mode) + ("\\.cpy\\'" . cobol-mode)) + auto-mode-alist)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; C mode +(defun my/indent-maybe-cpp-directive () + "Indent c pre-processor line according to my own standard." + (interactive) + (save-excursion + (back-to-indentation) + (when (looking-at "#") + (delete-char 1) + (indent-according-to-mode) + (beginning-of-line) + (when (looking-at " ") + (delete-char 1)) + (insert "#") + (beginning-of-line)))) + +(defun my/c-style () + "Some general C setup." + (interactive) + (c-set-style "k&r") + (c-set-offset 'knr-argdecl-intro '+) + (c-set-offset 'case-label '+) + (bind-keys :map c-mode-map + ("s-;" . my/indent-maybe-cpp-directive) + ("" . projectile-compile-project) + ("F" . self-insert-command)) + + (auto-complete-mode 0) + ;;(yas-minor-mode 1) + (flycheck-mode 1) + ;;(ggtags-mode 1) + (show-smartparens-mode 1) + (company-mode 1) + (auto-fill-mode 1) + (setq company-backends '((company-dabbrev-code company-gtags)) + c-basic-offset 4 + comment-column 50 + fill-column 100 + c-ignore-auto-fill '(string cpp) + comment-auto-fill-only-comments nil + comment-style 'extra-line)) + +(add-hook 'c-mode-hook 'my/c-style) + +;;;;;;;;;;;;; linux kernel style +(defun c-lineup-arglist-tabs-only (ignored) + "Line up argument lists by tabs, not spaces. fuck flycheck IGNORED." + (let* ((anchor (c-langelem-pos c-syntactic-element)) + (column (c-langelem-2nd-pos c-syntactic-element)) + (offset (- (1+ column) anchor)) + (steps (floor offset c-basic-offset))) + (* (max steps 1) + c-basic-offset))) + +;; Eudyptula challenge +(defvar my/eudyptula-dir + (expand-file-name "~/dev/eudyptula") + "Eudyptula challenge directory.") +(defvar my/kernel-dir + (concat my/eudyptula-dir "/linux") + "Kernel tree within Eudyptula challenge.") +(defvar my/kernel-scripts-dir + (concat my/kernel-dir "/scripts") + "Scripts dir within Eudyptula challenge's kernel directory.") +(defvar my/kernel-include-dirs + (list (concat my/kernel-dir "/include") + (concat my/kernel-dir "/arch/x86/include") + (concat my/kernel-dir "/arch/x86/include/generated")) + "Kernel include directory.") +(defvar my/running-kernel-include-dirs + (let ((kernel (concat "/lib/modules/" + (string-trim (shell-command-to-string "uname -r")) + "/build"))) + (list (concat kernel "/include") + (concat kernel "/arch/x86/include"))) + "Running kernel include directory.") + +;; https://stackoverflow.com/questions/29709967/using-flycheck-flymake-on-kernel-source-tree +(flycheck-define-checker my/flycheck-kernel-checker + "Linux source checker" + :command + ( + "make" "C=1" "-C" (eval my/kernel-dir) + (eval (concat "M=" + (file-name-directory buffer-file-name))) + (eval (concat (file-name-sans-extension (file-name-nondirectory buffer-file-name)) + ".o")) + ) + :error-patterns + ((error line-start + (message "In file included from") " " (file-name) ":" line ":" + column ":" + line-end) + (info line-start (file-name) ":" line ":" column + ": note: " (message) line-end) + (warning line-start (file-name) ":" line ":" column + ": warning: " (message) line-end) + (error line-start (file-name) ":" line ":" column + ": " (or "fatal error" "error") ": " (message) line-end)) + :modes (c-mode c++-mode)) +;; :error-filter +;; (lambda (errors) +;; (let ((errors (flycheck-sanitize-errors errors))) +;; (dolist (err errors) +;; (let* ((fn (flycheck-error-filename err)) +;; ;; flycheck-fix-error-filename converted to absolute, revert +;; (rn0 (file-relative-name fn default-directory)) +;; ;; make absolute relative to "make -C dir" +;; (rn1 (expand-file-name rn0 my/kernel-dir)) +;; ;; relative to source +;; (ef (file-relative-name rn1 default-directory)) +;; ) +;; (setf (flycheck-error-filename err) ef) +;; ))) +;; errors) + +;; (defun my/flycheck-mode-hook () +;; "Flycheck mode hook." +;; (setq flycheck-linux-makefile my/kernel-dir) +;; (flycheck-select-checker 'my/flycheck-kernel-checker) +;; ) + +(dir-locals-set-class-variables + 'linux-kernel + '((c-mode + . ((c-basic-offset . 8) + (c-label-minimum-indentation . 0) + (c-offsets-alist + . ((arglist-close . c-lineup-arglist) + (arglist-cont-nonempty . (c-lineup-gcc-asm-reg c-lineup-arglist)) + (arglist-intro . +) + (brace-list-intro . +) + (c . c-lineup-C-comments) + (case-label . 0) + (comment-intro . c-lineup-comment) + (cpp-define-intro . +) + (cpp-macro . -1000) + (cpp-macro-cont . +) + (defun-block-intro . +) + (else-clause . 0) + (func-decl-cont . +) + (inclass . +) + (inher-cont . c-lineup-multi-inher) + (knr-argdecl-intro . 0) + (label . -1000) + (statement . 0) + (statement-block-intro . +) + (statement-case-intro . +) + (statement-cont . +) + (substatement . +))) + (indent-tabs-mode . t) + (show-trailing-whitespace . t) + (eval . (flycheck-select-checker 'my/flycheck-kernel-checker) + ;; (setq flycheck-gcc-include-path my/kernel-include-dirs) + ) + )))) + +;; (setq flycheck-checkers (delete 'c/c++-clang flycheck-checkers)) + +;; linux kernel style +(defun my/maybe-linux-style () + "Apply linux kernel style when buffer path contain 'eudyptula'." + (interactive) + (when (and buffer-file-name + (string-match "eudyptula" buffer-file-name)) + (setq flycheck-checkers (delete '(c/c++-clang c/c++-cppcheck) flycheck-checkers) + flycheck-gcc-include-path my/kernel-include-dirs + flycheck-clang-include-path my/kernel-include-dirs))) + +;; (add-hook 'c-mode-hook 'my/maybe-linux-style) + +(dir-locals-set-directory-class my/eudyptula-dir 'linux-kernel) + +;; (add-hook 'flycheck-mode-hook 'my/flycheck-mode-hook) + +(defun my/checkpatch (file &optional nointree noterse nofilemode) + "Run checkpatch on FILE, or current buffer if FILE is nil. + +If NOTERSE is t, a full report will be done. If NOFILEMODE is t, FILE +is supposed to be a patchfile (otherwise a regular source file). +If NOINTREE is t, check will be done on file outside `my/kernel-dir'" + ;;(interactive) + (interactive "FFile name (default: current buffer): ") + (let* ((ckp (concat my/kernel-scripts-dir "checkpatch.pl ")) + (fn (or file (buffer-file-name))) + (terse (if noterse "" "--terse ")) + (tree (if nointree "--notree " "")) + (fm (if nofilemode "" "--file ")) + (opt (concat "--emacs --color=never " terse tree fm))) + (setq my/compile (concat ckp opt fn)) + (compile (concat ckp opt fn)))) + +(defun my/checkstaging () + "Zobi." + (interactive) + (my/checkpatch "drivers/staging/*/*.[ch]")) + +;; add kernel includes +;;(string-trim (shell-command-to-string "uname -r")) + +;; to avoid "free variable" warnings at compile +;; (eval-when-compile +;; (require 'cc-defs)) + +;; (add-hook 'c-mode-common-hook +;; (lambda () +;; ;; Add kernel style +;; (c-add-style +;; "linux-tabs-only" +;; '("linux" (c-offsets-alist +;; (arglist-cont-nonempty +;; c-lineup-gcc-asm-reg +;; c-lineup-arglist-tabs-only)))))) + +;; linux kernel style +;; (defun maybe-linux-style () +;; "Apply linux kernel style when buffer path contains 'linux'." +;; (interactive) +;; (when (and buffer-file-name +;; (string-match "linux" buffer-file-name)) +;; (c-set-style "linux"))) + +;; (add-hook 'c-mode-hook 'maybe-linux-style) + +;; ;; (defun br-linux-style () +;; ;; "Line up argument lists by tabs, not spaces" +;; ;; (interactive) +;; ;; (setq indent-tabs-mode t) +;; ;; (setq show-trailing-whitespace t) +;; ;; (c-set-style "linux-tabs-only")) + +;; (add-hook 'c-mode-hook +;; (lambda () +;; (let ((filename (buffer-file-name))) +;; ;; Enable kernel mode for the appropriate files +;; (when (and filename +;; (or (string-match "dev/eudyptula" filename) +;; (string-match "dev/kernel" filename))) +;; ;;(string-match (expand-file-name "~/dev/Eudyptula") +;; ;; (string-match "Eudyptula" buffer-file-name)) +;; ;;(cl-search "eudyptula" buffer-file-name)) +;; ;;(setq indent-tabs-mode t) +;; (setq show-trailing-whitespace t) +;; (c-set-style "linux-tabs-only"))))) + +;; exercism C style +(defvar my/exercism-dir + (expand-file-name "~/dev/exercism-tracks/") + "Exercism challenge directory.") + +(dir-locals-set-class-variables + 'exercism-style + '((c-mode + . ((c-basic-offset . 3) + (c-label-minimum-indentation . 0) + (c-offsets-alist + . ((arglist-close . c-lineup-arglist) + (arglist-cont-nonempty . (c-lineup-gcc-asm-reg c-lineup-arglist)) + (arglist-intro . +) + (brace-list-intro . +) + (c . c-lineup-C-comments) + (case-label . 0) + (comment-intro . c-lineup-comment) + (cpp-define-intro . +) + (cpp-macro . -1000) + (cpp-macro-cont . +) + (defun-block-intro . +) + (else-clause . 0) + (func-decl-cont . +) + (inclass . +) + (inher-cont . c-lineup-multi-inher) + (knr-argdecl-intro . 0) + (label . -1000) + (statement . 0) + (statement-block-intro . +) + (statement-case-intro . +) + (statement-cont . +) + (substatement . +))) + (indent-tabs-mode . nil) + (fill-column . 80) + (show-trailing-whitespace . t) + (comment-column . 33) + ;;(eval . (flycheck-select-checker 'my/flycheck-kernel-checker) + ;; (setq flycheck-gcc-include-path my/kernel-include-dirs) + ;;) + )))) + +(dir-locals-set-directory-class my/exercism-dir 'exercism-style) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; emacs lisp mode +(defun my/emacs-lisp-mode-hook () + "My Emacs Lisp mode hook." + (interactive) + (setq + indent-tabs-mode nil + tab-width 2 + lisp-body-indent 2 + ;; lisp-indent-offset 2 + + comment-column 50 + fill-column 128 + comment-auto-fill-only-comments t + auto-fill-mode t) + + (define-key emacs-lisp-mode-map + (kbd "") 'reindent-then-newline-and-indent)) + +(add-hook + 'lisp-interaction-mode-hook + (lambda () + (define-key lisp-interaction-mode-map + (kbd "") 'eval-last-sexp))) + +(add-hook + 'lisp-mode-hook + (lambda () + (outline-minor-mode) + (make-local-variable 'outline-regexp) + (setq outline-regexp "^(.*") + (ignore-errors (semantic-default-elisp-setup)) + (set (make-local-variable lisp-indent-function) + 'common-lisp-indent-function))) + +(add-hook 'emacs-lisp-mode-hook 'my/emacs-lisp-mode-hook) + + +;; eldoc - provides minibuffer hints when working in elisp +(use-package "eldoc" + :diminish eldoc-mode + :commands turn-on-eldoc-mode + :defer t + :init + (progn + (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode) + (add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode) + (add-hook 'ielm-mode-hook 'turn-on-eldoc-mode))) + +;; aggressive indent +;; (add-hook 'emacs-lisp-mode-hook #'aggressive-indent-mode) +;; (add-hook 'css-mode-hook #'aggressive-indent-mode) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lisp interaction mode + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; php mode +;;TODO (use-package php +;; +;; ) +(defun my/php-send-buffer () + "Send current buffer to PHP for execution. +The output will appear in the buffer *PHP*." + (interactive) + (php-send-region (if (string-match "\\(^#!.*$\\)" (buffer-string) nil) + (+ 1 (point-min) (match-end 1)) + (point-min)) + (point-max))) + +(defun my/php-mode-hook () + "Hook for php-mode." + (interactive) + (setq indent-tabs-mode nil + c-basic-offset 4 + comment-column 50 + fill-column 128 + comment-auto-fill-only-comments t + auto-fill-mode t + php-mode-template-compatibility nil) + ;;php-executable "php -f") + (paren-toggle-open-paren-context 1) + (php-enable-default-coding-style) + (c-set-offset 'case-label '+) + (define-key php-mode-map + (kbd "C-c f") 'php-search-documentation) + (define-key php-mode-map + (kbd "C-c r") 'my/php-send-buffer) + ;;(auto-complete-mode t) + ;;(require 'ac-php) + ;;(setq ac-sources '(ac-source-php)) + (require 'company-php) + (set (make-local-variable 'company-backends) + '((company-ac-php-backend company-dabbrev-code) + company-capf company-files)) + ) + +(use-package phpactor :ensure t) +(use-package company-phpactor :ensure t) +;;(setq lsp-clients-php-server-command '("phpactor" "language-server")) + +;; Add lsp or lsp-deferred function call to functions for your php-mode customization +;; https://phpactor.readthedocs.io/en/master/lsp/emacs.html +(defun init-php-mode () + "Zobi." + (lsp-deferred)) + +(with-eval-after-load 'php-mode + ;; If phpactor command is not installed as global, write the full path + ;; (custom-set-variables '(lsp-phpactor-path "/path/to/phpactor")) + (add-hook 'php-mode-hook #'init-php-mode)) + +;;(company-mode t) +;;(require 'company-php) +;;(set (make-local-variable 'company-backends) +;; '((company-ac-php-backend company-dabbrev-code) +;; company-capf company-files))) + +;; (add-to-list 'company-backends 'company-ac-php-backend )) + +(add-hook 'php-mode-hook 'my/php-mode-hook) + +;; autoload php-html-helper-mode +;;(autoload 'php-html-helper-mode "html-helper-mode" "html-helper-mode" t) +;;(add-to-list 'auto-mode-alist '("\\.inc\\'" . php-html-helper-mode)) +;;(add-to-list 'auto-mode-alist '("\\.html\\'" . html-mode)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; go mode +(add-hook + 'go-mode-hook + (lambda () + ;; (setq-default) + (setq + indent-tabs-mode nil + tab-width 2 + standard-indent 2))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; js mode +(add-hook + 'js-mode-hook + (lambda () + (setq + indent-tabs-mode nil + js-indent-level 3 + ;; tab-width 3 + c-basic-offset 3 + comment-column 50 + fill-column 128 + comment-auto-fill-only-comments t + auto-fill-mode t) + (define-key js-mode-map + (kbd "") 'reindent-then-newline-and-indent))) + +(use-package json-mode + :defer t + :mode "\\.json\\'" + :config + (setq indent-tabs-mode nil + js-indent-level 2) + ;; https://github.com/joshwnj/json-mode/issues/72 + (setq-default json-mode-syntax-table + (let ((st (make-syntax-table))) + ;; Objects + (modify-syntax-entry ?\{ "(}" st) + (modify-syntax-entry ?\} "){" st) + ;; Arrays + (modify-syntax-entry ?\[ "(]" st) + (modify-syntax-entry ?\] ")[" st) + ;; Strings + (modify-syntax-entry ?\" "\"" st) + ;; Comments + (modify-syntax-entry ?\n ">" st) + st)) + ) +;;(add-hook +;; 'json-mode-hook +;; (lambda () +;; (setq +;; indent-tabs-mode nil +;; js-indent-level 2) +;; )) + +;;(add-to-list 'auto-mode-alist '("\\.js\\'" . my/js-mode-hook)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hideshow mode +(use-package hideshow + :ensure nil + ;;:diminish hideshow + :hook + ((json-mode . hs-minor-mode) + (web-mode . hs-minor-mode) + (php-mode . hs-minor-mode) + (prog-mode . hs-minor-mode) + (lisp-mode . hs-minor-mode)) + :bind + (:map hs-minor-mode-map + ("H-" . hs-toggle-hiding) + ("H-h" . hs-hide-block) + ("H-s" . hs-show-block) + ("H-l" . hs-hide-level) + ("H-a" . hs-show-all) + ("H-t" . hs-hide-all)) + ;; :commands hs-toggle-hiding + ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; handle large buffers +(defun my/dabbrev-friend-buffer (other-buffer) + "Exclude very large buffers from dabbrev." + (< (buffer-size other-buffer) (* 1 1024 1024))) + +(setq dabbrev-friend-buffer-function 'my/dabbrev-friend-buffer) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; multiple cursors +(use-package multiple-cursors + :ensure t + :bind (("C-S-C C-S-C" . mc/edit-lines) + + ("H-SPC" . set-rectangular-region-anchor))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sql mode +;;(use-package sql-indent :defer t) +;;(use-package sqlup-mode :defer t) + +(use-package sql + :ensure t + :init + ;;(setq sql-product 'mysql + ;; sqlup-mode t + ;;(toggle-truncate-lines 1) + + ;; connect to a predefined connection (sql-connection-alist) + (defun my/sql-connect-preset (name) + "Connect to a predefined SQL connection listed in `sql-connection-alist'" + (eval `(let ,(cdr (assoc name sql-connection-alist)) + (flet ((sql-get-login (&rest what))) + (sql-product-interactive sql-product))))) + + (defun my/sql-mode-hook () + "Hook for SQL mode." + (toggle-truncate-lines 1) + (message "br sql hook")) + + (add-hook 'sql-interactive-mode-hook + (lambda () + (toggle-truncate-lines t) + ;;(my/sql-connect-preset) + (setq comint-move-point-for-output "all"))) + ;; (add-hook 'sql-interactive-mode-hook #'my/sql-mode-hook) + (font-lock-add-keywords 'sql-mode '(("greatest" . font-lock-builtin-face) + ("least" . font-lock-builtin-face))) + :config + (toggle-truncate-lines 1) + (sql-set-product-feature 'mysql :prompt-regexp + "^\\(MariaDB\\|MySQL\\) \\[[_a-zA-Z]*\\]> ") + + :hook + ((sql-mode . sqlind-minor-mode) + (sql-mode . sqlup-mode)) + ;;(sql . my/sql-mode-hook) + ;;(sql-interactive-mode . #'my/sql-mode-hook)) + ;;(sql-interactive-mode . (toggle-truncate-lines 1))) + ) + +;;(use-package sqlup-mode +;;:ensure +;;:after sql +;;:init +;;(local-set-key (kbd "C-c u") 'sqlup-capitalize-keywords-in-region) +;;:hook +;;(add-hook 'sql-mode-hook #'sqlup-mode) +;;:config +;;(add-to-list 'sqlup-blacklist "name") ; I use "name" a lot. +;; ) + +;;(use-package sql-indent +;;:after (sql-mode) +;;:after sql +;;:init +;;:hook +;;((sql . sqlind-minor-mode))) + +;; (use-package sql-interactive-mode +;; :ensure +;; :after sql +;; :config +;; (toggle-truncate-lines 0)) + +;;(add-hook 'sql-mode-hook #'my/sql-mode-hook) +;; When connected to a server within Emacs +;;(add-hook 'sql-interactive-mode-hook #'my/sql-mode-hook) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; html/xml mode +(add-hook + 'html-mode-hook + (lambda () + (setq + indent-tabs-mode nil + ;; tab-width 2 + sgml-basic-offset 2))) + +(defun xml-reformat () + "Reformats xml to make it readable (respects current selection)." + (interactive) + (save-excursion + (let ((beg (point-min)) + (end (point-max))) + (if (and mark-active transient-mark-mode) + (progn + (setq beg (min (point) (mark))) + (setq end (max (point) (mark)))) + (widen)) + (setq end (copy-marker end t)) + (goto-char beg) + (while (re-search-forward ">\\s-*<" end t) + (replace-match ">\n<" t t)) + (goto-char beg) + (indent-region beg end nil)))) + +(add-hook + 'nxml-mode-hook + (lambda () + (setq + indent-tabs-mode nil + ;; tab-width 2 + sgml-basic-offset 2))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; web mode +(use-package web-mode + ;;:demand t + :init + (require 'php-mode) + ;; (setq web-mode-enable-current-column-highlight t) + (make-local-variable 'web-mode-code-indent-offset) + (make-local-variable 'web-mode-markup-indent-offset) + (make-local-variable 'web-mode-css-indent-offset) + :mode + ("\\.phtml\\'" "\\.html?\\'") + ;;(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode)) + ;;(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode)) + + :bind + (:map web-mode-map + ("C-c f" . php-search-documentation)) + + ;;:hook + ;; (('web-mode . php-mode)) + + :config + (require 'company-php) + (set (make-local-variable 'company-backends) + '((company-ac-php-backend company-dabbrev-code) + company-capf company-files)) + (setq web-mode-markup-indent-offset 2 + web-mode-enable-auto-pairing nil ; overrides smartparens + web-mode-css-indent-offset 2 + web-mode-code-indent-offset 4 + web-mode-style-padding 1 + web-mode-script-padding 1 + web-mode-block-padding 2 + web-mode-enable-current-element-highlight t + web-mode-enable-current-column-highlight t + web-mode-sql-indent-offset 2 + web-mode-engines-alist '(("php" . "\\.phtml\\'"))) + (setq web-mode-ac-sources-alist + '(("css" . (ac-source-css-property)) + ("html" . (ac-source-words-in-buffer ac-source-abbrev))) + ) + ;;) + ;;(add-hook 'web-mode-hook 'my/web-mode-hook) + ;;(eval-after-load "web-mode" + ;;' + ;;(set-face-background 'web-mode-current-element-highlight-face "red") + (set-face-foreground 'web-mode-current-element-highlight-face "chartreuse") + + ) + +;; (defun my/web-mode-hook () +;; "br web-mode-hook." +;; (interactive) +;; (setq indent-tabs-mode nil +;; tab-width 2 +;; ;; web-mode-attr-indent-offset 2 +;; web-mode-enable-auto-pairing nil +;; web-mode-code-indent-offset 2 ; for php, js, etc... +;; web-mode-css-indent-offset 2 +;; web-mode-markup-indent-offset 2 ; for html +;; web-mode-sql-indent-offset 2 +;; web-mode-enable-current-column-highlight t +;; ) +;; (define-key web-mode-map +;; (kbd "C-c f") 'php-search-documentation) +;; (paren-toggle-open-paren-context 1) +;; (c-set-offset 'case-label '+) +;; (setq web-mode-engines-alist +;; '(("php" . "\\.phtml\\'"))) +;; (sp-local-pair 'web-mode "<" nil :when '(my/sp-web-mode-is-code-context)) +;; ) + +;; (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode)) +;; (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode)) +;; ;; (add-to-list 'auto-mode-alist '("\\.css\\'" . web-mode)) +;; ;; (add-to-list 'auto-mode-alist '("\\.php\\'" . web-mode)) +;; (add-hook 'web-mode-hook 'my/web-mode-hook) + +;; ;; from FAQ at http://web-mode.org/ for smartparens +;; (defun my/sp-web-mode-is-code-context (id action context) +;; (when (and (eq action 'insert) +;; (not (or (get-text-property (point) 'part-side) +;; (get-text-property (point) 'block-side)))) +;; t)) + +;; (use-package web-mode +;; ;;:mode "\\.html?\\'" +;; :init + +;; :hook +;; ((auto-mode-alist .'("\\.php\\'" . web-mode) +;; ) +;; :config +;; (progn +;; (setq web-mode-markup-indent-offset 2) +;; (setq web-mode-code-indent-offset 2) +;; (setq web-mode-css-indent-offset 2) +;; (setq web-mode-enable-current-element-highlight t) +;; (setq web-mode-ac-sources-alist +;; '(("css" . (ac-source-css-property)) +;; ("html" . (ac-source-words-in-buffer ac-source-abbrev))) +;; ))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; smartparens mode +;; inspired from http://pages.sachachua.com/.emacs.d/Sacha.html#org480d137 +(use-package smartparens + :diminish + :ensure t + :config + (progn + (require 'smartparens-config) + (smartparens-global-mode 1) + (show-smartparens-global-mode 1) + ;;(add-hook 'emacs-lisp-mode-hook 'smartparens-mode) + + (add-hook 'emacs-lisp-mode-hook 'show-smartparens-mode) + + (setq sp-navigate-close-if-unbalanced t) + + ;; keybinding management + ;;(define-key smartparens-mode-map (kbd "C-M-k") 'sp-kill-sexp) + ;;(define-key smartparens-mode-map (kbd "C-M-w") 'sp-copy-sexp) + (define-key smartparens-mode-map (kbd "s-k") 'sp-kill-hybridsexp) + (define-key smartparens-mode-map (kbd "s-w") 'sp-copy-sexp) + + (define-key smartparens-mode-map (kbd "C-c s r n") 'sp-narrow-to-sexp) + + ;; (define-key smartparens-mode-map (kbd "C-M-f") 'sp-forward-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-b") 'sp-backward-sexp) + (define-key smartparens-mode-map (kbd "s-f") 'sp-forward-sexp) + (define-key smartparens-mode-map (kbd "s-b") 'sp-backward-sexp) + + ;; (define-key smartparens-mode-map (kbd "C-S-a") 'sp-beginning-of-sexp) + ;; (define-key smartparens-mode-map (kbd "C-S-d") 'sp-end-of-sexp) + ;; (define-key smartparens-mode-map (kbd "C-S-e") 'sp-end-of-sexp) + (define-key smartparens-mode-map (kbd "s-a") 'sp-beginning-of-sexp) + (define-key smartparens-mode-map (kbd "s-e") 'sp-end-of-sexp) + + ;; (define-key smartparens-mode-map (kbd "C-M-n") 'sp-next-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-p") 'sp-previous-sexp) + (define-key smartparens-mode-map (kbd "s-n") 'sp-next-sexp) + (define-key smartparens-mode-map (kbd "s-p") 'sp-previous-sexp) + + ;; (define-key smartparens-mode-map (kbd "C-M-t") 'sp-transpose-sexp) + (define-key smartparens-mode-map (kbd "s-") 'sp-transpose-hybrid-sexp) + (define-key smartparens-mode-map (kbd "s-") 'sp-push-hybrid-sexp) + + ;; (define-key smartparens-mode-map (kbd "M-D") 'sp-splice-sexp) + (define-key smartparens-mode-map (kbd "s-d") 'sp-splice-sexp) + + ;; (define-key smartparens-mode-map (kbd "C-") 'sp-forward-slurp-sexp) + ;; (define-key smartparens-mode-map (kbd "C-") 'sp-forward-barf-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-") 'sp-backward-slurp-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-") 'sp-backward-barf-sexp) + (define-key smartparens-mode-map (kbd "s-") 'sp-slurp-hybrid-sexp) + (define-key smartparens-mode-map (kbd "s-") 'sp-forward-barf-sexp) + (define-key smartparens-mode-map (kbd "s-S-") 'sp-backward-slurp-sexp) + (define-key smartparens-mode-map (kbd "s-S-") 'sp-backward-barf-sexp) + + ;; nearly useless in C + ;; (define-key smartparens-mode-map (kbd "") 'sp-up-sexp) + ;; (define-key emacs-lisp-mode-map (kbd ")") 'sp-up-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-d") 'sp-down-sexp) + ;; (define-key smartparens-mode-map (kbd "C-M-e") 'sp-up-sexp) + + (define-key smartparens-mode-map (kbd "C-M-a") 'sp-backward-down-sexp) + (define-key smartparens-mode-map (kbd "C-M-u") 'sp-backward-up-sexp) + + (define-key smartparens-mode-map (kbd "M-") + 'sp-unwrap-sexp) + (define-key smartparens-mode-map (kbd "M-") + 'sp-backward-unwrap-sexp) + + (define-key smartparens-mode-map (kbd "C-M-") + 'sp-splice-sexp-killing-forward) + (define-key smartparens-mode-map (kbd "C-M-") + 'sp-splice-sexp-killing-backward) + (define-key smartparens-mode-map (kbd "C-S-") + 'sp-splice-sexp-killing-around) + + ;;(define-key smartparens-mode-map (kbd "C-]") 'sp-select-next-thing-exchange) + ;;(define-key smartparens-mode-map (kbd "C-") 'sp-select-previous-thing) + ;;(define-key smartparens-mode-map (kbd "C-M-]") 'sp-select-next-thing) + (define-key smartparens-mode-map (kbd "s-]") + 'sp-select-next-thing-exchange) + (define-key smartparens-mode-map (kbd "s-") + 'sp-select-previous-thing-exchange) + + ;;(define-key smartparens-mode-map (kbd "M-F") 'sp-forward-symbol) + ;;(define-key smartparens-mode-map (kbd "M-B") 'sp-backward-symbol) + + (define-key smartparens-mode-map (kbd "C-c s t") 'sp-prefix-tag-object) + (define-key smartparens-mode-map (kbd "C-c s p") 'sp-prefix-pair-object) + (define-key smartparens-mode-map (kbd "C-c s c") 'sp-convolute-sexp) + (define-key smartparens-mode-map (kbd "C-c s a") 'sp-absorb-sexp) + (define-key smartparens-mode-map (kbd "C-c s e") 'sp-emit-sexp) + (define-key smartparens-mode-map (kbd "C-c s p") 'sp-add-to-previous-sexp) + (define-key smartparens-mode-map (kbd "C-c s n") 'sp-add-to-next-sexp) + (define-key smartparens-mode-map (kbd "C-c s j") 'sp-join-sexp) + (define-key smartparens-mode-map (kbd "C-c s s") 'sp-split-sexp) + +;;;;;;;;;;;;;;;;;; + ;; pair management + + (sp-local-pair 'minibuffer-inactive-mode "'" nil :actions nil) + +;;; c-mode + (sp-with-modes '(c-mode c++-mode) + (sp-local-pair "{" nil :post-handlers '(("||\n[i]" "RET"))) + (sp-local-pair "/*" "*/" :post-handlers '((" | " "SPC") + ("* ||\n[i]" "RET")))) +;;; markdown-mode + (sp-with-modes '(markdown-mode gfm-mode rst-mode) + (sp-local-pair "*" "*" :bind "C-*") + (sp-local-tag "2" "**" "**") + (sp-local-tag "s" "```scheme" "```") + (sp-local-tag "<" "<_>" "" :transform 'sp-match-sgml-tags)) + +;;; tex-mode latex-mode + (sp-with-modes '(tex-mode plain-tex-mode latex-mode) + (sp-local-tag "i" "1d5f8e69396c521f645375107197ea4dfbc7b792quot;<" "1d5f8e69396c521f645375107197ea4dfbc7b792quot;>")) + +;;; html-mode + (sp-with-modes '(html-mode sgml-mode web-mode) + (sp-local-pair "<" ">")) + +;;; web-mode + (defun my/sp-web-mode-is-code-context (id action context) + (when (and (eq action 'insert) + (not (or (get-text-property (point) 'part-side) + (get-text-property (point) 'block-side)))) + t)) + (sp-local-pair 'web-mode "<" nil :when '(my/sp-web-mode-is-code-context)) + +;;; lisp modes + (sp-with-modes sp-lisp-modes + (sp-local-pair "(" nil :bind "C-(")))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; shell-script mode +(add-hook + 'sh-mode-hook + (lambda () + (setq indent-tabs-mode nil + tab-width 4 + sh-basic-offset 4 + comment-column 50 + comment-auto-fill-only-comments t + fill-column 128 + auto-fill-mode t + shfmt-command "~/go/bin/shfmt" + shfmt-arguments '("-i" "4" "-ci")) + (sh-electric-here-document-mode) + (define-key sh-mode-map (kbd "C-c f") 'shfmt-buffer))) + +;;(define-key sh-mode-map +;; (kbd "") 'reindent-then-newline-and-indent))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lsp-mode +(use-package lsp-mode + :ensure t + :diminish "LSP" + :commands (lsp lsp-deferred) + :config + (setq lsp-prefer-flymake nil + lsp-semantic-tokens-enable t + ;;lsp-enable-on-type-formatting nil + lsp-enable-snippet nil + lsp-enable-symbol-highlighting t + lsp-lens-enable t + lsp-headerline-breadcrumb-enable t + lsp-enable-indentation nil + lsp-enable-on-type-formatting nil + lsp-eldoc-enable-hover t + lsp-modeline-diagnostics-enable t + lsp-modeline-code-actions-enable t + lsp-modeline-code-actions-segments '(count icon name) + lsp-signature-render-documentation t) + :hook + ((sh-mode . lsp-deferred) + ;;(c-mode-common . lsp-deferred) + (lsp-mode . lsp-enable-which-key-integration))) + +(use-package lsp-ui + :ensure t + ;;:diminish + :config + (setq ; lsp-ui-doc-show-with-cursor t + ; lsp-ui-doc-show-with-mouse t + lsp-ui-sideline-enable t + lsp-ui-sideline-show-code-actions t + lsp-ui-sideline-enable t + lsp-ui-sideline-show-hover t + lsp-ui-sideline-enable t + lsp-ui-doc-enable nil) + + :commands + (lsp-ui-mode) + :bind-keymap + ("s-l" . lsp-command-map)) + +;;(use-package lsp-lens +;; :diminish) + +(use-package helm-lsp + :commands + helm-lsp-workspace-symbol) + +;;(use-package eglot +;; :ensure t +;; :diminish "EG") + +(use-package ccls + :ensure t + :diminish " ccls" + :init + (setq ccls-initialization-options + '(:index (:comments 2) :completion (:detailedLabel t))) + (setq-default flycheck-disabled-checkers '(c/c++-clang c/c++-cppcheck c/c++-gcc)) + (setq ccls-sem-highlight-method 'font-lock) + ;; alternatively, + ;;(setq ccls-sem-highlight-method 'overlay) + ;; For rainbow semantic highlighting + ;;(ccls-use-default-rainbow-sem-highlight) + :config + ;;(setq projectile-project-root (ccls--suggest-project-root)) + :hook + ((c-mode) . (lambda () (require 'ccls) (lsp))) + ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CSS mode +(add-hook + 'css-mode-hook + (lambda() + (setq cssm-indent-level 3 + cssm-newline-before-closing-bracket t + cssm-indent-function #'cssm-c-style-indenter + cssm-mirror-mode t + css-indent-offset 2 + indent-tabs-mode nil))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; additional files to load +;; load different files if they exist in user-emacs-directory directory: +;; emacs custom file, graphical system, system type, and hostname +;; in this order. + +;; special case for custom file. Need to do something (maybe use an alist below) +(setq custom-file + (concat user-emacs-directory "custom.el")) +(when (file-exists-p custom-file) + (load custom-file)) + +;; secret file: all sensitive data +(setq my/secret-file "~/data/private/secret.el") +(when (file-exists-p my/secret-file) + (load my/secret-file) + (message "+++%s" my/secret-file)) + +;; load graphic/terminal specific file +(let ((filename (concat user-emacs-directory + (if (display-graphic-p) + "graphic" + "term") + ".el"))) + (when (file-exists-p filename) + (load filename) + (message "+++%s" filename))) + +;; host specific file +(let ((filename (concat user-emacs-directory + (system-name) + ".el"))) + (when (file-exists-p filename) + (load filename) + (message "+++%s" filename))) + +;; start server if not running +(require 'server) +(unless (server-running-p) + (server-start) + (message "++++++ emacs server started")) + +;; (dolist +;; (filename +;; (list +;; ;; emacs self-generated - TO IMPROVE +;; ;; "custom" +;; ;; graphical system +;; (if (display-graphic-p) +;; "graphic" +;; "term") +;; ;; system type - we need to replace "/" with "!" here, for "gnu/linux" +;; (replace-regexp-in-string "/" "%" (symbol-name system-type)) +;; ;; hostname +;; (system-name))) +;; (let ((full-filename (concat user-emacs-directory filename ".el"))) +;; ;; load file +;; (message "+++%s" full-filename) +;; (if (file-exists-p full-filename) +;; (load full-filename) +;; ))) + +(message "++++++ init.el end") +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; nothing works in Emacs 25 +(defun my/trim-spaces (beg end) + "Trim all blank characters in region to one space, and remove whitespaces +at beginning and end of lines." + (interactive "r") + (save-excursion + (save-restriction + (narrow-to-region beg end) + ;; replace multiple spaces in one + (goto-char (point-min)) + (while (re-search-forward "[ \t]+" nil t) + (replace-match " ")) + ;; remove spaces at lines beginning + (goto-char (point-min)) + (while (re-search-forward "^[ \t]+" nil t) + (replace-match "")) + ;; remove spaces at line start/end + (delete-trailing-whitespace)))) + +(defun my/align (beg end) + "Align columns with spaces." + (interactive "r") + (save-excursion + (save-restriction + (narrow-to-region beg end) + (my/trim-spaces (point-min) (point-max)) + (align-regexp (point-min) (point-max) "\\(\\s-*\\)\\s-" 1 0 t) + (delete-trailing-whitespace)))) + +(defun align-cols (start end max-cols) + "Align text between point and mark as columns. +Columns are separated by whitespace characters. +Prefix arg means align that many columns. (default is all) +Attribution: ?" + (interactive "r\nP") + (save-excursion + (let ((p start) + pos + end-of-line + word + count + (max-cols (if (numberp max-cols) (max 0 (1- max-cols)) nil)) + (pos-list nil) + (ref-list nil)) + ;; find the positions + (goto-char start) + (while (< p end) + (beginning-of-line) + (setq count 0) + (setq end-of-line (save-excursion (end-of-line) (point))) + (re-search-forward "^\\s-*" end-of-line t) + (setq pos (current-column)) ;start of first word + (if (null (car ref-list)) + (setq pos-list (list pos)) + (setq pos-list (list (max pos (car ref-list)))) + (setq ref-list (cdr ref-list))) + (while (and (if max-cols (< count max-cols) t) + (re-search-forward "\\s-+" end-of-line t)) + (setq count (1+ count)) + (setq word (- (current-column) pos)) + ;; length of next word including following whitespaces + (setq pos (current-column)) + (if (null (car ref-list)) + (setq pos-list (cons word pos-list)) + (setq pos-list (cons (max word (car ref-list)) pos-list)) + (setq ref-list (cdr ref-list)))) + (while ref-list + (setq pos-list (cons (car ref-list) pos-list)) + (setq ref-list (cdr ref-list))) + (setq ref-list (nreverse pos-list)) + (forward-line) + (setq p (point))) + ;; align the cols starting with last row + (setq pos-list (copy-sequence ref-list)) + (setq start + (save-excursion (goto-char start) (beginning-of-line) (point))) + (goto-char end) + (beginning-of-line) + (while (>= p start) + (beginning-of-line) + (setq count 0) + (setq end-of-line (save-excursion (end-of-line) (point))) + (re-search-forward "^\\s-*" end-of-line t) + (goto-char (match-end 0)) + (setq pos (nth count pos-list)) + (while (< (current-column) pos) + (insert-char ?\040 1)) + (setq end-of-line (save-excursion (end-of-line) (point))) + (while (and (if max-cols (< count max-cols) t) + (re-search-forward "\\s-+" end-of-line t)) + (setq count (1+ count)) + (setq pos (+ pos (nth count pos-list))) + (goto-char (match-end 0)) + (while (< (current-column) pos) + (insert-char ?\040 1)) + (setq end-of-line (save-excursion (end-of-line) (point)))) + (forward-line -1) + (if (= p (point-min)) (setq p (1- p)) + (setq p (point))))))) +;;(setq +;;current-language-environment "UTF-8" +;;(prefer-coding-system 'UTF-8) +;;(set-default-coding-systems 'UTF-8) +;;(set-terminal-coding-system 'UTF-8) +;;(setq-default buffer-file-coding-system 'UTF-8) + +;; affichage direct des caractères sur 8 bits +;; (standard-display-european 1) +;; les caractères iso-latin1 qui sont des lettres, des majuscules... +;; (require 'iso-syntax ) + +;; (rplacd fancy-startup-text +;; `("\nZou are running a customized Emacs configuration. See " :link +;; ("here" +;; #[257 "\300\301!\207" +;; [browse-url-default-browser "http://github.com/izahn/dotemacs/"] +;; 3 "\n\n(fn BUTTON)"] +;; "Open the README file") +;; "\nfor information about these customizations.\n" +;; . +;; (cdr fancy-startup-text))) +;; (rplacd add-to-list 'fancy-startup-text +;; '("\nYou are running a customized Emacs configuration. See " :link +;; ("here" +;; #[257 "\300\301!\207" +;; [browse-url-default-browser "http://github.com/izahn/dotemacs/"] +;; 3 "\n\n(fn BUTTON)"] +;; "Open the README file") +;; "\nfor information about these customizations.\n")) + +;; Local Variables: +;; byte-compile-warnings: (not free-vars) +;; End: +(provide 'init) +;;; init.el ends here +(put 'narrow-to-region 'disabled nil) diff --git a/config/home/lorien.el b/config/home/lorien.el new file mode 100755 index 0000000..a3db095 --- /dev/null +++ b/config/home/lorien.el @@ -0,0 +1,141 @@ +;; ~/.emacs.d/lorien.el +;; +;; Emacs configuration - this file will be loaded only when run on lorien. +;; +;; br, 2010-2019 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; pre-load often-visited files + +;; avoids calling this twice +(when (not (boundp 'my/lorien-loaded)) + (setq my/lorien-loaded t) + + ;; use ESC as C-g + ;; (global-set-key [escape] 'keyboard-escape-quit) + ;; (global-unset-key [escape]) + (define-key key-translation-map (kbd "ESC") (kbd "C-g")) + + ;; mail + (require 'message) + (setq message-send-mail-function 'smtpmail-send-it + smtpmail-default-smtp-server "localhost" + smtpmail-smtp-server "localhost" + smtpmail-debug-info t + mail-signature "\n\n-- \n2 + 2 = 5, for very large values of 2.\n" + mail-default-headers "CC: \n" + send-mail-function 'smtpmail-send-it + ) + + ;; shortcuts for tramp + ;; (my/add-to-list + ;; 'directory-abbrev-alist + ;; '(("^/root" . "/su:/") + ;; ("^/rebel" . "/ssh:arwen:www/cf.bodi/rebels21/") + ;; ("^/strat" . "/ssh:arwen:www/cf.bodi/strat-dom/"))) + + (defconst my/loaded-files-at-startup + (list + "~/dev/brchess/Makefile" + "~/dev/tools/c/Makefile" + "~/org/boot-disk.org" + "~/org/beaglebone-buster-setup.org" + ;;"~/dev/www/cf.bodi/sql/coc.sql" + ;;"~/dev/www/cf.bodi/sql/coc-sql.org" + user-init-file + "~/org/emacs-cheatsheet.org" + ;;"~/dev/g910/g910-gkey-macro-support/lib/data_mappers/char_uinput_mapper.py" + "~/dev/advent-of-code/2022/Makefile" + "~/dev/www/com.raoult/devs/php/chess/list-pgn-games.php") + ;; "~/dev/eudyptula/ID") + "personal files always loaded at startup (no visible window).") + + (let ((num 1)) + (dolist + (filename my/loaded-files-at-startup) + (if (file-exists-p filename) + (progn + ;; set variable "my/buffer-1" to buffer returned by find-file + (set + (intern (concat "my/buffer-" (number-to-string num))) + (find-file-noselect filename nil nil nil)) + (message "file: [%s] loaded." filename)) + (message "cannot load file: [%s]." filename)) + (cl-incf num))) + + ;; set windows for current work buffers + (when (boundp 'my/graphic-loaded) + (set-window-buffer my/main-window my/buffer-1) + (set-window-buffer my/upper-window "*Messages*") + (set-window-buffer my/below-window my/buffer-2)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Coc sync + ;; mysql CoC connection (dev) + ;;(defun my/connect-coc () + ;;(interactive) + ;;(my/sql-connect-preset 'coc)) + + (defun my/connect-coc () + (interactive) + (sql-connect "coc")) + + ;; sync from/to idril + (defun my/coc-get-db () + "get last coc db from arwen" + (interactive) + ;; force run on local machine when in tramp buffer + (with-current-buffer (get-buffer "*scratch*") + (async-shell-command "sync-coc-db-from-idril.sh"))) + (defun my/sync-www () + "sync www to arwen - dry run" + (interactive) + (with-current-buffer (get-buffer "*scratch*") + (async-shell-command "sync-www-to-idril.sh"))) + (defun my/sync-www-doit () + "sync www to arwen" + (interactive) + (with-current-buffer (get-buffer "*scratch*") + (async-shell-command "sync-www-to-idril.sh -d"))) + + (setq org-publish-project-alist + '(("org" + :base-directory "~/org" + :base-extension "org" + :publishing-directory "~/dev/www/cf.bodi/org" + :recursive t + :publishing-function org-html-publish-to-html + ;;:headline-levels 4 + ;;:section-numbers nil + ;;:html-head nil + :html-head-include-default-style nil + :html-head-include-scripts nil + ;; :html-preamble my-blog-header + ;;:html-postamble my-blog-footer + ) + ("static" + :base-directory "~/org/" + :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf" + :publishing-directory "~/dev/www/cf.bodi/org/" + :recursive t + :publishing-function org-publish-attachment) + + ;; Define any other projects here... + )) + + (global-set-key (kbd "s-c c c") 'my/connect-coc) + (global-set-key (kbd "s-c c g") 'my/coc-get-db) + (global-set-key (kbd "s-c c s") 'my/sync-www) + (global-set-key (kbd "s-c c w") 'my/sync-www-doit)) + +;; (Define-key my/keys-mode-map +;; (kbd "s-c c g") 'my/coc-gewt-db) +;; (define-key my/keys-mode-map +;; (kbd "s-c c s") 'my/coc-sync-www) + + + +;; (set-window-buffer current-buffer (get-buffer "*messages*")))) +;; (set-window-buffer "*messages*") + +;; Local Variables: +;; flycheck-disabled-checkers: (emacs-lisp-checkdoc) +;; End: diff --git a/config/home/term.el b/config/home/term.el new file mode 100755 index 0000000..db80ff9 --- /dev/null +++ b/config/home/term.el @@ -0,0 +1,9 @@ +;; ~/.emacs.d/term.el +;; +;; emacs configuration - this file will be loaded only in terminal mode +;; +;; br, 2010-2018 + +;;(print "loading term.el") + +