summaryrefslogtreecommitdiff
path: root/modules/custom-file-buffer.el
diff options
context:
space:
mode:
Diffstat (limited to 'modules/custom-file-buffer.el')
-rw-r--r--modules/custom-file-buffer.el247
1 files changed, 0 insertions, 247 deletions
diff --git a/modules/custom-file-buffer.el b/modules/custom-file-buffer.el
deleted file mode 100644
index e0224a32..00000000
--- a/modules/custom-file-buffer.el
+++ /dev/null
@@ -1,247 +0,0 @@
-;;; custom-file-buffer.el --- Custom Buffer and File Operations -*- coding: utf-8; lexical-binding: t; -*-
-;;
-;;; Commentary:
-;; This module provides custom buffer and file operations including PostScript
-;; printing capabilities.
-;;
-;; Functions include:
-;; - printing buffers or regions as PostScript to the default printer (with color support)
-;; - moving/renaming/deleting buffer files
-;; - copying file paths and file:// links to the kill ring
-;; - copying entire buffer contents
-;; - clearing buffer contents from point to top or bottom.
-;;
-;; The PostScript printing auto-detects the system print spooler (lpr or lp)
-;; and prints with face/syntax highlighting. Bound to keymap prefix ~C-; b~.
-;;
-;;; Code:
-
-;; cj/custom-keymap defined in keybindings.el
-(eval-when-compile (defvar cj/custom-keymap))
-(eval-when-compile (require 'ps-print)) ;; for ps-print variables
-(declare-function ps-print-buffer-with-faces "ps-print")
-(declare-function ps-print-region-with-faces "ps-print")
-
-;; ------------------------- Print Buffer As Postscript ------------------------
-
-(defvar cj/print-spooler-command 'auto
- "Command used to send PostScript to the system print spooler.
-Set to a string to force a specific command (e.g., lpr or lp). Set to `auto' to
-auto-detect once per session.")
-
-(defvar cj/print--spooler-cache nil
- "Cached spooler command detected for the current Emacs session.")
-
-(defun cj/print--resolve-spooler ()
- "Return the spooler command to use, auto-detecting and caching if needed."
- (cond
- ;; User-specified command
- ((and (stringp cj/print-spooler-command)
- (> (length cj/print-spooler-command) 0))
- (or (executable-find cj/print-spooler-command)
- (user-error "Cannot print: spooler command '%s' not found in PATH"
- cj/print-spooler-command))
- cj/print-spooler-command)
- ;; Auto-detect once per session
- ((eq cj/print-spooler-command 'auto)
- (or cj/print--spooler-cache
- (let ((cmd (or (and (executable-find "lpr") "lpr")
- (and (executable-find "lp") "lp"))))
- (unless cmd
- (user-error "Cannot print: neither 'lpr' nor 'lp' found in PATH"))
- (setq cj/print--spooler-cache cmd)
- cmd)))
- (t
- (user-error "Invalid value for cj/print-spooler-command: %S"
- cj/print-spooler-command))))
-
-(defun cj/print-buffer-ps (&optional color)
- "Print the buffer (or active region) as PostScript to the default printer.
-With prefix argument COLOR, print in color; otherwise print in monochrome.
-Sends directly to the system spooler with no header."
- (interactive "P")
- (unless (require 'ps-print nil t)
- (user-error "Cannot print: ps-print library not found"))
- (let* ((spooler (cj/print--resolve-spooler))
- (want-color (not (null color)))
- (have-region (use-region-p)))
- (let ((ps-lpr-command spooler)
- (ps-printer-name nil) ; default system printer
- (ps-lpr-switches nil)
- (ps-print-color-p want-color)
- (ps-use-face-background want-color)
- (ps-print-header nil)) ; no headers
- (if have-region
- (ps-print-region-with-faces (region-beginning) (region-end))
- (ps-print-buffer-with-faces)))
- (message "Sent %s to default printer via %s (%s)"
- (if have-region "region" "buffer")
- spooler
- (if want-color "color" "monochrome"))))
-
-;; ------------------------- Buffer And File Operations ------------------------
-
-(defun cj/--move-buffer-and-file (dir &optional ok-if-exists)
- "Internal implementation: Move buffer and file to DIR.
-If OK-IF-EXISTS is nil and target exists, signal an error.
-If OK-IF-EXISTS is non-nil, overwrite existing file.
-Returns t on success, nil if buffer not visiting a file."
- (let* ((name (buffer-name))
- (filename (buffer-file-name))
- (dir (expand-file-name dir))
- (dir
- (if (string-match "[/\\\\]$" dir)
- (substring dir 0 -1) dir))
- (newname (concat dir "/" name)))
- (if (not filename)
- (progn
- (message "Buffer '%s' is not visiting a file!" name)
- nil)
- (progn (copy-file filename newname ok-if-exists)
- (delete-file filename)
- (set-visited-file-name newname)
- (set-buffer-modified-p nil)
- t))))
-
-(defun cj/move-buffer-and-file (dir)
- "Move both current buffer and the file it visits to DIR.
-When called interactively, prompts for confirmation if target file exists."
- (interactive (list (read-directory-name "Move buffer and file (to new directory): ")))
- (let* ((target (expand-file-name (buffer-name) (expand-file-name dir))))
- (condition-case _
- (cj/--move-buffer-and-file dir nil)
- (file-already-exists
- (if (yes-or-no-p (format "File %s exists; overwrite? " target))
- (cj/--move-buffer-and-file dir t)
- (message "File not moved"))))))
-
-(defun cj/--rename-buffer-and-file (new-name &optional ok-if-exists)
- "Internal implementation: Rename buffer and file to NEW-NAME.
-NEW-NAME can be just a basename or a full path to move to different directory.
-If OK-IF-EXISTS is nil and target exists, signal an error.
-If OK-IF-EXISTS is non-nil, overwrite existing file.
-Returns t on success, nil if buffer not visiting a file."
- (let ((filename (buffer-file-name))
- (new-basename (file-name-nondirectory new-name)))
- (if (not filename)
- (progn
- (message "Buffer '%s' is not visiting a file!" (buffer-name))
- nil)
- ;; Check if a buffer with the new name already exists
- (when (and (get-buffer new-basename)
- (not (eq (get-buffer new-basename) (current-buffer))))
- (error "A buffer named '%s' already exists" new-basename))
- ;; Expand new-name to absolute path (preserves directory if just basename)
- (let ((expanded-name (expand-file-name new-name
- (file-name-directory filename))))
- (rename-file filename expanded-name ok-if-exists)
- (rename-buffer new-basename)
- (set-visited-file-name expanded-name)
- (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.
-When called interactively, prompts for confirmation if target file exists."
- (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))))))
- (condition-case err
- (cj/--rename-buffer-and-file new-name nil)
- (file-already-exists
- (if (yes-or-no-p (format "File %s exists; overwrite? " new-name))
- (cj/--rename-buffer-and-file new-name t)
- (message "File not renamed")))
- (error
- ;; Handle buffer-already-exists and other errors
- (message "%s" (error-message-string err)))))
-
-(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."))
-
-(defun cj/copy-buffer-name ()
- "Copy current buffer name to kill ring."
- (interactive)
- (kill-new (buffer-name))
- (message "Copied: %s" (buffer-name)))
-
-;; --------------------------- Buffer And File Keymap --------------------------
-
-;; Buffer & file operations prefix and keymap
-(defvar-keymap cj/buffer-and-file-map
- :doc "Keymap for buffer and file operations."
- "m" #'cj/move-buffer-and-file
- "r" #'cj/rename-buffer-and-file
- "p" #'cj/print-buffer-ps
- "d" #'cj/delete-buffer-and-file
- "c" #'cj/copy-whole-buffer
- "n" #'cj/copy-buffer-name
- "t" #'cj/clear-to-top-of-buffer
- "b" #'cj/clear-to-bottom-of-buffer
- "x" #'erase-buffer
- "s" #'write-file ;; save as
-
- "l" #'cj/copy-link-to-buffer-file
- "P" #'cj/copy-path-to-buffer-file-as-kill)
-(keymap-set cj/custom-keymap "b" cj/buffer-and-file-map)
-
-(with-eval-after-load 'which-key
- (which-key-add-key-based-replacements "C-; b" "buffer and file menu"))
-
-
-(provide 'custom-file-buffer)
-;;; custom-file-buffer.el ends here.