2 * Copyright (C) 1984-2002 Mark Nudelman
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Less License, as specified in the README file.
7 * For more information about less, or for information on how to
8 * contact the author, see the README file.
13 * Functions which manipulate the command buffer.
14 * Used only by command() and related functions.
22 static char cmdbuf
[CMDBUF_SIZE
]; /* Buffer for holding a multi-char command */
23 static int cmd_col
; /* Current column of the cursor */
24 static int prompt_col
; /* Column of cursor just after prompt */
25 static char *cp
; /* Pointer into cmdbuf */
26 static int cmd_offset
; /* Index into cmdbuf of first displayed char */
27 static int literal
; /* Next input char should not be interpreted */
29 #if TAB_COMPLETE_FILENAME
30 static int cmd_complete();
32 * These variables are statics used by cmd_complete.
34 static int in_completion
= 0;
36 static char *tk_original
;
37 static char *tk_ipoint
;
38 static char *tk_trial
;
39 static struct textlist tk_tlist
;
42 static int cmd_left();
43 static int cmd_right();
45 #if SPACES_IN_FILENAMES
46 public char openquote
= '"';
47 public char closequote
= '"';
52 * A mlist structure represents a command history.
58 struct mlist
*curr_mp
;
63 * These are the various command histories that exist.
65 struct mlist mlist_search
=
66 { &mlist_search
, &mlist_search
, &mlist_search
, NULL
};
67 public void * constant ml_search
= (void *) &mlist_search
;
69 struct mlist mlist_examine
=
70 { &mlist_examine
, &mlist_examine
, &mlist_examine
, NULL
};
71 public void * constant ml_examine
= (void *) &mlist_examine
;
73 #if SHELL_ESCAPE || PIPEC
74 struct mlist mlist_shell
=
75 { &mlist_shell
, &mlist_shell
, &mlist_shell
, NULL
};
76 public void * constant ml_shell
= (void *) &mlist_shell
;
79 #else /* CMD_HISTORY */
81 /* If CMD_HISTORY is off, these are just flags. */
82 public void * constant ml_search
= (void *)1;
83 public void * constant ml_examine
= (void *)2;
84 #if SHELL_ESCAPE || PIPEC
85 public void * constant ml_shell
= (void *)3;
88 #endif /* CMD_HISTORY */
91 * History for the current command.
93 static struct mlist
*curr_mlist
= NULL
;
94 static int curr_cmdflags
;
98 * Reset command buffer (to empty).
111 * Clear command line on display.
117 cmd_col
= prompt_col
= 0;
121 * Display a string, usually as a prompt for input into the command buffer.
128 cmd_col
+= strlen(s
);
129 prompt_col
+= strlen(s
);
133 * How many characters are in the command buffer?
138 return (strlen(cmdbuf
));
142 * Repaint the line from cp onwards.
143 * Then position the cursor just after the char old_cp (a pointer into cmdbuf).
152 * Repaint the line from the current position.
155 for ( ; *cp
!= '\0'; cp
++)
158 if (cmd_col
+ (int)strlen(p
) >= sc_width
)
161 cmd_col
+= strlen(p
);
165 * Back up the cursor to the correct position.
172 * Put the cursor at "home" (just after the prompt),
173 * and set cp to the corresponding char in cmdbuf.
178 while (cmd_col
> prompt_col
)
184 cp
= &cmdbuf
[cmd_offset
];
188 * Shift the cmdbuf display left a half-screen.
198 * Start at the first displayed char, count how far to the
199 * right we'd have to move to reach the center of the screen.
201 s
= cmdbuf
+ cmd_offset
;
203 while (cols
< (sc_width
- prompt_col
) / 2 && *s
!= '\0')
204 cols
+= strlen(prchar(*s
++));
206 cmd_offset
= s
- cmdbuf
;
209 cmd_repaint(save_cp
);
213 * Shift the cmdbuf display right a half-screen.
224 * Start at the first displayed char, count how far to the
225 * left we'd have to move to traverse a half-screen width
226 * of displayed characters.
228 s
= cmdbuf
+ cmd_offset
;
230 while (cols
< (sc_width
- prompt_col
) / 2 && s
> cmdbuf
)
236 cmd_offset
= s
- cmdbuf
;
239 cmd_repaint(save_cp
);
243 * Move cursor right one character.
253 * Already at the end of the line.
258 if (cmd_col
+ (int)strlen(p
) >= sc_width
)
260 else if (cmd_col
+ (int)strlen(p
) == sc_width
- 1 && cp
[1] != '\0')
264 cmd_col
+= strlen(p
);
269 * Move cursor left one character.
278 /* Already at the beginning of the line */
282 if (cmd_col
< prompt_col
+ (int)strlen(p
))
285 cmd_col
-= strlen(p
);
292 * Insert a char into the command buffer, at the current position.
300 if (strlen(cmdbuf
) >= sizeof(cmdbuf
)-2)
303 * No room in the command buffer for another char.
310 * Insert the character into the buffer.
312 for (s
= &cmdbuf
[strlen(cmdbuf
)]; s
>= cp
; s
--)
316 * Reprint the tail of the line from the inserted char.
324 * Backspace in the command buffer.
325 * Delete the char to the left of the cursor.
335 * Backspace past beginning of the buffer:
336 * this usually means abort the command.
341 * Move cursor left (to the char being erased).
345 * Remove the char from the buffer (shift the buffer left).
347 for (s
= cp
; *s
!= '\0'; s
++)
350 * Repaint the buffer after the erased char.
355 * We say that erasing the entire command string causes us
356 * to abort the current command, if CF_QUIT_ON_ERASE is set.
358 if ((curr_cmdflags
& CF_QUIT_ON_ERASE
) && cp
== cmdbuf
&& *cp
== '\0')
364 * Delete the char under the cursor.
372 * At end of string; there is no char under the cursor.
377 * Move right, then use cmd_erase.
385 * Delete the "word" to the left of the cursor.
390 if (cp
> cmdbuf
&& cp
[-1] == ' ')
393 * If the char left of cursor is a space,
394 * erase all the spaces left of cursor (to the first non-space).
396 while (cp
> cmdbuf
&& cp
[-1] == ' ')
401 * If the char left of cursor is not a space,
402 * erase all the nonspaces left of cursor (the whole "word").
404 while (cp
> cmdbuf
&& cp
[-1] != ' ')
411 * Delete the "word" under the cursor.
419 * If the char under the cursor is a space,
420 * delete it and all the spaces right of cursor.
427 * If the char under the cursor is not a space,
428 * delete it and all nonspaces right of cursor (the whole word).
430 while (*cp
!= ' ' && *cp
!= '\0')
437 * Delete all chars in the command buffer.
442 if (cmdbuf
[0] == '\0')
445 * Buffer is already empty; abort the current command.
455 * We say that erasing the entire command string causes us
456 * to abort the current command, if CF_QUIT_ON_ERASE is set.
458 if (curr_cmdflags
& CF_QUIT_ON_ERASE
)
464 * Select an mlist structure to be the current command history.
467 set_mlist(mlist
, cmdflags
)
471 curr_mlist
= (struct mlist
*) mlist
;
472 curr_cmdflags
= cmdflags
;
477 * Move up or down in the currently selected command history list.
485 if (curr_mlist
== NULL
)
488 * The current command has no history list.
496 * Move curr_mp to the next/prev entry.
499 curr_mlist
->curr_mp
= curr_mlist
->curr_mp
->prev
;
501 curr_mlist
->curr_mp
= curr_mlist
->curr_mp
->next
;
503 * Copy the entry into cmdbuf and echo it on the screen.
505 s
= curr_mlist
->curr_mp
->string
;
508 for (cp
= cmdbuf
; *s
!= '\0'; s
++)
519 * Add a string to a history list.
522 cmd_addhist(mlist
, cmd
)
530 * Don't save a trivial command.
532 if (strlen(cmd
) == 0)
535 * Don't save if a duplicate of a command which is already
537 * But select the one already in the history to be current.
539 for (ml
= mlist
->next
; ml
!= mlist
; ml
= ml
->next
)
541 if (strcmp(ml
->string
, cmd
) == 0)
547 * Did not find command in history.
548 * Save the command and put it at the end of the history list.
550 ml
= (struct mlist
*) ecalloc(1, sizeof(struct mlist
));
551 ml
->string
= save(cmd
);
553 ml
->prev
= mlist
->prev
;
554 mlist
->prev
->next
= ml
;
558 * Point to the cmd just after the just-accepted command.
559 * Thus, an UPARROW will always retrieve the previous command.
561 mlist
->curr_mp
= ml
->next
;
566 * Accept the command in the command buffer.
567 * Add it to the currently selected history list.
574 * Nothing to do if there is no currently selected history list.
576 if (curr_mlist
== NULL
)
578 cmd_addhist(curr_mlist
, cmdbuf
);
583 * Try to perform a line-edit function on the command buffer,
584 * using a specified char as a line-editing command.
586 * CC_PASS The char does not invoke a line edit function.
587 * CC_OK Line edit function done.
588 * CC_QUIT The char requests the current command to be aborted.
597 #if TAB_COMPLETE_FILENAME
598 #define not_in_completion() in_completion = 0
600 #define not_in_completion()
604 * See if the char is indeed a line-editing command.
608 if (curr_mlist
== NULL
)
610 * No current history; don't accept history manipulation cmds.
612 flags
|= EC_NOHISTORY
;
614 #if TAB_COMPLETE_FILENAME
615 if (curr_mlist
== ml_search
)
617 * In a search command; don't accept file-completion cmds.
619 flags
|= EC_NOCOMPLETE
;
622 action
= editchar(c
, flags
);
628 return (cmd_right());
634 while (*cp
!= '\0' && *cp
!= ' ')
641 while (cp
> cmdbuf
&& cp
[-1] == ' ')
643 while (cp
> cmdbuf
&& cp
[-1] != ' ')
662 return (cmd_erase());
668 return (cmd_werase());
671 return (cmd_delete());
674 return (cmd_wdelete());
682 return (cmd_updown(action
));
684 #if TAB_COMPLETE_FILENAME
688 return (cmd_complete(action
));
698 #if TAB_COMPLETE_FILENAME
700 * Insert a string into the command buffer, at the current position.
709 for (s
= str
; *s
!= '\0'; s
++)
711 action
= cmd_ichar(*s
);
722 * Find the beginning and end of the "current" word.
723 * This is the word which the cursor (cp) is inside or at the end of.
724 * Return pointer to the beginning of the word and put the
725 * cursor at the end of the word.
731 #if SPACES_IN_FILENAMES
733 int delim_quoted
= 0;
735 char *esc
= get_meta_escape();
736 int esclen
= strlen(esc
);
740 * Move cursor to end of word.
742 if (*cp
!= ' ' && *cp
!= '\0')
745 * Cursor is on a nonspace.
746 * Move cursor right to the next space.
748 while (*cp
!= ' ' && *cp
!= '\0')
750 } else if (cp
> cmdbuf
&& cp
[-1] != ' ')
753 * Cursor is on a space, and char to the left is a nonspace.
754 * We're already at the end of the word.
761 * Cursor is on a space and char to the left is a space.
762 * Huh? There's no word here.
768 * Find the beginning of the word which the cursor is in.
772 #if SPACES_IN_FILENAMES
774 * If we have an unbalanced quote (that is, an open quote
775 * without a corresponding close quote), we return everything
776 * from the open quote, including spaces.
778 for (word
= cmdbuf
; word
< cp
; word
++)
783 for (p
= cmdbuf
; p
< cp
; p
++)
788 } else if (esclen
> 0 && p
+ esclen
< cp
&&
789 strncmp(p
, esc
, esclen
) == 0)
793 } else if (delim_quoted
)
795 if (*p
== closequote
)
797 } else /* (!delim_quoted) */
810 * Set things up to enter completion mode.
811 * Expand the word under the cursor into a list of filenames
812 * which start with that word, and set tk_text to that list.
821 * Get rid of any previous tk_text.
829 * Find the original (uncompleted) word in the command buffer.
831 word
= delimit_word();
835 * Set the insertion point to the point in the command buffer
836 * where the original (uncompleted) word now sits.
840 * Save the original (uncompleted) word
842 if (tk_original
!= NULL
)
844 tk_original
= (char *) ecalloc(cp
-word
+1, sizeof(char));
845 strncpy(tk_original
, word
, cp
-word
);
847 * Get the expanded filename.
848 * This may result in a single filename, or
849 * a blank-separated list of filenames.
853 if (*word
!= openquote
)
855 tk_text
= fcomplete(word
);
858 char *qword
= shell_quote(word
+1);
860 tk_text
= fcomplete(word
+1);
863 tk_text
= fcomplete(qword
);
871 * Return the next word in the current completion list.
874 next_compl(action
, prev
)
881 return (forw_textlist(&tk_tlist
, prev
));
883 return (back_textlist(&tk_tlist
, prev
));
890 * Complete the filename before (or under) the cursor.
891 * cmd_complete may be called multiple times. The global in_completion
892 * remembers whether this call is the first time (create the list),
893 * or a subsequent time (step thru the list).
901 if (!in_completion
|| action
== EC_EXPAND
)
904 * Expand the word under the cursor and
905 * use the first word in the expansion
906 * (or the entire expansion if we're doing EC_EXPAND).
914 if (action
== EC_EXPAND
)
917 * Use the whole list.
923 * Use the first filename in the list.
926 init_textlist(&tk_tlist
, tk_text
);
927 tk_trial
= next_compl(action
, (char*)NULL
);
932 * We already have a completion list.
933 * Use the next/previous filename from the list.
935 tk_trial
= next_compl(action
, tk_trial
);
939 * Remove the original word, or the previous trial completion.
941 while (cp
> tk_ipoint
)
944 if (tk_trial
== NULL
)
947 * There are no more trial completions.
948 * Insert the original (uncompleted) filename.
951 if (cmd_istr(tk_original
) != CC_OK
)
956 * Insert trial completion.
958 if (cmd_istr(tk_trial
) != CC_OK
)
961 * If it is a directory, append a slash.
963 if (is_dir(tk_trial
))
965 if (cp
> cmdbuf
&& cp
[-1] == closequote
)
967 s
= lgetenv("LESSSEPARATOR");
970 if (cmd_istr(s
) != CC_OK
)
983 #endif /* TAB_COMPLETE_FILENAME */
986 * Process a single character of a multi-character command, such as
987 * a number, or the pattern of a search command.
989 * CC_OK The char was accepted.
990 * CC_QUIT The char requests the command to be aborted.
991 * CC_ERROR The char could not be accepted due to an error.
1002 * Insert the char, even if it is a line-editing char.
1005 return (cmd_ichar(c
));
1009 * See if it is a special line-editing character.
1013 action
= cmd_edit(c
);
1025 * Insert the char into the command buffer.
1027 return (cmd_ichar(c
));
1031 * Return the number currently in the command buffer.
1039 for (p
= cmdbuf
; *p
!= '\0'; p
++)
1040 n
= (10 * n
) + (*p
- '0');
1045 * Return a pointer to the command buffer.