changeset 24232:e0bcd17ac070

smart indentation for selections or current line in code editor * file-editor.h, file-editor.cc (file_editor::fetab_smart_indent_line_or_selected_text): New signal. (file_editor::request_smart_indent_line_or_selected_text): New slot. (file_editor::m_smart_indent_line_or_selection_action): New menu action. (file_editor::construct): Create action. (file_editor::check_actions): Enable it. (file_editor::set_shortcuts): Define a shortcut for it. (file_editor::add_file_editor_tab): Connect fetab_smart_indent_line_or_selected_text signal to smart_indent_line_or_selected_text slot. * file-editor-tab.h, file-editor-tab.cc (file_editor_tab::smart_indent_line_or_selected_text): New slot. (file_editor_tab::do_smart_indent_line_or_selected_text): New function. * octave-qscintilla.h, octave-qscintilla.cc (octave_qscintilla::smart_indent_line_or_selected_text): New function.
author John W. Eaton <jwe@octave.org>
date Tue, 14 Nov 2017 16:52:42 -0500
parents 6bd7d2eb6434
children ec837ef7ee3b
files libgui/src/m-editor/file-editor-tab.cc libgui/src/m-editor/file-editor-tab.h libgui/src/m-editor/file-editor.cc libgui/src/m-editor/file-editor.h libgui/src/m-editor/octave-qscintilla.cc libgui/src/m-editor/octave-qscintilla.h
diffstat 6 files changed, 123 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/m-editor/file-editor-tab.cc	Thu Apr 06 13:30:47 2017 +0200
+++ b/libgui/src/m-editor/file-editor-tab.cc	Tue Nov 14 16:52:42 2017 -0500
@@ -1208,6 +1208,15 @@
 }
 
 void
+file_editor_tab::smart_indent_line_or_selected_text (const QWidget *ID)
+{
+  if (ID != this)
+    return;
+
+  do_smart_indent_line_or_selected_text ();
+}
+
+void
 file_editor_tab::convert_eol (const QWidget *ID, QsciScintilla::EolMode eol_mode)
 {
   if (ID != this)
@@ -1423,6 +1432,34 @@
 }
 
 void
+file_editor_tab::do_smart_indent_line_or_selected_text (void)
+{
+  _edit_area->beginUndoAction ();
+
+  int lineFrom, lineTo;
+
+  if (_edit_area->hasSelectedText ())
+    {
+      int colFrom, colTo;
+      _edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo);
+
+      if (colTo == 0)  // the beginning of last line is not selected
+        lineTo--;        // stop at line above
+    }
+  else
+    {
+      int col;
+      _edit_area->getCursorPosition (&lineFrom, &col);
+
+      lineTo = lineFrom;
+    }
+
+  _edit_area->smart_indent_line_or_selected_text (lineFrom, lineTo);
+
+  _edit_area->endUndoAction ();
+}
+
+void
 file_editor_tab::do_comment_selected_text (bool comment)
 {
   QString comment_str = _edit_area->comment_string ();
--- a/libgui/src/m-editor/file-editor-tab.h	Thu Apr 06 13:30:47 2017 +0200
+++ b/libgui/src/m-editor/file-editor-tab.h	Tue Nov 14 16:52:42 2017 -0500
@@ -108,6 +108,7 @@
 
   void indent_selected_text (const QWidget *ID);
   void unindent_selected_text (const QWidget *ID);
+  void smart_indent_line_or_selected_text (const QWidget *ID);
   void convert_eol (const QWidget *ID, QsciScintilla::EolMode);
 
   void zoom_in (const QWidget *ID);
@@ -250,6 +251,7 @@
   int check_file_modified ();
   void do_comment_selected_text (bool comment);
   void do_indent_selected_text (bool indent);
+  void do_smart_indent_line_or_selected_text (void);
 
   void add_breakpoint_callback (const bp_info& info);
   void remove_breakpoint_callback (const bp_info& info);
--- a/libgui/src/m-editor/file-editor.cc	Thu Apr 06 13:30:47 2017 +0200
+++ b/libgui/src/m-editor/file-editor.cc	Tue Nov 14 16:52:42 2017 -0500
@@ -263,6 +263,7 @@
   m_uncomment_selection_action->setEnabled (have_tabs);
   m_indent_selection_action->setEnabled (have_tabs);
   m_unindent_selection_action->setEnabled (have_tabs);
+  m_smart_indent_line_or_selection_action->setEnabled (have_tabs);
 
   m_context_help_action->setEnabled (have_tabs);
   m_context_doc_action->setEnabled (have_tabs);
@@ -797,6 +798,12 @@
 }
 
 void
