объединение строк истории libreadline

Это сводило меня с ума в течение приблизительно трех лет. Я не знаю, как полностью описать проблему, но я думаю, что могу наконец описать способ воссоздать ее. Ваш milage может варьироваться. У меня есть смесь сервера человечности и настольных машин различных версий и нескольких хинду машин с различными состояниями плохого состояния. Они все кажутся kindof, делают их собственную вещь, хотя с общими чертами.

Попробуйте это и сообщите мне, видите ли Вы то же самое.

  1. появитесь открывают два xterms (TERM=xterm)
  2. измените размер того, таким образом, они не то же
  3. выпустите экранный-R test1 в одном (TERM=screen)
  4. и экранный-x test1 в другом
  5. ура, ввод в каждый обнаруживается в другом; хотя уведомление, что их другой размер производит артефакты и вещи
  6. дайте пару команд в Вашей оболочке
  7. хит ^AF в том, который не соответствует совершенно верно, теперь это соответствует!!
  8. прокрутите назад по истории немного
  9. goto 6

В конечном счете Вы заметите пару объединения строк истории. Если Вы не делаете, то это - что-то уникальное для моей установки, которая охватывает различные дистрибутивы и компьютеры; таким образом, это - запутывающее понятие мне.

Если Вы видите вещь, я вижу затем это:

bash$ ls -al
bash$ ps auxfw

становится этим:

bash$ ls -al; ps auxfw

Этого не происходит каждый раз. Я должен действительно играть с ним — если я не хочу, чтобы это произошло, затем это всегда делает. В некоторых системах (или комбинации), я получаю разделитель строки как пример выше. В некоторых системах я не делаю. То, что я добираюсь, разделитель строки в некоторых системах, кажется, указывает мне, что удар поддерживает это поведение. Его история полностью обрабатывается libreadline и после просматривания (т.е., тщательно читая) страницы справочника, я не мог найти единственный readline, устанавливающий для объединения двух строк истории. И при этом я ничего не могу найти в странице справочника удара.

Так, как я могу вызвать это нарочно? Или, если я не могу сделать этого, как я могу отключить его полностью? Я взял бы любой ответ в качестве решения. В настоящее время я только вижу его, когда я не хочу это.

1
задан 15.04.2013, 18:26

1 ответ

От ЖУРНАЛА ИЗМЕНЕНИЙ для bash-4.2-rc2:

Этот документ детализирует изменения между этой версией, bash-4.2-alpha, и предыдущей версией, bash-4.1-release.

q. Исправленный ошибка, которая заставила побочные точки с запятой быть добавленными в историю команд в определенных случаях.

tarball предвыпускной версии доступен здесь.

Править:

Вот некоторые частичные diffs между Bash 3.2 и Bash 4.2 RC2:

y.tab.c:

#if defined (HISTORY)                                                                                                                   #if defined (HISTORY)
/* A list of tokens which can be followed by newlines, but not by                                                                       /* A list of tokens which can be followed by newlines, but not by
   semi-colons.  When concatenating multiple lines of history, the                                                                         semi-colons.  When concatenating multiple lines of history, the
   newline separator for such tokens is replaced with a space. */                                                                          newline separator for such tokens is replaced with a space. */
static int no_semi_successors[] = {                                                                                                  |  static const int no_semi_successors[] = {
  '\n', '{', '(', ')', ';', '&', '|',                                                                                                     '\n', '{', '(', ')', ';', '&', '|',
  CASE, DO, ELSE, IF, SEMI_SEMI, THEN, UNTIL, WHILE, AND_AND, OR_OR, IN,                                                             |    CASE, DO, ELSE, IF, SEMI_SEMI, SEMI_AND, SEMI_SEMI_AND, THEN, UNTIL,
                                                                                                                                     >    WHILE, AND_AND, OR_OR, IN,
  0                                                                                                                                       0
};                                                                                                                                      };

/* If we are not within a delimited expression, try to be smart                                                                         /* If we are not within a delimited expression, try to be smart
   about which separators can be semi-colons and which must be                                                                             about which separators can be semi-colons and which must be
   newlines.  Returns the string that should be added into the                                                                             newlines.  Returns the string that should be added into the
   history entry. */                                                                                                                 |     history entry.  LINE is the line we're about to add; it helps
                                                                                                                                     >     make some more intelligent decisions in certain cases. */
