Re: [pgAdmin][RM4631] PgAdmin IV browser locks up when trying to undo an edit

Dave Page <[email protected]>
Newsgroups gmane.comp.db.postgresql.pgadmin.devel
Message-ID <CA+OCxoyLoGP4NVgzuvnGqavie3mdiL4J1MPu4dr+KPxdDy02Fw@mail.gmail.com>
Hi

On Mon, Sep 2, 2019 at 11:05 AM Aditya Toshniwal <
[email protected]> wrote:

> Hi Hackers,
>
> Attached is the patch to:
> 1) Optimise code folding code for better performance.
> 2) Moved all editor related preferences like Font size, Tab size, Brace
> matching, etc. from options to a new category "Editor" .
> 3) Added two new preferences - Plain editor mode (text/plain), Disable
> code folding.
> 4) Codemirror has its own limitations and lags for long text line. Using
> plain editor mode will help improve the speed as it does not have the
> overhead of syntax highlighting and code folding. Optionally, one can
> disable code folding in normal SQL mode.
>

Cool. Attached is an update which tweaks the strings on the Preferences
panel. You'll find that useful when you add the missing screenshots and doc
updates :-)

Thanks!

-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
RM4631_v2.patch (application/octet-stream, 11.3 KB)
diff --git a/web/pgadmin/static/js/codemirror/addon/fold/pgadmin-sqlfoldcode.js b/web/pgadmin/static/js/codemirror/addon/fold/pgadmin-sqlfoldcode.js
index 595c7dc7..b5a3520c 100644
--- a/web/pgadmin/static/js/codemirror/addon/fold/pgadmin-sqlfoldcode.js
+++ b/web/pgadmin/static/js/codemirror/addon/fold/pgadmin-sqlfoldcode.js
@@ -17,21 +17,30 @@
 })(function(CodeMirror) {
   'use strict';
 
-  CodeMirror.pgadminKeywordRangeFinder = function(cm, start, startTkn, endTkn) {
+  var pgadminKeywordRangeFinder = function(cm, start, tokenSet) {
     var line = start.line,
       lineText = cm.getLine(line);
     var at = lineText.length,
       startChar, tokenType;
+
+    let tokenSetNo = 0;
+    let startTkn = tokenSet[tokenSetNo].start,
+      endTkn = tokenSet[tokenSetNo].end;
     for (; at > 0;) {
       var found = lineText.lastIndexOf(startTkn, at);
       var startToken = startTkn;
       var endToken = endTkn;
 
       if (found < start.ch) {
-        found = lineText.lastIndexOf('[', at);
-        if (found < start.ch) break;
-        startToken = '[';
-        endToken = ']';
+        /* If the start token is not found then search for the next set of token */
+        tokenSetNo++;
+        if(tokenSetNo >= tokenSet.length) {
+          return undefined;
+        }
+        startTkn = tokenSet[tokenSetNo].start;
+        endTkn = tokenSet[tokenSetNo].end;
+        at = lineText.length;
+        continue;
       }
 
       tokenType = cm.getTokenAt(CodeMirror.Pos(line, found + 1)).type;
@@ -73,32 +82,13 @@
     };
   };
 
-  CodeMirror.pgadminBeginRangeFinder = function(cm, start) {
-    var startToken = 'BEGIN';
-    var endToken = 'END;';
-    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
+  CodeMirror.registerHelper('fold', 'sql', function(cm, start) {
+    var fromToPos = pgadminKeywordRangeFinder(cm, start, [
+      {start: 'BEGIN', end:'END;'},
+      {start: 'IF', end:'END IF'},
+      {start: 'LOOP', end:'END LOOP'},
+      {start: 'CASE', end:'END CASE'},
+    ]);
     return fromToPos;
-  };
-
-  CodeMirror.pgadminIfRangeFinder = function(cm, start) {
-    var startToken = 'IF';
-    var endToken = 'END IF';
-    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
-    return fromToPos;
-  };
-
-  CodeMirror.pgadminLoopRangeFinder = function(cm, start) {
-    var startToken = 'LOOP';
-    var endToken = 'END LOOP';
-    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
-    return fromToPos;
-  };
-
-  CodeMirror.pgadminCaseRangeFinder = function(cm, start) {
-    var startToken = 'CASE';
-    var endToken = 'END CASE';
-    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
-    return fromToPos;
-  };
-
+  });
 });
diff --git a/web/pgadmin/static/js/sqleditor/query_tool_preferences.js b/web/pgadmin/static/js/sqleditor/query_tool_preferences.js
index 491f0ca9..8e74e65d 100644
--- a/web/pgadmin/static/js/sqleditor/query_tool_preferences.js
+++ b/web/pgadmin/static/js/sqleditor/query_tool_preferences.js
@@ -182,6 +182,15 @@ function updateUIPreferences(sqlEditor) {
   let sql_font_size = SqlEditorUtils.calcFontSize(preferences.sql_font_size);
   $(sqlEditor.query_tool_obj.getWrapperElement()).css('font-size', sql_font_size);
 
+  if(preferences.plain_editor_mode) {
+    sqlEditor.query_tool_obj.setOption('mode', 'text/plain');
+    /* Although not required, setting explicitly as codemirror will remove code folding only on next edit */
+    sqlEditor.query_tool_obj.setOption('foldGutter', false);
+  } else {
+    sqlEditor.query_tool_obj.setOption('mode', sqlEditor.handler.server_type === 'gpdb' ? 'text/x-gpsql' : 'text/x-pgsql');
+    sqlEditor.query_tool_obj.setOption('foldGutter', preferences.code_folding);
+  }
+  sqlEditor.query_tool_obj.setOption('foldGutter', preferences.code_folding);
   sqlEditor.query_tool_obj.setOption('indentWithTabs', !preferences.use_spaces);
   sqlEditor.query_tool_obj.setOption('indentUnit', preferences.tab_size);
   sqlEditor.query_tool_obj.setOption('tabSize', preferences.tab_size);
diff --git a/web/pgadmin/tools/debugger/static/js/direct.js b/web/pgadmin/tools/debugger/static/js/direct.js
index 123b9cf1..b7ee19c8 100644
--- a/web/pgadmin/tools/debugger/static/js/direct.js
+++ b/web/pgadmin/tools/debugger/static/js/direct.js
@@ -1792,14 +1792,7 @@ define([
           foldOptions: {
             widget: '\u2026',
           },
-          foldGutter: {
-            rangeFinder: CodeMirror.fold.combine(
-              CodeMirror.pgadminBeginRangeFinder,
-              CodeMirror.pgadminIfRangeFinder,
-              CodeMirror.pgadminLoopRangeFinder,
-              CodeMirror.pgadminCaseRangeFinder
-            ),
-          },
+          foldGutter: true,
           gutters: [
             'CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'breakpoints',
           ],
diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
index 905f8422..f6fbadf3 100644
--- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
@@ -356,14 +356,7 @@ define('tools.querytool', [
         foldOptions: {
           widget: '\u2026',
         },
-        foldGutter: {
-          rangeFinder: CodeMirror.fold.combine(
-            CodeMirror.pgadminBeginRangeFinder,
-            CodeMirror.pgadminIfRangeFinder,
-            CodeMirror.pgadminLoopRangeFinder,
-            CodeMirror.pgadminCaseRangeFinder
-          ),
-        },
+        foldGutter: true,
         gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
         extraKeys: pgBrowser.editor_shortcut_keys,
         scrollbarStyle: 'simple',
diff --git a/web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py b/web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py
index 12e5f363..079f9e72 100644
--- a/web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py
+++ b/web/pgadmin/tools/sqleditor/utils/query_tool_preferences.py
@@ -90,8 +90,61 @@ def RegisterQueryToolPreferences(self):
                          'Tool tabs.')
     )
 
+    self.show_prompt_save_query_changes = self.preference.register(
+        'Options', 'prompt_save_query_changes',
+        gettext("Prompt to save unsaved query changes?"), 'boolean', True,
+        category_label=gettext('Options'),
+        help_str=gettext(
+            'Specifies whether or not to prompt user to save unsaved '
+            'query on query tool exit.'
+        )
+    )
+
+    self.show_prompt_save_data_changes = self.preference.register(
+        'Options', 'prompt_save_data_changes',
+        gettext("Prompt to save unsaved data changes?"), 'boolean', True,
+        category_label=gettext('Options'),
+        help_str=gettext(
+            'Specifies whether or not to prompt user to save unsaved '
+            'data on data grid exit.'
+        )
+    )
+
+    self.show_prompt_commit_transaction = self.preference.register(
+        'Options', 'prompt_commit_transaction',
+        gettext("Prompt to commit/rollback active transactions?"), 'boolean',
+        True,
+        category_label=gettext('Options'),
+        help_str=gettext(
+            'Specifies whether or not to prompt user to commit or rollback '
+            'an active transaction on Query Tool exit.'
+        )
+    )
+
+    self.sql_font_size = self.preference.register(
+        'Editor', 'plain_editor_mode',
+        gettext("Plain text mode?"), 'boolean', False,
+        category_label=gettext('Editor'),
+        help_str=gettext(
+            'When set to True, keywords won''t be highlighted and code '
+            'folding will be disabled. Plain text mode will improve editor '
+            'performance with large files.'
+        )
+    )
+
     self.sql_font_size = self.preference.register(
-        'Options', 'sql_font_size',
+        'Editor', 'code_folding',
+        gettext("Code folding?"), 'boolean', True,
+        category_label=gettext('Editor'),
+        help_str=gettext(
+            'Enable or disable code folding. In plain text mode, this will '
+            'have no effect as code folding is always disabled in that mode. '
+            'Disabling will improve editor performance with large files.'
+        )
+    )
+
+    self.sql_font_size = self.preference.register(
+        'Editor', 'sql_font_size',
         gettext("Font size"), 'numeric', '1',
         min_val=0.1,
         max_val=10,
@@ -106,7 +159,7 @@ def RegisterQueryToolPreferences(self):
     )
 
     self.tab_size = self.preference.register(
-        'Options', 'tab_size',
+        'Editor', 'tab_size',
         gettext("Tab size"), 'integer', 4,
         min_val=2,
         max_val=8,
@@ -117,7 +170,7 @@ def RegisterQueryToolPreferences(self):
     )
 
     self.use_spaces = self.preference.register(
-        'Options', 'use_spaces',
+        'Editor', 'use_spaces',
         gettext("Use spaces?"), 'boolean', False,
         category_label=gettext('Options'),
         help_str=gettext(
@@ -127,7 +180,7 @@ def RegisterQueryToolPreferences(self):
     )
 
     self.wrap_code = self.preference.register(
-        'Options', 'wrap_code',
+        'Editor', 'wrap_code',
         gettext("Line wrapping?"), 'boolean', False,
         category_label=gettext('Options'),
         help_str=gettext(
@@ -136,7 +189,7 @@ def RegisterQueryToolPreferences(self):
     )
 
     self.insert_pair_brackets = self.preference.register(
-        'Options', 'insert_pair_brackets',
+        'Editor', 'insert_pair_brackets',
         gettext("Insert bracket pairs?"), 'boolean', True,
         category_label=gettext('Options'),
         help_str=gettext(
@@ -146,7 +199,7 @@ def RegisterQueryToolPreferences(self):
     )
 
     self.brace_matching = self.preference.register(
-        'Options', 'brace_matching',
+        'Editor', 'brace_matching',
         gettext("Brace matching?"), 'boolean', True,
         category_label=gettext('Options'),
         help_str=gettext(
@@ -155,37 +208,6 @@ def RegisterQueryToolPreferences(self):
         )
     )
 
-    self.show_prompt_save_query_changes = self.preference.register(
-        'Options', 'prompt_save_query_changes',
-        gettext("Prompt to save unsaved query changes?"), 'boolean', True,
-        category_label=gettext('Options'),
-        help_str=gettext(
-            'Specifies whether or not to prompt user to save unsaved '
-            'query on query tool exit.'
-        )
-    )
-
-    self.show_prompt_save_data_changes = self.preference.register(
-        'Options', 'prompt_save_data_changes',
-        gettext("Prompt to save unsaved data changes?"), 'boolean', True,
-        category_label=gettext('Options'),
-        help_str=gettext(
-            'Specifies whether or not to prompt user to save unsaved '
-            'data on data grid exit.'
-        )
-    )
-
-    self.show_prompt_commit_transaction = self.preference.register(
-        'Options', 'prompt_commit_transaction',
-        gettext("Prompt to commit/rollback active transactions?"), 'boolean',
-        True,
-        category_label=gettext('Options'),
-        help_str=gettext(
-            'Specifies whether or not to prompt user to commit or rollback '
-            'an active transaction on Query Tool exit.'
-        )
-    )
-
     self.csv_quoting = self.preference.register(
         'CSV_output', 'csv_quoting',
         gettext("CSV quoting"), 'options', 'strings',
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.