bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#22300: 25.1.50; Dired -- renaming folders/files to CamelCase/UPPERCA


From: Keith David Bershatsky
Subject: bug#22300: 25.1.50; Dired -- renaming folders/files to CamelCase/UPPERCASE/lowercase.
Date: Mon, 04 Jan 2016 11:45:22 -0800

Thank you, John, for helping me answer Eli's question about situations when OSX 
uses case-insensitive versus case-sensitive.  I didn't have the knowledge to be 
able to respond properly.

Here is an unsophisticated workaround that bypasses `dired-create-files' when 
dealing with renaming when (1) 'darwin; (2) just one file; and, (3) the file 
names of to/from are equal if both are lower-cased.  It doesn't do the fancy 
cutting/pasting of the new line in dired-mode and instead just reverts the 
entire buffer.

    (require 'dired-aux)

    (require 'cl) ;; for `lexical-let*'
    
    (defun dired-do-create-files (op-symbol file-creator operation arg
                                        &optional marker-char op1
                                        how-to)
      "Create a new file for each marked file.
    Prompt user for a target directory in which to create the new
      files.  The target may also be a non-directory file, if only
      one file is marked.  The initial suggestion for target is the
      Dired buffer's current directory (or, if `dired-dwim-target' is
      non-nil, the current directory of a neighboring Dired window).
    OP-SYMBOL is the symbol for the operation.  Function `dired-mark-pop-up'
      will determine whether pop-ups are appropriate for this OP-SYMBOL.
    FILE-CREATOR and OPERATION as in `dired-create-files'.
    ARG as in `dired-get-marked-files'.
    Optional arg MARKER-CHAR as in `dired-create-files'.
    Optional arg OP1 is an alternate form for OPERATION if there is
      only one file.
    Optional arg HOW-TO determines how to treat the target.
      If HOW-TO is nil, use `file-directory-p' to determine if the
       target is a directory.  If so, the marked file(s) are created
       inside that directory.  Otherwise, the target is a plain file;
       an error is raised unless there is exactly one marked file.
      If HOW-TO is t, target is always treated as a plain file.
      Otherwise, HOW-TO should be a function of one argument, TARGET.
       If its return value is nil, TARGET is regarded as a plain file.
       If it return value is a list, TARGET is a generalized
        directory (e.g. some sort of archive).  The first element of
        this list must be a function with at least four arguments:
          operation - as OPERATION above.
          rfn-list  - list of the relative names for the marked files.
          fn-list   - list of the absolute names for the marked files.
          target    - the name of the target itself.
          The rest of into-dir are optional arguments.
       For any other return value, TARGET is treated as a directory."
      (or op1 (setq op1 operation))
      (let* ((fn-list (dired-get-marked-files nil arg))
         (rfn-list (mapcar (function dired-make-relative) fn-list))
         (dired-one-file        ; fluid variable inside dired-create-files
          (and (consp fn-list) (null (cdr fn-list)) (car fn-list)))
         (target-dir (dired-dwim-target-directory))
         (default (and dired-one-file
                       (expand-file-name (file-name-nondirectory (car fn-list))
                                         target-dir)))
         (defaults (dired-dwim-target-defaults fn-list target-dir))
         (target (expand-file-name ; fluid variable inside dired-create-files
                  (minibuffer-with-setup-hook
                      (lambda ()
                        (set (make-local-variable 
'minibuffer-default-add-function) nil)
                        (setq minibuffer-default defaults))
                    (dired-mark-read-file-name
                     (concat (if dired-one-file op1 operation) " %s to: ")
                     target-dir op-symbol arg rfn-list default))))
         (into-dir (cond ((null how-to)
                          ;; Allow DOS/Windows users to change the letter
                          ;; case of a directory.  If we don't test these
                          ;; conditions up front, file-directory-p below
                          ;; will return t because the filesystem is
                          ;; case-insensitive, and Emacs will try to move
                          ;; foo -> foo/foo, which fails.
                          (if (and (memq system-type '(ms-dos windows-nt 
cygwin))
                                   (eq op-symbol 'move)
                                   dired-one-file
                                   (string= (downcase
                                             (expand-file-name (car fn-list)))
                                            (downcase
                                             (expand-file-name target)))
                                   (not (string=
                                         (file-name-nondirectory (car fn-list))
                                         (file-name-nondirectory target))))
                              nil
                            (file-directory-p target)))
                         ((eq how-to t) nil)
                         (t (funcall how-to target)))))
        (if (and (consp into-dir) (functionp (car into-dir)))
        (apply (car into-dir) operation rfn-list fn-list target (cdr into-dir))
          (if (not (or dired-one-file into-dir))
          (error "Marked %s: target must be a directory: %s" operation target))
          ;; rename-file bombs when moving directories unless we do this:
          (or into-dir (setq target (directory-file-name target)))
    ;;; BEGIN modification by @lawlist
          (if
              (and
                (eq system-type 'darwin)
                dired-one-file
                (equal op1 "Rename")
                (equal operation "Move")
                (equal (downcase (expand-file-name dired-one-file)) (downcase 
(expand-file-name target))))
            ;; Penetrate the `set-process-sentinel' with `lexical-let'.
            (lexical-let* ((dired-one-file dired-one-file)
                           (target target))
              (set-process-sentinel
                (start-process "rename" nil "mv" dired-one-file target)
                (lambda (p e) (when (= 0 (process-exit-status p))
                  (revert-buffer)
                  (message "Renamed %s to %s" dired-one-file target)))))
          (dired-create-files
           file-creator operation fn-list
           (if into-dir                 ; target is a directory
           ;; This function uses fluid variable target when called
           ;; inside dired-create-files:
           (function
            (lambda (from)
              (expand-file-name (file-name-nondirectory from) target)))
         (function (lambda (_from) target)))
           marker-char))
    ;;; END modification by @lawlist
      )))





reply via email to

[Prev in Thread] Current Thread [Next in Thread]