简体   繁体   中英

Emacs dired - using predefined variable

In emacs dired I want to do something I do quite often in Microsoft PowerShell.

In PowerShell, I have a set of folders that I always use, and I assign their full path to global variables in my profile script (similar to init.el in the emacs world) eg:

$standardTemp = "C:\Long\Path\To\Folder"

If I am in another folder and I want to copy something to the above folder, I do:

copy myFile $standardTemp

Even more useful as a feature, is if I put a backslash after $standardTemp , it will expand it out, so I can go into subfolders if I need to. This is a very awesome feature and saves me a lot of time.

With the dired copy command can I do something similar, if I define variables with eg setq in my init.el file?

How about something like this?

;; Use ido
(require 'ido)
(ido-mode t)

;; Make a hash table to hold the paths
(setq my-target-dirs (make-hash-table :test 'equal))

;; Put some paths in the hash (sorry for Unix pathnames)
(puthash "home" "/home/jhrr/" my-target-dirs)
(puthash "target" "/home/jhrr/target/" my-target-dirs)

;; A function to return all the keys from a hash.
(defun get-keys-from-hash (hash)
  (let ((keys ()))
    (maphash (lambda (k v) (push k keys)) hash)
    keys))

;; And the function to prompt for a directory by keyword that is looked
;; up in the hash-table and used to build the target path from the
;; value of the lookup.
(defun my-dired-expand-copy ()
  (interactive)
  (let* ((my-hash my-target-dirs)
         (files (dired-get-marked-files))
         (keys (get-keys-from-hash my-hash)))
    (mapc (lambda (file)
            (copy-file file
                       (concat
                        (gethash
                         (ido-completing-read
                          (concat "copy " file " to: ") keys) my-hash)
                        (file-name-nondirectory file))))
          files)))

It's not exhaustively tested as I just whipped it up in 10 minutes, but it does the job and it can handle multiple files.

You will need to open the dired buffer in the directory the files are in and mark each file you want to copy with 'm', then invoke my-dired-expand-copy and it will prompt you for a target destination (in the form of a keyword from the hash-table we set-up) for the file before, finally, copying the file over to the directory that maps to the target keyword.

It doesn't quite cover the sub-directories use-case you mention, but it shouldn't be too hard to get there given a bit more hacking.

UPDATE:

This should now prompt you to be able to descend into subdirectories from an original target; maybe not the most mind-shatteringly wonderful UX on the whole, but, it works:

(defun my-dired-expand-copy-2 ()
  (interactive)
  (let* ((my-hash my-target-dirs)
         (files (dired-get-marked-files))
         (keys (get-keys-from-hash my-hash)))
    (mapc (lambda (file)
            (let ((target (gethash
                           (ido-completing-read
                            (concat "copy " file " to: ") keys) my-hash)))
              (if (y-or-n-p "Descend?")
                  ;; Descend into subdirectories relative to target dir
                  (let ((new-target (ido-read-directory-name "new dir: " target))) 
                    (copy-file file (concat new-target
                                            (file-name-nondirectory file)))
                    (message (concat "File: " file " was copied to " new-target)))
                ;; Else copy to root of originally selected directory
                (copy-file file (concat target (file-name-nondirectory file)))
                (message (concat "File: " file " was copied to " target)))))
          files)))

When I need to use dired to get to frequently-used directories, I use the standard emacs bookmarking capabilities.

I manually navigate to the directory, and press

C-x r m

to execute the command

bookmark-set

You'll be prompted for a name for the bookmark. Enter a shortcut that you can remember.

At this point, anytime you want to open that directory within dired, simply execute the command

bookmark-jump

with the keys

C-x r b

Enter your shortcut to the directory, and dired will open to that location.

To copy from one directory to another, ensure you have the following set in your init file

(setq dired-dwim-target t)

Then you can open a dired window for the source directory, and another window for the target directory within in the same frame, and dired will automatically assign the source and target location to the appropriate directories.

Note this is just a subset of what emacs bookmarks can do for you!

  • Chris

In addition to using bookmarks, consider using directory-name aliases (eg symlinks) or directory-abbrev-alist . See the Emacs manual, node File Aliases .

If you want to insert the value of an environment variable into the minibuffer, you can do it this way:

C-u M-: (getenv "THE-VARIABLE")

where THE-VARIABLE is the variable name. Using Cu inserts the value of evaluating the sexp into the current buffer (in this case the minibuffer).

So you would, say, use C to copy the marked files in Dired, and then use Cu with a getenv sexp for the existing variable you have, to insert its value into the minibuffer when prompted for the directory to copy to.

(Depending on your Emacs setup, you might need to set enable-recursive-minibuffers to non- nil , to be able to use M-: from the minibuffer.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM