;;; 05-custom-functions --- custom functions prefixed with "leo/" ;;; Commentary: ;;; Code: (defun leo/compile-init () "If the current buffer is 'init.el', compile it." (interactive) (when (equal (buffer-file-name) (expand-file-name (concat user-emacs-directory "init.el"))) ;; Avoid running hooks when tangling. (let ((prog-mode-hook nil)) (byte-compile-file (concat user-emacs-directory "init.el"))))) (defun leo/find-user-init-file () "Edit the `~/.emacs.d/init.el' file." (interactive) (find-file "~/.emacs.d/init.el")) (defun leo/tidy () "Indent, untabify and unwhitespacify current buffer, or region if active." (interactive) (let ((beg (if (region-active-p) (region-beginning) (point-min))) (end (if (region-active-p) (region-end) (point-max)))) (let ((inhibit-message t)) (indent-region beg end)) (whitespace-cleanup) (untabify beg (if (< end (point-max)) end (point-max))) (if (region-active-p) (message "Indenting Region...Done") (message "Indenting File...Done")))) (defun leo/comment-or-uncomment-region-or-line () "Comment or uncomment the region or the current line if there's no active region." (interactive) (let (beg end) (if (region-active-p) (setq beg (region-beginning) end (region-end)) (setq beg (line-beginning-position) end (line-end-position))) (comment-or-uncomment-region beg end))) (defun leo/duplicate-thing (comment) "Duplicates the current line, or the region if active. If an argument (COMMENT) is given, the duplicated region will be commented out." (interactive "P") (save-excursion (let ((start (if (region-active-p) (region-beginning) (point-at-bol))) (end (if (region-active-p) (region-end) (point-at-eol)))) (goto-char end) (unless (region-active-p) (newline)) (insert (buffer-substring start end)) (when comment (comment-region start end))))) (defun leo/kill-this-buffer-unless-scratch () "Works like `kill-this-buffer' unless the current buffer is the *scratch* buffer. In which case the buffer content is deleted and the buffer is buried." (interactive) (if (or (string= (buffer-name) "*dashboard*") (string= (buffer-name) "*scratch*")) (progn (bury-buffer (buffer-name)) (switch-to-buffer (other-buffer))) (kill-this-buffer))) (defun leo/jump-to-symbol (&optional backwardp) "Jumps to the next symbol near the point if such a symbol exists. If BACKWARDP is non-nil it jumps backward." (let* ((point (point)) (bounds (find-tag-default-bounds)) (beg (car bounds)) (end (cdr bounds)) (str (isearch-symbol-regexp (find-tag-default))) (search (if backwardp 'search-backward-regexp 'search-forward-regexp))) (goto-char (if backwardp beg end)) (funcall search str nil t) (cond ((<= beg (point) end) (goto-char point)) (backwardp (forward-char (- point beg))) (t (backward-char (- end point)))))) (defun leo/jump-to-prev-symbol () "Jumps to the previous occurrence of the symbol at point." (interactive) (leo/jump-to-symbol t)) (defun leo/jump-to-next-symbol () "Jumps to the next occurrence of the symbol at point." (interactive) (leo/jump-to-symbol)) (defun leo/last-car (list) "Return only the item in the last position of a LIST." (car (last list)) ) (defun leo/get-package-from-url (url) "Accept a URL and return a stripped package name." (let ((mode (car (split-string (leo/last-car (split-string url "/" t)) "\\." nil) ) )) (message mode)) ) (defun leo/org-global-props (&optional property buffer) "Get the plists of global org PROPERTY of current BUFFER." (unless property (setq property "PROPERTY")) (with-current-buffer (or buffer (current-buffer)) (org-element-map (org-element-parse-buffer) 'keyword (lambda (el) (when (string-match property (org-element-property :key el)) el))))) (defun leo/org-global-prop-value (key) "Get global org property KEY (case sensitive) of current buffer." (org-element-property :value (car (leo/org-global-props key)))) (defun leo/deft-insert-boilerplate () "Insert boilerplate into newly create roam note." (interactive) (let ((title (leo/org-global-prop-value "TITLE")) (setupfile (leo/org-global-prop-value "SETUPFILE")) (startup (leo/org-global-prop-value "STARTUP"))) ;; If we have neither SETUPFILE nor STARTUP (when (and title (not setupfile) (not startup)) (kill-region (point-min) (point-max)) (goto-char (point-min)) (insert (format "#+TITLE: %s\n" title)) (insert "#+SETUPFILE: setup.org\n") (insert "\n") (insert "* Metadata:\n") (insert "** Tags: ") (goto-char (point-max))) ;; If we only have STARTUP (when (and title startup (not setupfile)) (goto-char (point-min)) (search-forward "STARTUP") (beginning-of-line) (kill-line) (insert "#+SETUPFILE: setup.org") (message "Updated Global Properties")) )) (defun leo/org-narrow-prev-tree () "When in a narrowed region, this will take you to the previous heading and narrow." (interactive) (goto-char (point-min)) (widen) (org-backward-element) (org-narrow-to-subtree)) (defun leo/org-narrow-next-tree () "When in a narrowed region, this will take you to the next heading and narrow." (interactive) (goto-char (point-min)) (widen) (org-forward-element) (org-narrow-to-subtree)) (defun leo/org-present () "Begin an `org-mode' presentation." (interactive) (defvar old-mlf nil "Temp storage of mode-line-format while in 'present mode'.") (if (buffer-narrowed-p) (progn (widen) (setq mode-line-format old-mlf) (setq cursor-type 'box) (read-only-mode -1) (text-scale-adjust 0) (visual-line-mode nil) (toggle-word-wrap nil) (message "No longer presenting") ) (setq old-mlf mode-line-format) (setq mode-line-format nil) (org-narrow-to-subtree) (setq cursor-type nil) (read-only-mode 1) (text-scale-adjust 6) (visual-line-mode 1) (toggle-word-wrap 1) (message "Presenting") )) (defun leo/org-roam-reformat-tags () "Search for Tags: in document and replace the old single-line format with a newline separated list." (interactive) (save-excursion (goto-char (point-min)) (if (re-search-forward "Tags:") (progn (replace-regexp "Tags: \\[" "Tags:\n- [" nil (point-at-bol) (point-at-eol)) (replace-regexp "\\] \\[" "] \n- [" nil (point-at-bol) (point-at-eol)) (message "Tags formatted!") ) (message "Tags not found, format aborted") ))) (defun leo/org-table-slurp () "Slurp a line below the table into current cell." (interactive) (save-excursion (forward-word) (beginning-of-line) (kill-line)) (yank)) (defun leo/auth-source-unfunc (secret) "Unfurl the SECRET." (if (functionp secret) (funcall secret) secret)) (defun leo/url-encode (str) "Poor man's url-encode of STR." (replace-regexp-in-string "@" '"%40" str nil t)) (defun leo/salesforce-login (un) "Login to Salesforce with UN and password from auth-source." (interactive) (let ((secret (plist-get (nth 0 (auth-source-search :max 1 :user un)) :secret)) (host (plist-get (nth 0 (auth-source-search :max 1 :user un)) :host))) (shell-command (format "sfdx force:org:open -u %s" un)) ;; (browse-url (concat "https://" host "/login.jsp?pw=" (leo/auth-source-unfunc secret) "&un=" (leo/url-encode un))) )) (provide '05-custom-functions) ;;; 05-custom-functions.el ends here