aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/comint.el4
-rw-r--r--lisp/progmodes/compile.el39
-rw-r--r--lisp/replace.el32
-rw-r--r--lisp/simple.el6
-rw-r--r--src/minibuf.c163
5 files changed, 189 insertions, 55 deletions
diff --git a/lisp/comint.el b/lisp/comint.el
index 938b559fc3..fc8ba3103e 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -538,8 +538,8 @@ Buffer local variable.")
"Searches backwards through input history for substring match."
(interactive (let* ((last-command last-command) ; preserve around r-f-m
(s (read-from-minibuffer
- (format "Command substring (default %s): "
- comint-last-input-match))))
+ (format "Command substring (default %s): "
+ comint-last-input-match))))
(list (if (string= s "") comint-last-input-match s))))
; (interactive "sCommand substring: ")
(setq comint-last-input-match str) ; update default
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 4930a7875e..888c5578db 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -139,12 +139,6 @@ You might also use mode hooks to specify it in certain modes, like this:
(concat \"make -k \"
buffer-file-name))))))")
-;;;###autoload
-(defvar grep-command "grep -n "
- "Last shell command used to do a grep search; default for next search.
-Typically \"grep -n\" or \"egrep -n\".
-\(The \"-n\" option tells grep to output line numbers.)")
-
(defconst compilation-enter-directory-regexp
": Entering directory `\\(.*\\)'$"
"Regular expression for a line in the compilation log that
@@ -169,6 +163,11 @@ The default value matches lines printed by the `-w' option of GNU Make.")
\`compilation-leave-directory-regexp'. The head element is the directory
the compilation was started in.")
+;; History of compile commands.
+(defvar compile-history nil)
+;; History of grep commands.
+(defvar grep-history nil)
+
;;;###autoload
(defun compile (command)
"Compile the program including the current buffer. Default: run `make'.
@@ -185,7 +184,9 @@ Then start the next one.
The name used for the buffer is actually whatever is returned by
the function in `compilation-buffer-name-function', so you can set that
to a function that generates a unique name."
- (interactive (list (read-string "Compile command: " compile-command)))
+ (interactive (list (read-from-minibuffer "Compile command: "
+ compile-command nil
+ '(compile-history . 1))))
(setq compile-command command)
(save-some-buffers nil nil)
(compile-internal compile-command "No more errors"))
@@ -196,26 +197,12 @@ to a function that generates a unique name."
While grep runs asynchronously, you can use the \\[next-error] command
to find the text that grep hits refer to.
-The variable `grep-command' holds the last grep command run,
-and is the default for future runs. The command should use the `-n'
-flag, so that line numbers are displayed for each match.
-What the user enters in response to the prompt for grep args is
-appended to everything up to and including the `-n' in `grep-command'."
+This command uses a special history list for its arguments, so you can
+easily repeat a grep command."
(interactive
- (list (read-string (concat "Run "
- (substring grep-command 0
- (string-match "[\t ]+" grep-command))
- " (with args): ")
- (progn
- (string-match "-n[\t ]+" grep-command)
- (substring grep-command (match-end 0))))))
- ;; why a redundant string-match? It might not be interactive ...
- (setq grep-command (concat (substring grep-command 0
- (progn
- (string-match "-n" grep-command)
- (match-end 0)))
- " " command-args))
- (compile-internal (concat grep-command " /dev/null")
+ (list (read-from-minibuffer "Run grep (like this): "
+ "grep -n " nil nil 'grep-history)))
+ (compile-internal (concat command-args " /dev/null")
"No more grep hits" "grep"))
(defun compile-internal (command error-message
diff --git a/lisp/replace.el b/lisp/replace.el
index 01dbeb5558..24a4818051 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -23,6 +23,18 @@
(defconst case-replace t "\
*Non-nil means query-replace should preserve case in replacements.")
+(defvar query-replace-history nil)
+
+(defun query-replace-read-args (string)
+ (let (from to)
+ (setq from (read-from-minibuffer (format "%s: " string)
+ nil nil nil
+ 'query-replace-history))
+ (setq to (read-from-minibuffer (format "%s %s with: " string from)
+ nil nil nil
+ 'query-replace-history))
+ (list from to current-prefix-arg)))
+
(defun query-replace (from-string to-string &optional arg)
"Replace some occurrences of FROM-STRING with TO-STRING.
As each match is found, the user must type a character saying
@@ -32,7 +44,7 @@ Preserves case in each replacement if case-replace and case-fold-search
are non-nil and FROM-STRING has no uppercase letters.
Third arg DELIMITED (prefix arg if interactive) non-nil means replace
only matches surrounded by word boundaries."
- (interactive "sQuery replace: \nsQuery replace %s with: \nP")
+ (interactive (query-replace-read-args "Query replace"))
(perform-replace from-string to-string t nil arg)
(message "Done"))
(define-key esc-map "%" 'query-replace)
@@ -48,7 +60,7 @@ Third arg DELIMITED (prefix arg if interactive) non-nil means replace
only matches surrounded by word boundaries.
In TO-STRING, \\& means insert what matched REGEXP,
and \\=\\<n> means insert what matched <n>th \\(...\\) in REGEXP."
- (interactive "sQuery replace regexp: \nsQuery replace regexp %s with: \nP")
+ (interactive (query-replace-read-args "Query replace regexp"))
(perform-replace regexp to-string t t arg)
(message "Done"))
@@ -63,7 +75,17 @@ Non-interactively, TO-STRINGS may be a list of replacement strings.
A prefix argument N says to use each replacement string N times
before rotating to the next."
- (interactive "sMap query replace (regexp): \nsQuery replace %s with (space-separated strings): \nP")
+ (interactive
+ (let (from to)
+ (setq from (read-from-minibuffer "Map query replace (regexp): "
+ nil nil nil
+ 'query-replace-history))
+ (setq to (read-from-minibuffer
+ (format "Query replace %s with (space-separated strings): "
+ from)
+ nil nil nil
+ 'query-replace-history))
+ (list from to current-prefix-arg)))
(let (replacements)
(if (listp to-strings)
(setq replacements to-strings)
@@ -92,7 +114,7 @@ What you probably want is a loop like this:
(while (search-forward OLD-STRING nil t)
(replace-match REPLACEMENT nil t))
which will run faster and will not set the mark or print anything."
- (interactive "sReplace string: \nsReplace string %s with: \nP")
+ (interactive (query-replace-read-args "Replace string"))
(perform-replace from-string to-string nil nil delimited)
(message "Done"))
@@ -110,7 +132,7 @@ What you probably want is a loop like this:
(while (re-search-forward REGEXP nil t)
(replace-match REPLACEMENT nil nil))
which will run faster and will not set the mark or print anything."
- (interactive "sReplace regexp: \nsReplace regexp %s with: \nP")
+ (interactive (query-replace-read-args "Replace regexp"))
(perform-replace regexp to-string nil t delimited)
(message "Done"))
diff --git a/lisp/simple.el b/lisp/simple.el
index 59211c9db2..6c7cce59c0 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -391,7 +391,9 @@ Whilst editing the command, the following commands are available:
(setq newcmd (read-from-minibuffer "Redo: "
(prin1-to-string elt)
minibuffer-local-map
- t))
+ t
+ (cons 'command-history
+ arg)))
;; If command to be redone does not match front of history,
;; add it to the history.
(or (equal newcmd (car command-history))
@@ -415,7 +417,7 @@ Whilst editing the command, the following commands are available:
(insert
(if minibuffer-history-sexp-flag
(prin1-to-string elt)
- elt))))
+ elt)))
(goto-char (point-min)))))
(defun previous-history-element (n)
diff --git a/src/minibuf.c b/src/minibuf.c
index 08abe94e78..1997f4f5cb 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -41,6 +41,8 @@ struct minibuf_save_data
int prompt_width;
Lisp_Object help_form;
Lisp_Object current_prefix_arg;
+ Lisp_Object history_position;
+ Lisp_Object history_variable;
};
int minibuf_save_vector_size;
@@ -63,6 +65,16 @@ int enable_recursive_minibuffers;
Lisp_Object Vminibuffer_help_form;
+/* Variable which is the history list to add minibuffer values to. */
+
+Lisp_Object Vminibuffer_history_variable;
+
+/* Current position in the history list (adjusted by M-n and M-p). */
+
+Lisp_Object Vminibuffer_history_position;
+
+Lisp_Object Qminibuffer_history;
+
/* Nonzero means completion ignores case. */
int completion_ignore_case;
@@ -81,13 +93,23 @@ void read_minibuf_unwind ();
Lisp_Object get_minibuffer ();
Lisp_Object read_minibuf ();
+/* Read from the minibuffer using keymap MAP, initial contents INITIAL
+ (a string), putting point BACKUP_N chars from the end of INITIAL,
+ prompting with PROMPT (a string), using history list HISTVAR
+ with initial position HISTPOS.
+
+ Normally return the result as a string (the text that was read),
+ but if EXPFLAG is non-nil, read it and return the object read. */
+
Lisp_Object
-read_minibuf (map, initial, prompt, backup_n, expflag)
+read_minibuf (map, initial, prompt, backup_n, expflag, histvar, histpos)
Lisp_Object map;
Lisp_Object initial;
Lisp_Object prompt;
Lisp_Object backup_n;
int expflag;
+ Lisp_Object histvar;
+ Lisp_Object histpos;
{
register Lisp_Object val;
int count = specpdl_ptr - specpdl;
@@ -121,6 +143,8 @@ read_minibuf (map, initial, prompt, backup_n, expflag)
/* >> Why is this done this way rather than binding these variables? */
minibuf_save_vector[minibuf_level].help_form = Vhelp_form;
minibuf_save_vector[minibuf_level].current_prefix_arg = Vcurrent_prefix_arg;
+ minibuf_save_vector[minibuf_level].history_position = Vminibuffer_history_position;
+ minibuf_save_vector[minibuf_level].history_variable = Vminibuffer_history_variable;
GCPRO2 (minibuf_save_vector[minibuf_level].help_form,
minibuf_save_vector[minibuf_level].current_prefix_arg);
@@ -180,6 +204,8 @@ read_minibuf (map, initial, prompt, backup_n, expflag)
Vhelp_form = Vminibuffer_help_form;
current_buffer->keymap = map;
+ Vminibuffer_history_position = histpos;
+ Vminibuffer_history_variable = histvar;
/* ??? MCC did redraw_screen here if switching screens. */
recursive_edit_1 ();
@@ -197,13 +223,19 @@ read_minibuf (map, initial, prompt, backup_n, expflag)
/* Make minibuffer contents into a string */
val = make_buffer_string (1, Z);
bcopy (GAP_END_ADDR, XSTRING (val)->data + GPT - BEG, Z - GPT);
+
+ /* Add the value to the appropriate history list. */
+ if (XTYPE (Vminibuffer_history_variable) == Lisp_Symbol
+ && XSYMBOL (Vminibuffer_history_variable)->value != Qunbound)
+ Fset (Vminibuffer_history_variable,
+ Fcons (val, Fsymbol_value (Vminibuffer_history_variable)));
+
unbind_to (count, Qnil); /* The appropriate frame will get selected
in set-window-configuration. */
UNGCPRO;
/* VAL is the string of minibuffer text. */
-
last_minibuf_string = val;
/* If Lisp form desired instead of string, parse it */
@@ -270,6 +302,10 @@ read_minibuf_unwind (data)
minibuf_prompt_width = minibuf_save_vector[minibuf_level].prompt_width;
Vhelp_form = minibuf_save_vector[minibuf_level].help_form;
Vcurrent_prefix_arg = minibuf_save_vector[minibuf_level].current_prefix_arg;
+ Vminibuffer_history_position
+ = minibuf_save_vector[minibuf_level].history_position;
+ Vminibuffer_history_variable
+ = minibuf_save_vector[minibuf_level].history_variable;
#ifdef MULTI_FRAME
/* Redirect the focus of the frame that called the minibuffer. */
@@ -282,21 +318,36 @@ DEFUN ("read-from-minibuffer", Fread_from_minibuffer, Sread_from_minibuffer, 1,
"Read a string from the minibuffer, prompting with string PROMPT.\n\
If optional second arg INITIAL-CONTENTS is non-nil, it is a string\n\
to be inserted into the minibuffer before reading input.\n\
+ If INITIAL-CONTENTS is (STRING . POSITION), the initial input\n\
+ is STRING, but point is placed POSITION characters into the string.\n\
Third arg KEYMAP is a keymap to use whilst reading;\n\
if omitted or nil, the default is `minibuffer-local-map'.\n\
If fourth arg READ is non-nil, then interpret the result as a lisp object\n\
and return that object:\n\
in other words, do `(car (read-from-string INPUT-STRING))'\n\
-Fifth arg POSITION, if non-nil, is where to put point\n\
- in the minibuffer after inserting INITIAL-CONTENTS.")
- (prompt, initial_input, keymap, read, position)
- Lisp_Object prompt, initial_input, keymap, read, position;
+Fifth arg HIST, if non-nil, specifies a history list\n\
+ and optionally the initial position in the list.\n\
+ It can be a symbol, which is the history list variable to use,\n\
+ or it can be a cons cell (HISTVAR . HISTPOS).\n\
+ In that case, HISTVAR is the history list variable to use,\n\
+ and HISTPOS is the initial position (the position in the list\n\
+ which INITIAL-CONTENTS corresponds to).\n\
+ Positions are counted starting from 1 at the beginning of the list.")
+ (prompt, initial_input, keymap, read, hist)
+ Lisp_Object prompt, initial_input, keymap, read, hist;
{
int pos = 0;
+ Lisp_Object histvar, histpos, position;
+ position = Qnil;
CHECK_STRING (prompt, 0);
if (!NILP (initial_input))
{
+ if (XTYPE (initial_input) == Lisp_Cons)
+ {
+ position = Fcdr (initial_input);
+ initial_input = Fcar (initial_input);
+ }
CHECK_STRING (initial_input, 1);
if (!NILP (position))
{
@@ -310,8 +361,24 @@ Fifth arg POSITION, if non-nil, is where to put point\n\
keymap = Vminibuffer_local_map;
else
keymap = get_keymap (keymap,2);
+
+ if (XTYPE (hist) == Lisp_Symbol)
+ {
+ histvar = hist;
+ histpos = Qnil;
+ }
+ else
+ {
+ histvar = Fcar_safe (hist);
+ histpos = Fcdr_safe (hist);
+ }
+ if (NILP (histvar))
+ histvar = Qminibuffer_history;
+ if (NILP (histpos))
+ XFASTINT (histpos) = 0;
+
return read_minibuf (keymap, initial_input, prompt,
- pos, !NILP (read));
+ pos, !NILP (read), histvar, histpos);
}
DEFUN ("read-minibuffer", Fread_minibuffer, Sread_minibuffer, 1, 2, 0,
@@ -324,7 +391,8 @@ is a string to insert in the minibuffer before reading.")
CHECK_STRING (prompt, 0);
if (!NILP (initial_contents))
CHECK_STRING (initial_contents, 1)
- return read_minibuf (Vminibuffer_local_map, initial_contents, prompt, Qnil, 1);
+ return read_minibuf (Vminibuffer_local_map, initial_contents,
+ prompt, Qnil, 1, Qminibuffer_history, make_number (0));
}
DEFUN ("eval-minibuffer", Feval_minibuffer, Seval_minibuffer, 1, 2, 0,
@@ -358,7 +426,8 @@ Prompt with PROMPT, and provide INIT as an initial value of the input string.")
if (! NILP (init))
CHECK_STRING (init, 1);
- return read_minibuf (Vminibuffer_local_ns_map, init, prompt, Qnil, 0);
+ return read_minibuf (Vminibuffer_local_ns_map, init, prompt, Qnil, 0,
+ Qminibuffer_history, make_number (0));
}
DEFUN ("read-command", Fread_command, Sread_command, 1, 1, 0,
@@ -732,7 +801,7 @@ Lisp_Object Vminibuffer_completion_confirm, Qminibuffer_completion_confirm;
DEFUN ("completing-read", Fcompleting_read, Scompleting_read, 2, 6, 0,
"Read a string in the minibuffer, with completion.\n\
-Args: PROMPT, TABLE, PREDICATE, REQUIRE-MATCH, INITIAL-INPUT, BACKUP-N.\n\
+Args: PROMPT, TABLE, PREDICATE, REQUIRE-MATCH, INITIAL-INPUT, HIST.\n\
PROMPT is a string to prompt with; normally it ends in a colon and a space.\n\
TABLE is an alist whose elements' cars are strings, or an obarray.\n\
PREDICATE limits completion to a subset of TABLE.\n\
@@ -741,25 +810,67 @@ If REQUIRE-MATCH is non-nil, the user is not allowed to exit unless\n\
the input is (or completes to) an element of TABLE.\n\
If it is also not t, Return does not exit if it does non-null completion.\n\
If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.\n\
-Case is ignored if ambient value of `completion-ignore-case' is non-nil.\n\
-If BACKUP-N is specified, point should be placed that many spaces from\n\
-the end of the buffer. This is useful when providing default values,\n\
-because you can put point before the last component of a filename or any\n\
-other component that is likely to be deleted.")
- (prompt, table, pred, require_match, init, backup_n)
- Lisp_Object prompt, table, pred, require_match, init, backup_n;
+ If it is (STRING . POSITION), the initial input\n\
+ is STRING, but point is placed POSITION characters into the string.\n\
+HIST, if non-nil, specifies a history list\n\
+ and optionally the initial position in the list.\n\
+ It can be a symbol, which is the history list variable to use,\n\
+ or it can be a cons cell (HISTVAR . HISTPOS).\n\
+ In that case, HISTVAR is the history list variable to use,\n\
+ and HISTPOS is the initial position (the position in the list\n\
+ which INITIAL-CONTENTS corresponds to).\n\
+ Positions are counted starting from 1 at the beginning of the list.\n\
+Completion ignores case if the ambient value of\n\
+ `completion-ignore-case' is non-nil.")
+ (prompt, table, pred, require_match, init, hist)
+ Lisp_Object prompt, table, pred, require_match, init, hist;
{
- Lisp_Object val;
+ Lisp_Object val, histvar, histpos, position;
+ int pos = 0;
int count = specpdl_ptr - specpdl;
specbind (Qminibuffer_completion_table, table);
specbind (Qminibuffer_completion_predicate, pred);
specbind (Qminibuffer_completion_confirm,
EQ (require_match, Qt) ? Qnil : Qt);
last_exact_completion = Qnil;
+
+ position = Qnil;
+ if (!NILP (init))
+ {
+ if (XTYPE (init) == Lisp_Cons)
+ {
+ position = Fcdr (init);
+ init = Fcar (init);
+ }
+ CHECK_STRING (init, 0);
+ if (!NILP (position))
+ {
+ CHECK_NUMBER (position, 0);
+ /* Convert to distance from end of input. */
+ pos = XINT (position) - 1 - XSTRING (init)->size;
+ }
+ }
+
+ if (XTYPE (hist) == Lisp_Symbol)
+ {
+ histvar = hist;
+ histpos = Qnil;
+ }
+ else
+ {
+ histvar = Fcar_safe (hist);
+ histpos = Fcdr_safe (hist);
+ }
+ if (NILP (histvar))
+ histvar = Qminibuffer_history;
+ if (NILP (histpos))
+ XFASTINT (histpos) = 0;
+
val = read_minibuf (NILP (require_match)
? Vminibuffer_local_completion_map
: Vminibuffer_local_must_match_map,
- init, prompt, backup_n, 0);
+ init, prompt, pos, 0,
+ histvar, histpos);
return unbind_to (count, val);
}
@@ -1252,7 +1363,8 @@ syms_of_minibuf ()
Quser_variable_p = intern ("user-variable-p");
staticpro (&Quser_variable_p);
-
+ Qminibuffer_history = intern ("minibuffer-history");
+ staticpro (&Qminibuffer_history);
DEFVAR_BOOL ("completion-auto-help", &auto_help,
"*Non-nil means automatically provide help for invalid completion input.");
@@ -1295,6 +1407,17 @@ t means to return a list of all possible completions of STRING.\n\
"Value that `help-form' takes on inside the minibuffer.");
Vminibuffer_help_form = Qnil;
+ DEFVAR_LISP ("minibuffer-history-variable", &Vminibuffer_history_variable,
+ "History list symbol to add minibuffer values to.\n\
+Each minibuffer output is added with\n\
+ (set minibuffer-history-variable\n\
+ (cons STRING (symbol-value minibuffer-history-variable)))");
+ XFASTINT (Vminibuffer_history_variable) = 0;
+
+ DEFVAR_LISP ("minibuffer-history-position", &Vminibuffer_history_position,
+ "Current position of redoing in the history list.");
+ Vminibuffer_history_position = Qnil;
+
defsubr (&Sread_from_minibuffer);
defsubr (&Seval_minibuffer);
defsubr (&Sread_minibuffer);