pkg update and first config fix

org-brain not working, add org-roam
This commit is contained in:
2022-12-19 23:02:34 +01:00
parent 02b3e07185
commit 82f05baffe
885 changed files with 356098 additions and 36993 deletions

View File

@@ -1,6 +1,6 @@
;;; treemacs.el --- A tree style file viewer package -*- lexical-binding: t -*-
;; Copyright (C) 2021 Alexander Miller
;; Copyright (C) 2022 Alexander Miller
;; 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
@@ -25,16 +25,24 @@
;;; Code:
(require 'dash)
(require 'hydra)
(require 'treemacs-core-utils)
(require 'treemacs-visuals)
(require 'treemacs-filewatch-mode)
(require 'treemacs-logging)
(require 'treemacs-rendering)
(require 'treemacs-annotations)
(eval-when-compile
(require 'inline)
(require 'treemacs-macros))
(declare-function string-join "subr-x.el")
(defconst treemacs--mark-annotation-source "treemacs-marked-paths")
(defvar-local treemacs--marked-paths nil)
(with-eval-after-load 'recentf
(declare-function recentf-remove-if-non-kept "recentf")
@@ -107,81 +115,230 @@ they will instead be wiped irreversibly."
(defalias 'treemacs-delete #'treemacs-delete-file)
(make-obsolete #'treemacs-delete #'treemacs-delete-file "v2.9.3")
;;;###autoload
(defun treemacs-delete-marked-files (&optional arg)
"Delete all marked files.
A delete action must always be confirmed. Directories are deleted recursively.
By default files are deleted by moving them to the trash. With a prefix ARG
they will instead be wiped irreversibly.
For marking files see `treemacs-bulk-file-actions'."
(interactive "P")
(treemacs-block
(let ((delete-by-moving-to-trash (not arg))
(to-delete (-filter #'file-exists-p treemacs--marked-paths)))
(treemacs-error-return-if (null treemacs--marked-paths)
"There are no marked files")
(unless (yes-or-no-p (format "Really delete %s marked files?"
(length to-delete)))
(treemacs-return (treemacs-log "Cancelled.")))
(treemacs--without-filewatch
(dolist (path to-delete)
;; 2nd check in case of recursive deletes
(when (file-exists-p path)
(cond
((or (file-symlink-p path) (file-regular-p path))
(delete-file path delete-by-moving-to-trash))
((file-directory-p path)
(delete-directory path t delete-by-moving-to-trash))))
(treemacs--on-file-deletion path)
(treemacs-without-messages
(treemacs-run-in-every-buffer
(treemacs-delete-single-node path)))
(run-hook-with-args 'treemacs-delete-file-functions path))
(treemacs--evade-image)
(setf treemacs--marked-paths (-difference treemacs--marked-paths to-delete))
(treemacs-log "Deleted %s files." (length to-delete))))))
;;;###autoload
(defun treemacs-move-file ()
"Move file (or directory) at point.
Destination may also be a filename, in which case the moved file will also
be renamed."
If the selected target is an existing directory the source file will be directly
moved into this directory. If the given target instead does not exist then it
will be treated as the moved file's new name, meaning the original source file
will be both moved and renamed."
(interactive)
(treemacs--copy-or-move :move))
(treemacs--copy-or-move
:action 'move
:no-node-msg "There is nothing to move here."
:wrong-type-msg "Only files and directories can be moved."
:action-fn #'rename-file
:prompt "Move to: "
:flat-prompt "File to copy: "
:finish-verb "Moved"))
;;;###autoload
(defun treemacs-copy-file ()
"Copy file (or directory) at point.
Destination may also be a filename, in which case the copied file will also
be renamed."
(interactive)
(treemacs--copy-or-move :copy))
(defun treemacs--copy-or-move (action)
If the selected target is an existing directory the source file will be directly
copied into this directory. If the given target instead does not exist then it
will be treated as the copied file's new name, meaning the original source file
will be both copied and renamed."
(interactive)
(treemacs--copy-or-move
:action 'copy
:no-node-msg "There is nothing to move here."
:wrong-type-msg "Only files and directories can be copied."
:action-fn (lambda (from to)
(if (file-directory-p from)
(copy-directory from to)
(copy-file from to)))
:prompt "Copy to: "
:flat-prompt "File to copy: "
:finish-verb "Copied"))
(cl-defun treemacs--copy-or-move
(&key
action
no-node-msg
wrong-type-msg
action-fn
prompt
flat-prompt
finish-verb)
"Internal implementation for copying and moving files.
ACTION will be either `:copy' or `:move', depending on whether we are calling
from `treemacs-copy-file' or `treemacs-move-file'."
(let ((no-node-msg)
(wrong-type-msg)
(prompt)
(action-function)
(finish-msg))
(pcase action
(:copy
(setf no-node-msg "There is nothing to copy here."
wrong-type-msg "Only files and directories can be copied."
prompt "Copy to: "
action-function (lambda (from to)
(if (file-directory-p from)
(copy-directory from to)
(copy-file from to)))
finish-msg "Copied %s to %s"))
(:move
(setf no-node-msg "There is nothing to move here."
wrong-type-msg "Only files and directories can be moved."
prompt "Move to: "
action-function #'rename-file
finish-msg "Moved %s to %s")))
(treemacs-block
(treemacs-unless-let (node (treemacs-node-at-point))
(treemacs-error-return no-node-msg)
(treemacs-error-return-if (not (treemacs-is-node-file-or-dir? node))
wrong-type-msg)
(let* ((source (treemacs--select-file-from-btn
node (if (eq action :copy "File to copy: " "File to move: "))))
(source-name (treemacs--filename source))
(destination (treemacs--unslash (read-file-name prompt nil default-directory)))
(target-is-dir? (file-directory-p destination))
(target-name (if target-is-dir? (treemacs--filename source) (treemacs--filename destination)))
(destination-dir (if target-is-dir? destination (treemacs--parent-dir destination)))
(target (treemacs--find-repeated-file-name (treemacs-join-path destination-dir target-name))))
(unless (file-exists-p destination-dir)
(make-directory destination-dir :parents))
(when (eq action :move)
;; do the deletion *before* moving the file, otherwise it will no longer exist and treemacs will
;; not recognize it as a file path
(treemacs-do-delete-single-node source))
(treemacs--without-filewatch
(funcall action-function source target))
;; no waiting for filewatch, if we copied to an expanded directory refresh it immediately
(-let [parent (treemacs--parent target)]
(when (treemacs-is-path-visible? parent)
(treemacs-do-update-node parent)))
(treemacs-goto-file-node target)
(run-hook-with-args
(pcase action
(:copy 'treemacs-copy-file-functions)
(:move 'treemacs-move-file-functions))
source target)
(treemacs-pulse-on-success finish-msg
(propertize source-name 'face 'font-lock-string-face)
(propertize destination 'face 'font-lock-string-face)))))))
ACTION: either `copy' or `move'
NO-NODE-MSG: error message in case there is no node in the current line
WRONG-TYPE-MSG: error message in case current node is not a file
ACTION-FN: function to actually copy or move a file
PROMPT: prompt to read the target directory
FLAT-PROMPT: prompt to select source file when node is flattened
FINISH-VERB: finisher for the success message."
(treemacs-block
(let ((btn (treemacs-current-button)))
(treemacs-error-return-if (null btn)
no-node-msg)
(treemacs-error-return-if
(not (memq (treemacs-button-get btn :state)
'(file-node-open file-node-closed dir-node-open dir-node-closed)))
wrong-type-msg)
(let* ((source (treemacs--select-file-from-btn btn flat-prompt))
(destination (treemacs--canonical-path
(read-directory-name prompt nil default-directory)))
(destination-dir (if (file-directory-p destination)
destination
(treemacs--parent-dir destination)))
(target-name (treemacs--filename
(if (file-directory-p destination)
source
destination)))
(target (->> target-name
(treemacs-join-path destination-dir)
(treemacs--find-repeated-file-name))))
(unless (file-exists-p destination-dir)
(make-directory destination-dir :parents))
(when (eq action 'move)
;; do the deletion *before* moving the file, otherwise it will
;; no longer exist and treemacs will not recognize it as a file path
(treemacs-do-delete-single-node source))
(treemacs--without-filewatch
(funcall action-fn source target))
(pcase action
('move
(run-hook-with-args 'treemacs-copy-file-functions source target)
(treemacs--on-file-deletion source))
('copy
(run-hook-with-args 'treemacs-move-file-functions source target)
(treemacs-remove-annotation-face source "treemacs-marked-paths")))
(treemacs-update-node destination-dir)
(when (treemacs-is-path target :in-workspace)
(treemacs-goto-file-node target))
(treemacs-pulse-on-success "%s %s to %s"
finish-verb
(propertize (treemacs--filename target) 'face 'font-lock-string-face)
(propertize destination-dir 'face 'font-lock-string-face))))))
;;;###autoload
(defun treemacs-move-marked-files ()
"Move all marked files.
For marking files see `treemacs-bulk-file-actions'."
(interactive)
(treemacs--bulk-copy-or-move
:action 'move
:action-fn #'rename-file
:prompt "Move to: "
:finish-verb "Moved"))
;;;###autoload
(defun treemacs-copy-marked-files ()
"Copy all marked files.
For marking files see `treemacs-bulk-file-actions'."
(interactive)
(treemacs--bulk-copy-or-move
:action 'copy
:action-fn (lambda (from to)
(if (file-directory-p from)
(copy-directory from to)
(copy-file from to)))
:prompt "Copy to: "
:finish-verb "Copied"))
(cl-defun treemacs--bulk-copy-or-move
(&key
action
action-fn
prompt
finish-verb)
"Internal implementation for bulk-copying and -moving files.
ACTION: either `copy' or `move'
ACTION-FN: function to actually copy or move a file
PROMPT: prompt to read the target directory
FINISH-VERB: finisher for the success message."
(treemacs-block
(let* ((to-move (-filter #'file-exists-p treemacs--marked-paths))
(destination-dir (treemacs--canonical-path
(read-directory-name prompt nil default-directory)))
(projects (->> to-move
(-map #'treemacs--find-project-for-path)
(cl-remove-duplicates)
(-filter #'identity))))
(treemacs-save-position
(dolist (source to-move)
(let ((target (->> source
(treemacs--filename)
(treemacs-join-path destination-dir)
(treemacs--find-repeated-file-name))))
(unless (string= source target)
(unless (file-exists-p destination-dir)
(make-directory destination-dir :parents))
(when (eq action 'move)
;; do the deletion *before* moving the file, otherwise it will
;; no longer exist and treemacs will not recognize it as a file path
(treemacs-do-delete-single-node source))
(treemacs--without-filewatch
(funcall action-fn source target))
(pcase action
('move
(run-hook-with-args 'treemacs-copy-file-functions source target)
(treemacs--on-file-deletion source))
('copy
(run-hook-with-args 'treemacs-move-file-functions source target)
(treemacs-remove-annotation-face source "treemacs-marked-paths"))))))
(dolist (project projects)
(treemacs-project->refresh! project)))
(when (treemacs-is-path destination-dir :in-workspace)
(treemacs-goto-file-node destination-dir))
(setf treemacs--marked-paths (-difference treemacs--marked-paths to-move))
(treemacs-pulse-on-success "%s %s files to %s"
finish-verb
(propertize (number-to-string (length to-move)) 'face 'font-lock-constant-face)
(propertize destination-dir 'face 'font-lock-string-face)))))
;;;###autoload
(cl-defun treemacs-rename-file ()
@@ -219,7 +376,10 @@ will likewise be updated."
(-let [treemacs-silent-refresh t]
(treemacs-run-in-every-buffer
(treemacs--on-rename old-path new-path treemacs-filewatch-mode)
(treemacs-update-node (treemacs-button-get parent :path)))))
;; save-excursion does not work for whatever reason
(-let [p (point)]
(treemacs-do-update-node (treemacs-button-get parent :path))
(goto-char p)))))
(treemacs--reload-buffers-after-rename old-path new-path)
(run-hook-with-args
'treemacs-rename-file-functions
@@ -231,6 +391,103 @@ will likewise be updated."
(defalias 'treemacs-rename #'treemacs-rename-file)
(make-obsolete #'treemacs-rename #'treemacs-rename-file "v2.9.3")
;;; Bulk Actions
;;;###autoload
(defun treemacs-show-marked-files ()
"Print a list of all files marked by treemacs."
(interactive)
(let* ((len (length treemacs--marked-paths))
(message
(pcase len
(0 "There are currently no marked files.")
(1 (format "There is currently 1 marked file:\n%s"
(car treemacs--marked-paths)))
(_ (format "There are currently %s marked files:\n%s"
len
(string-join treemacs--marked-paths "\n"))))))
(treemacs-log message)))
;;;###autoload
(defun treemacs-mark-or-unmark-path-at-point ()
"Mark or unmark the absolute path of the node at point."
(interactive)
(treemacs-block
(-let [path (treemacs--prop-at-point :path)]
(treemacs-error-return-if (null path)
"There is nothing to mark here")
(treemacs-error-return-if
(or (not (stringp path)) (not (file-exists-p path)))
"Path at point is not a file or directory.")
(if (member path treemacs--marked-paths)
(progn
(setq treemacs--marked-paths
(remove path treemacs--marked-paths))
(treemacs-log "Unmarked path: %s" (propertize path 'face 'font-lock-string-face))
(treemacs-remove-annotation-face path "treemacs-marked-paths"))
(progn
(setq treemacs--marked-paths
(append treemacs--marked-paths (list path)))
(treemacs-log "Marked path: %s" (propertize path 'face 'font-lock-string-face))
(treemacs-set-annotation-face path 'treemacs-marked-file-face "treemacs-marked-paths")))
(treemacs-apply-annotations (treemacs--parent-dir path)))))
;;;###autoload
(defun treemacs-reset-marks ()
"Unmark all previously marked files in the current buffer."
(interactive)
(let ((count (length treemacs--marked-paths))
(projects))
(dolist (path treemacs--marked-paths)
(treemacs-remove-annotation-face path treemacs--mark-annotation-source)
(push (treemacs--find-project-for-path path) projects))
(setf treemacs--marked-paths nil)
(dolist (project (-uniq projects))
(treemacs-apply-annotations (treemacs-project->path project)))
(treemacs-pulse-on-success "Unmarked %s file(s)." count)))
;;;###autoload
(defun treemacs-delete-marked-paths ()
"Delete all previously marked files."
(interactive)
(treemacs-save-position
(when (yes-or-no-p
(format "Really delete %s marked file(s)?"
(length treemacs--marked-paths)))
(-let [count (length treemacs--marked-paths)]
(dolist (path treemacs--marked-paths)
(if (file-directory-p path)
(delete-directory path t)
(delete-file path))
(treemacs-do-delete-single-node path)
(treemacs-remove-annotation-face path treemacs--mark-annotation-source))
(setf treemacs--marked-paths nil)
(hl-line-highlight)
(treemacs-log "Deleted %s files." count)))))
;; shut down docstring width warnings
(with-no-warnings
(defhydra treemacs-bulk-file-actions-hydra (:exit t :hint nil)
("m" #'treemacs-mark-or-unmark-path-at-point "(un)mark")
("u" #'treemacs-reset-marks "unmark all")
("s" #'treemacs-show-marked-files "show")
("d" #'treemacs-delete-marked-files "delete")
("c" #'treemacs-copy-marked-files "copy")
("o" #'treemacs-move-marked-files "move")
("q" nil "cancel")))
;;;###autoload
(defun treemacs-bulk-file-actions ()
"Activate the bulk file actions hydra.
This interface allows to quickly (unmark) files, so as to copy, move or delete
them in bulk.
Note that marking files is *permanent*, files will stay marked until they are
either manually unmarked or deleted. You can show a list of all currently
marked files with `treemacs-show-marked-files' or `s' in the hydra."
(interactive)
(treemacs-bulk-file-actions-hydra/body))
;;;###autoload
(defun treemacs-create-file ()
"Create a new file.
@@ -256,9 +513,9 @@ itself, using $HOME when there is no path at or near point to grab."
IS-FILE?: Bool"
(interactive)
(let* ((curr-path (--if-let (treemacs-current-button)
(treemacs--select-file-from-btn it "Create in: ")
(expand-file-name "~")))
(let* ((curr-path (treemacs--select-file-from-btn
(treemacs-current-button)
"Create in: " :dir-only))
(path-to-create (treemacs-canonical-path
(read-file-name
(if is-file? "Create File: " "Create Directory: ")
@@ -291,13 +548,27 @@ IS-FILE?: Bool"
(treemacs-pulse-on-success
"Created %s." (propertize path-to-create 'face 'font-lock-string-face)))))
(defun treemacs--select-file-from-btn (btn prompt)
"Select the file represented by BTN for file management.
Offer a specifying dialogue with PROMPT when BTN is flattened."
(defun treemacs--select-file-from-btn (btn prompt &optional dir-only)
"Select the file at BTN for file management.
Offer a specifying dialogue with PROMPT when the button is flattened.
Pick only directories when DIR-ONLY is non-nil."
(declare (side-effect-free t))
(-if-let (collapse-info (treemacs-button-get btn :collapsed))
(completing-read prompt collapse-info nil :require-match)
(treemacs-button-get btn :key)))
(let* ((path (and btn (treemacs-button-get btn :path)))
(collapse-info (and btn (treemacs-button-get btn :collapsed)))
(is-str (and path (stringp path)))
(is-dir (and is-str (file-directory-p path)))
(is-file (and is-str (file-regular-p path))))
(cond
(collapse-info
(completing-read prompt collapse-info nil :require-match))
(is-dir
path)
((and is-file dir-only)
(treemacs--parent-dir path))
(is-file
path)
(t
(expand-file-name "~")))))
(provide 'treemacs-file-management)