aboutsummaryrefslogtreecommitdiff
path: root/gptel-tools/move_to_trash.el
diff options
context:
space:
mode:
Diffstat (limited to 'gptel-tools/move_to_trash.el')
-rw-r--r--gptel-tools/move_to_trash.el149
1 files changed, 0 insertions, 149 deletions
diff --git a/gptel-tools/move_to_trash.el b/gptel-tools/move_to_trash.el
deleted file mode 100644
index 923da790..00000000
--- a/gptel-tools/move_to_trash.el
+++ /dev/null
@@ -1,149 +0,0 @@
-;;; move_to_trash.el --- Move files/directories to trash for gptel -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2025
-
-;; Author: gptel-tool-writer
-;; Keywords: convenience, tools, files
-
-;; This file is not part of GNU Emacs.
-
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;;; Commentary:
-
-;; This file provides a gptel tool for moving files and directories to the trash.
-;; Files are moved to ~/.local/share/Trash/files with automatic timestamping for
-;; name conflicts. The tool operates only within the home directory and /tmp
-;; for security reasons.
-
-;;; Code:
-
-(require 'gptel)
-(require 'subr-x)
-
-(defun gptel--move-to-trash-generate-unique-name (original-name trash-dir)
- "Generate a unique name for ORIGINAL-NAME in TRASH-DIR.
-If a file with the same name exists, append a timestamp in the format
-YYYY-MM-DD-HH-MM-SS."
- (let* ((base-name (file-name-nondirectory original-name))
- (target-path (expand-file-name base-name trash-dir)))
- (if (not (file-exists-p target-path))
- target-path
- ;; Name conflict: add timestamp
- (let* ((extension (file-name-extension base-name t))
- (name-sans-ext (file-name-sans-extension base-name))
- (timestamp (format-time-string "%Y-%m-%d-%H-%M-%S"))
- (new-name (if (and extension (not (string= extension "")))
- (concat name-sans-ext "-" timestamp extension)
- (concat base-name "-" timestamp))))
- (expand-file-name new-name trash-dir)))))
-
-(defun gptel--move-to-trash-validate-path (path)
- "Validate that PATH is safe to trash.
-Returns the expanded path if valid, signals an error otherwise.
-Ensures path is within home directory or /tmp, and prevents
-trashing of critical system directories."
- (let* ((expanded-path (expand-file-name path))
- (resolved-path (and (file-exists-p expanded-path)
- (file-truename expanded-path)))
- (home-dir (file-name-as-directory (file-truename (expand-file-name "~"))))
- (tmp-dir (file-name-as-directory (file-truename "/tmp")))
- (critical-dirs (list (directory-file-name home-dir)
- (file-truename (expand-file-name "~/.emacs.d"))
- (file-truename (expand-file-name "~/.config"))
- (directory-file-name tmp-dir))))
- ;; Security check: must be within allowed directories
- (unless (or (string-prefix-p home-dir expanded-path)
- (string-prefix-p tmp-dir expanded-path))
- (error "Path must be within home directory or /tmp: %s" path))
-
- ;; Prevent trashing critical directories
- (when (member expanded-path critical-dirs)
- (error "Cannot trash critical directory: %s" path))
-
- ;; Existence check
- (unless (file-exists-p expanded-path)
- (error "File or directory does not exist: %s" path))
-
- (unless (or (string-prefix-p home-dir resolved-path)
- (string-prefix-p tmp-dir resolved-path))
- (error "Resolved path must be within home directory or /tmp: %s" path))
-
- expanded-path))
-
-(defun gptel--move-to-trash-perform (expanded-path trash-dir)
- "Move EXPANDED-PATH to TRASH-DIR with unique naming.
-Returns a formatted message describing the operation."
- (let* ((is-directory (file-directory-p expanded-path))
- (is-symlink (file-symlink-p expanded-path))
- (trash-path (gptel--move-to-trash-generate-unique-name
- expanded-path trash-dir))
- (item-type (cond
- (is-symlink "Symlink")
- (is-directory "Directory")
- (t "File"))))
-
- ;; Perform the move
- (condition-case move-err
- (progn
- (rename-file expanded-path trash-path)
-
- ;; Verify success
- (cond
- ((file-exists-p expanded-path)
- (error "Failed to move %s to trash - file still exists at original location"
- expanded-path))
- ((not (file-exists-p trash-path))
- (error "Move operation failed - file not found in trash"))
- (t
- (format "%s moved to trash: %s → %s"
- item-type
- (abbreviate-file-name expanded-path)
- (file-name-nondirectory trash-path)))))
- (permission-denied
- (error "Permission denied: cannot move %s to trash" expanded-path))
- (error
- (error "Failed to move %s to trash: %s"
- expanded-path (error-message-string move-err))))))
-
-;; Main tool definition
-(with-eval-after-load 'gptel
- (gptel-make-tool
- :name "move_to_trash"
- :function (lambda (path)
- "Move PATH to the trash directory.
-Creates the trash directory if needed, handles naming conflicts,
-and provides detailed error messages."
- (condition-case err
- (let* ((trash-dir (expand-file-name "~/.local/share/Trash/files"))
- (expanded-path (gptel--move-to-trash-validate-path path)))
-
- ;; Ensure trash directory exists
- (unless (file-exists-p trash-dir)
- (make-directory trash-dir t))
-
- ;; Move and return status message
- (gptel--move-to-trash-perform expanded-path trash-dir))
- (error
- (error "Tool error: %s" (error-message-string err)))))
- :description "Move a file or directory to the trash (~/.local/share/Trash/files). Works recursively for directories. Handles name conflicts with timestamps. Operates only within home directory and /tmp. Does not follow symlinks. Synonyms: delete, remove, trash file/directory."
- :args (list '(:name "path"
- :type string
- :description "Path to the file or directory to move to trash. Must be within home directory or /tmp."))
- :category "filesystem"
- :confirm nil ; No confirmation needed
- :include t))
-
-;; Automatically add to gptel-tools on load
-(add-to-list 'gptel-tools (gptel-get-tool '("filesystem" "move_to_trash")))
-
-(provide 'move_to_trash)
-;;; move_to_trash.el ends here