Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 1139 lines (1031 sloc) 38.5 KB
(provide 'air-utils)
;;;;;;;;;;;;;;;;;;
; fancy delete-other-windows
; from: http://www.cs.berkeley.edu/~smcpeak/elisp/scott.emacs.el
(defvar util-saved-window-config-list nil)
(defun mdi-maximize-restore-toggle ()
"When called in a multi-window frame it will save the window
configuration by calling `current-window-configuration', then call
`delete-other-windows'. When called in a single-window frame it will
restore the frame configuration by calling `set-window-configuration'."
(interactive)
(if (> (count-windows) 1)
(progn
(gc-util-window-config-list (selected-frame))
(setq util-saved-window-config-list
(cons (list (buffer-name) (current-window-configuration))
util-saved-window-config-list))
(delete-other-windows))
(restore-applicable-window-configuration util-saved-window-config-list)))
(defun gc-util-window-config-list (frame)
"Remove any saved configs that apply to deleted frames or to
the 'frame' argument."
(setq util-saved-window-config-list
(filter-list util-saved-window-config-list
#'(lambda (config)
(and
(member (window-configuration-frame (car (cdr config))) (frame-list))
(not (eq (window-configuration-frame (car (cdr config))) frame))
))
)))
(defun restore-applicable-window-configuration (list)
"Look through 'list' for a window config that applies to the selected
frame. If found, restore via that config. If not, say so."
(if (not list)
(princ "There is no saved window config for this buffer.")
(let ((bufname (car (car list)))
(windowconfig (car (cdr (car list)))))
(if (and (eq (window-configuration-frame windowconfig) (selected-frame))
(eq bufname (buffer-name)))
; restore it
(set-window-configuration windowconfig)
; else, proceed down list
(restore-applicable-window-configuration (cdr list))))))
(defun util-iswitchb-otherwindow ()
(interactive)
"Toggle new buffer in otherwindow setting"
(let ((buffer (car iswitchb-matches)))
(if (not (eq iswitchb-method 'otherwindow))
(progn
(message "Other window: %s" buffer)
(setq iswitchb-method 'otherwindow))
(progn (message "Same window: %s" buffer)
(setq iswitchb-method 'always-frame)))))
(defun filter-list (list predicate)
"Return a list containing only those elements from 'list' which
cause 'predicate' to return true."
(if (not list)
nil ; recursion base case
(if (funcall predicate (car list))
; keep the item
(cons (car list) (filter-list (cdr list) predicate))
; else, remove it
(filter-list (cdr list) predicate)
)))
(defun util-kill-this-buffer ()
(interactive)
(if (window-minibuffer-p) (keyboard-escape-quit)
(if (string= "*Buffer List*" (buffer-name)) (keyboard-quit)
(progn
(kill-buffer (current-buffer))
(if (> (count-windows) (util-count-buffers)) (delete-window))
))))
;; Stolen wholesale http://www.cb1.com/~john/ (John Sturdy)
(defun util-count-buffers (&optional display-anyway)
"Display or return the number of buffers."
(interactive)
(let ((buf-count (length (buffer-list))))
(if (or (interactive-p) display-anyway)
(message "%d buffers in this Emacs" buf-count)) buf-count))
;; Override this with a regex to add your own special buffers.
(setq util-special-buffers "")
(defun util-delete-other-buffers ()
"Delete other buffers, but use a regex to prevent special buffers from being deleted."
(interactive)
(util-save-and-save-some-buffers)
(let ((tobe-killed (cdr (buffer-list (current-buffer)))))
(while tobe-killed
(let ((current (car tobe-killed)))
(if (not (string-match util-special-buffers (buffer-name current)))
(progn
(kill-buffer current)
(message (format "kill buffer: %s" current))))
(setq tobe-killed (cdr tobe-killed)))))
(delete-other-windows))
(defun util-kill-other-buffers ()
"Kill all other buffers."
(interactive)
(mapc 'kill-buffer (delq (current-buffer) (buffer-list))))
(defun util-shell-function (cmd &optional buffername quiet)
"Run a function defined in our bash configuration"
(interactive (list (read-string "% ")))
(compile cmd)
)
(defun util-shell-function-basic (cmd &optional args)
(let ((bufname (format "*%s*" cmd)))
(when args (setq cmd (format "%s %s" cmd args)))
(util-shell-function cmd bufname)))
(defun util-shell-function-no-output (cmd &optional args)
(when args (setq cmd (format "%s %s" cmd args)))
(util-shell-function cmd "discard output" 't))
(defun util-shell-function-eval (cmd)
"Evaluate a function and return its output"
(with-output-to-string
(with-current-buffer
standard-output
(util-shell-function cmd "stdout" 't))))
(defun eval-fun()
"Looks for the above defun, then evaluates the function"
(interactive)
(save-excursion
(search-backward-regexp "^\(defun")
(let ((line (current-line)))
(string-match "defun \\([^(]+\\)" line)
(message (format "evaling function: '%s'" (match-string 1 line))))
(set-mark (point))
(util-goto-matching-char)
(forward-char)
(eval-region (region-beginning) (region-end))
(deactivate-mark)
))
(defun util-select-empty-output-buffer (buffername)
(switch-to-buffer (get-buffer-create buffername))
(util-erase-buffer))
(defun util-erase-buffer ()
(setq buffer-read-only 'nil)
(erase-buffer))
(defun util-generate-empty-output-buffer (buffername)
(let (current-buffer (current-buffer))
(util-select-empty-output-buffer buffername)
(switch-to-buffer current-buffer)))
(defun first-line-matching (regexp)
(let ((line-char 'nil))
(save-excursion
(goto-char 0)
(if (search-forward-regexp regexp 'nil 't)
(setq line-char (line-beginning-position))
)
line-char
)
))
(defun firstword ()
(save-excursion
(beginning-of-buffer)
( let ((beg) (end) )
(setq beg (point))
(search-forward-regexp "[ \n]")
(setq end (- (point) 1))
(buffer-substring beg end)
)))
(defun shebang ()
"return the shebang of the current buffer"
(interactive)
(save-excursion
(let ((word (firstword)))
(if (string-match "^#!.*" word)
(progn
(beginning-of-buffer)
(search-forward-regexp "#!")
(let ((beg) (end) )
(setq beg (point))
(search-forward-regexp "[ \n]")
(setq end (- (point) 1))
(buffer-substring beg end)
)
))
)
))
(defun util-save-and-save-some-buffers ()
(interactive)
(if (buffer-file-name) (save-buffer))
(save-some-buffers))
(defun run-current-file ()
(interactive)
(let* (
(bang (shebang))
(filename (buffer-file-name))
(extension (file-name-extension filename))
)
(message (format "bang = %s %s" bang extension))
(if (not(string= bang nil))
(progn
(util-save-and-save-some-buffers)
(util-shell-function
(format "%s %s" bang buffer-file-name)
)
)
(if (string-match "webpack.config" filename)
(progn
(message (format "webpack = %s" filename))
(util-shell-function
(format "%s --config %s" "webpack" filename)
)
)
(if (string= extension "js")
(progn
(message (format "string-match = %s" filename))
(util-shell-function
(format "%s %s" "/usr/local/bin/node" filename)
)
)
)
)
)
)
)
(defun util-zap-to-char (arg char)
"Kill up to *but not including* ARG'th occurrence of CHAR.
Case is ignored if `case-fold-search' is non-nil in the current buffer.
Goes backward if ARG is negative; error if CHAR not found."
(interactive "p\ncZap to char: ")
(kill-region (point) (progn
(search-forward (char-to-string char) nil nil arg)
(backward-char 1)
(point))))
(defun isearch-occur ()
"Invoke `occur' from within isearch."
(interactive)
(let ((case-fold-search isearch-case-fold-search))
(occur (if isearch-regexp isearch-string (regexp-quote isearch-string)))))
(defun current-line-full ()
(buffer-substring (line-beginning-position) (+ 1 (line-end-position))))
(defun util-comment-dwim ()
(interactive)
(if (not mark-active)
(progn
(if (eq last-command 'util-comment-dwim)
(kill-append (current-line-full) 'nil)
(kill-new (current-line-full)))
(comment-region (line-beginning-position) (line-end-position))
(forward-line 1)
)
(comment-dwim nil)))
(defun util-kill-line-or-region ()
"Kill region if active, otherwise kill line"
(interactive)
(if mark-active (kill-region (mark) (point)) (kill-line)))
(defun util-kill-word ()
"Kill characters forward until the end of a word or line"
(interactive)
(let (endofword (endofline (line-end-position)))
(save-excursion (forward-word 1) (setq endofword (point)))
(kill-region (point)
(if (= endofline (point))
(1+ endofline)
(if (< endofline endofword) endofline endofword)))))
(defun util-backward-kill-word ()
"Kill characters backward until the beg of a word or line"
(interactive)
(let (begofword (begofline (line-beginning-position)))
(save-excursion (forward-word -1) (setq begofword (point)))
(kill-region (point)
(if (= begofline (point))
(1- begofline)
(if (> begofline begofword) begofline begofword)))))
(defun util-forward-word ()
;; Move one word forward. Leave the pointer at start of word
;; instead of emacs default end of word. Treat _ as part of word
(interactive)
(let ((start (point)) boundary at-boundary jump)
(setq at-boundary (eolp))
(setq boundary (line-end-position))
(forward-char 1)
(backward-word 1)
(forward-word 2)
(backward-word 1)
(backward-char 1)
(cond ((or (looking-at "_") (looking-at "\\.[0-9]\\.")) (forward-char 1)
(util-forward-word))
(t (forward-char 1)))
(if (and (not at-boundary) (> (point) boundary)) (goto-char boundary))
(setq jump (util-count-lines start (point)))
(if (> jump 0) (progn (forward-line (- 1 jump)) (back-to-indentation)))
))
(defun util-backward-word ()
;; Move one word backward. Leave the pointer at start of word
;; Treat _ as part of word
(interactive)
(let ((start (point)) boundary at-boundary jump)
(setq at-boundary (empty-line-prefix))
(setq boundary (line-beginning-position))
(backward-word 1)
(backward-char 1)
(cond ((or (looking-at "_") (looking-at "\\.[0-9]\\."))
(util-backward-word))
(t (forward-char 1)))
(if (and (not at-boundary) (< (point) boundary))
(progn (goto-char boundary) (back-to-indentation)))
(setq jump (util-count-lines start (point)))
(if (> jump 0) (progn (forward-line (- jump 1)) (end-of-line)))
))
(defun util-count-lines (beg end)
(let (tmp)
(if (< end beg) (progn (setq tmp beg) (setq beg end) (setq end tmp)))
(save-excursion
(goto-char beg) (setq beg (line-beginning-position))
(goto-char end) (setq end (line-beginning-position))
)
(count-lines beg end)))
(defun current-line ()
(buffer-substring (line-beginning-position) (line-end-position)))
(defun current-line-full ()
(buffer-substring (line-beginning-position) (+ 1 (line-end-position))))
(defun current-line-prefix ()
(buffer-substring (line-beginning-position) (point)))
(defun current-line-suffix () (buffer-substring (point) (line-end-position)))
(defun current-line-number ()
(let ((linenum (string-to-int (substring (what-line) 5))))
(message "")
linenum))
(defun current-number ()
(save-excursion
(let (beg)
(skip-chars-backward "0-9")
(setq beg (point))
(skip-chars-forward "0-9")
(buffer-substring beg (point)))))
(defun empty-line-suffix () (only-whitespace (current-line-suffix)))
(defun empty-line-prefix () (only-whitespace (current-line-prefix)))
(defun only-whitespace (str) (and (string-match "^[ \r\t]*\$" str) 't))
(defun next-char ()
(if (>= (point) (1- (point-max)))
(current-char)
(char-to-string (char-after (1+ (point))))))
(defun current-char ()
(char-to-string (following-char)))
(defun previous-char ()
(char-to-string (preceding-char)))
(defun previous-string (&rest strlist)
(let (found length)
(loop for str in (flatten strlist) do
(setq length (length str))
(and (not found) (> length 0) (< length (point))
(save-excursion
(backward-char length)
(when (looking-at str) (setq found str)))))
found
))
(defun previous-key (&optional arg)
(if (not arg) (setq arg 1))
(let (recent-keys index)
(setq recent-keys (recent-keys))
(setq index (- (length recent-keys) (1+ arg)))
(if (>= index 0)
(aref recent-keys index)
'nil)))
(defun util-chord-for-key (key)
(key-description key))
(defun previous-key-string (&optional arg)
(util-chord-for-key (vector (previous-key arg))))
(defun util-goto-end (&optional ARG)
(interactive)
(let ((prevkey (previous-key-string)))
(if (or (string= prevkey "<end>")
(string= prevkey "<kp-end>")
(and (string= (previous-key-string 7) "ESC")
(string= (previous-key-string 6) "[")
(string= (previous-key-string 5) "4")
(string= (previous-key-string 4) "~")))
(end-of-buffer ARG)
(end-of-line ARG))))
(defun util-goto-beg (&optional ARG)
(interactive)
(let ((prevkey (previous-key-string)))
(if (or (string= prevkey "<home>")
(string= prevkey "<kp-home>")
(and (string= (previous-key-string 7) "ESC")
(string= (previous-key-string 6) "[")
(string= (previous-key-string 5) "1")
(string= (previous-key-string 4) "~")))
(beginning-of-buffer ARG)
(beginning-of-line ARG))))
(defun copy-from-above-or-below (&optional arg below)
"Copy characters from previous nonblank line, starting just above point.
Copy ARG characters, but not past the end of that line.
If no argument given, copy the entire rest of the line.
The characters copied are inserted in the buffer before point."
(interactive "P")
(let ((cc (current-column)) n (string "") wordlen)
(save-excursion
(if below (progn (end-of-line) (skip-chars-forward "\ \t\n"))
(progn (beginning-of-line) (skip-chars-backward "\ \t\n")))
(move-to-column cc)
;; Default is enough to copy the whole rest of the line.
(save-excursion
(let ((start (point)))
(forward-word 1)
(setq wordlen (- (point) start))))
(setq n (if arg wordlen (point-max)))
;; If current column winds up in middle of a tab,
;; copy appropriate number of "virtual" space chars.
(if (< cc (current-column))
(if (= (preceding-char) ?\t)
(progn
(setq string (make-string (min n (- (current-column) cc)) ?\ ))
(setq n (- n (min n (- (current-column) cc)))))
;; In middle of ctl char => copy that whole char.
(backward-char 1)))
(setq string (concat string
(buffer-substring
(point)
(min (save-excursion (end-of-line) (point))
(+ n (point)))))))
(insert string)))
(defun util-toggle-kbd-macro-recording ()
(interactive)
(if defining-kbd-macro (end-kbd-macro) (start-kbd-macro 'nil)))
(defun util-beginning-or-toindent ()
(interactive)
(if (and (eq (current-column) 0)
(string= (previous-key-string) "C-a"))
(back-to-indentation)
(beginning-of-line)))
(defun end-of-line-ignore-whitespace ()
(interactive)
(goto-char (line-end-position-ignore-whitespace)))
(defun line-end-position-ignore-whitespace ()
(save-excursion
(end-of-line)
(while (or (string= (previous-char) " ")
(string= (previous-char) " "))
(backward-char 1))
(point)))
(defun util-ending-or-nextline-end ()
(interactive)
(if (string= (previous-key-string) "C-e") (forward-line 1))
(end-of-line-ignore-whitespace))
(defun util-jump-to-top ()
(interactive)
(goto-line (- (current-line-number) (window-line))))
(defun util-jump-to-bottom ()
(interactive)
(goto-line (- (+ (current-line-number) (window-line-from-bottom)) 1)))
(defun util-scootch-up ()
(interactive)
(util-scootch -1))
(defun util-scootch-down ()
(interactive)
(util-scootch 1))
(defun util-scootch-left ()
(interactive)
(util-scootch -1 't))
(defun util-scootch-right ()
(interactive)
(util-scootch 1 't))
(defun util-scootch (linecount &optional horizontal)
(let ((col (current-column)) mark-was-active beg end region)
(if mark-active
(progn
(setq mark-was-active t)
(if (< (point) (mark)) (exchange-point-and-mark))
(setq beg (mark))
(setq end (point))
)
(progn
(setq beg (line-beginning-position))
(setq end (1+ (line-end-position)))
))
(setq region (buffer-substring beg end))
(delete-region beg end)
(if horizontal (forward-char linecount) (forward-line linecount))
(setq beg (point))
(insert region)
(if mark-was-active
(progn
(goto-char beg)
(setq deactivate-mark 'nil)
(set-mark (point))
(goto-char (+ (point) (length region)))
)
(progn
(if horizontal (forward-char linecount) (forward-line linecount))
(move-to-column col)
))))
(defun util-matching-char-position (matchchar closechar backward)
(save-excursion
(let ((count 0) currchar pos
(regexp (concat (regexp-quote matchchar) "\\|" (regexp-quote closechar)))
(myface (face-at-point))
)
(while (not pos)
(if backward
(search-backward-regexp regexp)
(progn
(forward-char 1)
(search-forward-regexp regexp)
(backward-char 1)
))
(if (not (equal (face-at-point) myface)) 'nil
(if (string= (current-char) matchchar)
(setq count (1- count))
(if (= count 0) (setq pos (point))
(setq count (1+ count))))
(if (string= matchchar closechar)
(setq pos (point))
)
))
pos
)))
(defun util-find-matching-position (&optional opt-backward)
(save-excursion
(let ((matchchar (current-char)) closechar (backward opt-backward) pos)
(when (string= matchchar "(") (setq closechar ")"))
(when (string= matchchar ")") (setq closechar "(") (setq backward 't))
(when (string= matchchar "[") (setq closechar "]"))
(when (string= matchchar "]") (setq closechar "[") (setq backward 't))
(when (string= matchchar "{") (setq closechar "}"))
(when (string= matchchar "}") (setq closechar "{") (setq backward 't))
(when (string= matchchar "<") (setq closechar ">"))
(when (string= matchchar ">") (setq closechar "<") (setq backward 't))
(when (string= matchchar "/") (setq closechar "/"))
(when (string= matchchar "\"") (setq closechar "\""))
(when (string= matchchar "\'") (setq closechar "\'"))
(when (string= matchchar "`") (setq closechar "`"))
(if (not closechar) (error "Not on a blinkable char, try one of '(){}[]<>/\'\"'"))
(condition-case nil
(util-matching-char-position matchchar closechar backward)
(error (error "Couldn't find matching '%s'." closechar))))))
(defun util-goto-matching-char (&optional opt-backward)
(interactive)
(let ((pos (util-find-matching-position opt-backward)))
(goto-char pos)))
(defun util-blink-matching-char ()
(interactive)
(save-excursion
(util-goto-matching-char)
(if blink-matching-paren-on-screen
(if (pos-visible-in-window-p) (sit-for 0.5)
(message "Matches: %s" (current-line))))))
(defun util-apply-hunk (&optional revert)
(interactive)
(save-excursion
(let ((filename (diff-find-file-name)) errormsg)
(condition-case err (diff-apply-hunk revert)
(error (setq errormsg (error-message-string err))))
(save-other-buffer (get-file-buffer filename))
(when (and errormsg (not (string= errormsg "No next hunk")))
(message errormsg)))))
(defun util-revert-hunk ()
(interactive)
(util-apply-hunk 't))
(defun util-revert-file ()
(interactive)
(save-excursion
(beginning-of-buffer)
(search-forward-regexp "[iI]ndex")
(util-walk-diff-hunks 'util-revert-hunk)))
(defun util-apply-file ()
(interactive)
(save-excursion
(util-walk-diff-hunks 'util-apply-hunk)))
(defun util-walk-diff-hunks (func)
(let (beg)
(beginning-of-line 1)
(if (looking-at "[Ii]ndex:? ") (forward-line))
(search-backward-regexp "[Ii]ndex:? ")
(forward-line)
(setq beg (point))
(condition-case nil (search-forward-regexp "^[Ii]ndex:? ")
(error (goto-char (point-max))))
(while (> (point) beg)
(progn
(condition-case nil (search-backward-regexp "^@@ ")
(error (goto-char (point-min))))
(if (> (point) beg) (funcall func))))))
(defun active-region ()
(buffer-substring (point) (mark)))
(defun current-keyword-or-quoted-active-region (&optional f)
(if mark-active (concat "'" (active-region) "'")
(let ((string (or (current-word nil t) "")))
(if f (funcall f string) string))))
(defun string-join (str_list &optional join_str)
"Joins a list of strings"
(mapconcat 'identity str_list (or join_str " "))
)
(defun save-other-buffer (buffer)
(with-current-buffer buffer
(progn
(set-buffer-modified-p 't)
(save-buffer))))
(defun chomp (str)
"Chomp leading and tailing whitespace from STR."
(while (string-match "\\`\n+\\|^\\s-+\\|\\s-+$\\|\n+\\'"
str)
(setq str (replace-match "" t t str)))
str)
(defun util-update-buffers ()
"Refreshs all open buffers from their respective files"
(interactive)
(let* ((list (buffer-list)) (buffer (car list)) errmesg)
(loop for buffer in (buffer-list) do
(if (and (not (string-match "\\*" (buffer-name buffer)))
(buffer-file-name buffer)
(file-exists-p (buffer-file-name buffer)))
(if (and (not (verify-visited-file-modtime buffer)) ; been touched
(buffer-modified-p buffer)) ; and modified
(setq errmesg (concat errmesg
(format "Buffer '%s' has file and buffer changes!\n" buffer)))
(util-update-buffer buffer))))
(if errmesg (setq errmesg (chomp errmesg)))
(message "%s" (or errmesg "Done refreshing all open non-modified files..."))))
(defun util-update-buffer (buffer)
(set-buffer buffer)
(message "Refreshing %s" (buffer-file-name buffer))
(if (not (verify-visited-file-modtime buffer))
(if (buffer-modified-p buffer) (error "Buffer has file and buffer changes")
(revert-buffer t t t))) ; revert if touched and not modified
(vc-file-clearprops (buffer-file-name)))
(defun fix_quotes (tofix)
(let (variable beg_c end_c variable_len)
(setq variable tofix)
(setq variable_len (length variable))
(setq beg_c (substring tofix 0 1))
(setq end_c (substring tofix (- variable_len 1)))
;; handle the case where the beginning is quote, but the end is not
(if (and
(not (equal end_c "'"))
(equal beg_c "'"))
(setq variable (format "%s'" variable)))
;; handle the case where the end is quote, but the beginning is not
(if (and
(not (equal beg_c "'"))
(equal end_c "'"))
(setq variable (format "'%s" variable)))
variable)
)
;; current-variable matches this:
;; perl: $var, @var, %var, $C'VAR, 'asdf', $var[0]
;; with expressions like @{$var{foo}}, depending on your cursor, you can get $var or foo
;; $other->[0] returns only $other, and $other->($a, $b) returns $other
;; $other->()[0] only returns $other
;; javascript: somevar, namespace.foo.var, bar[0]
;; foo(a, b) only gets foo, a, or b depending on your cursor
;; 'some str' will match 'some' when over some, 'str' when over str
;; pretty much, anything but complex function calls
(defun current-variable ()
(save-excursion
(skip-chars-backward "\':@$%[A-Za-z0-9_\.")
(let (beg end variable)
(setq beg (point))
(skip-chars-forward "\':$[]@%A-Za-z0-9_\.")
(setq end (point))
(setq variable (fix_quotes (buffer-substring beg end)))
)
))
;; current-expression matches this:
;; perl: $var, @var, %var, $C'VAR, @{$var{foo}}, 'asdf', $bar[{$var{foo}}] +{}, +()
;; $other->[0] returns $other->[0], and $other->($a, $b) returns $other->($a, $b)
;; $other->()[0] only return s $other->()
;; javascript: somevar, namespace.foo.var, bar[0]
;; foo(a, b) only works up to the last paren, so
;; foo(a, b) will match foo(a, b), but foo(a, b)[0] will only match foo(a, b)
;; 'some str' will match 'some' when over some, 'str' when over str
;; pretty much, anything but complex function calls
(defun current-expression ()
(save-excursion
(skip-chars-backward "\':{[]}@$%A-Za-z0-9_\.\\->")
(let (beg end variable variable_len end_c)
(setq beg (point))
(skip-chars-forward "\'{}:$@%A-Za-z0-9_\.\\->")
(setq end (point))
(setq variable (buffer-substring beg end))
(setq variable_len (length variable))
;; handle function calls
(setq end_c (buffer-substring end (+ end 1)))
(if (or (equal end_c "(") (equal end_c "[") (equal end_c "{") )
(progn
(setq beg (point))
(forward-list) ;; go to the ending paren
(setq end (point))
(setq variable (format "%s%s" variable (buffer-substring beg end)))
)
)
;; make sure -> doesn't trail
(if (equal (substring variable (- variable_len 2)) "->")
(setq variable (substring variable 0 (- variable_len 2))))
(fix_quotes variable))))
(defun current-line ()
(buffer-substring (line-beginning-position) (line-end-position)))
(defun current-line-full ()
(buffer-substring (line-beginning-position) (+ 1 (line-end-position))))
(defun current-line-prefix ()
(buffer-substring (line-beginning-position) (point)))
(defun current-line-suffix () (buffer-substring (point) (line-end-position)))
(defun current-line-number ()
(let ((linenum (string-to-int (substring (what-line) 5))))
(message "")
linenum))
(defun current-number ()
(save-excursion
(let (beg)
(skip-chars-backward "0-9")
(setq beg (point))
(skip-chars-forward "0-9")
(buffer-substring-no-properties beg (point)))))
(defun util-mark-whole-line ()
(interactive)
(push-mark (line-beginning-position))
(forward-line 1)
(beginning-of-line)
(exchange-point-and-mark)
(exchange-point-and-mark))
(defun util-kill-whole-line ()
(interactive)
(util-mark-whole-line)
(kill-region (mark) (point)))
(defun util-pretty-xml ()
"Prettify ugly xml in buffer"
(interactive)
(save-excursion
(beginning-of-buffer)
(while (search-forward-regexp "><" 'nil t)
(backward-char)
(insert "\n"))
(mark-whole-buffer)
(indent-for-tab-command)
(while (search-forward-regexp "\" " 'nil t)
(if (> (current-column) 80)
(progn
(insert "\n")
(indent-for-tab-command)
)))))
(defun util-ensure-trailing-thing (thing)
"Toggle a trailing thing on the line"
(interactive)
(save-excursion
(end-of-line)
(unless (bobp)
(backward-char 1)
(cond
((looking-at thing)
(delete-char 1)
t)
(t
(forward-char 1)
(insert thing)))))
(next-line 1))
(defun util-generic-indent-region-or-line (indent-command)
(if mark-active
(progn ; set beg end to marked region
(if (< (point) (mark)) (exchange-point-and-mark))
(indent-region (mark) (1- (point)))
)
(let ((previous-key (previous-key)))
(if (and (or (looking-at "\\>")
(empty-line-suffix)
(string-equal (previous-char) ":")
(eq previous-key 'left)
(eq previous-key 'right))
(not (eq previous-key 'down))
(not (eq previous-key 'up))
(not (and (eolp) (string-match "[\]\)\}\,]" (previous-char))))
(not (empty-line-prefix)))
(hippie-expand 'nil)
(progn
(setq he-num -1)
(funcall indent-command))))))
(defun util-indent-region-or-line ()
(interactive)
(util-generic-indent-region-or-line (function indent-according-to-mode)))
(defun util-try-expand-hashitems (old)
(let (wordsize)
(if (not old)
(progn
(if (gethash (buffer-substring (- (point) 4) (point)) util-tab-completions)
(setq wordsize 4)
(if (gethash (buffer-substring (- (point) 3) (point)) util-tab-completions)
(setq wordsize 3)
(if (gethash (buffer-substring (- (point) 2) (point)) util-tab-completions)
(setq wordsize 2)
(setq wordsize 1))))
(he-init-string (- (point) wordsize) (point))
(if (not (he-string-member he-search-string he-tried-table))
(setq he-tried-table (cons he-search-string he-tried-table)))
(let ((item (gethash he-search-string util-tab-completions)))
(setq he-expand-list
(cond
((functionp item) (list (funcall item)))
(t item))))))
(while (and he-expand-list
(he-string-member (car he-expand-list) he-tried-table))
(setq he-expand-list (cdr he-expand-list)))
(if (null he-expand-list)
(progn (if old (he-reset-string)) 'nil)
(progn
(he-substitute-string (car he-expand-list))
(setq he-expand-list (cdr he-expand-list))
t))))
(defvar util-tab-completions (make-hash-table :test 'equal))
(defun util-populate-hash (hash pairs)
(loop for keyvalue in pairs do
(let ((key (car keyvalue)) (value (cadr keyvalue)))
(puthash key value hash))))
(defun util-region-replace (&optional from to)
(interactive)
(util-region-replace-func 'search-forward 'nil from to))
(defun util-region-replace-regex (&optional from to)
(interactive)
(util-region-replace-func 'search-forward-regexp t from to))
(defun util-region-replace-func (func asregex &optional from to)
(let ((beg (point-min)) (end (point-max)) (region "Buffer") begend lastm done)
(when mark-active
(setq region "Region")
(setq beg (point))
(setq end (mark))
(when (> beg end)
(setq begend beg)
(setq beg end)
(setq end begend)))
;; convert 'end' to a marker object so that it gets adjusted properly across text replacement
(setq end (copy-marker end))
(if asregex (setq region (format "%s regexp" region)))
(if (not from)
(setq from (read-string (format "%s replace: " region))))
(if (not to)
(setq to (read-string (format "%s replace %s with: " region from))))
(goto-char beg)
(while (and (< (point) (marker-position end)) (not done))
(setq lastm (point))
(if (not (funcall func from nil t))
(setq done 1))
(if (<= (point) (marker-position end)) (replace-match to nil nil)))
(goto-char lastm)
))
(defun util-vc-root ()
(interactive)
(condition-case nil
(let ((backend 'Git))
(message "Backend %s" backend)
(vc-call-backend backend 'root (file-name-directory (buffer-file-name))))
(error nil)))
(defun vc-root-or-current-dir ()
"Get the vc root or the current directory"
(interactive)
(let ((the-root (util-vc-root)))
(message (format "root: %s" the-root))
(if the-root
the-root
(file-name-directory (or load-file-name buffer-file-name)))))
(defun strip-c-apostrophe (s) (replace-regexp-in-string "^C'" "" s))
(defun findcode-on (my-findcode-command)
"Delegate findcode to"
(message (format "Findcode: %s" my-findcode-command))
(let ((compilation-buffer-name-function
(lambda (mode-name)
(format "*%s*" my-findcode-command)))
(default-directory (vc-root-or-current-dir)))
(message (format "Default directory: %s" default-directory))
(grep my-findcode-command)))
(setq findcode-command "grep --mmap -Rin %s .")
(defun util-findcode (findcode-command)
"Run findcode on your current repo, or default path, if defined"
(interactive
(list (read-string
(concat "Run findcode in " (vc-root-or-current-dir) " as: ")
(format findcode-command (current-keyword-or-quoted-active-region 'strip-c-apostrophe)))))
(findcode-on findcode-command))
(defun findgrep-on (my-findgrep-command)
"Delegate findgrep to"
(message (format "Findgrep: %s" my-findgrep-command))
(let ((compilation-buffer-name-function
(lambda (mode-name)
(format "*%s*" my-findgrep-command)))
(default-directory (vc-root-or-current-dir)))
(message (format "Default directory: %s" default-directory))
(compile my-findgrep-command)))
(setq findgrep-command "find %s | grep -i %s")
(defun util-findgrep (findgrep-command)
"Run findgrep on your current repo, or default path, if defined"
(interactive
(list (read-string
(concat "Run findgrep in " (vc-root-or-current-dir) " as: ")
(format findgrep-command (vc-root-or-current-dir) (current-keyword-or-quoted-active-region 'strip-c-apostrophe)))))
(findgrep-on findgrep-command))
(defun chmod (mode)
"Set the mode of the current file, in octal, as per the chmod program.
If the current file doesn't exist yet the buffer is saved to create it."
(interactive "sMode (3 or 4 octal digits): ")
(or (string-match "[0-3]?[0-7][0-7][0-7]" mode)
(error "Invalid mode"))
;; make sure the file exists
(unless (file-exists-p (buffer-file-name))
(save-buffer))
(set-file-modes (buffer-file-name) (string-to-number mode 8))
(message (format "File permission set to %s" mode)))
(defun util-custom-compile (cmd custom-compile-name)
"Run a custom compile command in a custom buffer"
(util-save-and-save-some-buffers)
(let* ((mybuf (buffer-name (current-buffer))))
(message (format "Running cmd: %s" cmd))
(if (get-buffer custom-compile-name)
(kill-buffer custom-compile-name))
(compile cmd)
(switch-to-buffer "*compilation*")
(rename-buffer custom-compile-name)
(switch-to-buffer mybuf)
))
(defun remove-dos-eol ()
"Do not show ^M in files containing mixed UNIX and DOS line endings."
(interactive)
(setq buffer-display-table (make-display-table))
(aset buffer-display-table ?\^M []))
(defun indent-then-insert (to-insert)
"indent then insert"
(indent-according-to-mode) (insert to-insert))
(defun insert-then-indent (to-insert)
"insert then indent"
(insert to-insert) (indent-according-to-mode))
(defun insert-multiline-js-comment ()
"/** * */"
(interactive)
(beginning-of-line)
(indent-then-insert "/**\n")
(indent-then-insert "*\n")
(indent-then-insert "*/"))
(defun util-region-or-word ()
"Current word or region"
(if (not mark-active)
(current-word)
(buffer-substring (region-beginning) (region-end))
))
(defun delete-this-buffer-and-file ()
"Removes file connected to current buffer and kills buffer."
(interactive)
(let ((filename (buffer-file-name))
(buffer (current-buffer))
(name (buffer-name)))
(if (not (and filename (file-exists-p filename)))
(error "Buffer '%s' is not visiting a file!" name)
(when (yes-or-no-p "Are you sure you want to remove this file? ")
(delete-file filename)
(kill-buffer buffer)
(message "File '%s' successfully removed" filename)))))
(defun sort-lines-nocase ()
"Sorts case insensitive"
(interactive)
(let ((sort-fold-case t))
(call-interactively 'sort-lines)))
(defun util-toggle-quotes()
"Toggle the quotes under the current quoted region"
(interactive)
(save-excursion
(er/mark-outside-quotes)
(let ((startpoint (region-beginning))
(endpoint (region-end))
(changechar (if (looking-at "'") "\"" "'"))
)
(if (not (= startpoint endpoint))
(progn
(deactivate-mark)
(delete-char 1)
(insert changechar)
(forward-char (- (- endpoint startpoint) 1))
(delete-backward-char 1)
(insert changechar))))))
(defun zap-backward-whitespace ()
"Deletes any whitespace to the left of the cursor"
(interactive)
(backward-char 1)
(let ((delete-count 0))
(while (looking-at " \\|\n")
(progn
(delete-forward-char 1)
(backward-char 1)
(setq delete-count (+ 1 delete-count))))
delete-count))
(defun collapse-list ()
"Take a comma separated list and remove all special newlines/whitespace/tabs around commas"
(interactive)
(save-excursion
(er/mark-outside-pairs)
(set-mark-command t)
(backward-char)
(save-excursion
(if (looking-at "\\]\\|)") ;; if i'm looking at a list
(let ((end-point (point))
(end-char (current-char)))
(er/mark-outside-pairs)
(deactivate-mark)
(forward-char)
(setq end-point (- end-point (zap-forward-whitespace)))
(while (<= (point) end-point)
(progn
(search-forward-regexp ",")
(setq end-point (+ (- end-point (zap-forward-whitespace)) 1))
(insert " "))))))
(zap-backward-whitespace)))
(defun go-to-80-spot ()
"Goes to the 80 spot of a line, or the end of the line"
(interactive)
(beginning-of-line)
(let ((startpoint (point)) (endpoint) (difference))
(end-of-line)
(setq endpoint (point))
(setq difference (- (- endpoint startpoint) 80))
(if (> difference 0)
(backward-char difference)
)))
(defun eightyify-list ()
"Convert a comma separated list into lines not much longer than 80 characters"
(interactive)
(save-excursion
(collapse-list)
(er/mark-outside-pairs)
(set-mark-command t)
(backward-char)
(if (looking-at "\\]\\|)") ;; if i'm looking at a list
(let ((end-point (point)))
(er/mark-outside-pairs)
(deactivate-mark)
(forward-char)
(insert-then-indent "\n")
(go-to-80-spot)
(while (<= (point) end-point)
(progn
(search-forward-regexp ",")
(forward-char)
(insert-then-indent "\n")
(go-to-80-spot)))
(search-forward-regexp "\\]\\|)")
(backward-char)
(insert-then-indent "\n")))))