char *                                                                                                                                  char *
history_delimiting_chars ()                                                                                                          |  history_delimiting_chars (line)
                                                                                                                                     >       const char *line;
{                                                                                                                                       {
                                                                                                                                     >    static int last_was_heredoc = 0;      /* was the last entry the start of a here document? */
  register int i;                                                                                                                         register int i;

                                                                                                                                     >    if ((parser_state & PST_HEREDOC) == 0)
                                                                                                                                     >      last_was_heredoc = 0;
                                                                                                                                     >
  if (dstack.delimiter_depth != 0)                                                                                                        if (dstack.delimiter_depth != 0)
    return ("\n");                                                                                                                          return ("\n");
                                                                                                                                     |
                                                                                                                                     >    /* We look for current_command_line_count == 2 because we are looking to
                                                                                                                                     >       add the first line of the body of the here document (the second line
                                                                                                                                     >       of the command).  We also keep LAST_WAS_HEREDOC as a private sentinel
                                                                                                                                     >       variable to note when we think we added the first line of a here doc
                                                                                                                                     >       (the one with a "<<" somewhere in it) */
                                                                                                                                     >    if (parser_state & PST_HEREDOC)
                                                                                                                                     >      {
                                                                                                                                     >        if (last_was_heredoc)
                                                                                                                                     >          {
                                                                                                                                     >            last_was_heredoc = 0;
                                                                                                                                     >            return "\n";
                                                                                                                                     >          }
                                                                                                                                     >        return (current_command_line_count == 2 ? "\n" : "");
                                                                                                                                     >      }
                                                                                                                                     >
  /* First, handle some special cases. */                                                                                                 /* First, handle some special cases. */
  /*(*/                                                                                                                                   /*(*/
  /* If we just read `()', assume it's a function definition, and don't                                                                   /* If we just read `()', assume it's a function definition, and don't
     add a semicolon.  If the token before the `)' was not `(', and we're                                                                    add a semicolon.  If the token before the `)' was not `(', and we're
     not in the midst of parsing a case statement, assume it's a                                                                             not in the midst of parsing a case statement, assume it's a
     parenthesized command and add the semicolon. */                                                                                         parenthesized command and add the semicolon. */
  /*)(*/                                                                                                                                  /*)(*/
  if (token_before_that == ')')                                                                                                           if (token_before_that == ')')
    {                                                                                                                                       {
      if (two_tokens_ago == '(')        /*)*/   /* function def */                                                                            if (two_tokens_ago == '(')        /*)*/   /* function def */
        return " ";                                                                                                                             return " ";
      /* This does not work for subshells inside case statement                                                                               /* This does not work for subshells inside case statement
         command lists.  It's a suboptimal solution. */                                                                                          command lists.  It's a suboptimal solution. */
      else if (parser_state & PST_CASESTMT)     /* case statement pattern */                                                                  else if (parser_state & PST_CASESTMT)     /* case statement pattern */
        return " ";                                                                                                                             return " ";
      else                                                                                                                                    else
        return "; ";                            /* (...) subshell */                                                                            return "; ";                            /* (...) subshell */
    }                                                                                                                                       }
  else if (token_before_that == WORD && two_tokens_ago == FUNCTION)                                                                       else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
    return " ";         /* function def using `function name' without `()' */                                                               return " ";         /* function def using `function name' without `()' */

                                                                                                                                     >    /* If we're not in a here document, but we think we're about to parse one,
                                                                                                                                     >       and we would otherwise return a `;', return a newline to delimit the
                                                                                                                                     >       line with the here-doc delimiter */
                                                                                                                                     >    else if ((parser_state & PST_HEREDOC) == 0 && current_command_line_count > 1 && last_read_token == '\n' && strstr (line, "<<"))
                                                                                                                                     >      {
                                                                                                                                     >        last_was_heredoc = 1;
                                                                                                                                     >        return "\n";
                                                                                                                                     >      }
                                                                                                                                     >
  else if (token_before_that == WORD && two_tokens_ago == FOR)                                                                            else if (token_before_that == WORD && two_tokens_ago == FOR)
    {                                                                                                                                       {
      /* Tricky.  `for i\nin ...' should not have a semicolon, but                                                                            /* Tricky.  `for i\nin ...' should not have a semicolon, but
         `for i\ndo ...' should.  We do what we can. */                                                                                          `for i\ndo ...' should.  We do what we can. */
      for (i = shell_input_line_index; whitespace(shell_input_line[i]); i++)                                                         |        for (i = shell_input_line_index; whitespace (shell_input_line[i]); i++)
        ;                                                                                                                                       ;
      if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')                                                  if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
        return " ";                                                                                                                             return " ";
      return ";";                                                                                                                             return ";";
    }                                                                                                                                       }
  else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))                                          else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))
    return " ";                                                                                                                             return " ";

  for (i = 0; no_semi_successors[i]; i++)                                                                                                 for (i = 0; no_semi_successors[i]; i++)
    {                                                                                                                                       {
      if (token_before_that == no_semi_successors[i])                                                                                         if (token_before_that == no_semi_successors[i])
        return (" ");                                                                                                                           return (" ");
    }                                                                                                                                       }

  return ("; ");                                                                                                                          return ("; ");
}                                                                                                                                       }
#endif /* HISTORY */                                                                                                                    #endif /* HISTORY */

bashhist.c:

/* Add a line to the history list.                                                                                                      /* Add a line to the history list.
   The variable COMMAND_ORIENTED_HISTORY controls the style of history                                                                     The variable COMMAND_ORIENTED_HISTORY controls the style of history
   remembering;  when non-zero, and LINE is not the first line of a                                                                        remembering;  when non-zero, and LINE is not the first line of a
   complete parser construct, append LINE to the last history line instead                                                                 complete parser construct, append LINE to the last history line instead
   of adding it as a new line. */                                                                                                          of adding it as a new line. */
void                                                                                                                                    void
bash_add_history (line)                                                                                                                 bash_add_history (line)
     char *line;                                                                                                                             char *line;
{                                                                                                                                       {
  int add_it, offset, curlen;                                                                                                             int add_it, offset, curlen;
  HIST_ENTRY *current, *old;                                                                                                              HIST_ENTRY *current, *old;
  char *chars_to_add, *new_line;                                                                                                          char *chars_to_add, *new_line;

  add_it = 1;                                                                                                                             add_it = 1;
  if (command_oriented_history && current_command_line_count > 1)                                                                         if (command_oriented_history && current_command_line_count > 1)
    {                                                                                                                                       {
      chars_to_add = literal_history ? "\n" : history_delimiting_chars ();                                                           |        chars_to_add = literal_history ? "\n" : history_delimiting_chars (line);

      using_history ();                                                                                                                       using_history ();
      current = previous_history ();                                                                                                          current = previous_history ();

      if (current)                                                                                                                            if (current)
        {                                                                                                                                       {
          /* If the previous line ended with an escaped newline (escaped                                                                          /* If the previous line ended with an escaped newline (escaped
             with backslash, but otherwise unquoted), then remove the quoted                                                                         with backslash, but otherwise unquoted), then remove the quoted
             newline, since that is what happens when the line is parsed. */                                                                         newline, since that is what happens when the line is parsed. */
          curlen = strlen (current->line);                                                                                                        curlen = strlen (current->line);

          if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' &&                                                                 if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' &&
              current->line[curlen - 2] != '\\')                                                                                                      current->line[curlen - 2] != '\\')
            {                                                                                                                                       {
              current->line[curlen - 1] = '\0';                                                                                                       current->line[curlen - 1] = '\0';
              curlen--;                                                                                                                               curlen--;
              chars_to_add = "";                                                                                                                      chars_to_add = "";
            }                                                                                                                                       }

                                                                                                                                     >            /* If we're not in some kind of quoted construct, the current history
                                                                                                                                     >               entry ends with a newline, and we're going to add a semicolon,
                                                                                                                                     >               don't.  In some cases, it results in a syntax error (e.g., before
                                                                                                                                     >               a close brace), and it should not be needed. */
                                                                                                                                     >            if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\n' && *chars_to_add == ';')
                                                                                                                                     >              chars_to_add++;
                                                                                                                                     >
          new_line = (char *)xmalloc (1                                                                                                           new_line = (char *)xmalloc (1
                                      + curlen                                                                                                                                + curlen
                                      + strlen (line)                                                                                                                         + strlen (line)
                                      + strlen (chars_to_add));                                                                                                               + strlen (chars_to_add));
          sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);                                                                        sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
          offset = where_history ();                                                                                                              offset = where_history ();
          old = replace_history_entry (offset, new_line, current->data);                                                                          old = replace_history_entry (offset, new_line, current->data);
          free (new_line);                                                                                                                        free (new_line);

          if (old)                                                                                                                                if (old)
            free_history_entry (old);                                                                                                               free_history_entry (old);

          add_it = 0;                                                                                                                             add_it = 0;
        }                                                                                                                                       }
    }                                                                                                                                       }

  if (add_it)                                                                                                                             if (add_it)
    really_add_history (line);                                                                                                              really_add_history (line);

                                                                                                                                     >  #if defined (SYSLOG_HISTORY)
                                                                                                                                     >    bash_syslog_history (line);
                                                                                                                                     >  #endif
                                                                                                                                     >
  using_history ();                                                                                                                       using_history ();
}                                                                                                                                       }
0
ответ дан 24.11.2019, 01:12

Теги

Похожие вопросы