octave-bug-tracker
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Octave-bug-tracker] [bug #56160] editor: inappropriate auto insert of "


From: Rik
Subject: [Octave-bug-tracker] [bug #56160] editor: inappropriate auto insert of "end*" when inserting newlines after keyword
Date: Thu, 18 Apr 2019 19:07:13 -0400 (EDT)
User-agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko

Follow-up Comment #8, bug #56160 (project octave):

Don't have a fix, but I found the problematic code.  The code which
automatically closes (adds "endXXX") a keyword is in
libgui/src/m-editor/octave-qscintilla.cc.  Quoting it:


void octave_qscintilla::auto_close (int auto_endif, int linenr,
                                    const QString& line, QString& first_word)
{
  // Insert and "end" for an "if" etc., if needed.
  // (Use of "while" allows "return" to skip the rest.
  // It may be clearer to use "if" and "goto",
  // but that violates the coding standards.)

  bool autofill_simple_end = (auto_endif == 2);

  size_t start = line.toStdString ().find_first_not_of (" \t");

  // Check if following line has the same or less indentation
  // Check if the following line does not start with
  //       end* (until) (catch)
  if (linenr < lines () - 1)
    {
      int offset = 1;
      size_t next_start;
      QString next_line;
      do                            // find next non-blank line
        {
          next_line = text (linenr + offset++);
          next_start = next_line.toStdString ().find_first_not_of (" \t\n");
        }
      while (linenr + offset < lines ()
             && next_start == std::string::npos);
      if (next_start == std::string::npos)
        next_start = 0;
      if (next_start > start)       // more indented => don't add "end"
        return;
      if (next_start == start)      // same => check if already is "end"
        {
          QRegExp rx_start = QRegExp (R"((\w+))");
          int tmp = rx_start.indexIn (next_line, start);
          if (tmp != -1 && is_end (rx_start.cap(1), first_word))
            return;
        }
    }

  // If all of the above, insert a new line, with matching indent
  // and either 'end' or 'end...', depending on a flag.

  // If we insert directly after the last line, the "end" is autoindented,
  // so add a dummy line.
  if (linenr + 2 == lines ())
    insertAt (QString ("\n"), linenr + 2, 0);

  // For try/catch/end, fill "end" first, so "catch" is top of undo stack
  if (first_word == "try")
    insertAt (QString (start, ' ')
              + (autofill_simple_end ? "end\n" : "end_try_catch\n"),
              linenr + 2, 0);
  else if (first_word == "unwind_protect")
    insertAt (QString (start, ' ')
              + (autofill_simple_end ? "end\n" : "end_unwind_protect\n"),
              linenr + 2, 0);

  QString next_line;
  if (first_word == "do")
    next_line = "until\n";
  else if (first_word == "try")
    next_line = "catch\n";
  else if (first_word == "unwind_protect")
    next_line = "unwind_protect_cleanup\n";
  else if (autofill_simple_end)
    next_line = "end\n";
  else
    {
      if (first_word == "unwind_protect")
        first_word = '_' + first_word;
      next_line = "end" + first_word + "\n";
    }

  insertAt (QString (start, ' ') + next_line, linenr + 2, 0);
}


When executed, the code searchs downwards from the line containing the keyword
looking for a non-blank line.  If this line is at a greater indent level, then
itassumes that the block has already been correctly constructed.  So, this is
correct


function foo

  x = 1;

endfunction


But if the indent is at the same level as the keyword it is checking then it
verifies that the first non-blank line is an end keyword.  This too is
correct


function foo

endfunction


If the the indent matches, and it is not an end keyword, then it closes the
expression.  So, the indentation of "x = 1;" fools the code in to thinking
that there is no "endfunction" and it adds one


function foo

endfunction

x = 1;

endfunction


This is somewhat clever in that the entire file does not need to be parsed,
but it can make mistakes as in this case.



    _______________________________________________________

Reply to this item at:

  <https://savannah.gnu.org/bugs/?56160>

_______________________________________________
  Message sent via Savannah
  https://savannah.gnu.org/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]