diff options
| author | Craig Jennings <c@cjennings.net> | 2025-10-12 12:09:36 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2025-10-12 12:09:36 -0500 |
| commit | 6977f5424c638dc2ee930020ef746f52f3b3a5db (patch) | |
| tree | 8528b32a7799da2859bec611df949e0e7c19d024 /modules | |
| parent | 938c2402c0444f52257f8d5a4513f2f6898db084 (diff) | |
maint: assemble file and buffer operations into single module
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/custom-file-buffer.el | 148 | ||||
| -rw-r--r-- | modules/custom-functions.el | 136 |
2 files changed, 148 insertions, 136 deletions
diff --git a/modules/custom-file-buffer.el b/modules/custom-file-buffer.el new file mode 100644 index 00000000..2918ed97 --- /dev/null +++ b/modules/custom-file-buffer.el @@ -0,0 +1,148 @@ +;;; custom-file-buffer.el --- Custom Buffer and File Operations -*- coding: utf-8; lexical-binding: t; -*- + +;;; Commentary: +;; + +;;; Code: + +;; ------------------------- Buffer And File Operations ------------------------ + +(defun cj/move-buffer-and-file (dir) + "Move both current buffer and the file it visits to DIR." + (interactive "DMove buffer and file (to new 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 cj/rename-buffer-and-file (new-name) + "Rename both current buffer and the file it visits to NEW-NAME." + (interactive + (list (if (not (buffer-file-name)) + (user-error "Buffer '%s' is not visiting a file!" (buffer-name)) + (read-string "Rename buffer and file (to new name): " + (file-name-nondirectory (buffer-file-name)))))) + (let ((name (buffer-name)) + (filename (buffer-file-name))) + (if (get-buffer new-name) + (message "A buffer named '%s' already exists!" new-name) + (progn + (rename-file filename new-name 1) + (rename-buffer new-name) + (set-visited-file-name new-name) + (set-buffer-modified-p nil))))) + +(defun cj/delete-buffer-and-file () + "Kill the current buffer and delete the file it visits." + (interactive) + (let ((filename (buffer-file-name))) + (when filename + (if (vc-backend filename) + (vc-delete-file filename) + (progn + (delete-file filename t) + (message "Deleted file %s" filename) + (kill-buffer)))))) + +(defun cj/copy-link-to-buffer-file () + "Copy the full file:// path of the current buffer's source file to the kill ring." + (interactive) + (let ((file-path (buffer-file-name))) + (when file-path + (setq file-path (concat "file://" file-path)) + (kill-new file-path) + (message "Copied file link to kill ring: %s" file-path)))) + +(defun cj/copy-path-to-buffer-file-as-kill () + "Copy the full path of the current buffer's file to the kill ring. +Signal an error if the buffer is not visiting a file." + (interactive) + (let ((path (buffer-file-name))) + (if (not path) + (user-error "Current buffer is not visiting a file") + (kill-new path) + (message "Copied file path: %s" path) + path))) + +(defun cj/copy-whole-buffer () + "Copy the entire contents of the current buffer to the kill ring. +Point and mark are left exactly where they were. No transient region +is created. A message is displayed when done." + (interactive) + (let ((contents (buffer-substring-no-properties (point-min) (point-max)))) + (kill-new contents) + (message "Buffer contents copied to kill ring"))) + +(defun cj/clear-to-bottom-of-buffer () + "Delete all text from point to the end of the current buffer. +This does not save the deleted text in the kill ring." + (interactive) + (delete-region (point) (point-max)) + (message "Buffer contents removed to the end of the buffer.")) + +(defun cj/clear-to-top-of-buffer () + "Delete all text from point to the beginning of the current buffer. +Do not save the deleted text in the kill ring." + (interactive) + (delete-region (point) (point-min)) + (message "Buffer contents removed to the beginning of the buffer.")) + + + +;; ------------------------- Print Buffer As Postscript ------------------------ + +;; prints using postscript for much nicer output +(use-package ps-print + :ensure nil ;; built-in + :config + (defun cj/print-buffer-ps () + "Print the current buffer as PostScript (monochrome) to the system default printer. +Sends directly to the spooler (no temp files), with no page header." + (interactive) + (let* ((spooler + (cond + ((executable-find "lpr") "lpr") + ((executable-find "lp") "lp") + (t (user-error "Cannot print: neither 'lpr' nor 'lp' found in PATH")))) + ;; Configure spooler for this invocation + (ps-lpr-command spooler) + (ps-printer-name nil) ;; nil => system default printer + (ps-lpr-switches nil) + ;; Force monochrome and ignore face backgrounds for this job + (ps-print-color-p nil) + (ps-use-face-background nil) + ;; Ensure no headers + (ps-print-header nil) + (ps-header-lines 0) + (ps-left-header nil) + (ps-right-header nil)) + (ps-print-buffer-with-faces) + (message "Sent print job via %s to default printer (no header)" spooler)))) + +;; --------------------------- Buffer And File Keymap -------------------------- + +;; Buffer & file operations prefix and keymap +(define-prefix-command 'cj/buffer-and-file-map nil + "Keymap for buffer-and-file operations.") +(define-key cj/custom-keymap "b" 'cj/buffer-and-file-map) +(define-key cj/buffer-and-file-map "m" 'cj/move-buffer-and-file) +(define-key cj/buffer-and-file-map "r" 'cj/rename-buffer-and-file) +(define-key cj/buffer-and-file-map "p" 'cj/print-buffer-ps) +(define-key cj/buffer-and-file-map "d" 'cj/delete-buffer-and-file) +(define-key cj/buffer-and-file-map "c" 'cj/copy-whole-buffer) +(define-key cj/buffer-and-file-map "t" 'cj/clear-to-top-of-buffer) +(define-key cj/buffer-and-file-map "b" 'cj/clear-to-bottom-of-buffer) +(define-key cj/buffer-and-file-map "x" 'erase-buffer) +(define-key cj/buffer-and-file-map "s" 'write-file) ;; save as :) + +(define-key cj/buffer-and-file-map "l" 'cj/copy-link-to-buffer-file) +(define-key cj/buffer-and-file-map "P" 'cj/copy-path-to-buffer-file-as-kill) + +(provide 'custom-file-buffer) +;;; custom-file-buffer.el ends here. diff --git a/modules/custom-functions.el b/modules/custom-functions.el index 5899eec7..61c6e883 100644 --- a/modules/custom-functions.el +++ b/modules/custom-functions.el @@ -175,142 +175,6 @@ This advice ensures `align-regexp' uses spaces by binding `indent-tabs-mode' to Other key maps extend from this key map to hold categorized functions.") (global-set-key (kbd "C-;") cj/custom-keymap) -;;; ------------------- Buffer And File Operations And Keymap ------------------- - -(defun cj/move-buffer-and-file (dir) - "Move both current buffer and the file it visits to DIR." - (interactive "DMove buffer and file (to new 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 cj/rename-buffer-and-file (new-name) - "Rename both current buffer and the file it visits to NEW-NAME." - (interactive - (list (if (not (buffer-file-name)) - (user-error "Buffer '%s' is not visiting a file!" (buffer-name)) - (read-string "Rename buffer and file (to new name): " - (file-name-nondirectory (buffer-file-name)))))) - (let ((name (buffer-name)) - (filename (buffer-file-name))) - (if (get-buffer new-name) - (message "A buffer named '%s' already exists!" new-name) - (progn - (rename-file filename new-name 1) - (rename-buffer new-name) - (set-visited-file-name new-name) - (set-buffer-modified-p nil))))) - -(defun cj/delete-buffer-and-file () - "Kill the current buffer and delete the file it visits." - (interactive) - (let ((filename (buffer-file-name))) - (when filename - (if (vc-backend filename) - (vc-delete-file filename) - (progn - (delete-file filename t) - (message "Deleted file %s" filename) - (kill-buffer)))))) - -(defun cj/copy-link-to-buffer-file () - "Copy the full file:// path of the current buffer's source file to the kill ring." - (interactive) - (let ((file-path (buffer-file-name))) - (when file-path - (setq file-path (concat "file://" file-path)) - (kill-new file-path) - (message "Copied file link to kill ring: %s" file-path)))) - -(defun cj/copy-path-to-buffer-file-as-kill () - "Copy the full path of the current buffer's file to the kill ring. -Signal an error if the buffer is not visiting a file." - (interactive) - (let ((path (buffer-file-name))) - (if (not path) - (user-error "Current buffer is not visiting a file") - (kill-new path) - (message "Copied file path: %s" path) - path))) - -(defun cj/copy-whole-buffer () - "Copy the entire contents of the current buffer to the kill ring. - -Point and mark are left exactly where they were. No transient region -is created. A message is displayed when done." - (interactive) - (let ((contents (buffer-substring-no-properties (point-min) (point-max)))) - (kill-new contents) - (message "Buffer contents copied to kill ring"))) - -(defun cj/clear-to-bottom-of-buffer () - "Delete all text from point to the end of the current buffer. - -This does not save the deleted text in the kill ring." - (interactive) - (delete-region (point) (point-max)) - (message "Buffer contents removed to the end of the buffer.")) - -(defun cj/clear-to-top-of-buffer () - "Delete all text from point to the beginning of the current buffer. - -Do not save the deleted text in the kill ring." - (interactive) - (delete-region (point) (point-min)) - (message "Buffer contents removed to the beginning of the buffer.")) - -;; prints using postscript for much nicer output -(use-package ps-print - :ensure nil ;; built-in - :config - (defun cj/print-buffer-ps () - "Print the current buffer as PostScript (monochrome) to the system default printer. -Sends directly to the spooler (no temp files), with no page header." - (interactive) - (let* ((spooler - (cond - ((executable-find "lpr") "lpr") - ((executable-find "lp") "lp") - (t (user-error "Cannot print: neither 'lpr' nor 'lp' found in PATH")))) - ;; Configure spooler for this invocation - (ps-lpr-command spooler) - (ps-printer-name nil) ;; nil => system default printer - (ps-lpr-switches nil) - ;; Force monochrome and ignore face backgrounds for this job - (ps-print-color-p nil) - (ps-use-face-background nil) - ;; Ensure no headers - (ps-print-header nil) - (ps-header-lines 0) - (ps-left-header nil) - (ps-right-header nil)) - (ps-print-buffer-with-faces) - (message "Sent print job via %s to default printer (no header)" spooler)))) - -;; Buffer & file operations prefix and keymap -(define-prefix-command 'cj/buffer-and-file-map nil - "Keymap for buffer-and-file operations.") -(define-key cj/custom-keymap "b" 'cj/buffer-and-file-map) -(define-key cj/buffer-and-file-map "m" 'cj/move-buffer-and-file) -(define-key cj/buffer-and-file-map "r" 'cj/rename-buffer-and-file) -(define-key cj/buffer-and-file-map "p" 'cj/print-buffer-ps) -(define-key cj/buffer-and-file-map "d" 'cj/delete-buffer-and-file) -(define-key cj/buffer-and-file-map "c" 'cj/copy-whole-buffer) -(define-key cj/buffer-and-file-map "t" 'cj/clear-to-top-of-buffer) -(define-key cj/buffer-and-file-map "b" 'cj/clear-to-bottom-of-buffer) -(define-key cj/buffer-and-file-map "x" 'erase-buffer) -(define-key cj/buffer-and-file-map "s" 'write-file) ;; save as :) - -(define-key cj/buffer-and-file-map "l" 'cj/copy-link-to-buffer-file) -(define-key cj/buffer-and-file-map "P" 'cj/copy-path-to-buffer-file-as-kill) - ;;; ---------------------- Whitespace Operations And Keymap --------------------- (defun cj/remove-leading-trailing-whitespace () |
