228 lines
6.8 KiB
EmacsLisp
228 lines
6.8 KiB
EmacsLisp
|
;; functions.el --- Helper functions for my Emacs development -*- lexical-binding: t -*-
|
||
|
;; Author: William Carroll <wpcarro@gmail.com>
|
||
|
|
||
|
;;; Commentary:
|
||
|
;; This file hopefully contains friendly APIs that making ELisp development more enjoyable.
|
||
|
|
||
|
;;; Code:
|
||
|
|
||
|
;; TODO: clean up this file so this isn't necessary
|
||
|
(setq evil-want-integration nil)
|
||
|
(require 'evil)
|
||
|
|
||
|
(require 'projectile)
|
||
|
(require 'paredit)
|
||
|
(require 'term)
|
||
|
(require 'f)
|
||
|
(require 'yasnippet)
|
||
|
(require 'ido)
|
||
|
|
||
|
(defun wpc/evil-window-vsplit-right ()
|
||
|
(interactive)
|
||
|
(evil-window-vsplit)
|
||
|
(windmove-right))
|
||
|
|
||
|
(defun wpc/evil-window-split-down ()
|
||
|
(interactive)
|
||
|
(evil-window-split)
|
||
|
(windmove-down))
|
||
|
|
||
|
(defun wpc/reindent-defun-and-align-clojure-map ()
|
||
|
(interactive)
|
||
|
(call-interactively #'paredit-reindent-defun)
|
||
|
(call-interactively #'clojure-align))
|
||
|
|
||
|
(defun wpc/find-file ()
|
||
|
"Prefer project-based file-finding if inside of project; otherwise gracefully fallback."
|
||
|
(interactive)
|
||
|
(with-current-buffer (current-buffer)
|
||
|
(if (projectile-project-p)
|
||
|
(call-interactively #'projectile-find-file)
|
||
|
(call-interactively #'find-file))))
|
||
|
|
||
|
(defun wpc/find-or-create-js-test ()
|
||
|
(->> buffer-file-name
|
||
|
(s-chop-suffix ".js")
|
||
|
(s-append ".test.js")
|
||
|
(find-file)))
|
||
|
|
||
|
(defun wpc/find-or-create-js-module ()
|
||
|
(->> buffer-file-name
|
||
|
(s-chop-suffix ".test.js")
|
||
|
(s-append ".js")
|
||
|
(find-file)))
|
||
|
|
||
|
(defun wpc/find-or-create-js-store ()
|
||
|
(->> buffer-file-name
|
||
|
(s-replace "index.js" "store.js")
|
||
|
(find-file)))
|
||
|
|
||
|
(defun wpc/find-or-create-js-component ()
|
||
|
(->> buffer-file-name
|
||
|
(s-replace "store.js" "index.js")
|
||
|
(find-file)))
|
||
|
|
||
|
(defun wpc/bind-ido-keys ()
|
||
|
"Adds custom KBDs for ido. This function is recommended in the ido source code."
|
||
|
(define-key ido-completion-map (kbd "<tab>") #'ido-next-match)
|
||
|
(define-key ido-completion-map (kbd "<backtab>") #'ido-prev-match))
|
||
|
|
||
|
(defun wpc/toggle-between-js-test-and-module ()
|
||
|
"Toggle between a Javascript test or module."
|
||
|
(interactive)
|
||
|
(if (s-ends-with? ".test.js" buffer-file-name)
|
||
|
(wpc/find-or-create-js-module)
|
||
|
(if (s-ends-with? ".js" buffer-file-name)
|
||
|
(wpc/find-or-create-js-test)
|
||
|
(message "Not in a Javascript file. Exiting..."))))
|
||
|
|
||
|
(defun wpc/toggle-between-js-component-and-store ()
|
||
|
"Toggle between a React component and its Redux store."
|
||
|
(interactive)
|
||
|
(if (s-ends-with? "index.js" buffer-file-name)
|
||
|
(wpc/find-or-create-js-store)
|
||
|
(if (or (s-ends-with? "store.js" buffer-file-name)
|
||
|
(s-ends-with? "store.test.js" buffer-file-name))
|
||
|
(wpc/find-or-create-js-component)
|
||
|
(message "Not in a React/Redux file. Exiting..."))))
|
||
|
|
||
|
(defun wpc/read-file-as-string (filename)
|
||
|
(with-temp-buffer
|
||
|
(insert-file-contents filename)
|
||
|
(s-trim (buffer-string))))
|
||
|
|
||
|
(defun wpc/create-snippet ()
|
||
|
"Creates a window split and then opens the Yasnippet editor."
|
||
|
(interactive)
|
||
|
(evil-window-vsplit)
|
||
|
(call-interactively #'yas-new-snippet))
|
||
|
|
||
|
(defun wpc/edit-init-el ()
|
||
|
"Creates a window split and then edits the init.el file."
|
||
|
(interactive)
|
||
|
(evil-window-vsplit)
|
||
|
(find-file "~/.emacs.d/init.el"))
|
||
|
|
||
|
(defun wpc/set-flow-executable ()
|
||
|
(interactive)
|
||
|
(let* ((root (locate-dominating-file buffer-file-name "node_modules/flow-bin"))
|
||
|
(executable (car (file-expand-wildcards
|
||
|
(concat root "node_modules/flow-bin/*osx*/flow")))))
|
||
|
(setq-local company-flow-executable executable)
|
||
|
;; These are not necessary for this package, but a good idea if you use
|
||
|
;; these other packages
|
||
|
(setq-local flow-minor-default-binary executable)
|
||
|
(setq-local flycheck-javascript-flow-executable executable)))
|
||
|
|
||
|
(defun wpc/jump-to-parent-file ()
|
||
|
"Jumps to a React store or component's parent file. Useful for store or index file."
|
||
|
(interactive)
|
||
|
(-> buffer-file-name
|
||
|
f-dirname
|
||
|
(f-join "..")
|
||
|
(f-join (f-filename buffer-file-name))
|
||
|
find-file))
|
||
|
|
||
|
(defun wpc/tmux-emacs-windmove (dir)
|
||
|
"Move windows in a Tmux-friendly way."
|
||
|
(let* ((dir->opts '((left . ("-L" . windmove-left))
|
||
|
(right . ("-R" . windmove-right))
|
||
|
(above . ("-U" . windmove-up))
|
||
|
(below . ("-D" . windmove-down))))
|
||
|
(opts (alist-get dir dir->opts))
|
||
|
(tmux-opt (car opts))
|
||
|
(emacs-fn (cdr opts)))
|
||
|
(if (window-in-direction dir)
|
||
|
(funcall emacs-fn)
|
||
|
(shell-command (format "tmux select-pane %s" tmux-opt)))))
|
||
|
|
||
|
(defun wpc/tmux-emacs-windmove-left ()
|
||
|
(interactive)
|
||
|
(wpc/tmux-emacs-windmove 'left))
|
||
|
|
||
|
(defun wpc/tmux-emacs-windmove-right ()
|
||
|
(interactive)
|
||
|
(wpc/tmux-emacs-windmove 'right))
|
||
|
|
||
|
(defun wpc/tmux-emacs-windmove-up ()
|
||
|
(interactive)
|
||
|
(wpc/tmux-emacs-windmove 'above))
|
||
|
|
||
|
(defun wpc/tmux-emacs-windmove-down ()
|
||
|
(interactive)
|
||
|
(wpc/tmux-emacs-windmove 'below))
|
||
|
|
||
|
(defun wpc/get-window-by-buffername (buffername)
|
||
|
"Finds a window by the name of the buffer it's hosting."
|
||
|
(let ((buffer (get-buffer buffername)))
|
||
|
(when buffer
|
||
|
(get-buffer-window buffer))))
|
||
|
|
||
|
(defun wpc/add-earmuffs (x)
|
||
|
"Returns X surrounded by asterisks."
|
||
|
(format "*%s*" x))
|
||
|
|
||
|
(defun wpc/get-default-shell ()
|
||
|
(or explicit-shell-file-name
|
||
|
(getenv "SHELL")
|
||
|
(getenv "ESHELL")))
|
||
|
|
||
|
(defun wpc/find-terminal-buffer ()
|
||
|
(get-buffer (wpc/add-earmuffs wpc/terminal-name)))
|
||
|
|
||
|
(defun wpc/find-terminal-window ()
|
||
|
(wpc/get-window-by-buffername (wpc/add-earmuffs wpc/terminal-name)))
|
||
|
|
||
|
(defun wpc/create-terminal-session ()
|
||
|
(wpc/evil-window-vsplit-right)
|
||
|
(ansi-term (wpc/get-default-shell) wpc/terminal-name))
|
||
|
|
||
|
(defun wpc/toggle-terminal ()
|
||
|
"Toggles a custom terminal session in Emacs."
|
||
|
(interactive)
|
||
|
(let ((window (wpc/find-terminal-window)))
|
||
|
(if window
|
||
|
(delete-window window)
|
||
|
(wpc/find-or-create-terminal))))
|
||
|
|
||
|
(defun wpc/find-or-create-terminal ()
|
||
|
(let ((buffer (wpc/find-terminal-buffer)))
|
||
|
(if buffer
|
||
|
(display-buffer buffer)
|
||
|
(wpc/create-terminal-session))))
|
||
|
|
||
|
(defun wpc/put-file-name-on-clipboard ()
|
||
|
"Put the current file name on the clipboard"
|
||
|
(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 wpc/evil-replace-under-point ()
|
||
|
"Faster than typing %s//thing/g"
|
||
|
(interactive)
|
||
|
(save-excursion
|
||
|
(evil-ex (concat "%s/\\b" (symbol-name (symbol-at-point)) "\\b/"))))
|
||
|
|
||
|
(defun wpc/disable-linum-mode ()
|
||
|
"Convenience function defined to make adding hooks easier without a lambda."
|
||
|
(linum-mode -1))
|
||
|
|
||
|
(defun wpc/disable-company-mode ()
|
||
|
"Convenience function defined to make adding hooks easier without a lambda."
|
||
|
(company-mode -1))
|
||
|
|
||
|
(defun wpc/toggle-term-mode ()
|
||
|
"Toggle between term-line-mode and temr-char-mode."
|
||
|
(if (term-in-line-mode)
|
||
|
(term-char-mode)
|
||
|
(term-line-mode)))
|
||
|
|
||
|
(provide 'functions)
|
||
|
;;; functions.el ends here
|