+file_editor::request_smart_indent_line_or_selected_text ()
+{
+  emit fetab_smart_indent_line_or_selected_text (m_tab_widget->currentWidget ());
+}
+
+void
 file_editor::request_conv_eol_windows (bool)
 {
   emit fetab_convert_eol (m_tab_widget->currentWidget (),
@@ -1209,6 +1216,7 @@
   shortcut_manager::set_shortcut (m_lower_case_action, "editor_edit:lower_case");
   shortcut_manager::set_shortcut (m_indent_selection_action, "editor_edit:indent_selection");
   shortcut_manager::set_shortcut (m_unindent_selection_action, "editor_edit:unindent_selection");
+  shortcut_manager::set_shortcut (m_smart_indent_line_or_selection_action, "editor_edit:smart_indent_line_or_selection");
   shortcut_manager::set_shortcut (m_completion_action, "editor_edit:completion_list");
   shortcut_manager::set_shortcut (m_goto_line_action, "editor_edit:goto_line");
   shortcut_manager::set_shortcut (m_move_to_matching_brace, "editor_edit:move_to_brace");
@@ -1844,9 +1852,13 @@
   m_edit_fmt_menu->addSeparator ();
 
   m_indent_selection_action = add_action (m_edit_fmt_menu, QIcon (),
-          tr ("&Indent"), SLOT (request_indent_selected_text (bool)));
+          tr ("&Indent Selection Rigidly"), SLOT (request_indent_selected_text (bool)));
   m_unindent_selection_action = add_action (m_edit_fmt_menu, QIcon (),
-          tr ("&Unindent"), SLOT (request_unindent_selected_text (bool)));
+          tr ("&Unindent Selection Rigidly"), SLOT (request_unindent_selected_text (bool)));
+
+  m_smart_indent_line_or_selection_action
+    = add_action (m_edit_fmt_menu, QIcon (),
+          tr ("Indent Code"), SLOT (request_smart_indent_line_or_selected_text (void)));
 
   m_edit_fmt_menu->addSeparator ();
 
@@ -2219,6 +2231,9 @@
   connect (this, SIGNAL (fetab_unindent_selected_text (const QWidget*)),
            f, SLOT (unindent_selected_text (const QWidget*)));
 
+  connect (this, SIGNAL (fetab_smart_indent_line_or_selected_text (const QWidget*)),
+           f, SLOT (smart_indent_line_or_selected_text (const QWidget*)));
+
   connect (this,
            SIGNAL (fetab_convert_eol (const QWidget*, QsciScintilla::EolMode)),
            f, SLOT (convert_eol (const QWidget*, QsciScintilla::EolMode)));
--- a/libgui/src/m-editor/file-editor.h	Thu Apr 06 13:30:47 2017 +0200
+++ b/libgui/src/m-editor/file-editor.h	Tue Nov 14 16:52:42 2017 -0500
@@ -173,6 +173,7 @@
   void fetab_uncomment_selected_text (const QWidget *ID);
   void fetab_indent_selected_text (const QWidget *ID);
   void fetab_unindent_selected_text (const QWidget *ID);
