summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2025-10-12 12:09:36 -0500
committerCraig Jennings <c@cjennings.net>2025-10-12 12:09:36 -0500
commit6977f5424c638dc2ee930020ef746f52f3b3a5db (patch)
tree8528b32a7799da2859bec611df949e0e7c19d024
parent938c2402c0444f52257f8d5a4513f2f6898db084 (diff)
maint: assemble file and buffer operations into single module
-rw-r--r--init.el3
-rw-r--r--modules/custom-file-buffer.el148
-rw-r--r--modules/custom-functions.el136
3 files changed, 150 insertions, 137 deletions
diff --git a/init.el b/init.el
index 04970ca6..413ccf67 100644
--- a/init.el
+++ b/init.el
@@ -22,9 +22,10 @@
;; -------------------------- Utilities And Libraries --------------------------
-(require 'media-utils) ;; download and play urls
(require 'custom-functions) ;; custom function library w/ keybindings
+(require 'custom-file-buffer) ;; custom buffer and file operations and keymap
(require 'external-open) ;; files to open outside of Emacs
+(require 'media-utils) ;; download and play urls
;; ------------------------- System Level Functionality ------------------------
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 ()