* minibuffer.el (minibuffer--double-dollars, read-file-name-internal):
New functions. * fileio.c (read_file_name_cleanup, Fread_file_name_internal): Move functions to minibuffer.el. (syms_of_fileio): Don't declare them.
This commit is contained in:
parent
d2925a49b4
commit
34b67b0f6b
4 changed files with 63 additions and 130 deletions
|
@ -1,5 +1,8 @@
|
|||
2008-04-10 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* minibuffer.el (minibuffer--double-dollars, read-file-name-internal):
|
||||
New functions.
|
||||
|
||||
* minibuffer.el (minibuffer--do-completion): Don't forget to propagate
|
||||
the arg to recursive calls.
|
||||
|
||||
|
|
|
@ -450,5 +450,59 @@ during running `completion-setup-hook'."
|
|||
(ding))
|
||||
(exit-minibuffer))
|
||||
|
||||
(defun minibuffer--double-dollars (str)
|
||||
(replace-regexp-in-string "\\$" "$$" str))
|
||||
|
||||
(defun read-file-name-internal (string dir action)
|
||||
"Internal subroutine for read-file-name. Do not call this."
|
||||
(setq dir (expand-file-name dir))
|
||||
(if (and (zerop (length string)) (eq 'lambda action))
|
||||
nil ; FIXME: why?
|
||||
(let* ((str (substitute-in-file-name string))
|
||||
(name (file-name-nondirectory str))
|
||||
(specdir (file-name-directory str))
|
||||
(realdir (if specdir (expand-file-name specdir dir)
|
||||
(file-name-as-directory dir))))
|
||||
|
||||
(cond
|
||||
((null action)
|
||||
(let ((comp (file-name-completion name realdir
|
||||
read-file-name-predicate)))
|
||||
(if (stringp comp)
|
||||
;; Requote the $s before returning the completion.
|
||||
(minibuffer--double-dollars (concat specdir comp))
|
||||
;; Requote the $s before checking for changes.
|
||||
(setq str (minibuffer--double-dollars str))
|
||||
(if (string-equal string str)
|
||||
comp
|
||||
;; If there's no real completion, but substitute-in-file-name
|
||||
;; changed the string, then return the new string.
|
||||
str))))
|
||||
|
||||
((eq action t)
|
||||
(let ((all (file-name-all-completions name realdir)))
|
||||
(if (memq read-file-name-predicate '(nil file-exists-p))
|
||||
all
|
||||
(let ((comp ())
|
||||
(pred
|
||||
(if (eq read-file-name-predicate 'file-directory-p)
|
||||
;; Brute-force speed up for directory checking:
|
||||
;; Discard strings which don't end in a slash.
|
||||
(lambda (s)
|
||||
(let ((len (length s)))
|
||||
(and (> len 0) (eq (aref s (1- len)) ?/))))
|
||||
;; Must do it the hard (and slow) way.
|
||||
read-file-name-predicate)))
|
||||
(let ((default-directory realdir))
|
||||
(dolist (tem all)
|
||||
(if (funcall pred tem) (push tem comp))))
|
||||
(nreverse comp)))))
|
||||
|
||||
(t
|
||||
;; Only other case actually used is ACTION = lambda.
|
||||
(let ((default-directory dir))
|
||||
(funcall (or read-file-name-predicate 'file-exists-p) str)))))))
|
||||
|
||||
|
||||
(provide 'minibuffer)
|
||||
;;; minibuffer.el ends here
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2008-04-10 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* fileio.c (read_file_name_cleanup, Fread_file_name_internal):
|
||||
Move functions to minibuffer.el.
|
||||
(syms_of_fileio): Don't declare them.
|
||||
|
||||
2008-04-09 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* minibuf.c (Vcompletion_auto_help): Move to minibuffer.el.
|
||||
|
|
130
src/fileio.c
130
src/fileio.c
|
@ -6119,135 +6119,6 @@ double_dollars (val)
|
|||
return val;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
read_file_name_cleanup (arg)
|
||||
Lisp_Object arg;
|
||||
{
|
||||
return (current_buffer->directory = arg);
|
||||
}
|
||||
|
||||
DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_internal,
|
||||
3, 3, 0,
|
||||
doc: /* Internal subroutine for read-file-name. Do not call this. */)
|
||||
(string, dir, action)
|
||||
Lisp_Object string, dir, action;
|
||||
/* action is nil for complete, t for return list of completions,
|
||||
lambda for verify final value */
|
||||
{
|
||||
Lisp_Object name, specdir, realdir, val, orig_string;
|
||||
int changed;
|
||||
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
|
||||
|
||||
CHECK_STRING (string);
|
||||
|
||||
realdir = dir;
|
||||
name = string;
|
||||
orig_string = Qnil;
|
||||
specdir = Qnil;
|
||||
changed = 0;
|
||||
/* No need to protect ACTION--we only compare it with t and nil. */
|
||||
GCPRO5 (string, realdir, name, specdir, orig_string);
|
||||
|
||||
if (SCHARS (string) == 0)
|
||||
{
|
||||
if (EQ (action, Qlambda))
|
||||
{
|
||||
UNGCPRO;
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
orig_string = string;
|
||||
string = Fsubstitute_in_file_name (string);
|
||||
changed = NILP (Fstring_equal (string, orig_string));
|
||||
name = Ffile_name_nondirectory (string);
|
||||
val = Ffile_name_directory (string);
|
||||
if (! NILP (val))
|
||||
realdir = Fexpand_file_name (val, realdir);
|
||||
}
|
||||
|
||||
if (NILP (action))
|
||||
{
|
||||
specdir = Ffile_name_directory (string);
|
||||
val = Ffile_name_completion (name, realdir, Vread_file_name_predicate);
|
||||
UNGCPRO;
|
||||
if (!STRINGP (val))
|
||||
{
|
||||
if (changed)
|
||||
return double_dollars (string);
|
||||
return val;
|
||||
}
|
||||
|
||||
if (!NILP (specdir))
|
||||
val = concat2 (specdir, val);
|
||||
#ifndef VMS
|
||||
return double_dollars (val);
|
||||
#else /* not VMS */
|
||||
return val;
|
||||
#endif /* not VMS */
|
||||
}
|
||||
UNGCPRO;
|
||||
|
||||
if (EQ (action, Qt))
|
||||
{
|
||||
Lisp_Object all = Ffile_name_all_completions (name, realdir);
|
||||
Lisp_Object comp;
|
||||
int count;
|
||||
|
||||
if (NILP (Vread_file_name_predicate)
|
||||
|| EQ (Vread_file_name_predicate, Qfile_exists_p))
|
||||
return all;
|
||||
|
||||
#ifndef VMS
|
||||
if (EQ (Vread_file_name_predicate, Qfile_directory_p))
|
||||
{
|
||||
/* Brute-force speed up for directory checking:
|
||||
Discard strings which don't end in a slash. */
|
||||
for (comp = Qnil; CONSP (all); all = XCDR (all))
|
||||
{
|
||||
Lisp_Object tem = XCAR (all);
|
||||
int len;
|
||||
if (STRINGP (tem) &&
|
||||
(len = SBYTES (tem), len > 0) &&
|
||||
IS_DIRECTORY_SEP (SREF (tem, len-1)))
|
||||
comp = Fcons (tem, comp);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Must do it the hard (and slow) way. */
|
||||
Lisp_Object tem;
|
||||
GCPRO3 (all, comp, specdir);
|
||||
count = SPECPDL_INDEX ();
|
||||
record_unwind_protect (read_file_name_cleanup, current_buffer->directory);
|
||||
current_buffer->directory = realdir;
|
||||
for (comp = Qnil; CONSP (all); all = XCDR (all))
|
||||
{
|
||||
tem = call1 (Vread_file_name_predicate, XCAR (all));
|
||||
if (!NILP (tem))
|
||||
comp = Fcons (XCAR (all), comp);
|
||||
}
|
||||
unbind_to (count, Qnil);
|
||||
UNGCPRO;
|
||||
}
|
||||
return Fnreverse (comp);
|
||||
}
|
||||
|
||||
/* Only other case actually used is ACTION = lambda */
|
||||
#ifdef VMS
|
||||
/* Supposedly this helps commands such as `cd' that read directory names,
|
||||
but can someone explain how it helps them? -- RMS */
|
||||
if (SCHARS (name) == 0)
|
||||
return Qt;
|
||||
#endif /* VMS */
|
||||
string = Fexpand_file_name (string, dir);
|
||||
if (!NILP (Vread_file_name_predicate))
|
||||
return call1 (Vread_file_name_predicate, string);
|
||||
return Ffile_exists_p (string);
|
||||
}
|
||||
|
||||
DEFUN ("next-read-file-uses-dialog-p", Fnext_read_file_uses_dialog_p,
|
||||
Snext_read_file_uses_dialog_p, 0, 0, 0,
|
||||
doc: /* Return t if a call to `read-file-name' will use a dialog.
|
||||
|
@ -6803,7 +6674,6 @@ A non-nil value may result in data loss! */);
|
|||
defsubr (&Sclear_buffer_auto_save_failure);
|
||||
defsubr (&Srecent_auto_save_p);
|
||||
|
||||
defsubr (&Sread_file_name_internal);
|
||||
defsubr (&Sread_file_name);
|
||||
defsubr (&Snext_read_file_uses_dialog_p);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue