- _rl_isearch_dispatch: do translation for keys that map to
rl_do_lowercase_version like we do when dispatching while reading a
key sequence
+
+ 4/23
+ ----
+lib/readline/isearch.c
+ - _rl_isearch_dispatch: if bracketed paste mode is enabled and there are
+ enough characters waiting in the terminal's input queue, try to read
+ the bracketed paste prefix and jump straight to the opcode execution
+ if we read it. Otherwise, just go on with the ESC. Inspired by report
+ from <gentoo_eshoes@tutanota.com>
+
+parse.y
+ - parse_comsub: posix-mode shells don't allow a closing right paren to
+ delimit a pending here-document -- it requires the newline
+
+doc/bashref.texi
+ - POSIX mode: updated posix mode description with the new here-document
+ delimiter requirement
+
+lib/readline/search.c
+ - _rl_nsearch_dispatch: if bracketed paste mode is enabled, and we read
+ an ESC, try to see if we have a bracketed paste op and insert the
+ pasted next. If we don't, go on with the ESC
+ - _rl_nsearch_dosearch: experimental code to highlight the search string
+ when displaying the line found in the history. Only done when we are
+ not searching for a pattern, since we don't have information on the
+ end of the matching portion of the line. Experimental because it
+ changes where we put point and mark if searching is successful
+
+expr.c
+ - expr_streval: if find_variable for the case where the string is not
+ an array reference doesn't find anything, see if we can find
+ something by using find_variable_last_nameref and use the value
+ from there in the call to expr_streval, kind of using the expression
+ recursion to complement the nameref recursion. Report from
+ Daniel Molina <lluvia@autistici.org>
+
+ 4/24
+ ----
+jobs.c
+ - {start,stop}_pipeline: don't reset pipeline_pgrp to 0 if it's already
+ the same as shell_pgrp, since we don't want to reset it in the middle
+ of a shell started to run a command or process substitution (after
+ forking a child to run one command, but before forking another, for
+ instance). Reported by Rob Landley <rob@landley.net>
The parser does not recognize @code{time} as a reserved word if the next
token begins with a @samp{-}.
+@ignore
+@item
+When parsing @code{$()} command substitutions containing here-documents,
+the parser does not allow a here-document to be delimited by the closing
+right parenthesis. The newline after the here-document delimiter is required.
+@end ignore
+
@item
The @samp{!} character does not introduce history expansion within a
double-quoted string, even if the @code{histexpand} option is enabled.
return (EXECUTION_FAILURE);
}
- if (list == 0)
+ if (list == 0 && which == 0)
{
builtin_error ("string argument required");
return (EX_USAGE);
op.npos = npos;
op.poslist = poslist;
- /* we can eventually implement cut as a builtin with a cutfile() function
- that opens cutstring as a filename (or `-' for stdin) and runs cutline
- on every line in the file. */
if (which == 0)
rval = cutline (v, cutstring, &op);
return (cut_internal (0, list));
}
-/* Called when builtin is enabled and loaded from the shared object. If this
- function returns 0, the load fails. */
-int
-lcut_builtin_load (name)
- char *name;
-{
- return (1);
-}
-
-/* Called when builtin is disabled. */
-void
-lcut_builtin_unload (name)
- char *name;
-{
-}
-
char *lcut_doc[] = {
"Extract selected fields from a string.",
"",
#else
v = find_variable (tok);
#endif
+ if (v == 0 && e != ']')
+ v = find_variable_last_nameref (tok, 0);
if ((v == 0 || invisible_p (v)) && unbound_vars_is_error)
{
if (the_pipeline)
{
cleanup_the_pipeline ();
- pipeline_pgrp = 0;
+ /* If job_control == 0, pipeline_pgrp will always be equal to shell_pgrp;
+ if job_control != 0, pipeline_pgrp == shell_pgrp for command and
+ process substitution, in which case we want it to be the same as
+ shell_pgrp for the lifetime of this shell instance. */
+ if (pipeline_pgrp != shell_pgrp)
+ pipeline_pgrp = 0;
#if defined (PGRP_PIPE)
sh_closepipe (pgrp_pipe);
#endif
the_pipeline = (PROCESS *)NULL;
newjob->pgrp = pipeline_pgrp;
- pipeline_pgrp = 0;
+ if (pipeline_pgrp != shell_pgrp)
+ pipeline_pgrp = 0;
newjob->flags = 0;
if (pipefail_opt)
_rl_add_executing_keyseq (c);
+ /* XXX - experimental code to allow users to bracketed-paste into the search
+ string even when ESC is one of the isearch-terminators. Not perfect yet. */
+ if (_rl_enable_bracketed_paste && c == ESC && strchr (cxt->search_terminators, c) && (n = _rl_nchars_available ()) > (2*BRACK_PASTE_SLEN-1))
+ {
+ j = _rl_read_bracketed_paste_prefix (c);
+ if (j == 1)
+ {
+ cxt->lastc = -7; /* bracketed paste, see below */
+ goto opcode_dispatch;
+ }
+ else if (_rl_pushed_input_available ()) /* eat extra char we pushed back */
+ c = cxt->lastc = rl_read_key ();
+ else
+ c = cxt->lastc; /* last ditch */
+ }
+
/* If we are moving into a new keymap, modify cxt->keymap and go on.
This can be a problem if c == ESC and we want to terminate the
incremental search, so we check */
_rl_init_executing_keyseq ();
+opcode_dispatch:
/* Now dispatch on the character. `Opcodes' affect the search string or
state. Other characters are added to the string. */
switch (cxt->lastc)
/* kill.c -- kill ring management. */
-/* Copyright (C) 1994-2019 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2020 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library
for reading lines of text with interactive input and history editing.
/* search.c - code for non-incremental searching in emacs and vi modes. */
-/* Copyright (C) 1992-2017 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2020 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library
for reading lines of text with interactive input and history editing.
static int
noninc_dosearch (char *string, int dir, int flags)
{
- int oldpos, pos;
+ int oldpos, pos, ind;
HIST_ENTRY *entry;
if (string == 0 || *string == '\0' || noninc_history_pos < 0)
return 0;
}
- pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, (int *)0);
+ pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir, flags, &ind);
if (pos == -1)
{
/* Search failed, current history position unchanged. */
make_history_line_current (entry);
- rl_point = 0;
- rl_mark = rl_end;
+ if (_rl_enable_bracketed_paste && ((flags & SF_PATTERN) == 0) && ind > 0 && ind < rl_end)
+ {
+ rl_point = ind;
+ rl_mark = ind + strlen (string);
+ if (rl_mark > rl_end)
+ rl_mark = rl_end; /* can't happen? */
+ rl_activate_mark ();
+ }
+ else
+ {
+ rl_point = 0;
+ rl_mark = rl_end;
+ }
rl_clear_message ();
return 1;
static int
_rl_nsearch_dispatch (_rl_search_cxt *cxt, int c)
{
+ int n;
+
if (c < 0)
c = CTRL ('C');
_rl_nsearch_abort (cxt);
return -1;
+ case ESC:
+ /* XXX - experimental code to allow users to bracketed-paste into the
+ search string. Similar code is in isearch.c:_rl_isearch_dispatch().
+ The difference here is that the bracketed paste sometimes doesn't
+ paste everything, so checking for the prefix and the suffix in the
+ input queue doesn't work well. We just have to check to see if the
+ number of chars in the input queue is enough for the bracketed paste
+ prefix and hope for the best. */
+ if (_rl_enable_bracketed_paste && ((n = _rl_nchars_available ()) >= (BRACK_PASTE_SLEN-1)))
+ {
+ if (_rl_read_bracketed_paste_prefix (c) == 1)
+ rl_bracketed_paste_begin (1, c);
+ else
+ {
+ c = rl_read_key (); /* get the ESC that got pushed back */
+ _rl_insert_char (1, c);
+ }
+ }
+ else
+ _rl_insert_char (1, c);
+ break;
+
default:
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
}
(*rl_redisplay_function) ();
+ rl_deactivate_mark ();
return 1;
}
if (ch == '\n' && SHOULD_PROMPT ())
prompt_again ();
- /* XXX -- possibly allow here doc to be delimited by ending right
- paren. */
+ /* XXX -- we currently allow here doc to be delimited by ending right
+ paren in default mode and posix mode. To change posix mode, change
+ the #if 1 to #if 0 below */
if ((tflags & LEX_INHEREDOC) && ch == close && count == 1)
{
int tind;
tind = lex_firstind;
while ((tflags & LEX_STRIPDOC) && ret[tind] == '\t')
tind++;
- if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen))
+#if 1
+ if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen))
+#else
+ /* Posix-mode shells require the newline after the here-document
+ delimiter. */
+ if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen) &&
+ posixly_correct == 0)
+#endif
{
tflags &= ~(LEX_STRIPDOC|LEX_INHEREDOC|LEX_QUOTEDDOC);
/*itrace("parse_comsub:%d: found here doc end `%*s'", line_number, hdlen, ret + tind);*/
ab
+abcd
abcd
sh_352.26ax
sh_352.26ay
after 6
x
x
+x
quoted )
comment
here-doc with )
+here-doc with \()
here-doc terminated with a parenthesis
' # or a single back- or doublequote
+line terminated with a backslash
./comsub-posix1.sub: command substitution: line 2: syntax error near unexpected token `)'
./comsub-posix1.sub: command substitution: line 2: ` if x; then echo foo )'
after
)
echo $()
echo ab$()cd
+echo ab$( )cd
echo $(case a in (a) echo sh_352.26ax; esac )
echo $(case a in (a) echo sh_352.26ay; esac)
case x in x) echo x;; esac
)
+echo $(
+ case x in x) echo x;; esac # followed by a comment
+)
+
echo $(
case x in (x) echo x;; esac
)
eof
)
+echo $(
+ cat <<\eof
+ here-doc with \()
+eof
+)
+
echo $(
cat <<\)
here-doc terminated with a parenthesis
eof
)
+echo $(
+ echo line terminated with a backslash # \
+)
+
${THIS_SH} ./comsub-posix1.sub
${THIS_SH} ./comsub-posix2.sub
--- /dev/null
+: ${THIS_SH:=./bash}
+set -o posix
+
+# tests from Sven Mascheck that check whether a here-doc in a command
+# substitution can be terminated by EOF (the closing paren)
+#
+# currently unused
+
+# Example D.3 # should fail with unterminated here-doc
+${THIS_SH} -o posix -c 'echo $(
+ cat <<\eof
+ D.3: here-doc with )
+eof)'
+
+# Example D.4
+# the first EOF has a trailing blank
+# the third EOF is the correct one
+echo $(cat <<'EOF'
+ D.4 error-prone use of here-doc terminator
+EOF
+EOF)
+EOF
+)
+echo after here-document