+  void fetab_smart_indent_line_or_selected_text (const QWidget *ID);
   void fetab_convert_eol (const QWidget *ID, QsciScintilla::EolMode eol_mode);
   void fetab_find (const QWidget *ID, QList<QAction *>);
   void fetab_find_next (const QWidget *ID);
@@ -251,6 +252,7 @@
   void request_lower_case (bool);
   void request_indent_selected_text (bool);
   void request_unindent_selected_text (bool);
+  void request_smart_indent_line_or_selected_text (void);
   void request_conv_eol_windows (bool);
   void request_conv_eol_unix (bool);
   void request_conv_eol_mac (bool);
@@ -377,6 +379,7 @@
   QAction *m_uncomment_selection_action;
   QAction *m_indent_selection_action;
   QAction *m_unindent_selection_action;
+  QAction *m_smart_indent_line_or_selection_action;
   QAction *m_conv_eol_windows_action;
   QAction *m_conv_eol_unix_action;
   QAction *m_conv_eol_mac_action;
--- a/libgui/src/m-editor/octave-qscintilla.cc	Thu Apr 06 13:30:47 2017 +0200
+++ b/libgui/src/m-editor/octave-qscintilla.cc	Tue Nov 14 16:52:42 2017 -0500
@@ -558,7 +558,69 @@
         }
       return;
     }
+}
 
+// Do smart indendation of current selection or line.
+void
+octave_qscintilla::smart_indent_line_or_selected_text (int lineFrom, int lineTo)
+{
+  QRegExp blank_line_regexp = QRegExp ("^[\t ]*$");
+
+  QRegExp begin_block_regexp
+    = QRegExp ("^([\t ]*)(if|elseif|else"
+               "|for|while|do|parfor"
+               "|switch|case|otherwise"
+               "|function"
+               "|classdef|properties|events|enumeration|methods"
+               "|unwind_protect|unwind_protect_cleanup|try|catch)"
+               "[\r\n\t #%]");
+
+  QRegExp end_block_regexp
+    = QRegExp ("^([\t ]*)(end"
+               "|end(for|function|if|parfor|switch|while"
+               "|classdef|enumeration|events|methods|properties)"
+               "|end_(try_catch|unwind_protect)"
+               "|until)"
+               "[\r\n\t #%]");
+
+  int indent_column = -1;
+  int indent_increment = indentationWidth ();
+
+  for (int line = lineFrom-1; line >= 0; line--)
+    {
+      QString line_text = text (line);
+
+      if (blank_line_regexp.indexIn (line_text) < 0)
+        {
+          // Found first non-blank line above beginning of region or
+          // current line.  Base indentation from this line, increasing
+          // indentation by indentationWidth if it looks like the
+          // beginning of a code block.
+
+          indent_column = indentation (line);
+
+          if (begin_block_regexp.indexIn (line_text) > -1)
+            indent_column += indent_increment;
+
+          break;
+        }
+    }
+
+  if (indent_column < 0)
+    indent_column = indentation (lineFrom);
+
+  for (int line = lineFrom; line <= lineTo; line++)
+    {
+      QString line_text = text (line);
+
+      if (end_block_regexp.indexIn (line_text) > -1)
+        indent_column -= indent_increment;
+
+      setIndentation (line, indent_column);
+
+      if (begin_block_regexp.indexIn (line_text) > -1)
+        indent_column += indent_increment;
+    }
 }
 
 void
--- a/libgui/src/m-editor/octave-qscintilla.h	Thu Apr 06 13:30:47 2017 +0200
+++ b/libgui/src/m-editor/octave-qscintilla.h	Tue Nov 14 16:52:42 2017 -0500
@@ -63,6 +63,8 @@
   int is_style_comment (int pos = -1);
   void smart_indent (bool do_smart_indent, int do_auto_close, int line);
 
+  void smart_indent_line_or_selected_text (int lineFrom, int lineTo);
+
   void set_word_selection (const QString& word = QString ());
 
   void show_selection_markers (int line, int col, int len);