collect supports adding files and webpage content
This commit is contained in:
parent
726734b04f
commit
277d15d4bd
|
|
@ -10,8 +10,24 @@
|
|||
|
||||
|
||||
;;; collect/store-path is a variable that stores a string defining the path to the directory under which collections are stored.
|
||||
|
||||
(require 'url)
|
||||
(require 'time-date)
|
||||
|
||||
(defvar collect/store-path "~/collections")
|
||||
|
||||
(defvar collect/supported-mime-types
|
||||
'("text/plain"
|
||||
"text/html"
|
||||
"text/css"
|
||||
"text/javascript"
|
||||
"application/json"
|
||||
"application/xml"
|
||||
"text/xml"
|
||||
"text/markdown"
|
||||
"text/csv")
|
||||
"List of MIME types supported for collection.")
|
||||
|
||||
(defun collect/delete-collection-internal (collection-name)
|
||||
"Delete an existing collection, moving its contents (except .collection-metadata) into the no-name collection."
|
||||
(let ((source-dir (expand-file-name collection-name collect/store-path))
|
||||
|
|
@ -33,36 +49,40 @@
|
|||
(message "Collection '%s' deleted and contents moved to 'no-name' collection." collection-name))
|
||||
(error "Collection '%s' does not exist" collection-name))))
|
||||
|
||||
(defun collect/delete-collection ()
|
||||
"Interactively delete an existing collection."
|
||||
(interactive)
|
||||
(let* ((collections (collect/get-collections))
|
||||
(choice (completing-read "Select collection to delete: " (mapcar #'car collections) nil t))
|
||||
(dir-to-delete (cdr (assoc choice collections))))
|
||||
(when dir-to-delete
|
||||
(collect/delete-collection-internal (file-name-nondirectory dir-to-delete)))))
|
||||
|
||||
(defun collect/create-collection ()
|
||||
"Interactively create a new collection."
|
||||
(interactive)
|
||||
(let ((collection-name (read-string "Enter collection name: ")))
|
||||
(collect/create-collection-internal collection-name)))
|
||||
|
||||
(defun collect/delete-collection ()
|
||||
"Interactively delete an existing collection."
|
||||
(interactive)
|
||||
(let* ((all-files (directory-files collect/store-path t "^[^.]"))
|
||||
(collections (cl-remove-if
|
||||
(lambda (dir)
|
||||
(or (not (file-directory-p dir))
|
||||
(string= (file-name-nondirectory dir) "no-name")))
|
||||
all-files))
|
||||
(collection-names
|
||||
(mapcar (lambda (dir)
|
||||
(let ((metadata-file (expand-file-name ".collection-metadata" dir)))
|
||||
(if (file-exists-p metadata-file)
|
||||
(with-temp-buffer
|
||||
(insert-file-contents metadata-file)
|
||||
(if (re-search-forward "^name: \\(.*\\)$" nil t)
|
||||
(match-string 1)
|
||||
(file-name-nondirectory dir)))
|
||||
(file-name-nondirectory dir))))
|
||||
collections))
|
||||
(choice (completing-read "Select collection to delete: " collection-names nil t))
|
||||
(dir-to-delete (nth (cl-position choice collection-names :test 'string=) collections)))
|
||||
(when dir-to-delete
|
||||
(collect/delete-collection-internal (file-name-nondirectory dir-to-delete)))))
|
||||
(defun collect/create-collection-internal (collection-name)
|
||||
"Create a new collection with the given name."
|
||||
(let* ((unix-path (replace-regexp-in-string "[^[:alnum:]_-]" "-"
|
||||
(downcase (string-trim collection-name))))
|
||||
(full-path (expand-file-name unix-path collect/store-path))
|
||||
(metadata-file (expand-file-name ".collection-metadata" full-path))
|
||||
(current-time (format-time-string "%Y-%m-%d %H:%M:%S")))
|
||||
(cond
|
||||
((string-empty-p unix-path)
|
||||
(error "Collection name cannot be empty"))
|
||||
((file-exists-p full-path)
|
||||
(error "Collection '%s' already exists" collection-name))
|
||||
(t
|
||||
(make-directory full-path t)
|
||||
(with-temp-file metadata-file
|
||||
(insert (format "name: %s\n" collection-name)
|
||||
(format "created: %s\n" current-time)
|
||||
(format "updated: %s\n" current-time)))
|
||||
(message "Collection '%s' created successfully with metadata." collection-name)))))
|
||||
|
||||
(defun collect/rename-collection-internal (old-name new-name)
|
||||
"Rename collection from OLD-NAME to NEW-NAME."
|
||||
|
|
@ -101,27 +121,11 @@
|
|||
(defun collect/rename-collection ()
|
||||
"Interactively rename an existing collection."
|
||||
(interactive)
|
||||
(let* ((all-files (directory-files collect/store-path t "^[^.]"))
|
||||
(collections (cl-remove-if
|
||||
(lambda (dir)
|
||||
(or (not (file-directory-p dir))
|
||||
(string= (file-name-nondirectory dir) "no-name")))
|
||||
all-files))
|
||||
(collection-names
|
||||
(mapcar (lambda (dir)
|
||||
(let ((metadata-file (expand-file-name ".collection-metadata" dir)))
|
||||
(if (file-exists-p metadata-file)
|
||||
(with-temp-buffer
|
||||
(insert-file-contents metadata-file)
|
||||
(if (re-search-forward "^name: \\(.*\\)$" nil t)
|
||||
(match-string 1)
|
||||
(file-name-nondirectory dir)))
|
||||
(file-name-nondirectory dir))))
|
||||
collections))
|
||||
(old-name (completing-read "Select collection to rename: " collection-names nil t))
|
||||
(let* ((collections (collect/get-collections))
|
||||
(old-name (completing-read "Select collection to rename: " (mapcar #'car collections) nil t))
|
||||
(new-name (read-string (format "Enter new name for collection '%s': " old-name))))
|
||||
(when (and old-name new-name)
|
||||
(let ((dir-to-rename (nth (cl-position old-name collection-names :test 'string=) collections)))
|
||||
(let ((dir-to-rename (cdr (assoc old-name collections))))
|
||||
(when dir-to-rename
|
||||
(collect/rename-collection-internal (file-name-nondirectory dir-to-rename) new-name))))))
|
||||
|
||||
|
|
@ -159,5 +163,93 @@
|
|||
(file-name-nondirectory file-to-add)
|
||||
selected-collection)))))
|
||||
|
||||
(defun collect/add-webpage-to-collection ()
|
||||
"Add a webpage to a specified collection."
|
||||
(interactive)
|
||||
(let* ((url (read-string "Enter URL to add: "))
|
||||
(all-files (directory-files collect/store-path t "^[^.]"))
|
||||
(collections (cl-remove-if
|
||||
(lambda (dir)
|
||||
(or (not (file-directory-p dir))
|
||||
(string= (file-name-nondirectory dir) "no-name")))
|
||||
all-files))
|
||||
(collection-names
|
||||
(mapcar (lambda (dir)
|
||||
(let ((metadata-file (expand-file-name ".collection-metadata" dir)))
|
||||
(if (file-exists-p metadata-file)
|
||||
(with-temp-buffer
|
||||
(insert-file-contents metadata-file)
|
||||
(if (re-search-forward "^name: \\(.*\\)$" nil t)
|
||||
(match-string 1)
|
||||
(file-name-nondirectory dir)))
|
||||
(file-name-nondirectory dir))))
|
||||
collections))
|
||||
(selected-collection (completing-read "Select collection to add to: " collection-names nil t))
|
||||
(target-dir (nth (cl-position selected-collection collection-names :test 'string=) collections)))
|
||||
(when (and url target-dir)
|
||||
(plz 'get url
|
||||
:as 'response
|
||||
:then (lambda (response)
|
||||
(collect/process-webpage-response url response target-dir selected-collection))
|
||||
:else (lambda (error)
|
||||
(message "Error fetching webpage: %s" error))))))
|
||||
|
||||
(defun collect/get-collections ()
|
||||
"Get a list of collections with their names and directories."
|
||||
(let ((all-dirs (directory-files collect/store-path t "^[^.]")))
|
||||
(cl-remove-if #'null
|
||||
(mapcar (lambda (dir)
|
||||
(when (file-directory-p dir)
|
||||
(let* ((metadata-file (expand-file-name ".collection-metadata" dir))
|
||||
(name (collect/get-collection-name metadata-file)))
|
||||
(when name
|
||||
(cons name dir)))))
|
||||
all-dirs))))
|
||||
|
||||
(defun collect/get-collection-name (metadata-file)
|
||||
"Get the collection name from the metadata file."
|
||||
(when (file-exists-p metadata-file)
|
||||
(with-temp-buffer
|
||||
(insert-file-contents metadata-file)
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "^name: \\(.+\\)$" nil t)
|
||||
(match-string 1)))))
|
||||
|
||||
|
||||
(defun collect/add-webpage-to-collection ()
|
||||
"Add a webpage to a specified collection."
|
||||
(interactive)
|
||||
(let* ((url (read-string "Enter URL to add: "))
|
||||
(collections (collect/get-collections))
|
||||
(selected-collection (completing-read "Select collection to add to: " (mapcar #'car collections) nil t))
|
||||
(target-dir (cdr (assoc selected-collection collections)))
|
||||
(filename (collect/generate-filename url))
|
||||
(target-file (expand-file-name filename target-dir)))
|
||||
(when (and url (file-directory-p target-dir))
|
||||
(url-retrieve url
|
||||
(lambda (status target-file filename collection-name)
|
||||
(if (plist-get status :error)
|
||||
(message "Error fetching webpage: %s" (plist-get status :error))
|
||||
(goto-char (point-min))
|
||||
(re-search-forward "\n\n")
|
||||
(write-region (point) (point-max) target-file)
|
||||
(message "Webpage '%s' added to collection '%s'." filename collection-name)))
|
||||
(list target-file filename selected-collection)))))
|
||||
|
||||
(defun collect/generate-filename (url)
|
||||
"Generate a filename for the given URL."
|
||||
(let* ((timestamp (format-time-string "%Y%m%dT%H%M%S"))
|
||||
(parsed-url (url-generic-parse-url url))
|
||||
(host (url-host parsed-url))
|
||||
(path (url-filename parsed-url))
|
||||
(path-without-schema (replace-regexp-in-string "^/+" "" path))
|
||||
(sanitized-path (replace-regexp-in-string "[^a-zA-Z0-9._-]" "_" path-without-schema))
|
||||
(full-path (concat host "_" sanitized-path))
|
||||
(extension (if (string-match "\\.[^.]+$" full-path)
|
||||
(match-string 0 full-path)
|
||||
".html")))
|
||||
(concat timestamp "_" (file-name-sans-extension full-path) extension)))
|
||||
|
||||
|
||||
(provide 'module-collect)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue