This file contains my configurations and adaptations to my now graphene based setup.
Lambda as λ
(defmacro λ (&rest body)
`(lambda ()
(interactive)
,@body))
(global-set-key (kbd "C-M-l") (λ (insert "\u03bb")))
(setq lsp-keymap-prefix "H-y")
(setq read-process-output-max (* 1024 1024))
(defvar tom/gc-cons-threshold (* 100 1024 1024) "Don't make this too big")
(setq gc-cons-threshold most-positive-fixnum) ; don't gc during startup
(require 'subr-x)
Package management and loading of utility packages.
Cask manages the packages installed.
(require 'cask "~/.cask/cask.el")
(cask-initialize)
Using pallet
allows to use Cask and M-x list-packages
together –
manual operations performed using packages.el
are reflected in the
Cask file.
(require 'pallet)
(pallet-mode t)
(require 'gnu-elpa-keyring-update)
(gnu-elpa-keyring-update)
Recompile elisp code on load or require.
Since auto-compile is installed via cask, we cannot require it before package Management is setup.
(setq load-prefer-newer t)
(require 'auto-compile)
(auto-compile-on-load-mode 1)
Github integration.
(require 'netrc)
(let ((github-paradox (netrc-machine (netrc-parse "~/.netrc.gpg") "paradox")))
(setq paradox-github-token (netrc-get github-paradox "password")))
Some things have to be configured differently depending on where I am – at home or at work.
(defun tom/work? ()
"Returns `T` if the current machine is at work, `NIL` otherwise"
(file-exists-p (expand-file-name "~/.work")))
(require 'hook-helpers)
(setq custom-file "~/.emacs.d/custom.el")
(load custom-file)
Basics found on ergoemacs.org.
(defun tom/replace-html-chars (text)
"Replace “<” to “<” and other chars in TEXT."
(save-restriction
(with-temp-buffer
(insert text)
(goto-char (point-min))
(while (search-forward "&" nil t) (replace-match "&" nil t))
(goto-char (point-min))
(while (search-forward "<" nil t) (replace-match "<" nil t))
(goto-char (point-min))
(while (search-forward ">" nil t) (replace-match ">" nil t))
(buffer-string))))
Stuff looted from graphene.
(defun kill-default-buffer ()
"Kill the currently active buffer -- set to C-x k so that users are not asked which buffer they want to kill."
(interactive)
(let (kill-buffer-query-functions) (kill-buffer)))
(defun kill-buffer-if-file (buf)
"Kill a buffer only if it is file-based."
(when (buffer-file-name buf)
(when (buffer-modified-p buf)
(when (y-or-n-p (format "Buffer %s is modified - save it?" (buffer-name buf)))
(save-some-buffers nil buf)))
(set-buffer-modified-p nil)
(kill-buffer buf)))
(defun kill-all-buffers ()
"Kill all file-based buffers."
(interactive)
(mapc (lambda (buf) (kill-buffer-if-file buf))
(buffer-list)))
(defun kill-buffer-and-window ()
"Close the current window and kill the buffer it's visiting."
(interactive)
(progn
(kill-buffer)
(delete-window)))
(defun create-new-buffer ()
"Create a new buffer named *new*[num]."
(interactive)
(switch-to-buffer (generate-new-buffer-name "*new*")))
(defun insert-semicolon-at-end-of-line ()
"Add a closing semicolon from anywhere in the line."
(interactive)
(save-excursion
(end-of-line)
(insert ";")))
(defun tom/comment-line-dwim (n)
"Comment or uncomment current line and leave point after
it. With positive prefix, apply to N lines including current
one. With negative prefix, apply to -N lines above."
(interactive "p")
(comment-or-uncomment-region
(line-beginning-position)
(goto-char (line-end-position n)))
(forward-line 1) (back-to-indentation))
(defun comment-current-line-dwim ()
"Comment or uncomment the current line."
(interactive)
(save-excursion
(push-mark (beginning-of-line) t t)
(end-of-line)
(comment-dwim nil)))
(defun newline-anywhere ()
"Add a newline from anywhere in the line."
(interactive)
(end-of-line)
(newline-and-indent))
(defun increase-window-height (&optional arg)
"Make the window taller by one line. Useful when bound to a repeatable key combination."
(interactive "p")
(enlarge-window arg))
(defun decrease-window-height (&optional arg)
"Make the window shorter by one line. Useful when bound to a repeatable key combination."
(interactive "p")
(enlarge-window (- 0 arg)))
(defun decrease-window-width (&optional arg)
"Make the window narrower by one column. Useful when bound to a repeatable key combination."
(interactive "p")
(enlarge-window (- 0 arg) t))
(defun increase-window-width (&optional arg)
"Make the window wider by one column. Useful when bound to a repeatable key combination."
(interactive "p")
(enlarge-window arg t))
;; Create a new instance of emacs
(when window-system
(defun new-emacs-instance ()
(interactive)
(let ((path-to-emacs
(locate-file invocation-name
(list invocation-directory) exec-suffixes)))
(call-process path-to-emacs nil 0 nil))))
;;(delete-selection-mode t)
(global-visual-line-mode t)
(setq nlinum-format "%4d")
(setq default-tab-width 2)
(setq-default tab-width 2)
(setq-default indent-tabs-mode nil)
(prefer-coding-system 'utf-8)
(set-language-environment 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(show-paren-mode t)
(setq blink-matching-paren t)
(electric-pair-mode t)
(push '("\\.json\\'" . json-mode) auto-mode-alist)
;; don't compile sass/scss on saving
(setq scss-compile-at-save nil)
;; 2-space indent for CSS
(setq css-indent-offset 2)
;; Default Ruby filetypes
(dolist (regex
'("\\.watchr$" "\\.arb$" "\\.rake$" "\\.gemspec$" "\\.ru$" "Rakefile$" "Gemfile$" "Capfile$" "Guardfile$" "Rakefile$" "Cheffile$" "Vagrantfile$"))
(add-to-list 'auto-mode-alist `(,regex . ruby-mode)))
;; Remap newline to newline-and-indent in ruby-mode
(define-hook-helper ruby-mode ()
(define-key (current-local-map) [remap newline] 'reindent-then-newline-and-indent))
(require 'ivy)
(require 'swiper)
(require 'counsel)
(require 'counsel-projectile)
(global-set-key "\C-s" 'swiper)
(ivy-mode 1)
(setq ivy-use-virtual-buffers t)
(setq enable-recursive-minibuffers t)
(setq ivy-re-builders-alist '((swiper . ivy--regex-plus) (t . ivy--regex-fuzzy)))
(global-set-key (kbd "C-c C-r") 'ivy-resume)
(global-set-key (kbd "<f6>") 'ivy-resume)
(all-the-icons-ivy-rich-mode 1)
(ivy-rich-mode 1)
(setq inhibit-startup-message t
color-theme-is-global t
uniquify-buffer-name-style 'forward
backup-directory-alist `((".*" . ,temporary-file-directory))
auto-save-file-name-transforms `((".*" ,temporary-file-directory t)))
(global-set-key (kbd "M-x") 'counsel-M-x)
(global-set-key (kbd "C-x C-f") 'counsel-find-file)
(global-set-key (kbd "<F1> f") 'counsel-describe-function)
(global-set-key (kbd "<F1> v") 'counsel-describe-variable)
(global-set-key (kbd "<F1> l") 'counsel-find-library)
(global-set-key (kbd "<F2> i") 'counsel-info-lookup-symbol)
(global-set-key (kbd "<F2> u") 'counsel-unicode-char)
(global-set-key (kbd "C-c g") 'counsel-git)
(global-set-key (kbd "C-c j") 'counsel-git-grep)
(global-set-key (kbd "C-c k") 'counsel-ag)
(global-set-key (kbd "C-x l") 'counsel-locate)
(global-set-key (kbd "C-S-o") 'counsel-rhythmbox)
(define-key minibuffer-local-map (kbd "C-r") 'counsel-minibuffer-history)
(define-key ivy-mode-map (kbd "C-x b") 'persp-switch-to-buffer)
(fset 'yes-or-no-p 'y-or-n-p)
(require 'uniquify)
(setq uniquify-buffer-name-style 'forward)
(global-auto-revert-mode t)
(put 'autopair-newline 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(require 'lv)
(defun ivy-display-function-lv (text)
(let ((lv-force-update t))
(lv-message
(if (string-match "\\`\n" text)
(substring text 1)
text))))
(all-the-icons-ivy-setup)
(global-set-key (kbd "C-x k")
'kill-default-buffer)
(global-set-key (kbd "C-x C-k")
'kill-buffer-and-window)
(global-set-key (kbd "C-c N")
'new-emacs-instance)
(global-set-key (kbd "C-;")
'insert-semicolon-at-end-of-line)
(global-set-key (kbd "C-<return>")
'newline-anywhere)
(global-set-key (kbd "M-C-;")
'tom/comment-line-dwim)
(global-set-key (kbd "C->")
'increase-window-height)
(global-set-key (kbd "C-<")
'decrease-window-height)
(global-set-key (kbd "C-,")
'decrease-window-width)
(global-set-key (kbd "C-.")
'increase-window-width)
(global-set-key (kbd "M-x")
'smex)
(global-set-key (kbd "M-X")
'smex-major-mode-commands)
(global-set-key (kbd "C-c s")
'sr-speedbar-select-window)
;; Work around Emacs frame sizing bug when line-spacing
;; is non-zero, which impacts e.g. grizzl.
(setq redisplay-dont-pause t)
(require 'fullframe)
- Meta-Pause will delete the current frame
- use f2 as tool-bar toggle (analog to f1 for menu-bar-mode)
(global-set-key (kbd "M-<pause>") 'delete-frame)
(global-set-key (kbd "<f1>") 'menu-bar-mode)
(global-set-key (kbd "<f2>") 'tool-bar-mode)
(global-set-key (kbd "<f5>") 'flyspell-mode)
(global-set-key (kbd "<f6>") 'flyspell-prog-mode)
(global-set-key (kbd "<f9>") 'flymake-mode)
Try out swsw.el
,
(require 'swsw)
(swsw-mode t)
(global-set-key
(kbd "H-o")
(defhydra hydra-window (:color amaranth)
"window"
("h" windmove-left)
("j" windmove-down)
("k" windmove-up)
("l" windmove-right)
("V" (lambda ()
(interactive)
(split-window-right)
(windmove-right))
"vert")
("X" (lambda ()
(interactive)
(split-window-below)
(windmove-down))
"horz")
(">" enlarge-window-horizontally)
("<" shrink-window-horizontally)
("v" shrink-window)
("^" enlarge-window)
("t" transpose-frame "'")
("o" delete-other-windows "one" :color blue)
("a" (lambda () (interactive) (call-interactively 'swsw-select)) "swsw" :color blue)
("s" ace-swap-window "swap")
("d" ace-delete-window "del")
("i" ace-maximize-window "ace-one" :color blue)
("b" ido-switch-buffer "buf")
("m" headlong-bookmark-jump "bmk")
("q" nil "cancel")))
Launch seldom used emacs tools via C-x l <KEY>.
Inspired/copied from endless parentheses blog
(global-set-key
(kbd "H-L")
(defhydra hydra-launch (:color blue :timeout 3)
"launch"
("c" calc "calc")
("g" git-timemachine "git timemachine")
("d" ediff-buffers "ediff")
("f" find-dired "find")
("r" tom/projectile-ranger)
("G" rgrep "grep")
("h" man "man")
("p" paradox-list-packages "packages")
("s" tom/vterm "shell")
("t" proced "proced")
))
(global-set-key
(kbd "H-V")
(defhydra hydra-vim-navi (:color red)
"navigate"
("h" backward-char "left")
("j" next-line "down")
("k" previous-line "up")
("l" forward-char "right")))
(global-set-key
(kbd "H-t")
(defhydra hydra-toggle (:color red :timeout 3)
"toggle"
("c" column-number-mode "col-nums")
("d" toggle-debug-on-error "debug on error")
("f" auto-fill-mode "auto fill")
("l" display-line-numbers-mode "show line numbers")
("L" toggle-truncate-lines "truncate lines")
("g" golden-ratio-mode "1.61803")
("q" toggle-debug-on-quit "debug on quit")
("n" narrow-or-widen-dwim "narrow")
("b" tom/ob-confirm-toggle "babel confirmation")))
(setq narrow-to-defun-include-comments t)
(defun narrow-or-widen-dwim (p)
"If the buffer is narrowed, it widens. Otherwise, it narrows intelligently.
Intelligently means: region, org-src-block, org-subtree, or defun,
whichever applies first.
Narrowing to org-src-block actually calls `org-edit-src-code'.
With prefix P, don't widen, just narrow even if buffer is already
narrowed."
(interactive "P")
(declare (interactive-only))
(cond ((and (buffer-narrowed-p) (not p)) (widen))
((region-active-p)
(narrow-to-region (region-beginning) (region-end)))
((derived-mode-p 'org-mode)
;; `org-edit-src-code' is not a real narrowing command.
;; Remove this first conditional if you don't want it.
(cond ((org-in-src-block-p)
(org-edit-src-code)
(delete-other-windows))
((org-at-block-p)
(org-narrow-to-block))
(t (org-narrow-to-subtree))))
(t (narrow-to-defun))))
(defun tom/rec-ex-point-mark ()
(interactive)
(if rectangle-mark-mode
(exchange-point-and-mark)
(let ((mk (mark)))
(rectangle-mark-mode 1)
(goto-char mk))))
(global-set-key
(kbd "H-C-r")
(defhydra hydra-rectangle (:color amaranth
:body-pre (rectangle-mark-mode 1)
:post (deactivate-mark))
"
^_k_^ _d_elete _s_tring
_h_ _l_ _o_k _y_ank
^_j_^ _n_ew-copy _r_eset
^^^^ _e_xchange _u_ndo
^^^^ ^ ^ _p_aste
"
("h" backward-char nil)
("l" forward-char nil)
("k" previous-line nil)
("j" next-line nil)
("e" tom/rec-ex-point-mark nil)
("n" copy-rectangle-as-kill nil)
("d" delete-rectangle nil)
("r" (if (region-active-p)
(deactivate-mark)
(rectangle-mark-mode 1)) nil)
("y" yank-rectangle nil)
("u" undo nil)
("s" string-rectangle nil)
("p" kill-rectangle nil)
("o" nil nil)))
(global-set-key
(kbd "H-C-f")
(defhydra hydra-folding (:color red)
"
_o_pen node _n_ext fold toggle _f_orward _s_how current only
_c_lose node _p_revious fold toggle _a_ll
"
("o" origami-open-node)
("c" origami-close-node)
("n" origami-next-fold)
("p" origami-previous-fold)
("f" origami-forward-toggle-node)
("a" origami-toggle-all-nodes)
("s" origami-show-only-node)))
(require 'undo-fu)
A few variables to be used in snippets.
(setq fb-author "tregner")
(require 'yasnippet)
(require 'warnings)
(yas-reload-all)
(add-to-list 'warning-suppress-types '(yasnippet backquote-change))
(require 'popwin)
(popwin-mode 1)
;; (pop popwin:special-display-config)
(push '("*Flycheck error messages*" :height 0.1 :noselect t :position bottom) popwin:special-display-config)
(push '("\*GEBEN<.*> output\*" :regexp t :position left :width 0.3 :stick t :dedicated t) popwin:special-display-config)
(defun tom/sticky-window (name)
"Make the window NAME sticky."
(let ((curr-win (car (get-buffer-window-list name))))
(set-window-buffer curr-win (get-buffer name))
(set-window-dedicated-p curr-win t)))
(defvar tom/workspaces-last-persp nil
"A variable that contains the last accessed perspective")
(defun tom/workspace-exists-p (name)
"Returns t if NAME is the name of an existing workspace."
(when (symbolp name)
(setq name (symbol-name name)))
(unless (stringp name)
(error "Expected a string, got a %s" (type-of name)))
(member name (persp-names-current-frame-fast-ordered)))
(defun tom/workspace-switch-last ()
"Switches to the last workspace"
(interactive)
(if (tom/workspace-exists-p tom/workspaces-last-persp)
(persp-switch tom/workspaces-last-persp)
(error "No previous workspace.")))
(defun tom/workspace-switch-project ()
(interactive)
(ivy-read "Switch to Project Perspective: "
(if (projectile-ensure-project (projectile-project-p))
(cons (projectile-default-project-name (projectile-project-root))
(projectile-relevant-known-projects))
projectile-known-projects)
:action (lambda (project)
(let ((-buff (current-buffer)))
(persp-switch "none")
(let ((projectile-completion-system 'ivy))
(projectile-switch-project-by-name project)
(persp-switch (file-name-nondirectory (directory-file-name project)))
(persp-remove-buffer -buff))))))
(require 'persp-mode)
(with-eval-after-load "persp-mode-projectile-bridge-autoloads"
(add-hook 'persp-mode-projectile-bridge-mode-hook
#'(lambda ()
(if persp-mode-projectile-bridge-mode
(persp-mode-projectile-bridge-find-perspectives-for-all-buffers)
(persp-mode-projectile-bridge-kill-perspectives))))
(add-hook 'after-init-hook
#'(lambda ()
(persp-mode-projectile-bridge-mode 1))
t))
(defmacro with-perspective (name &rest body)
"Switch to the perspective given by NAME while evaluating BODY."
(declare (indent 1))
(let ((old (cl-gensym)))
`(progn
(let ((,old (when (get-current-persp) (persp-name (get-current-persp))))
(last-persp-cache persp-last-persp-name))
(unwind-protect
(progn
(persp-switch ,name)
,@body)
(when ,old (persp-switch ,old)))
(setq persp-last-persp-name last-persp-cache)))))
(setq wg-morph-on nil
persp-autokill-buffer-on-remove 'kill
persp-nil-name "nil"
persp-nil-hidden t
persp-auto-save-fname "autosave"
persp-auto-resume-time 1
persp-auto-save-opt 1
persp-save-dir (concat tom/--emacs-dir "/workspaces/"))
(defun tom/workspaces*track-last-persp (switch-fun &rest args)
(let ((before-persp (safe-persp-name (get-current-persp)))
(after-persp (apply switch-fun args)))
(when (not (string= before-persp after-persp))
(setq tom/workspaces-last-persp before-persp))))
(advice-add #'persp-switch :around #'tom/workspaces*track-last-persp)
(global-set-key (kbd "H-P")
(defhydra hydra-persp (:color red :timeout 3)
"Perspective"
("d" tom/workspace-switch-project "Switch dired")
("s" (call-interactively 'persp-switch) "Switch/Create")
("m" (call-interactively 'persp-set-buffer) "Move buffer")
("n" persp-next "Next Perspective")
("p" persp-prev "Previous Perspective")
("i" projectile-invalidate-cache "Invalidate file cache")
("q" nil "Quit")))
(setq tramp-shell-prompt-pattern "\\(?:^\\| \\)[^]#$%>❯\n]*#?[]#$%>❯] *\\(�\\[[0-9;]*[a-zA-Z] *\\)*")
GPG is handled almost transparently in emacs nowadays; this setup helps for remote sessions.
<wgreenhouse> tomterl: this assumes emacsclient/emacs –daemon are [15:35] invoked from a shell that is properly setting GPG_AGENT_INFO already <wgreenhouse> but according to documentation, GPG_TTY needs to be adjusted for each terminal > wgreenhouse: thanks – should be the case, I’ll make a note <taylanub> “arc4random_uniform(9000) + 1000” should give me a good [15:36] 4-digit random number, right ? <wgreenhouse> tomterl: also, I really don’t like it because it will [15:38] screw up DISPLAY for any jobs started from the gui emacsclient when I am back at that machine > wgreenhouse: Yepp - we see, when I have the time to tackle gpg, [15:39] maybe I find a cleaner solution <baboon`> how can I call several functions over a single selection without re-selecting between each
(defun tom/kludge-gpg-agent (frame) (unless (display-graphic-p) (setenv “DISPLAY” nil) (setenv “GPG_TTY” (terminal-name frame))))
(add-hook ‘after-make-frame-functions ‘wg/kludge-gpg-agent)
(defun tom/vterm ()
"Run projectile-run-vterm in a dedicated frame."
(interactive)
(unless
(and tom/shellframe (framep tom/shellframe) (frame-live-p tom/shellframe))
(setq tom/shellframe (make-frame)))
(if (projectile-project-p)
(let* ((proj (projectile-ensure-project (projectile-project-p)))
(projectile-switch-project-action #'(lambda () t)))
(select-frame tom/shellframe)
(raise-frame)
(projectile-with-default-dir proj
(projectile-run-vterm)))
(projectile-run-vterm)))
(define-hook-helper vterm-mode ()
:name vterm_hide_modeline
(setq mode-line-format nil)
(setq header-line-format nil))
(define-hook-helper vterm-mode ()
:name vterm_ctrl_y
(local-set-key (kbd "C-y") 'vterm--self-insert)
(local-set-key (kbd "TAB") 'vterm--self-insert))
I use vim
and htop
, so let’s add those to eshell-visual-commands
.
(require 'eshell)
(require 'em-term)
(require 'em-smart)
(setq eshell-where-to-jump 'begin)
(setq eshell-review-quick-commands nil)
(setq eshell-smart-space-goes-to-end t)
(add-to-list 'eshell-visual-commands "htop")
(add-to-list 'eshell-visual-commands "vim")
(add-hook 'eshell-mode-hook 'eshell-smart-initialize)
(setq eshell-prompt-regexp "^[^#$]*[#$] ")
(defvar tom/shellframe nil)
(add-to-list 'frame-inherited-parameters 'alpha)
(define-hook-helper eshell-mode ()
:name eshell_hide_modeline
(setq mode-line-format nil))
(defun tom/eshell ()
"Start or switch to an eshell specific to the current
projectile project, or the global '*eshell*' if not in a
project"
(interactive)
(let ((pers (get-current-persp))
(proj (if (projectile-project-p) (projectile-project-root))))
(unless
(and tom/shellframe (framep tom/shellframe) (frame-live-p tom/shellframe))
(setq tom/shellframe (make-frame)))
(select-frame tom/shellframe)
(raise-frame)
(if proj
(let* ((-project (projectile-default-project-name proj))
(eshell-buffer-name (concat "* " -project " eshell *")))
(if pers (persp-switch (persp-name pers)))
(cd proj)
(if (buffer-live-p (get-buffer eshell-buffer-name))
(switch-to-buffer eshell-buffer-name)
(eshell)))
(eshell))))
(defun tom/short-path (p-lst &optional len)
(let ((len (or len 3))
(path (if (listp p-lst) p-lst (split-string p-lst "/"))))
(if (> (length path) len)
(concat
(mapconcat (lambda (elm) (if (zerop (length elm)) ""
(substring elm 0 1)))
(butlast path len)
"/")
"/"
(mapconcat (lambda (elm) elm)
(last path len)
"/"))
(mapconcat (lambda (elm) elm)
path
"/"))))
(defun eshell/ef (fname-regexp &rest dir) (ef fname-regexp default-directory))
;;; ---- path manipulation
(defun pwd-repl-home (pwd)
(interactive)
(let* ((home (expand-file-name (getenv "HOME")))
(home-len (length home)))
(if (and
(>= (length pwd) home-len)
(equal home (substring pwd 0 home-len)))
(concat "~" (substring pwd home-len))
pwd)))
(defun curr-dir-git-branch-string (pwd)
"Returns current git branch as a string, or the empty string if
PWD is not in a git repo (or the git command is not found)."
(interactive)
(when (and (eshell-search-path "git")
(locate-dominating-file pwd ".git"))
(let ((git-output (shell-command-to-string (concat "cd " pwd " && git branch | grep '\\*' | sed -e 's/^\\* //'"))))
(propertize (concat "["
(if (> (length git-output) 0)
(substring git-output 0 -1)
"(no branch)")
"]") 'face `(:foreground "darkgreen"))
)))
(setq eshell-prompt-function
(lambda ()
(concat
(propertize
(tom/short-path (pwd-repl-home (eshell/pwd)))
'face `(:foreground "darkorange"))
(or (curr-dir-git-branch-string (eshell/pwd)))
(propertize "$ " 'face 'default))))
(setq eshell-highlight-prompt nil)
I use company-mode
as completion system. For most languages I use
the newer GNU global – with pygmentize backend – to provide tags for
code traversal and (additional) completion.
Use company-mode
globally.
I live in a case sensitive world, so don’t alter the case of completions, but provide completions without regard for the case fo the stuff I entered.
;(global-auto-complete-mode -1)
(require 'company)
(add-hook 'after-init-hook 'global-company-mode)
(setq company-dabbrev-downcase nil
company-dabbrev-ignore-case t)
(eval-after-load 'company
'(define-key company-active-map (kbd "C-c h") #'company-quickhelp-manual-begin))
Fasten seat belts, we enter hyper space…
(global-set-key (kbd "H-SPC") 'company-complete)
(require 'company-box)
(add-hook 'company-mode-hook 'company-box-mode)
(defun gtags-root-dir ()
"Returns GTAGS root directory or nil if doesn't exist."
(with-temp-buffer
(if (zerop (call-process "global" nil t nil "-pr"))
(buffer-substring (point-min) (1- (point-max)))
nil)))
(defun gtags-update ()
"Make GTAGS incremental update"
(call-process "global" nil nil nil "-u"))
(defun gtags-root-dir ()
"Returns GTAGS root directory or nil if doesn't exist."
(with-temp-buffer
(if (zerop (call-process "global" nil t nil "-pr"))
(buffer-substring (point-min) (1- (point-max)))
nil)))
(defun gtags-update-single(filename)
"Update Gtags database for changes in a single file"
(interactive)
(start-process "update-gtags" "update-gtags" "bash" "-c" (concat "cd " (gtags-root-dir) " ; gtags --single-update " filename )))
(defun gtags-update-current-file()
(interactive)
(defvar filename)
(setq filename (replace-regexp-in-string (gtags-root-dir) "." (buffer-file-name (current-buffer))))
(gtags-update-single filename)
(message "Gtags updated for %s" filename))
(defun gtags-update-hook()
"Update GTAGS file incrementally upon saving a file"
(when (and (boundp 'ggtags-mode) ggtags-mode)
(when (gtags-root-dir)
(gtags-update-current-file))))
(add-hook 'after-save-hook 'gtags-update-hook)
I use projectile
to manage my projects.
(require 'projectile)
(projectile-global-mode)
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
Use projectile automatically.
(define-hook-helper prog-mode ()
:name projectile
(progn (require 'dash)(projectile-mode 1)))
Ignore .git, and especially those in base/includes which are always to be treated as part of the project by projectile.
Marking the root of a project are only
RoboFile.php
for php-projectsmanifest.json
for node/foxx applications (javascript).projectile
as manually added mark for other project types
(require 'projectile)
(defun tom/projectile-ranger ()
"Open `ranger' at the root of the project."
(interactive)
(golden-ratio-mode -1)
(ranger (projectile-project-root)))
(add-to-list 'projectile-globally-ignored-directories ".git")
(add-to-list 'projectile-globally-ignored-directories "base/.git")
(add-to-list 'projectile-globally-ignored-directories "includes/.git")
(add-to-list 'projectile-globally-ignored-directories ".cask")
(add-to-list 'projectile-project-root-files "RoboFile.php")
(add-to-list 'projectile-project-root-files "manifest.json")
(add-to-list 'projectile-project-root-files ".projectile")
(setq projectile-project-root-files-functions '(projectile-root-top-down))
(setq projectile-find-dir-includes-top-level t)
(setq projectile-indexing-method 'native)
(setq projectile-enable-caching t)
(when (not (fboundp 'make-variable-frame-local))
(defun make-variable-frame-local (variable) variable))
(persp-mode)
(global-set-key (kbd "H-p") 'projectile-commander)
Use ivy/counsel for Completion
(counsel-projectile-mode 1)
(setq projectile-completion-system 'ivy)
(require 'org-projectile)
(setq org-projectile-projects-file
(concat tom/--emacs-dir "/projects_todos.org"))
(add-to-list 'org-capture-templates
(org-projectile-project-todo-entry
:capture-character "t"))
(setq org-agenda-files (append org-agenda-files (org-projectile-todo-files)))
(global-set-key (kbd "C-c o") 'org-capture)
(global-set-key (kbd "C-c n p") 'org-projectile-project-todo-completing-read)
(require 'elescope)
(setf elescope-root-folder "~/projects"
elescope-use-full-path t
elescope-clone-depth nil)
-> ==
;;(require 'unicode-fonts)
;;(unicode-fonts-setup)
(defvar tom/default-font "Fira Code Medium-10"
"The font to use under normal circumstances")
(unless (tom/work?)
(setq tom/default-font "Courier Prime Code-12"))
(defvar tom/fallback-font "-Free-Symbola-normal-normal-semicondensed-*-12-*-*-*-*-0-iso10646-1"
"Font to use, if the default font misses a glyph.")
(require 'composite)
(defvar composition-ligature-table (make-char-table nil))
(define-hook-helper prog-mode ()
:name pm-ligatures
(progn (setq-local composition-function-table composition-ligature-table)
(let ((alist '((33 . ".\\(?:\\(?:==\\|!!\\)\\|[!=]\\)")
(35 . ".\\(?:###\\|##\\|_(\\|[#(?[_{]\\)")
(36 . ".\\(?:>\\)")
(37 . ".\\(?:\\(?:%%\\)\\|%\\)")
(38 . ".\\(?:\\(?:&&\\)\\|&\\)")
(42 . ".\\(?:\\(?:\\*\\*/\\)\\|\\(?:\\*[*/]\\)\\|[*/>]\\)")
(43 . ".\\(?:\\(?:\\+\\+\\)\\|[+>]\\)")
(45 . ".\\(?:\\(?:-[>-]\\|<<\\|>>\\)\\|[<>}~-]\\)")
(46 . ".\\(?:\\(?:\\.[.<]\\)\\|[.=-]\\)")
(47 . ".\\(?:\\(?:\\*\\*\\|//\\|==\\)\\|[*/=>]\\)")
(48 . ".\\(?:x[a-zA-Z]\\)")
(58 . ".\\(?:::\\|[:=]\\)")
(59 . ".\\(?:;;\\|;\\)")
(60 . ".\\(?:\\(?:!--\\)\\|\\(?:~~\\|->\\|\\$>\\|\\*>\\|\\+>\\|--\\|<[<=-]\\|=[<=>]\\||>\\)\\|[*$+~/<=>|-]\\)")
(61 . ".\\(?:\\(?:/=\\|:=\\|<<\\|=[=>]\\|>>\\)\\|[<=>~]\\)")
(62 . ".\\(?:\\(?:=>\\|>[=>-]\\)\\|[=>-]\\)")
(63 . ".\\(?:\\(\\?\\?\\)\\|[:=?]\\)")
(91 . ".\\(?:]\\)")
(92 . ".\\(?:\\(?:\\\\\\\\\\)\\|\\\\\\)")
(94 . ".\\(?:=\\)")
(119 . ".\\(?:ww\\)")
(123 . ".\\(?:-\\)")
(124 . ".\\(?:\\(?:|[=|]\\)\\|[=>|]\\)")
(126 . ".\\(?:~>\\|~~\\|[>=@~-]\\)")
)
))
(dolist (char-regexp alist)
(set-char-table-range composition-function-table (car char-regexp)
`([,(cdr char-regexp) 0 font-shape-gstring]))))
))
(setq default-frame-alist `((font . ,tom/default-font)))
;; (require 'all-the-icons)
;; (require 'all-the-icons-ivy)
;(set-fontset-font t 'unicode (font-spec :family "all-the-icons") nil 'append)
;(set-fontset-font t 'unicode (font-spec :family "file-icons") nil 'append)
;(set-fontset-font t 'unicode (font-spec :family "Material Icons") nil 'append)
;(set-fontset-font t 'unicode (font-spec :family "github-octicons") nil 'append)
;(set-fontset-font t 'unicode (font-spec :family "FontAwesome") nil 'append)
;(set-fontset-font t 'unicode (font-spec :family "Weather Icons") nil 'append)
(add-to-list 'load-path "~/.local/share/icons-in-terminal/")
(require 'icons-in-terminal)
(global-font-lock-mode 1)
(global-hl-line-mode -1)
(line-number-mode 1)
(column-number-mode 1)
(setq mouse-buffer-menu-mode-mult 1)
(setq ranger-show-literal nil)
(when (fboundp 'scroll-bar-mode)
(scroll-bar-mode -1))
(when (fboundp tool-bar-mode)
(tool-bar-mode -1))
(when (fboundp menu-bar-mode)
(menu-bar-mode -1))
(add-to-list 'custom-theme-load-path "~/.emacs.d/site/themes/")
(load-file "~/.emacs.d/site/elegance.el")
;;;(load-theme 'doom-dark+ t)
(require 'color)
(let ((bg (face-attribute 'default :background))
(fg (face-attribute 'default :foreground)))
(custom-set-faces
`(company-tooltip ((t (:inherit default :background ,(color-lighten-name bg 20)))))
`(company-scrollbar-bg ((t (:background ,(color-lighten-name bg 12)))))
`(company-scrollbar-fg ((t (:background ,(color-lighten-name bg 2)))))
`(company-tooltip-selection ((t (:inherit default :foreground ,(color-lighten-name bg 12) :background ,(color-lighten-name fg 20)))))
`(company-tooltip-common ((t (:inherit default :background ,(color-lighten-name bg 12) :foreground ,(color-lighten-name fg 20)))))))
(setq tree-widget-image-enable 1)
(require 'color-theme-approximate)
Show uncomitted changes in the fringe.
(require 'diff-hl)
(global-diff-hl-mode)
(add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh)
I find it unnecessary to mark normal spaces, but to visualize tab characters and newlines is a possible lifesaver.
(setq whitespace-display-mappings ‘( (newline-mark 10 [8629 10]) (tab-mark 9 [8677 9] [92 9]) ))
(setq whitespace-style ‘(face tabs newline tab-mark newline-mark)) (add-hook ‘prog-mode-hook ‘whitespace-mode) (add-hook ‘text-mode-hook ‘whitespace-mode)
This is interesting for presentations (e.g.).
(defvar-local hidden-mode-line-mode nil)
(defvar-local hide-mode-line nil)
(define-minor-mode hidden-mode-line-mode
"Minor mode to hide the mode-line in the current buffer."
:init-value nil
:global nil
:variable hidden-mode-line-mode
:group 'editing-basics
(if hidden-mode-line-mode
(setq hide-mode-line mode-line-format
mode-line-format nil)
(setq mode-line-format hide-mode-line
hide-mode-line nil))
(force-mode-line-update)
;; Apparently force-mode-line-update is not always enough to
;; redisplay the mode-line
(redraw-display)
(when (and (called-interactively-p 'interactive)
hidden-mode-line-mode)
(run-with-idle-timer
0 nil 'message
(concat "Hidden Mode Line Mode enabled. "
"Use M-x hidden-mode-line-mode to make the mode-line appear."))))
This is a birds eye view of the current buffer.
(global-set-key (kbd "H-M") 'minimap-mode)
(fringe-mode (cons 10 8))
(setq frame-title-format
'(""
(:eval
(let ((project-name (projectile-project-name)))
(if (not (string= "-" project-name))
project-name
invocation-name)))
""
(:eval
(if (buffer-file-name)
(concat ": " (tom/short-path (abbreviate-file-name (buffer-file-name)) 1))
": %b"))))
(define-hook-helper focus-out ()
(set-frame-parameter (selected-frame)
'title (let ((project-name (projectile-project-name)))
(if (not (string= "-" project-name))
project-name
invocation-name))))
(define-hook-helper focus-in ()
(set-frame-parameter (selected-frame)
'title nil))
(setq dashboard-set-heading-icons t)
(setq dashboard-set-file-icons t)
(setq dashboard-set-navigator t)
(setq dashboard-items '((projects . 10)(bookmarks . 10)))
(dashboard-setup-startup-hook)
(require 'rainbow-delimiters)
(define-hook-helper prog-mode ()
:name rainbow
(rainbow-delimiters-mode 1))
(setq
cyphejor-rules
'(:upcase
("bookmark" "→")
("buffer" "β")
("diff" "Δ")
("dired" "δ")
("emacs" "ε")
("fundamental" "Ⓕ")
("inferior" "i" :prefix)
("interaction" "i" :prefix)
("interactive" "i" :prefix)
("lisp" "λ" :postfix)
("menu" "▤" :postfix)
("mode" "")
("package" "↓")
("python" "π")
("php" "Ψ")
("shell" "sh" :postfix)
("text" "ξ")
("wdired" "↯δ")))
(cyphejor-mode 1)
(doom-modeline-mode 1)
Allways find the cursor.
(require 'beacon)
(beacon-mode 1)
(require 'alert)
(setq alert-default-style 'libnotify)
(define-hook-helper prog-mode ()
:name indent-guide
(indent-guide-mode t))
(setq
org-directory "~/ownCloud/org-mode"
org-return-follows-link t
org-src-fontify-natively t
org-tags-exclude-from-inheritance '("PROJECT")
org-list-allow-alphabetical nil
org-agenda-include-inactive-timestamps t
org-todo-keywords '((sequence "TODO(t)" "ACTIVE(a)" "PAUSED(p)" "BLOCKED(b)" "DELEGATED(D)" "WAITING(w)" "|" "CANCELED(c)" "DONE(d)"))
org-todo-keyword-faces '(
("TODO" . org-warning)
("ACTIVE" . "yellow")
("PAUSED" . "goldenrod")
("BLOCKED" . "red")
("CANCELED" . "dimgray")
("DELEGATED" . "purple")
("WAITING" . "salmon")
("DONE" . "darkgreen")))
(if (tom/work?)
(setq org-agenda-files nil
org-agenda-file-regexp "^\[0-9\]+")
(setq org-agenda-files (quote ("~/ownCloud/org-mode/todos.org"
"~/ownCloud/org-mode/joocom.org"))))
Use org-cladav
to integrate with an owncloud calendar.
x#+BEGIN_SRC emacs-lisp (defvar tom/–org-caldav-dir (expand-file-name “org-caldav” tom/–src-base)) (add-to-list ‘load-path tom/–org-caldav-dir) (require ‘org-caldav)
(defvar tom/–owncloud-base “https://muehlenweg.dyndns-home.com/owncloud/remote.php/”) (setq org-caldav-url (concat tom/–owncloud-base “caldav/calendars/tom”) org-caldav-calendar-id “orgmode” org-caldav-inbox “~/ownCloud/org-mode/incoming.org” org-caldav-files (quote (“~/ownCloud/org-mode/todos.org” “~/ownCloud/org-mode/joocom.org”)) org-icalendar-timezone “Europe/Berlin”)
x#+END_SRC
(setq
org-mobile-directory (expand-file-name "~/ownCloud/org-mode")
org-mobile-files (quote (org-agenda-files))
org-mobile-inbox-for-pull (expand-file-name "~/ownCloud/org-mode/mobileorg.org"))
(setq
org-refile-targets (quote ((nil :maxlevel . 9)
(org-agenda-files :maxlevel . 9)))
)
Set the converter paths before loading the languages, some packages need them at load time.
The ditaa.jar
location;
(setq org-ditaa-jar-path (concat tom/--emacs-dir "/site/ditaa.jar"))
The plantuml.jar
location
(require 'plantuml-mode)
(setq org-plantuml-jar-path (concat tom/--emacs-dir "/site/plantuml.jar"))
The mermaid.cli
location
(setq ob-mermaid-cli-path (concat (expand-file-name "~") "/bin/mmdc"))
I really like org-babel to use zsh
(setq org-babel-sh-command "zsh")
The languages I like to use.
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t) (shell . t)
(ditaa . t) (sass . t)
(lisp . t) (gnuplot . t)
(http . t) (plantuml .t)
(sql-mode .t) (mermaid . t)))
Don’t confirm evaluation.
(defun tom/ob-confirm-toggle ()
"Turn confirmation for babel code block evaluation on/off."
(interactive)
(setq org-confirm-babel-evaluate (not org-confirm-babel-evaluate)))
(global-set-key (kbd "C-c c") 'tom/ob-confirm-toggle)
Use inheritance for properties, needed for e.g. my zshorg project.
(setq org-use-property-inheritance t)
Execute code-blocks on publishing
(setq org-export-babel-evaluate t)
Remove code references in code prior to tangling; that way I can use them anywhere in the code and get nice links/references in the weaved document, but don’t have to hide them in code comments.
I always use the form (ref:label)
for code references.
(defun tr/remove-code-labels ()
"remove (ref:.*) from all lines"
(goto-char (point-min))
(let* (
(lbl-re "[ \t]*(ref:[a-zA-Z0-9_-]*)"
))
(while (re-search-forward lbl-re nil t)
(replace-match "")
)))
;(add-hook 'org-babel-tangle-body-hook
; (λ () (tr/remove-code-labels)))
(setq org-agenda-custom-commands
'(
("P" "Projects"
((tags "PROJECT")))
("H" "Office and Home Lists"
((agenda)
(tags-todo "OFFICE")
(tags-todo "HOME")
(tags-todo "COMPUTER")
(tags-todo "DVD")
(tags-todo "READING")))
("O" "Office and Home Lists"
((agenda)
(tags-todo "OFFICE")
))
("D" "Daily Action List"
(
(agenda "" ((org-agenda-ndays 1)
(org-agenda-sorting-strategy
(quote ((agenda time-up priority-down tag-up)
)))
(org-deadline-warning-days 0)
))))
)
)
Currently not functioning correctly.
(require 'netrc)
(setq blog (netrc-machine (netrc-parse "~/.netrc.gpg") "joocomblog" t))
(setq org2blog/wp-blog-alist '(("joocom"
:url "http://www.joocom.de/blog/xmlrpc.php"
:username (netrc-get blog "login")
:password (netrc-get blog "password")
; :default-title "Toms Discovery: "
; :default-categories ("Geeks!", "Software Entwicklung", "Systemadministration")
; :tags-as-categories nil
)
))
Settings to set code in latex documents with syntax highlighting.
(setq org-latex-listings 'minted)
(setq org-latex-packages-alist '(("" "minted")))
(setq org-latex-custom-lang-environments
'(
(emacs-lisp "common-lispcode")
(lisp "common-lispcode")
(R "rcode")))
(setq org-latex-minted-options
'(("frame" "lines")
("fontsize" "\\scriptsize")
))
(setq org-latex-pdf-process
'("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
(font-lock-add-keywords
'org-mode
'(("\\(src_\\)\\([^[{]+\\)\\(\\[:.*\\]\\){\\([^}]*\\)}"
(1 '(:foreground "black" :weight 'normal :height 10)) ; src_ part
(2 '(:foreground "cyan" :weight 'bold :height 75 :underline "red")) ; "lang" part.
(3 '(:foreground "#555555" :height 70)) ; [:header arguments] part.
(4 'org-code) ; "code..." part.
)))
Why the hell do I do this?
(require 'org-macs)
(require 'org-popnote)
(setq org-popnote-file (concat tom/--emacs-dir "/notes.org"))
(require 'yequake)
(setq yequake-frames
(list (cons "org-popnote"
(list (cons 'buffer-fns '(org-popnote))
(cons 'width 0.25)
(cons 'height 0.5)))))
(if (not (tom/work?))
(setq org-journal-dir (expand-file-name "~/ownCloud/org-mode/journal/"))
(setq org-journal-dir (expand-file-name "~/Documents/journal/")))
;; (require 'org-publish)
(if (not (tom/work?))
(let* ((tdo (netrc-machine (netrc-parse "~/.netrc.gpg") "tdo"))
(remote-dir (concat (netrc-get tdo "login") (netrc-get tdo "account")))
(remote-static-dir (concat remote-dir "static/")))
(setq org-publish-project-alist
`(("tdo"
:components ("tdo-content" "tdo-static"))
("tdo-content"
:base-directory "~/Projekte/tomsdiner.org/"
:base-extension "org"
:publishing-directory ,remote-dir
:recursive t
:publishing-function org-html-publish-to-html
:export-with-tags nil
:headline-levels 4 ; Just the default for this project.
:with-toc nil
:section-numbers nil
:with-sub-superscript nil
:with-todo-keywords nil
:with-author nil
:with-creator nil
:with-title nil
:html-preamble "<div class=\"navi\">
<b>
<a href=\"/index.html\" class=\"home\">Me+Myself+I</a>
</b>
—
<a href=\"/myself/index.html\">myself</a>
—
<a href=\"/blog/index.html\">posts</a>
—
<a href=\"http://github.com/tomterl\">projects</a>
</div>
<hr/>"
:html-postamble "<hr/><div class=\"footer\">
<a href=\"/imprint.html\">imprint</a>
</div>"
:html-head "<link rel=\"stylesheet\"
href=\"/static/css/style.css\" type=\"text/css\"/><title>tomsdiner.org</title>"
:html-head-include-default-style nil
:with-timestamp t
:exclude-tags ("noexport" "todo")
:auto-preamble t)
("tdo-static"
:base-directory "~/Projekte/tomsdiner.org/static/"
:base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|otf"
:publishing-directory ,remote-static-dir
:recursive t
:publishing-function org-publish-attachment)))))
(setq org-reveal-root "file:///home/tregner/opt/reveal.js")
Sections marked with `:newpage` will start on a new page when exporting to LaTeX.
(defun org/get-headline-string-element (headline backend info)
(let ((prop-point (next-property-change 0 headline)))
(if prop-point (plist-get (text-properties-at prop-point headline) :parent))))
(defun org/ensure-latex-clearpage (headline backend info)
(when (org-export-derived-backend-p backend 'latex)
(let ((elmnt (org/get-headline-string-element headline backend info)))
(when (member "newpage" (org-element-property :tags elmnt))
(concat "\\clearpage\n" headline)))))
(eval-after-load 'ox
'(add-to-list 'org-export-filter-headline-functions
'org/ensure-latex-clearpage))
(add-hook 'org-mode-hook 'poly-org-mode)
(require 'company-postgresql)
(require 'ob-sql-mode)
(sql-set-product-feature 'postgres :prompt-regexp "^[-[:alnum:]_]*=[#>] ")
(sql-set-product-feature 'postgres :prompt-cont-regexp
"^[-[:alnum:]_]*[-(][#>] ")
(define-hook-helper sql-mode ()
:name pqsql-completion
(progn
(setq company-sql-db-host "postgres.toolserver.fbr")
(setq company-sql-db-name "fbtools")
(setq company-sql-db-user "fbtools")
(set (make-local-variable 'company-backends)
'((company-postgresql)))))
Make it easier to reference tickets. se
(require 'bug-reference)
(define-hook-helper bug-reference-mode ()
"Setup bug reference links"
:name bug-reference-org
(progn
(let* ((bugs (netrc-machine (netrc-parse "~/.netrc") "bugs" t))
(bug-url (netrc-get bugs "default")))
(setq bug-reference-url-format bug-url
bug-reference-bug-regexp (if (tom/work?)
"\\(##\\)\\([A-Z]\\{3,7\\}\\-[0-9][0-9]*\\)"
"\\(##\\)\\([0-9][0-9]*\\)")))))
(define-hook-helper org-mode
:name org-bug-reference
(bug-reference-mode))
(setq save-interprogram-paste-before-kill t)
(require 'boon-qwerty)
(boon-mode)
(require 'which-key)
(setq which-key-popup-type 'side-window)
(which-key-setup-side-window-bottom)
(custom-set-variables
'(mini-frame-show-parameters
'((top . 10)
(width . 0.7)
(left . 0.5))))
(mini-frame-mode)
(fullframe vc-annotate quit-window nil)
(fullframe/split-screen rgrep quit-window "*grep*" 'horizontal 't)
Everything should be in utf-8.
(prefer-coding-system 'utf-8)
Both commands are from Bozhidar Batsov.
(defun tom/rename-file-and-buffer ()
"Rename the current buffer and file it is visiting."
(interactive)
(let ((filename (buffer-file-name)))
(if (not (and filename (file-exists-p filename)))
(message "Buffer is not visiting a file!")
(let ((new-name (read-file-name "New name: " filename)))
(cond
((vc-backend filename) (vc-rename-file filename new-name))
(t
(rename-file filename new-name t)
(set-visited-file-name new-name t t)))))))
(defun tom/delete-file-and-buffer ()
"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)
(progn
(delete-file filename)
(message "Deleted file %s" filename)
(kill-buffer))))))
(global-set-key (kbd "C-x C-b") 'ibuffer)
(all-the-icons-ibuffer-mode 1)
(defhydra hydra-ibuffer-main (:color pink :hint nil)
"
^Navigation^ | ^Mark^ | ^Actions^ | ^View^
-^----------^-+-^----^--------+-^-------^--------+-^----^-------
_k_: ʌ | _m_: mark | _D_: delete | _g_: refresh
_RET_: visit | _u_: unmark | _S_: save | _s_: sort
_j_: v | _*_: specific | _a_: all actions | _/_: filter
-^----------^-+-^----^--------+-^-------^--------+-^----^-------
"
("j" ibuffer-forward-line)
("RET" ibuffer-visit-buffer :color blue)
("k" ibuffer-backward-line)
("m" ibuffer-mark-forward)
("u" ibuffer-unmark-forward)
("*" hydra-ibuffer-mark/body :color blue)
("D" ibuffer-do-delete)
("S" ibuffer-do-save)
("a" hydra-ibuffer-action/body :color blue)
("g" ibuffer-update)
("s" hydra-ibuffer-sort/body :color blue)
("/" hydra-ibuffer-filter/body :color blue)
("o" ibuffer-visit-buffer-other-window "other window" :color blue)
("q" quit-window "quit ibuffer" :color blue)
("." nil "toggle hydra" :color blue))
(defhydra hydra-ibuffer-mark (:color teal :columns 5
:after-exit (hydra-ibuffer-main/body))
"Mark"
("*" ibuffer-unmark-all "unmark all")
("M" ibuffer-mark-by-mode "mode")
("m" ibuffer-mark-modified-buffers "modified")
("u" ibuffer-mark-unsaved-buffers "unsaved")
("s" ibuffer-mark-special-buffers "special")
("r" ibuffer-mark-read-only-buffers "read-only")
("/" ibuffer-mark-dired-buffers "dired")
("e" ibuffer-mark-dissociated-buffers "dissociated")
("h" ibuffer-mark-help-buffers "help")
("z" ibuffer-mark-compressed-file-buffers "compressed")
("b" hydra-ibuffer-main/body "back" :color blue))
(defhydra hydra-ibuffer-action (:color teal :columns 4
:after-exit
(if (eq major-mode 'ibuffer-mode)
(hydra-ibuffer-main/body)))
"Action"
("A" ibuffer-do-view "view")
("E" ibuffer-do-eval "eval")
("F" ibuffer-do-shell-command-file "shell-command-file")
("I" ibuffer-do-query-replace-regexp "query-replace-regexp")
("H" ibuffer-do-view-other-frame "view-other-frame")
("N" ibuffer-do-shell-command-pipe-replace "shell-cmd-pipe-replace")
("M" ibuffer-do-toggle-modified "toggle-modified")
("O" ibuffer-do-occur "occur")
("P" ibuffer-do-print "print")
("Q" ibuffer-do-query-replace "query-replace")
("R" ibuffer-do-rename-uniquely "rename-uniquely")
("T" ibuffer-do-toggle-read-only "toggle-read-only")
("U" ibuffer-do-replace-regexp "replace-regexp")
("V" ibuffer-do-revert "revert")
("W" ibuffer-do-view-and-eval "view-and-eval")
("X" ibuffer-do-shell-command-pipe "shell-command-pipe")
("b" nil "back"))
(defhydra hydra-ibuffer-sort (:color amaranth :columns 3)
"Sort"
("i" ibuffer-invert-sorting "invert")
("a" ibuffer-do-sort-by-alphabetic "alphabetic")
("v" ibuffer-do-sort-by-recency "recently used")
("s" ibuffer-do-sort-by-size "size")
("f" ibuffer-do-sort-by-filename/process "filename")
("m" ibuffer-do-sort-by-major-mode "mode")
("b" hydra-ibuffer-main/body "back" :color blue))
(defhydra hydra-ibuffer-filter (:color amaranth :columns 4)
"Filter"
("m" ibuffer-filter-by-used-mode "mode")
("M" ibuffer-filter-by-derived-mode "derived mode")
("n" ibuffer-filter-by-name "name")
("c" ibuffer-filter-by-content "content")
("e" ibuffer-filter-by-predicate "predicate")
("f" ibuffer-filter-by-filename "filename")
(">" ibuffer-filter-by-size-gt "size")
("<" ibuffer-filter-by-size-lt "size")
("/" ibuffer-filter-disable "disable")
("b" hydra-ibuffer-main/body "back" :color blue))
(define-key ibuffer-mode-map "." 'hydra-ibuffer-main/body)
(add-hook 'ibuffer-hook #'hydra-ibuffer-main/body)
(require 'bufler)
(fullframe bufler quit-window)
(defun goto-match-paren (arg)
"Go to the matching parenthesis if on parenthesis, otherwise insert
the character typed."
(interactive "p")
(cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1))
((looking-at "\\s\)") (forward-char 1) (backward-list 1))
(t (self-insert-command (or arg 1))) ))
(global-set-key "%" `goto-match-paren)
Indent using spaces, 2 spaces for each indentation step.
(setq-default tab-width 2)
(setq-default indent-tabs-mode nil)
(setq-default c-basic-offset 2)
(setq flyspell-abbrev-p t
flyspell-issue-message-flag nil
flyspell-issue-welcome-flag nil)
(require 'flyspell-correct-ivy)
(setq flyspell-correct-interface 'flyspell-correct-ivy)
(global-set-key
(kbd "H-s")
(defhydra hydra-spelling (:color blue)
"
^
^Spelling^ ^Errors^ ^Checker^
^────────^──────────^──────^────────────^───────^───────
_q_ quit _<_ cor. previous _c_ correction
^^ _>_ cor. next _d_ dictionary
^^ _f_ check _m_ mode
^^ ^^ ^^
"
("q" nil)
("<" flyspell-correct-previous :color pink)
(">" flyspell-correct-next :color pink)
("c" ispell)
("d" ispell-change-dictionary)
("f" flyspell-buffer)
("m" flyspell-mode)))
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C-c M-.") 'mc/mark-next-like-this)
(global-set-key (kbd "C-c M-,") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c M-a") 'mc/mark-all-like-this)
After using expand-region the point remains at the start of the region. Switch point and mark and call multi-cursor.
(defun tom/mcdwim ()
""
(interactive)
(progn
(exchange-point-and-mark)
(mc/mark-all-dwim nil)))
(global-set-key (kbd "\C-c r") 'tom/mcdwim)
Context/Language aware region expansion/contraction.
(require 'expand-region)
(global-set-key (kbd "C-=") 'er/expand-region)
(require 'repl-toggle)
(setq rtog/mode-repl-alist '(
(php-mode . tom/psysh)
(emacs-lisp-mode . ielm)
(elixir-mode . elixir-mode-iex)
(ruby-mode . inf-ruby)
(js2-mode . nodejs-repl)
(js3-mode . nodejs-repl)))
(setq rtog/fullscreen t)
(setq rtog/split-screen t)
Send them to firefox, with keysnail much better then anything else.
(setq
browse-url-browser-function (quote browse-url-default-browser))
Use the ‘calendar’ to get and format the date.
(require 'calendar)
(defun tom/insert-current-date (&optional omit-day-of-week-p)
"Insert today's date using the current locale.
With a prefix argument, the date is inserted without the day of
the week."
(interactive "P*")
(insert (calendar-date-string (calendar-current-date) nil
omit-day-of-week-p)))
(global-set-key (kbd "\C-c d") 'tom/insert-current-date)
See hydra above for movement!
(global-set-key (kbd "H-r") 'rotate-window)
(global-set-key (kbd "H-C-l") 'rotate-layout)
Sensible setup found at ‘or emacs(‘.
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
(setq ediff-split-window-function 'split-window-horizontally)
(setq ediff-diff-options "-w")
(defun tom/ediff-hook ()
(ediff-setup-keymap)
(define-key ediff-mode-map "j" 'ediff-next-difference)
(define-key ediff-mode-map "k" 'ediff-previous-difference))
(add-hook 'ediff-mode-hook 'tom/ediff-hook)
(require 'dired-x)
(put 'dired-find-alternate-file 'disabled nil)
(setq dired-omit-files "^\\..*$")
(require 'volatile-highlights)
(define-hook-helper prog-mode ()
:name volatile-highlight
(volatile-highlights-mode 1))
(defun tom/sudo ()
"Use TRAMP to `sudo' the current buffer"
(interactive)
(when buffer-file-name
(find-alternate-file
(concat "/sudo:root@localhost:"
buffer-file-name))))
(global-set-key (kbd "H-c") 'string-inflection-all-cycle)
(global-set-key (kbd "H-z") 'zeal-at-point)
(defun tom/occur-tap ()
"Call occur with word-at-point"
(interactive)
(occur (word-at-point))
)
(defun tom/kill-occur-window ()
"Kill the *Occur* buffer/window"
(interactive)
(let ((buffer (get-buffer "*Occur*")))
(when buffer
(with-current-buffer-window
buffer
nil
nil
(kill-buffer-and-window)))))
(global-set-key (kbd "H-f") 'tom/occur-tap)
(global-set-key (kbd "H-F") 'tom/kill-occur-window)
(global-set-key (kbd "H-v") 'view-mode)
(require 'polymode)
(require 'aql-mode)
(define-hostmode poly-php-hostmode
:mode 'php-mode)
(define-innermode poly-php-aql-innermode
:mode 'aql-mode
:head-matcher "^[ \t]*\\(protected \\|private \\)?\\(static \\)?$[_a-zA-Z0-9]* = <<<'?AQL'?\n"
:tail-matcher "^AQL;\n"
:head-mode 'host
:tail-mode 'host)
(define-innermode poly-php-sql-innermode
:mode 'sql-mode
:head-matcher "^[ \t]*protected static $source = ['\"](?\n"
:tail-matcher "^.*)?['\"];\n"
:head-mode 'host
:tail-mode 'host)
(define-innermode poly-php-js-innermode
:mode 'js-mode
:head-matcher "^[ \t]*\\(protected static \\)?$[_a-zA-Z0-9]* = <<<'?JST'?\n"
:tail-matcher "^JST;\n"
:head-mode 'host
:tail-mode 'host)
(define-polymode poly-php-mode
:hostmode 'poly-php-hostmode
:innermodes '(poly-php-aql-innermode
poly-php-sql-innermode
poly-php-js-innermode))
(define-hostmode poly-js-hostmode
:mode 'js-mode)
(define-innermode poly-js-aql-innermode
:mode 'aql-mode
:head-matcher "aql`"
:tail-matcher "`"
:head-mode 'host
:tail-mode 'host)
(define-polymode poly-js-mode
:hostmode 'poly-js-hostmode
:innermodes '(poly-js-aql-innermode))
(define-hostmode poly-yaml-hostmode
:mode 'yaml-mode)
(define-innermode poly-yaml-js-innermode
:mode 'js-mode
:head-matcher "body: >"
:tail-matcher "^ *\\(- \\)?[a-z_-]+:"
:head-mode 'host
:tail-mode 'host)
(define-polymode poly-yaml-mode
:hostmode 'poly-yaml-hostmode
:innermodes '(poly-yaml-js-innermode))
(global-set-key
(kbd "H-h")
(defhydra hydra-help (:color blue :timeout 3)
"launch"
("h" helpful-at-point "Loopup Function/Macro")
("v" helpful-variable "Lookup Variable")
("g" helpful-update "Refresh Helpful Buffer")
))
(require 'popup-imenu)
(global-set-key (kbd "H-i") 'popup-imenu)
(setq popup-use-optimized-column-computation nil)
(setq popup-imenu-position 'point)
(setq popup-imenu-force-position t)
(setq popup-imenu-style 'indent)
(define-key popup-isearch-keymap (kbd "H-i") 'popup-isearch-cancel)
(require 'which-key)
(require 'which-key-posframe)
(which-key-mode 1)
(which-key-posframe-mode 1)
(setq which-key-posframe-poshandler 'posframe-poshandler-frame-bottom-left-corner)
(require 'engine-mode)
(setq engine/browser-function 'eww-browse-url)
(defengine amazon
"http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=%s"
:keybinding "a")
(defengine duckduckgo
"https://duckduckgo.com/?q=%s"
:keybinding "d")
(defengine github
"https://github.com/search?ref=simplesearch&q=%s"
:keybinding "g")
(defengine google-images
"http://www.google.com/images?hl=en&source=hp&biw=1440&bih=795&gbv=2&aq=f&aqi=&aql=&oq=&q=%s"
:keybinding "i")
(defengine google-maps
"http://maps.google.com/maps?q=%s"
:keybinding "m"
:docstring "Mappin' it up.")
(defengine stack-overflow
"https://stackoverflow.com/search?q=%s"
:keybinding "s")
(defengine youtube
"http://www.youtube.com/results?aq=f&oq=&search_query=%s"
:keybinding "y")
(defengine wikipedia
"http://www.wikipedia.org/search-redirect.php?language=en&go=Go&search=%s"
:keybinding "w"
:docstring "Searchin' the wikis.")
(engine-mode t)
Don’t ask for confirmation to kill running processes on exit; I always answered yes the last couple of years.
(setq confirm-kill-processes nil)
(require 'linum-relative)
(setq linum-relative-current-symbol "")
(setq linum-relative-backend 'display-line-numbers-mode)
(add-hook 'prog-mode-hook 'linum-relative-mode)
(with-eval-after-load 'lsp-intelephense
(setf (lsp--client-multi-root (gethash 'iph lsp-clients)) nil))
(with-eval-after-load 'lsp-mode
(add-hook 'lsp-mode-hook #'lsp-enable-which-key-integration))
(setq lsp-enable-file-watchers nil)
(setq lsp-prefer-flymake nil)
(setq lsp-auto-guess-root t)
(require 'lsp-mode)
(require 'lsp)
;(require 'lsp-clients)
;(require 'lsp-php)
(require 'lsp-ui)
(require 'lsp-diagnostics) ; for lsp-ui-flycheck--start
(require 'origami)
(require 'lsp-origami)
(require 'lsp-ivy)
(add-hook 'lsp-mode-hook 'lsp-ui-mode)
(add-hook 'lsp-mode-hook 'lsp-enable-which-key-integration)
(add-hook 'origami-mode-hook #'lsp-origami-mode)
(require 'company-capf)
(defun tom/company-transformer (candidates)
(let ((completion-ignore-case t))
(all-completions (company-grab-symbol) candidates)))
(global-set-key
(kbd "H-l")
(defhydra hydra-lsp (:exit t :hint nil)
"
Buffer^^ Server^^ Symbol
-------------------------------------------------------------------------------------
[_f_] format [_M-r_] restart [_d_] declaration [_i_] implementation [_o_] documentation
[_m_] imenu [_S_] shutdown [_D_] definition [_t_] type [_r_] rename
[_x_] execute action [_M-s_] describe session [_R_] references [_s_] signature"
("d" lsp-find-declaration)
("D" lsp-ui-peek-find-definitions)
("R" lsp-ui-peek-find-references)
("i" lsp-ui-peek-find-implementation)
("t" lsp-find-type-definition)
("s" lsp-signature-activate)
("o" lsp-describe-thing-at-point)
("r" lsp-rename)
("f" lsp-format-buffer)
("m" lsp-ui-imenu)
("x" lsp-execute-code-action)
("M-s" lsp-describe-session)
("M-r" lsp-restart-workspace)
("S" lsp-shutdown-workspace)))
(global-set-key
(kbd "H-e")
(defhydra hydra-flycheck
(:pre (progn (setq hydra-lv t) (flycheck-list-errors))
:post (progn (setq hydra-lv nil) (quit-windows-on "*Flycheck errors*"))
:hint nil)
"Errors"
("f" flycheck-error-list-set-filter "Filter")
("j" flycheck-next-error "Next")
("k" flycheck-previous-error "Previous")
("gg" flycheck-first-error "First")
("G" (progn (goto-char (point-max)) (flycheck-previous-error)) "Last")
("q" nil)))
Automatically add end
when typing do
.
(require 'elixir-mode)
(add-to-list
'elixir-mode-hook
(defun auto-activate-ruby-end-mode-for-elixir-mode ()
(set (make-variable-buffer-local 'ruby-end-expand-keywords-before-re)
"\\(?:^\\|\\s-+\\)\\(?:do\\)")
(set (make-variable-buffer-local 'ruby-end-check-statement-modifiers) nil)
(ruby-end-mode +1)))
(define-hook-helper elixir-mode ()
(progn
(require 'alchemist)
(set (make-local-variable 'company-backends)
'((Alchemist-company :with company-yasnippet company-dabbrev-code)))
(flycheck-mode 1)
(yas-minor-mode 1)))
Add speedbar support for elixir files.
(require 'speedbar)
(speedbar-add-supported-extension ".ex")
(speedbar-add-supported-extension ".exs")
(setenv "RUST_SRC_PATH" "/home/tom/Projects/rust/src")
(define-hook-helper rust-mode ()
(progn
(require 'company-racer)
(setq tab-width 4
c-basic-offset 4
indent-tabs-mode nil
)
(set (make-local-variable 'company-backends)
'((company-racer :with :sorted company-yasnippet)))
(cargo-minor-mode 1)))
(define-hook-helper sh-mode ()
(define-key lsp-ui-mode-map [remap xref-find-definitions] #'lsp-ui-peek-find-definitions)
(define-key lsp-ui-mode-map [remap xref-find-references] #'lsp-ui-peek-find-references)
(define-key lsp-ui-mode-map (kbd "M-.") #'lsp-ui-peek-find-definitions))
(lsp-register-client
(make-lsp-client :new-connection (lsp-stdio-connection "bash-language-server start")
:major-modes '(sh-mode)
:server-id 'bls))
;; (add-hook 'sh-mode-hook #'flycheck-mode)
(require 'php-mode)
(add-to-list 'auto-mode-alist '("\\.php$" . php-mode))
(add-to-list 'auto-mode-alist '("\\.inc$" . php-mode))
Use web-mode
for smarty templates.
(setq web-mode-engines-alist
'(("smarty" . "\\.tpl$")))
(add-to-list 'auto-mode-alist '("\\.tpl$" . web-mode))
(when (tom/work?)
(setq web-mode-engine "smarty"))
Indent with 4 spaces. Use flycheck, but dont’t use the “controversial” and “cleancode” rulesets of phpmd. Use ac-php
as company backend. Recreate the tags when a file is saved.
(setq lsp-intelephense-licence-key (expand-file-name "~/.config/intelephense/licence.txt"))
(lsp-register-custom-settings
`(("intelephense.phpdoc.functionTemplate"
,(list :summary "$1"
:tags (vector "@param ${1:$SYMBOL_TYPE} $SYMBOL_NAME $2"
""
"@return ${1:$SYMBOL_TYPE} $2"
"@throws ${1:$SYMBOL_TYPE} $2"
"@author `fb-author`"
"@since `(tom/insert-current-date 4)`")))))
(lsp-register-custom-settings
`(("intelephense.phpdoc.classTemplate"
,(list :summary "$1"
:tags (vector ""
"@author `fb-author`"
"@package ${1:$SYMBOL_NAMESPACE}"
"@since `(tom/insert-current-date 4)`")))))
(defun tom/dtw ()
"Delete trailing whitespace in a save excursion."
(save-excursion
(delete-trailing-whitespace)))
(flycheck-define-generic-checker 'lsp-php-ui
"A syntax checker using the Language Server Protocol (RLS)
provided by lsp-mode.
See https://github.com/emacs-lsp/lsp-mode."
:start #'lsp-diagnostics--flycheck-start
:modes '(php-mode) ; Need a default mode
:predicate (lambda () lsp-mode)
:error-explainer (lambda (e) (flycheck-error-message e))
:next-checkers '((warning . php)))
(define-hook-helper php-mode ()
:name php-personal
(progn
(ggtags-mode -1)
(repl-toggle-mode 1)
(yas-minor-mode 1)
(company-mode 1)
(origami-mode 1)
(modify-syntax-entry ?$ "_")
(make-local-variable 'company-transformers)
(push 'tom/company-transformer company-transformers)
(local-set-key (kbd "C-c a") 'tom/edit-sql)
(php-enable-wordpress-coding-style)
(flycheck-may-enable-checker 'php-phpcs)
(flycheck-disable-checker 'phpstan)
(flycheck-disable-checker 'php-phpmd)
(setq tab-width 4
c-basic-offset 4
indent-tabs-mode nil
php-template-compatibility nil
php-mode-coding-style (quote wordpress)
php-lineup-cascaded-calls t
lsp-enable-semantic-highlighting nil)
(add-hook 'write-contents-functions 'tom/dtw nil t)
(define-key lsp-ui-mode-map [remap xref-find-definitions] #'lsp-ui-peek-find-definitions)
(define-key lsp-ui-mode-map [remap xref-find-references] #'lsp-ui-peek-find-references)
(poly-php-mode 1)
(font-lock-mode 1)
(setq-local flycheck-checker 'lsp-php-ui)))
(add-hook 'php-mode-hook 'flycheck-mode)
(add-hook 'php-mode-hook #'lsp)
dap is the way to go…
(require 'dap-php)
(dap-php-setup)
(dap-tooltip-mode 1)
(tooltip-mode 1)
(setq dap-auto-show-output nil)
(setq dap-inhibit-io nil)
(define-key php-mode-map (kbd "H-d") 'dap-hydra)
(dap-register-debug-template "Php tcp4"
(list :type "php"
:cwd nil
:request "launch"
:name "Php Debug"
:hostname "0.0.0.0"
:sourceMaps t))
Check the doc comment of the current function for @param tags, create them if not present. This is used in the function-snippet, but needs an overhaul…
(require 'php-doc-block)
(define-hook-helper php-mode ()
:name phpdoc
(local-set-key (kbd "<C-tab>") 'php-doc-block))
(defun tom/php-unit ()
""
(interactive)
(let* ((pr (projectile-project-root))
(confdir (concat pr "/tests"))
(conf (concat confdir "/phpunit.xml"))
(wd default-directory))
(if (and (file-directory-p confdir) (file-exists-p conf))
(progn
(cd confdir)
(phpunit-run '())
(cd wd)))))
(defun tom/psysh ()
"Start or switch to a psysh specific to the current
projectile project, or the global '*PsySh*' if not in a
project"
(interactive)
(if (projectile-ensure-project (projectile-project-p))
(let* ((-project-root (projectile-project-root))
(-project (projectile-default-project-name -project-root))
(-buffer-name (concat "* " -project " psysh *")))
(projectile-with-default-dir -project-root
(if (and (buffer-live-p (get-buffer -buffer-name)))
(progn (switch-to-buffer -buffer-name))
(progn
(vterm -buffer-name)
(vterm-send-string "set -k")
(vterm-send-return)
(vterm-send-string "if [ -f ./bin/shell.php ]; then ./bin/shell.php; else psysh; fi #")
(vterm-send-return)))))
(psysh-run "*PsySh*" "psysh")))
(define-hook-helper psysh-mode ()
(progn (company-mode -1) (auto-complete-mode)))
(define-hook-helper c-mode ()
(setq tab-width 2
c-basic-offset 2
indent-tabs-mode nil))
(if (tom/work?)
(setq js-indent-level 4
js2-basic-offset 4
js2-bounce-indent-p t)
(setq js-indent-level 2
js2-basic-offset 2
js2-bounce-indent-p t))
(add-to-list 'auto-mode-alist '("\\.js$" . js-mode))
(add-to-list 'load-path "/usr/lib/node_modules/tern/emacs")
(flycheck-define-generic-checker 'lsp-js-ui
"A syntax checker using the Language Server Protocol (RLS)
provided by lsp-mode.
See https://github.com/emacs-lsp/lsp-mode."
:start #'lsp-diagnostics--flycheck-start
:modes '(js-mode) ; Need a default mode
:predicate (lambda () lsp-mode)
:error-explainer (lambda (e) (flycheck-error-message e)))
(define-hook-helper js-mode ()
:name js-personal
(progn
(ggtags-mode -1)
(repl-toggle-mode 1)
(yas-minor-mode 1)
(company-mode 1)
(make-local-variable 'company-transformers)
(push 'tom/company-transformer company-transformers)
(define-key lsp-ui-mode-map [remap xref-find-definitions] #'lsp-ui-peek-find-definitions)
(define-key lsp-ui-mode-map [remap xref-find-references] #'lsp-ui-peek-find-references)
(define-key lsp-ui-mode-map (kbd "M-.") #'lsp-ui-peek-find-definitions)
(add-hook 'js-mode-hook 'flycheck-mode)
(setq-local flycheck-checker 'lsp-js-ui)
(local-set-key (kbd "C-c a") 'tom/edit-aql)
(poly-js-mode 1)))
(add-hook 'js-mode-hook #'lsp)
;;; (require 'lsp-javascript-typescript)
;;;(add-hook 'js-mode-hook #'lsp-javascript-typescript-enable)
(defun tom/edit-js ()
"If point is between a `^ body: > ... \\(^ - name:
\\)\\|\\(^ types:\\)' block, create a narrowed, indirect
buffer in `js2-mode' to edit the function-body. Press
`C-c C-c' inside the buffer to close the window and kill
the indirect buffer."
(interactive)
(tom/edit-narrowed 'js2-mode ".js" "^ body: >" "\\(^ - name: \\)\\|\\(^ types:\\)"))
(require 'nodejs-repl)
(add-to-list 'auto-mode-alist '("\\.aql" . js-mode))
Associate yaml-mode
with formular (.frm
) and table (.tbl
)
definitions as used in fb-core et.al.
(require 'yaml-mode)
(add-to-list 'auto-mode-alist '("\\.yml$" . yaml-mode))
(add-to-list 'auto-mode-alist '("\\.frm$" . yaml-mode))
(add-to-list 'auto-mode-alist '("\\.tbl$" . yaml-mode))
(define-hook-helper yaml-mode ()
(progn
(setq tab-width 2
c-basic-offset 2
indent-tabs-mode nil)
(yas-minor-mode 1)
(poly-yaml-mode 1)
(local-set-key (kbd "C-c a") 'tom/edit-js)))
;;; (require 'inf-groovy)
(add-to-list 'auto-mode-alist '("\\.gvy$" . groovy-mode))
(rtog/add-repl 'groovy-mode (rtog/switch-to-shell-buffer "*groovy*" 'run-groovy))
(define-hook-helper haskell-mode ()
(progn
(hindent-mode 1)))
(let ((my-cabal-path (expand-file-name "~/.cabal/bin")))
(setenv "PATH" (concat my-cabal-path path-separator (getenv "PATH")))
(add-to-list 'exec-path my-cabal-path))
(custom-set-variables '(haskell-tags-on-save t))
(custom-set-variables
'(haskell-process-suggest-remove-import-lines t)
'(haskell-process-auto-import-loaded-modules t)
'(haskell-process-log t)
'(haskell-process-type 'cabal-repl)
'(hindent-style "gibiansky"))
(eval-after-load 'haskell-mode
'(progn
(define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-or-reload)
(define-key haskell-mode-map (kbd "C-c C-z") 'haskell-interactive-switch)
(define-key haskell-mode-map (kbd "C-c C-n C-t") 'haskell-process-do-type)
(define-key haskell-mode-map (kbd "C-c C-n C-i") 'haskell-process-do-info)
(define-key haskell-mode-map (kbd "C-c C-n C-c") 'haskell-process-cabal-build)
(define-key haskell-mode-map (kbd "C-c C-n c") 'haskell-process-cabal)))
(eval-after-load 'haskell-cabal
'(progn
(define-key haskell-cabal-mode-map (kbd "C-c C-z") 'haskell-interactive-switch)
(define-key haskell-cabal-mode-map (kbd "C-c C-k") 'haskell-interactive-mode-clear)
(define-key haskell-cabal-mode-map (kbd "C-c C-c") 'haskell-process-cabal-build)
(define-key haskell-cabal-mode-map (kbd "C-c c") 'haskell-process-cabal)))
(require 'aql-mode)
(define-hook-helper aql-mode ()
(progn
(setq tab-width 2
c-basic-offset 2
indent-tabs-mode nil)
(yas-minor-mode 1)))
(require 'sql)
(require 'sql-indent)
(sql-set-product "postgres")
(define-hook-helper sql-mode ()
(progn
(setq tab-width 2
c-basic-offset 2
indent-tabs-mode nil)
(yas-minor-mode 1)
(sqlind-minor-mode 1)))
(defun tom/extract-json (name)
"Extract the field `NAME' from the restclient-result
buffer (`*HTTP Response*'). Caution: This parses the
hole buffer as json-data, so may be costly.
`NAME' may be given as dotted path to address nested json-objects"
(with-current-buffer "*HTTP Response*"
(let* ((json-object-type 'hash-table)
(json-array-type 'list)
(json-key-type 'string)
(names (split-string name "\\." t))
(result nil)
(data (json-read-from-string (buffer-string))))
(reduce #'(lambda (value key) "" (gethash key value)) names :initial-value data))))
(eval-after-load 'outline
'(progn
(require 'outline-magic)
(define-key outline-minor-mode-map
(kbd "<C-tab>")
'outline-cycle)))
(autoload 'es-mode "es-mode.el" "Major mode for editing Elasticsearch queries." t)
(add-to-list 'auto-mode-alist '("\\.es$" . es-mode))
(add-hook 'es-result-mode-hook 'hs-minor-mode)
;;;(load (expand-file-name "~/quicklisp/slime-helper.el"))
;; Replace "sbcl" with the path to your implementation
(setq inferior-lisp-program "sbcl")
(setq magithub-feature-autoinject t)
(require 'magithub)
(require 'magit)
(setq magit-completing-read-function 'ivy-completing-read)
(setq magit-wip-merge-branch t)
(magit-wip-mode 1)
(with-eval-after-load 'magit
(require 'forge))
(global-set-key (kbd "<f7>") 'magit-status)
(global-set-key (kbd "H-g") 'magit-file-dispatch)
(fullframe magit-status magit-mode-quit-window nil)
(defhydra tom/smerge-hydra
(:color pink :hint nil :post (smerge-auto-leave))
"
^Move^ ^Keep^ ^Diff^ ^Other^
^^-----------^^-------------------^^---------------------^^-------
_n_ext _b_ase _<_: upper/base _C_ombine
_p_rev _u_pper _=_: upper/lower _r_esolve
^^ _l_ower _>_: base/lower _k_ill current
^^ _a_ll _R_efine
^^ _RET_: current _E_diff
"
("n" smerge-next)
("p" smerge-prev)
("b" smerge-keep-base)
("u" smerge-keep-upper)
("l" smerge-keep-lower)
("a" smerge-keep-all)
("RET" smerge-keep-current)
("\C-m" smerge-keep-current)
("<" smerge-diff-base-upper)
("=" smerge-diff-upper-lower)
(">" smerge-diff-base-lower)
("R" smerge-refine)
("E" smerge-ediff)
("C" smerge-combine-with-next)
("r" smerge-resolve)
("k" smerge-kill-current)
("ZZ" (lambda ()
(interactive)
(save-buffer)
(bury-buffer))
"Save and bury buffer" :color blue)
("q" nil "cancel" :color blue))
(define-hook-helper magit-diff-visit-file ()
:name magit-smerge-diff
(when smerge-mode
(tom/smerge-hydra/body)))
Manage ssh tunnel via prodigy.
(require 'prodigy)
(defun tom/build-tunnel-args (args)
"Assemble the ssh tunnel argument list."
`("-v" ;; allows us to parse for the ready message
"-N" ;; don't start an interactive shell remotely
"-L" ,(concat (getf args :localport) ;; the tunnel spec
":"
(getf args :tunnel-ip)
":"
(getf args :tunnel-port))
"-l" ,(getf args :user) ;; the username
"-p" ,(getf args :port) ;; the remote port
,(getf args :host))) ;; the remote host
(prodigy-define-tag
:name 'ssh-tunnel
:command "ssh"
:cwd (getenv "HOME")
:args (prodigy-callback (service)
(tom/build-tunnel-args
(getf service :tunnel)))
:ready-message "debug1: Entering interactive session.")
Tunnel definitions are held outside this config to protect the innocent…
(load-file "~/ownCloud/dotfiles/prodigy.el")
(when (tom/work?)
(load-file "~/ownCloud/dotfiles/workservices.el"))
Set an org-mode html export as readme text for a sourcehut repository. Use bin/srht_repoid.sh
to determin the numerical id of the repository. Standard org-mode image links may not work as expected – melpa badges for example– use export-html blocks with the correct html code in these cases.
(require 'json)
(defun tom/srht-set-readme (id)
"Export the current file to html and set the result as readme for the
sourcehut repo identified by ID."
(interactive "sRepo id: ")
(let* ((srht (netrc-machine (netrc-parse "~/.netrc.gpg") "git.sr.ht"))
(srht-token (netrc-get srht "password"))
(oauth2-token (concat "Bearer " srht-token))
(readme.html (org-export-as (org-export-get-backend 'html) nil nil t))
(json-object-type 'hash-table)
(json-array-type 'list)
(json-key-type 'string)
(query (make-hash-table))
(variables (make-hash-table)))
(puthash "id" id variables) ; the sourcehut repo id
(puthash "readme" readme.html variables)
(puthash
"query"
"mutation UpdateRepo($id: Int!, $readme: String!) {
updateRepository(id: $id, input: { readme: $readme }) { id }
}"
query)
(puthash
"variables" variables query)
(request
"https://git.sr.ht/query"
:type "POST"
:data (json-serialize query)
:headers `(("Content-Type" . "application/json") ("Authorization" . ,oauth2-token))
:parser 'json-read
:complete (cl-function (lambda (&key symbol-status &allow-other-keys) (message "Set: %S" symbol-status))))))
(let ((ix-io (netrc-machine (netrc-parse "~/.netrc.gpg") "ix-io")))
(setq ix-user (netrc-get ix-io "login"))
(setq ix-token (netrc-get ix-io "password")))
(let ((github (netrc-machine (netrc-parse "~/.netrc.gpg") "yagist")))
(setq yagist-github-token (netrc-get github "password")))
I use ag.el to interact with ag, a fine replacement for grep. Ignore all ignore-files :-)
(setq ag-arguments (list "-U" "--numbers" "--smart-case" "--nogroup" "--column" "--stats" "--"))
Focus on the current window and the ag-result buffer.
(fullframe/split-screen ag quit-window "*ag search*" 'horizontal 't)
Setup `wgrep-ag`.
(autoload 'wgrep-ag-setup "wgrep-ag")
(add-hook 'ag-mode-hook 'wgrep-ag-setup)
Delete the File:
prefix appended by ag
to the output, let `compile-find-file` work again.
(define-advice compilation-find-file (:around (orig-fun &rest args) remove-file-prefix -100)
(let* ((to-find (car (cdr args)))
(newname (s-replace "File: " "" to-find)))
(setcar (cdr args) newname)
(apply orig-fun args)))
Do this after everything is setup.
(diminish 'golden-ratio-mode "")
(diminish 'undo-tree-mode "")
(diminish 'whitespace-mode "")
(diminish 'company-mode "")
(diminish 'org-src-mode "")
(diminish 'projectile-mode "")
(diminish 'yas-minor-mode "")
(diminish 'flycheck-mode "")
(diminish 'repl-toggle-mode "")
(diminish 'mmm-mode "")
(diminish 'persp-mode "")
(diminish 'company-box-mode "")
(diminish 'volatile-highlights-mode "")
(diminish 'eldoc-mode "")
(diminish 'visual-line-mode "")
(diminish 'abbrev-mode "")
(diminish 'auto-revert-mode "")
(load-file "~/.emacs.d/site/sanity.el")
(setq gc-cons-threshold tom/gc-cons-threshold)
(setq httpd-port 8081)
(setq httpd-host "0.0.0.0")
Always have an emacs server running.
(require 'server)
(unless (server-running-p)
(org-reload) ; switch to newest org from melpa
(server-start)
(message "Server started."))