doom-emacs/site-functions.el

391 lines
11 KiB
EmacsLisp
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; site-functions.el -*- lexical-binding: t; -*-
;;(require 'eshell)
;;(require 'em-dirs)
(provide 'site-functions)
;;; Code:
(defun kill-whitespace ()
"Kill the whitespace from here to the next non-whitespace character."
(interactive "*")
(save-excursion
(save-restriction
(save-match-data
(progn
(re-search-forward "[ \t\r\n]+" nil t)
(replace-match "" nil nil))))))
;; (defun split-line ()
;; "Split the current line into two at the current point."
;; (interactive "*")
;; (save-excursion
;; (save-restriction
;; (save-match-data
;; (progn (newline-and-indent))))))
(defun bind-hooks-to-modes (hooks modes)
"Takes a list of HOOKS and a list of MODES, add all hooks to all modes."
(dolist (hook hooks)
(dolist (mode modes)
(add-hook mode hook))))
(defun bind-hook-to-modes (hook modes)
"Bind a single HOOK to many MODES."
(bind-hooks-to-modes (list hook) modes))
(defun bind-hooks-to-mode (hooks mode)
"Bind many HOOKS to a single MODE."
(bind-hooks-to-modes hooks (list mode)))
;; (defun remote-shell (host)
;; "Open a remote shell on the given host"
;; (interactive "sRemote host name: \n")
;; (let ((default-directory (concat "/" host ":/home/" (user-login-name) "/")))
;; (shell (concat "*" host "*"))))
;; Emacs Lisp doesnt come with a filter function to keep elements that satisfy
;; a conditional and excise the elements that do not satisfy it. One can use mapcar
;; to iterate over a list with a conditional, and then use delq to remove the nil
;; values.
(defun filter (condp lst)
"Remove all elements not matching CONDP from LST."
(delq nil
(mapcar (lambda (x) (and (funcall condp x) x)) lst)))
;; Therefore
;;
;; (my-filter 'identity my-list)
;; is equivalent to
;; (delq nil my-list)
;;
;; For example:
;;(let ((num-list '(1 'a 2 "nil" 3 nil 4)))
;; (my-filter 'numberp num-list)) ==> (1 2 3 4)
;;
;; Actually the package cl-seq contains the functions remove-if and remove-if-not.
;; The latter can be used instead of my-filter.
;;
;; Never understood why Emacs doesn't have this function.
;;
(defun rename-file-and-buffer (new-name)
"Renames both current buffer and file it's visiting to NEW-NAME."
(interactive "sNew name: ")
(let ((name (buffer-name))
(filename (buffer-file-name)))
(if (not filename)
(message "Buffer '%s' is not visiting a file!" name)
(if (get-buffer new-name)
(message "A buffer named '%s' already exists!" new-name)
(progn
(rename-file name new-name 1)
(rename-buffer new-name)
(set-visited-file-name new-name)
(set-buffer-modified-p nil))))))
;;
;; Never understood why Emacs doesn't have this function, either.
;;
(defun move-buffer-file (dir)
"Move both current buffer and file it's visiting to DIR."
(interactive "DNew directory: ")
(let* ((name (buffer-name))
(filename (buffer-file-name))
(dir
(if (string-match dir "\\(?:/\\|\\\\)$")
(substring dir 0 -1) dir))
(newname (concat dir "/" name)))
(if (not filename)
(message "Buffer '%s' is not visiting a file!" name)
(progn
(copy-file filename newname 1)
(delete-file filename)
(set-visited-file-name newname)
(set-buffer-modified-p nil)
t))))
(defun join-dirs (&rest strings)
"Connect a list of STRINGS with a path separator, /."
(mapconcat 'identity strings "/"))
(defun my-copy-line (&optional arg)
"Copy ARG lines to kill ring."
(interactive "P")
(let ((n (if arg
arg
1)))
(kill-ring-save (line-beginning-position)
(line-beginning-position (+ n 1)))
(message "%d line%s copied" n (if (= 1 n) "" "s"))))
(defvar my-time-format "%k:%M:%S")
(defvar my-date-format "%Y-%m-%d")
(defun my-run-command-on-this-line (cmd)
"Run the CMD found on this line in an external shell."
(beginning-of-line-text)
(let ((start (point)))
(end-of-line)
(command start (end-of-line))))
(defun my-kill-this-buffer ()
"Kill the current buffer."
(interactive)
(kill-buffer (buffer-name))
(set-name))
(defun my-forward-word ()
"Move one word forward. Leave the pointer at start of word."
(interactive)
(forward-char 1)
(backward-word 1)
(forward-word 2)
(backward-word 1)
(backward-char 1)
(forward-char 1))
(defun my-backward-word ()
"Move one word backward. Leave the pointer at start of word."
(interactive)
(backward-word 1)
(backward-char 1)
(forward-char 1))
(defun smart-tab ()
(interactive)
(if (minibufferp)
(unless (minibuffer-complete)
(dabbrev-expand nil))
(if mark-active
(indent-region (region-beginning)
(region-end))
(indent-for-tab-command))))
(defun copy-line (&optional arg)
(interactive)
(save-excursion
(beginning-of-line-text)
(let ((start (point)))
(end-of-line)
(kill-ring-save start (point)))))
(defun get-point (symbol &optional arg)
"get the point"
(funcall symbol arg)
(point))
(defun copy-thing (begin-of-thing end-of-thing &optional arg)
"copy thing between beg & end into kill ring"
(let ((beg (get-point begin-of-thing 1))
(end (get-point end-of-thing arg)))
(copy-region-as-kill beg end)))
(defun copy-word (&optional arg)
"Copy words at point into kill-ring"
(interactive "P")
(save-excursion
(copy-thing 'backward-word 'forward-word arg)))
(defun move-text-internal (arg)
(cond
((and mark-active transient-mark-mode)
(let ((column (current-column))
(text (delete-and-extract-region (point) (mark))))
(forward-line arg)
(move-to-column column t)
(set-mark (point))
(insert text)
(exchange-point-and-mark)
(setq deactivate-mark nil)))
(t
(beginning-of-line)
(when (or (> arg 0) (not (bobp)))
(forward-line)
(when (or (< arg 0) (not (eobp)))
(transpose-lines arg))
(forward-line -1)))))
(defun move-text-down (arg)
"Move region (transient-mark-mode active) or current line
arg lines down."
(interactive "*p")
(move-text-internal arg))
(defun move-text-up (arg)
"Move region (transient-mark-mode active) or current line
arg lines up."
(interactive "*p")
(move-text-internal (- arg)))
(defun ido-find-file-in-tag-files ()
(interactive)
(save-excursion
(let ((enable-recursive-minibuffers t))
(visit-tags-table-buffer))
(ido-completing-read "Project file "
(tags-table-files)
nil t)))
(defun untabify-this-file ()
(interactive)
(save-excursion
(end-of-buffer)
(let ((pos (point)))
(untabify 0 pos))))
(defun ensime-remote-connect (host port)
(interactive (list
(read-from-minibuffer "Host: " ensime-default-server-host)
(read-from-minibuffer "Port: " (format "%d" ensime-default-port)
nil t)))
(let ((c (ensime-connect host port))
(config (ensime-config-load "/Users/whunmr/lab/scala/.ensime")))
(ensime-set-config c config)
(setq ensime-buffer-connection c)))
(defun path-join (paths)
(mapconcat 'identity paths ":"))
(defun strip-dup-paths (path)
(path-join
(delete-dups
(split-string path ":"))))
(defun strip-invalid-paths (path)
(path-join
(filter (lambda (p)
(string-match "^/" p))
(split-string path ":"))))
(defun get-path ()
(split-string (getenv "PATH") ":"))
(cl-defun string-join (lst &optional (chr ""))
(mapconcat 'identity lst chr))
(defun any-p (f lst)
(reduce
(lambda (a b) (or a b))
(mapcar f lst)
:initial-value '()))
(defun every-p (f lst)
(reduce
(lambda (a b) (and a b))
(mapcar f lst)
:initial-value t))
(defun odd-p (n)
(= (% n 2) 1))
(defun even-p (n)
(not (odd-p n)))
(defun subpath-p (parent child-p)
(string-match (concat "^" parent ".+") child-p))
(defvar read-only-paths '())
(defun should-be-readonly (filepath)
(any-p
(lambda (path)
(subpath-p path filepath))
read-only-paths))
(defun goto-match-paren (arg)
"Go to the matching parenthesis if on parenthesis,
vi style of % jumping to matching brace."
(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)))))
(defun yank-buffer-path ()
"Yank the current buffer's path"
(interactive)
(let ((filename (if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name))))
(when filename
(with-temp-buffer
(insert filename)
(clipboard-kill-region (point-min) (point-max)))
(message filename))))
(defun kill-matching-lines (regexp &optional rstart rend interactive)
"Kill lines containing matches for REGEXP.
See `flush-lines' or `keep-lines' for behavior of this command.
If the buffer is read-only, Emacs will beep and refrain from deleting
the line, but put the line in the kill ring anyway. This means that
you can use this command to copy text from a read-only buffer.
\(If the variable `kill-read-only-ok' is non-nil, then this won't
even beep.)"
(interactive
(keep-lines-read-args "Kill lines containing match for regexp"))
(let ((buffer-file-name nil)) ;; HACK for `clone-buffer'
(with-current-buffer (clone-buffer nil nil)
(let ((inhibit-read-only t))
(keep-lines regexp rstart rend interactive)
(kill-region (or rstart (line-beginning-position))
(or rend (point-max))))
(kill-buffer)))
(unless (and buffer-read-only kill-read-only-ok)
;; Delete lines or make the "Buffer is read-only" error.
(flush-lines regexp rstart rend interactive)))
(defun eshell/x ()
(insert "exit")
(eshell-send-input)
(delete-window))
;; (save-excursion
;; (save-restriction
;; (save-match-data
;; (progn
;; (re-search-forward "[ \t\r\n]+" nil t)
;; (replace-match "" nil nil)))))
(defun open-and-indent-line ()
(interactive)
(save-restriction
(save-match-data
(progn (end-of-line)
(newline-and-indent)))))
(defun open-and-indent-previous-line ()
(interactive)
(save-restriction
(save-match-data
(progn (beginning-of-line)
(newline)
(forward-line -1)
(indent-according-to-mode)))))
(defun foreach (f alist)
(while alist
(progn (funcall f (car alist))
(setq alist (cdr alist)))))
(defun bash-env-var (varname)
(replace-regexp-in-string "\n$" ""
(shell-command-to-string
(string-join (list ". ~/.bash_profile; echo $"
varname)))))
(defun intern-bash-env-var (varname)
(let ((val (bash-env-var varname)))
(setenv varname val)
val))
(provide 'site-functions)
;; site-functions.el ends here