Álvaro Ramírez
Interactive ordering of dired items
Redditor sauntcartas offers a nice solution for getting Emacs dired filenames in an arbitrary order. I have to say, while relatively rare, this is something I need from time to time. You see, I like to apply batch file operations from the comfort of dired buffers (via dwim-shell-command).
Take, for example, M-x dwim-shell-commands-join-images-horizontally. It does what it says on the tin. I can mark a handful of image files via dired and easily join them into a single file. The problem is that the file listing isn't always in the desired order, so this is where custom ordering comes in handy.
I wanted an interactive way of reordering dired items. While bouncing ideas with arthurno1, it led us to a drag-stuff experience, which I'm already a fan of. While drag-stuff works in most editable buffers, it breaks on dired. For now, I figured I could just write a couple of dired-specific interactive commands to provide a similar dragging experience, and so I did.
We can likely improve the commands a bit, but hey they do the job as is…
(defun ar/dired-drag-item-up () "Drag dired item down in buffer." (interactive) (unless (dired-get-filename nil t) (error "Not a dired draggable item")) (when (= (line-number-at-pos) 2) (error "Already at top")) (let* ((inhibit-read-only t) (col (current-column)) (item-start (line-beginning-position)) (item-end (1+ (line-end-position))) (item (buffer-substring item-start item-end))) (delete-region item-start item-end) (forward-line -1) (beginning-of-line) (insert item) (forward-line -1) (move-to-column col))) (defun ar/dired-drag-item-down () "Drag dired item down in buffer." (interactive) (unless (dired-get-filename nil t) (error "Not a dired draggable item")) (when (save-excursion (forward-line 1) (eobp)) (error "Already at bottom")) (let* ((inhibit-read-only t) (col (current-column)) (item-start (line-beginning-position)) (item-end (1+ (line-end-position))) (item (buffer-substring item-start item-end))) (delete-region item-start item-end) (forward-line 1) (beginning-of-line) (insert item) (forward-line -1) (move-to-column col)))
I gotta say, these dired dragging commands work great with M-x dwim-shell-commands-join-images-horizontally. I bind them to M-<up> and M-<down> same as drag-stuff elsewhere (already in my config).
(use-package dired :bind (:map dired-mode-map ("M-<up>" . ar/dired-drag-item-up) ("M-<down>" . ar/dired-drag-item-down)))
You can see the new dired commands in action.
Bonus
While bouncing ideas with arthurno1, we also came up with another helper to create new dired buffers populated from marked items, maybe needed for those times you want a more focused experience.
(defun ar/dired-from-marked-items () "Create a new dired buffer containing only the marked files. Also allow dragging items up and down via M-<up> and M-x<down>." (interactive) (let ((marked-files (dired-get-marked-files)) (buffer-name (generate-new-buffer-name (format "*%s (selection)*" (file-name-nondirectory (directory-file-name default-directory)))))) (unless marked-files (error "No dired marked files")) (dired (cons buffer-name (mapcar (lambda (path) (file-relative-name path default-directory)) marked-files)))))
Make it all sustainable
Learned something new? Enjoying this blog or my projects? Help make it sustainable by ✨sponsoring✨
Need a blog? I can help with that. Maybe buy my iOS apps too ;)