;;; dot-core-functions.el --- -*- lexical-binding: t; -*- ;;; Commentary: ;; Custom elisp functions and macros. ;;; Code: ;; ----------------------------------------- ;; General Functions ;; Functions that only use built-in Emacs functionality. (defun display-startup-echo-area-message () "Hide default startup message." (message nil)) (defun dot/config-visit () "Edit config file." (interactive) (find-file (expand-file-name "init.el" dot-emacs-dir))) (defun dot/config-reload () "Reload config file." (interactive) (load (expand-file-name "init.el" dot-emacs-dir))) (defun dot/copy-cpp-function-implementation () "Copy C++ function implementation to clipboard." (interactive) (save-excursion (let ((func (save-excursion (re-search-backward "\\b") (re-search-forward "\\([^;]+\\);") (match-string 1))) (type (progn (re-search-backward "\\b") (push-mark) (back-to-indentation) (buffer-substring (mark) (point)))) (class (progn (backward-up-list) (backward-sexp) (back-to-indentation) (forward-to-word 1) (current-word)))) (kill-new (concat type class "::" func "\n{\n}")))) (message "Copied function implementation")) ;; Reference: http://turingmachine.org/bl/2013-05-29-recursively-listing-directories-in-elisp.html (defun dot/directory-files-recursively-depth (dir regexp include-directories maxdepth) "Depth limited variant of the built-in `directory-files-recursively'." (let ((result '()) (current-directory-list (directory-files dir t))) (dolist (path current-directory-list) (cond ((and (file-regular-p path) (file-readable-p path) (string-match regexp path)) (setq result (cons path result))) ((and (file-directory-p path) (file-readable-p path) (not (string-equal "/.." (substring path -3))) (not (string-equal "/." (substring path -2)))) (when (and include-directories (string-match regexp path)) (setq result (cons path result))) (when (> maxdepth 1) (setq result (append (nreverse (dot/directory-files-recursively-depth path regexp include-directories (- maxdepth 1))) result)))) (t))) (reverse result))) (defun dot/dired-find-file () "In Dired, visit the file or directory named on this line." (interactive) (if (file-directory-p (dired-file-name-at-point)) (dired-find-alternate-file) (dired-find-file))) (defun dot/dired-up-directory () "Run Dired on parent directory of current directory." (interactive) (find-alternate-file "..")) (defun dot/find-file-emacsd () "Find file under `dot-emacs-dir', recursively." (interactive) (let ((files (mapcar 'abbreviate-file-name (directory-files-recursively dot-emacs-dir "")))) (find-file (completing-read "Find file (emacs): " files nil t)))) (defun dot/indent-buffer () "Indent each nonblank line in the buffer." (interactive) (save-excursion (indent-region (point-min) (point-max) nil))) (defun dot/insert-spaces-until-column (until-column) "Insert spaces from point to UNTIL-COLUMN." (interactive "nInsert spaces until column: ") (let ((current-column (current-column))) ;; Increment column if the index is 1 based (when (not column-number-indicator-zero-based) (setq current-column (+ current-column 1))) ;; Insert spaces (let ((diff (- until-column current-column))) (if (> diff 0) (save-excursion (insert (make-string diff ?\ ))) (user-error "Column should be higher than point"))))) (defun dot/reload-theme () "Reload custom theme." (interactive) (mapc 'load (file-expand-wildcards (concat (car custom-theme-load-path) "*.el"))) (load-theme (car custom-enabled-themes) t)) (defun dot/sudo-find-file (filename) "Edit file FILENAME as root." (interactive "FOpen file (as root): ") (find-file (concat "/sudo:root@localhost:" filename))) (defun dot/sudo-this-file () "Edit the current file as root." (interactive) (if buffer-file-name (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)) (princ "Current buffer isn't a file"))) (defun dot/toggle-fringe (&optional arg) "Toggle left-only fringe, or set state with ARG." (interactive) (if (or (and (eq fringe-mode 0) (eq arg nil)) (eq arg 1)) (set-fringe-mode '(nil . 0)) (set-fringe-mode 0))) (defun dot/M-x (command) "Prompt and execute COMMAND." (interactive "CCommand: ") (command-execute command)) (defun split-follow-horizontally () "Split and follow window." (interactive) (split-window-below) (other-window 1)) (defun split-follow-vertically () "Split and follow window." (interactive) (split-window-right) (other-window 1)) ;; https://emacsredux.com/blog/2013/05/04/rename-file-and-buffer/ (defun 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))))))) ;; ----------------------------------------- ;; Hook call functions (defun dot/hook-disable-line-numbers () "Disable the line numbers." (display-line-numbers-mode 0)) (defun dot/hook-disable-mode-line () "Disable the mode line." (setq-local mode-line-format nil)) (provide 'dot-core-functions) ;; ----------------------------------------- ;; Macros ;; Reference: https://github.com/arcticicestudio/nord-emacs/issues/59#issuecomment-414882071 (defmacro dot/run-after-new-frame (func) "Run FUNC once or after every frame creation. This is needed for UI initialization when running with the daemon." `(if (daemonp) (add-hook 'after-make-frame-functions (lambda (frame) (with-selected-frame frame ,func))) ,func)) ;;; dot-core-functions.el ends here