doom-emacs/site-functions.el

391 lines
11 KiB
EmacsLisp
Raw Normal View History

2020-12-01 15:09:35 -08:00
;;; 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)
2020-12-01 15:09:35 -08:00
(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 ""))
2020-12-01 15:09:35 -08:00
(mapconcat 'identity lst chr))
(defun any-p (f lst)
(reduce
(lambda (a b) (or a b))
(mapcar f lst)
:initial-value '()))
2021-01-15 10:57:15 -08:00
2020-12-01 15:09:35 -08:00
(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)
2020-12-01 15:09:35 -08:00
;; site-functions.el ends here