aboutsummaryrefslogtreecommitdiff
path: root/gptel-tools/list_directory_files.el
diff options
context:
space:
mode:
Diffstat (limited to 'gptel-tools/list_directory_files.el')
-rw-r--r--gptel-tools/list_directory_files.el200
1 files changed, 0 insertions, 200 deletions
diff --git a/gptel-tools/list_directory_files.el b/gptel-tools/list_directory_files.el
deleted file mode 100644
index 8da9ba28..00000000
--- a/gptel-tools/list_directory_files.el
+++ /dev/null
@@ -1,200 +0,0 @@
-;;; list_directory_files.el --- List directory files for GPTel -*- coding: utf-8; lexical-binding: t; -*-
-
-;; Copyright (C) 2025
-
-;; Author: gptel-tool-writer
-;; Keywords: convenience, tools
-;; Version: 2.0.0
-
-;; 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 tool provides a comprehensive directory listing function for use within gptel.
-;; It lists files and directories with detailed attributes such as size, last modification time,
-;; permissions, and executable status, supporting optional recursive traversal and filtering
-;; by file extension.
-;;
-;; Features:
-;; - Lists files with Unix-style permissions, size, and modification date
-;; - Optional recursive directory traversal
-;; - Filter files by extension
-;; - Graceful error handling and reporting
-;; - Human-readable file sizes and dates
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'seq)
-(require 'subr-x)
-
-;;; Helper Functions
-
-(defun list-directory-files--mode-to-permissions (mode)
- "Convert numeric MODE to symbolic Unix style permissions string."
- (concat
- (if (eq (logand #o40000 mode) #o40000) "d" "-")
- (mapconcat
- (lambda (bit)
- (cond ((eq bit ?r) (if (> (logand mode #o400) 0) "r" "-"))
- ((eq bit ?w) (if (> (logand mode #o200) 0) "w" "-"))
- ((eq bit ?x) (if (> (logand mode #o100) 0) "x" "-"))))
- '(?r ?w ?x) "")
- (mapconcat
- (lambda (bit)
- (cond ((eq bit ?r) (if (> (logand mode #o040) 0) "r" "-"))
- ((eq bit ?w) (if (> (logand mode #o020) 0) "w" "-"))
- ((eq bit ?x) (if (> (logand mode #o010) 0) "x" "-"))))
- '(?r ?w ?x) "")
- (mapconcat
- (lambda (bit)
- (cond ((eq bit ?r) (if (> (logand mode #o004) 0) "r" "-"))
- ((eq bit ?w) (if (> (logand mode #o002) 0) "w" "-"))
- ((eq bit ?x) (if (> (logand mode #o001) 0) "x" "-"))))
- '(?r ?w ?x) "")))
-
-(defun list-directory-files--get-file-info (filepath)
- "Get file information for FILEPATH as a plist."
- (condition-case err
- (let* ((attrs (file-attributes filepath 'string))
- (size (file-attribute-size attrs))
- (last-mod (file-attribute-modification-time attrs))
- (dirp (eq t (file-attribute-type attrs)))
- (mode (file-modes filepath))
- (perm (list-directory-files--mode-to-permissions mode))
- (execp (file-executable-p filepath)))
- (list :success t
- :path filepath
- :size size
- :last-modified last-mod
- :is-directory dirp
- :permissions perm
- :executable execp))
- (error
- (list :success nil
- :path filepath
- :error (error-message-string err)))))
-
-(defun list-directory-files--filter-by-extension (extension)
- "Create a filter function for files with EXTENSION."
- (when extension
- (lambda (file-info)
- (or (plist-get file-info :is-directory) ; Always include directories
- (and (plist-get file-info :success)
- (string-suffix-p (concat "." extension)
- (file-name-nondirectory (plist-get file-info :path))
- t))))))
-
-(defun list-directory-files--format-file-entry (file-info base-path)
- "Format a single FILE-INFO entry relative to BASE-PATH."
- (format " %s%s %10s %s %s"
- (plist-get file-info :permissions)
- (if (plist-get file-info :executable) "*" " ")
- (file-size-human-readable (or (plist-get file-info :size) 0))
- (format-time-string "%Y-%m-%d %H:%M" (plist-get file-info :last-modified))
- (file-relative-name (plist-get file-info :path) base-path)))
-
-;;; Core Implementation
-
-(defun list-directory-files--list-directory (path &optional recursive filter max-depth current-depth)
- "List files in PATH directory.
-RECURSIVE enables subdirectory traversal.
-FILTER is a predicate function for filtering files.
-MAX-DEPTH limits recursion depth (nil for unlimited).
-CURRENT-DEPTH tracks the current recursion level."
- (let ((files '())
- (errors '())
- (current-depth (or current-depth 0))
- (expanded-path (expand-file-name (or path ".") "~")))
-
- (if (not (file-directory-p expanded-path))
- ;; Return error if not a directory
- (list :files nil
- :errors (list (format "Not a directory: %s" expanded-path)))
- ;; Process directory
- (condition-case err
- (dolist (entry (directory-files expanded-path t "^\\([^.]\\|\\.[^.]\\|\\.\\..\\)"))
- (let ((info (list-directory-files--get-file-info entry)))
- (if (plist-get info :success)
- (progn
- ;; Add file if it passes the filter
- (when (or (not filter) (funcall filter info))
- (push info files))
- ;; Recurse into directories if needed
- (when (and recursive
- (plist-get info :is-directory)
- (or (not max-depth) (< current-depth max-depth)))
- (let ((subdir-result (list-directory-files--list-directory
- entry recursive filter max-depth (1+ current-depth))))
- (setq files (nconc files (plist-get subdir-result :files)))
- (setq errors (nconc errors (plist-get subdir-result :errors))))))
- ;; Handle file access error
- (push (format "%s: %s" (plist-get info :path) (plist-get info :error)) errors))))
- (error
- (push (format "Error accessing directory %s: %s" expanded-path (error-message-string err)) errors)))
-
- (list :files (nreverse files) :errors (nreverse errors)))))
-
-(defun list-directory-files--format-output (path result)
- "Format the directory listing RESULT for PATH as a string."
- (let ((files (plist-get result :files))
- (errors (plist-get result :errors))
- (base-path (expand-file-name "~")))
- (concat
- (when files
- (format "Found %d file%s in %s:\n%s"
- (length files)
- (if (= (length files) 1) "" "s")
- path
- (mapconcat (lambda (f) (list-directory-files--format-file-entry f base-path))
- files "\n")))
- (when (and files errors) "\n\n")
- (when errors
- (format "Errors encountered:\n%s"
- (mapconcat (lambda (e) (format " - %s" e)) errors "\n")))
- ;; Handle case where there are no files and no errors
- (when (and (not files) (not errors))
- (format "No files found in %s" path)))))
-
-;;; Tool Registration
-
-(gptel-make-tool
- :name "list_directory_files"
- :function (lambda (path &optional recursive filter-extension)
- "List files in directory PATH.
-RECURSIVE enables subdirectory listing.
-FILTER-EXTENSION limits results to files with the specified extension."
- (let* ((filter (list-directory-files--filter-by-extension filter-extension))
- (result (list-directory-files--list-directory path recursive filter)))
- (list-directory-files--format-output (or path ".") result)))
- :description "List files in a directory with detailed attributes. Returns formatted listing with permissions, size, modification time."
- :args (list '(:name "path"
- :type string
- :description "Directory path to list (relative to home directory)")
- '(:name "recursive"
- :type boolean
- :description "Recursively list subdirectories"
- :optional t)
- '(:name "filter-extension"
- :type string
- :description "Only include files with this extension"
- :optional t))
- :category "filesystem"
- :confirm nil
- :include t)
-
-;; Automatically add to gptel-tools on load
-(add-to-list 'gptel-tools (gptel-get-tool '("filesystem" "list_directory_files")))
-
-(provide 'list_directory_files)
-;;; list_directory_files.el ends here \ No newline at end of file