mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Add an option to auto-complete keywords in upper case. Fixes #2686
This commit is contained in:
parent
df7b4d55c6
commit
b48145f01f
BIN
docs/en_US/images/preferences_sql_auto_completion.png
Normal file
BIN
docs/en_US/images/preferences_sql_auto_completion.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 129 KiB |
@ -127,6 +127,13 @@ Please note: the default help paths include the *VERSION* placeholder; the $VERS
|
||||
|
||||
Expand the *SQL Editor* node to access panels that allow you to specify your preferences for the SQL Editor tool.
|
||||
|
||||
.. image:: images/preferences_sql_auto_completion.png
|
||||
:alt: Preferences dialog sqleditor auto completion option
|
||||
|
||||
Use the fields on the *Auto Completion* panel to set the auto completion options.
|
||||
|
||||
* When the *Keywords in uppercase* switch is set to *True* then keywords are shown in upper case.
|
||||
|
||||
.. image:: images/preferences_sql_csv_output.png
|
||||
:alt: Preferences dialog sqleditor csv output option
|
||||
|
||||
|
@ -11,6 +11,7 @@ Features
|
||||
********
|
||||
|
||||
| `Feature #1447 <https://redmine.postgresql.org/issues/1447>`_ - Add support for SSH tunneled connections
|
||||
| `Feature #2686 <https://redmine.postgresql.org/issues/2686>`_ - Add an option to auto-complete keywords in upper case
|
||||
| `Feature #3204 <https://redmine.postgresql.org/issues/3204>`_ - Add support for LISTEN/NOTIFY in the query tool
|
||||
| `Feature #3362 <https://redmine.postgresql.org/issues/3362>`_ - Function and procedure support for PG11
|
||||
|
||||
@ -36,5 +37,5 @@ Bug fixes
|
||||
| `Bug #3342 <https://redmine.postgresql.org/issues/3342>`_ - Set SESSION_COOKIE_SAMESITE='Lax' per Flask recommendation to prevents sending cookies with CSRF-prone requests from external sites, such as submitting a form
|
||||
| `Bug #3353 <https://redmine.postgresql.org/issues/3353>`_ - Handle errors properly if they occur when renaming a database
|
||||
| `Bug #3374 <https://redmine.postgresql.org/issues/3374>`_ - Fix autocomplete
|
||||
| `Bug #3392 <https://redmine.postgresql.org/issues/3392>`_ - Fix IPv6 support in the container build.
|
||||
| `Bug #3392 <https://redmine.postgresql.org/issues/3392>`_ - Fix IPv6 support in the container build
|
||||
| `Bug #3409 <https://redmine.postgresql.org/issues/3409>`_ - Avoid an exception on GreenPlum when retrieving RE-SQL on a table
|
@ -1,2 +1,7 @@
|
||||
{# SQL query for getting keywords #}
|
||||
{% if upper_case %}
|
||||
SELECT upper(word) as word FROM pg_get_keywords()
|
||||
{% else %}
|
||||
SELECT word FROM pg_get_keywords()
|
||||
{% endif %}
|
||||
|
||||
|
@ -136,6 +136,7 @@ function keyboardShortcutsQueryTool(
|
||||
let downloadCsvKeys = keyboardShortcutConfig['download_csv'];
|
||||
let nextPanelKeys = keyboardShortcutConfig['move_next'];
|
||||
let previousPanelKeys = keyboardShortcutConfig['move_previous'];
|
||||
let toggleCaseKeys = keyboardShortcutConfig['toggle_case'];
|
||||
|
||||
if (this.validateShortcutKeys(executeKeys, event)) {
|
||||
this._stopEventPropagation(event);
|
||||
@ -149,6 +150,9 @@ function keyboardShortcutsQueryTool(
|
||||
} else if (this.validateShortcutKeys(downloadCsvKeys, event)) {
|
||||
this._stopEventPropagation(event);
|
||||
queryToolActions.download(sqlEditorController);
|
||||
} else if (this.validateShortcutKeys(toggleCaseKeys, event)) {
|
||||
this._stopEventPropagation(event);
|
||||
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
||||
} else if ((
|
||||
(this.isMac() && event.metaKey) ||
|
||||
(!this.isMac() && event.ctrlKey)
|
||||
|
@ -132,6 +132,8 @@ let queryToolActions = {
|
||||
'sqleditor', 'move_next');
|
||||
let previousPanelPerf = window.top.pgAdmin.Browser.get_preference(
|
||||
'sqleditor', 'move_previous');
|
||||
let toggleCasePerf = window.top.pgAdmin.Browser.get_preference(
|
||||
'sqleditor', 'toggle_case');
|
||||
|
||||
if(!executeQueryPref && sqlEditorController.handler.is_new_browser_tab) {
|
||||
executeQueryPref = window.opener.pgAdmin.Browser.get_preference(
|
||||
@ -151,6 +153,9 @@ let queryToolActions = {
|
||||
),
|
||||
previousPanelPerf = window.opener.pgAdmin.Browser.get_preference(
|
||||
'sqleditor', 'move_previous'
|
||||
),
|
||||
toggleCasePerf = window.opener.pgAdmin.Browser.get_preference(
|
||||
'sqleditor', 'toggle_case'
|
||||
);
|
||||
}
|
||||
|
||||
@ -161,9 +166,23 @@ let queryToolActions = {
|
||||
'download_csv': downloadCsvPref.value,
|
||||
'move_next': nextPanelPerf.value,
|
||||
'move_previous': previousPanelPerf.value,
|
||||
'toggle_case': toggleCasePerf.value,
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
toggleCaseOfSelectedText: function (sqlEditorController) {
|
||||
let codeMirrorObj = sqlEditorController.gridView.query_tool_obj;
|
||||
let selectedText = codeMirrorObj.getSelection();
|
||||
|
||||
if (!selectedText) return;
|
||||
|
||||
if (selectedText === selectedText.toUpperCase()) {
|
||||
codeMirrorObj.replaceSelection(selectedText.toLowerCase());
|
||||
} else {
|
||||
codeMirrorObj.replaceSelection(selectedText.toUpperCase());
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = queryToolActions;
|
||||
|
@ -535,6 +535,32 @@ def RegisterQueryToolPreferences(self):
|
||||
fields=accesskey_fields
|
||||
)
|
||||
|
||||
self.preference.register(
|
||||
'keyboard_shortcuts',
|
||||
'toggle_case',
|
||||
gettext('Toggle case of selected text'),
|
||||
'keyboardshortcut',
|
||||
{
|
||||
'alt': False,
|
||||
'shift': True,
|
||||
'control': True,
|
||||
'key': {
|
||||
'key_code': 91,
|
||||
'char': 'u'
|
||||
}
|
||||
},
|
||||
category_label=gettext('Keyboard shortcuts'),
|
||||
fields=shortcut_fields
|
||||
)
|
||||
|
||||
self.preference.register(
|
||||
'auto_completion', 'keywords_in_uppercase',
|
||||
gettext("Keywords in uppercase"), 'boolean', True,
|
||||
category_label=gettext('Auto completion'),
|
||||
help_str=gettext('If set to True, Keywords will be displayed '
|
||||
'in upper case for auto completion.')
|
||||
)
|
||||
|
||||
|
||||
def get_query_tool_keyboard_shortcuts():
|
||||
|
||||
@ -564,6 +590,7 @@ def get_query_tool_keyboard_shortcuts():
|
||||
explain_query = qt_perf.preference('explain_query').get()
|
||||
explain_analyze_query = qt_perf.preference('explain_analyze_query').get()
|
||||
find_options = qt_perf.preference('btn_find_options').get()
|
||||
toggle_case = qt_perf.preference('toggle_case').get()
|
||||
|
||||
return {
|
||||
'keys': {
|
||||
@ -587,7 +614,8 @@ def get_query_tool_keyboard_shortcuts():
|
||||
'explain_analyze_query': explain_analyze_query.get('key').get(
|
||||
'char'
|
||||
),
|
||||
'find_options': find_options.get('key').get('char')
|
||||
'find_options': find_options.get('key').get('char'),
|
||||
'toggle_case': toggle_case.get('key').get('char')
|
||||
},
|
||||
'shortcuts': {
|
||||
'conn_status': conn_status,
|
||||
@ -608,7 +636,8 @@ def get_query_tool_keyboard_shortcuts():
|
||||
'execute_query': execute_query,
|
||||
'explain_query': explain_query,
|
||||
'explain_analyze_query': explain_analyze_query,
|
||||
'find_options': find_options
|
||||
'find_options': find_options,
|
||||
'toggle_case': toggle_case
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ from .function_metadata import FunctionMetadata
|
||||
from .parseutils import (
|
||||
last_word, extract_tables, find_prev_keyword, parse_partial_identifier)
|
||||
from .prioritization import PrevalenceCounter
|
||||
from pgadmin.utils.preferences import Preferences
|
||||
|
||||
PY2 = sys.version_info[0] == 2
|
||||
PY3 = sys.version_info[0] == 3
|
||||
@ -101,8 +102,17 @@ class SQLAutoComplete(object):
|
||||
for record in res['rows']:
|
||||
self.search_path.append(record['schema'])
|
||||
|
||||
pref = Preferences.module('sqleditor')
|
||||
keywords_in_uppercase = \
|
||||
pref.preference('keywords_in_uppercase').get()
|
||||
|
||||
# Fetch the keywords
|
||||
query = render_template("/".join([self.sql_path, 'keywords.sql']))
|
||||
# If setting 'Keywords in uppercase' is set to True in
|
||||
# Preferences then fetch the keywords in upper case.
|
||||
if keywords_in_uppercase:
|
||||
query = render_template(
|
||||
"/".join([self.sql_path, 'keywords.sql']), upper_case=True)
|
||||
status, res = self.conn.execute_dict(query)
|
||||
if status:
|
||||
for record in res['rows']:
|
||||
|
@ -11,7 +11,8 @@ import queryToolActions from 'sources/sqleditor/query_tool_actions';
|
||||
describe('queryToolActions', () => {
|
||||
let sqlEditorController,
|
||||
getSelectionSpy, getValueSpy,
|
||||
selectedQueryString, entireQueryString;
|
||||
selectedQueryString, entireQueryString,
|
||||
replaceSelectionSpy;
|
||||
|
||||
describe('executeQuery', () => {
|
||||
describe('when the command is being run from the query tool', () => {
|
||||
@ -437,9 +438,93 @@ describe('queryToolActions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleCaseOfSelectedText', () => {
|
||||
describe('when there is no query text', () => {
|
||||
beforeEach(() => {
|
||||
setUpSpies('', '');
|
||||
});
|
||||
it('does nothing', () => {
|
||||
expect(
|
||||
queryToolActions.toggleCaseOfSelectedText(sqlEditorController)
|
||||
).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there is empty selection', () => {
|
||||
beforeEach(() => {
|
||||
setUpSpies('', 'a string\nddd\nsss');
|
||||
|
||||
sqlEditorController.gridView.query_tool_obj.getCursor = (isFrom) => {
|
||||
return isFrom ? 3 : 3;
|
||||
};
|
||||
});
|
||||
|
||||
it('does nothing', () => {
|
||||
expect(
|
||||
queryToolActions.toggleCaseOfSelectedText(sqlEditorController)
|
||||
).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selected query is in lower case', () => {
|
||||
beforeEach(() => {
|
||||
setUpSpies('string', 'a string\nddd\nsss');
|
||||
});
|
||||
|
||||
it('toggle the selection and string should be in upper case', () => {
|
||||
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
||||
expect(replaceSelectionSpy
|
||||
).toHaveBeenCalledWith('STRING');
|
||||
});
|
||||
|
||||
it('(negative scenario toggle the selection and string should be in upper case', () => {
|
||||
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
||||
expect(replaceSelectionSpy
|
||||
).not.toHaveBeenCalledWith('string');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selected query is in upper case', () => {
|
||||
beforeEach(() => {
|
||||
setUpSpies('STRING', 'a string\nddd\nsss');
|
||||
});
|
||||
|
||||
it('toggle the selection and string should be in lower case', () => {
|
||||
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
||||
expect(replaceSelectionSpy
|
||||
).toHaveBeenCalledWith('string');
|
||||
});
|
||||
|
||||
it('(negative scenario toggle the selection and string should be in lower case', () => {
|
||||
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
||||
expect(replaceSelectionSpy
|
||||
).not.toHaveBeenCalledWith('STRING');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selected query is in mixed case', () => {
|
||||
beforeEach(() => {
|
||||
setUpSpies('sTRIng', 'a string\nddd\nsss');
|
||||
});
|
||||
|
||||
it('toggle the selection and string should be in upper case', () => {
|
||||
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
||||
expect(replaceSelectionSpy
|
||||
).toHaveBeenCalledWith('STRING');
|
||||
});
|
||||
|
||||
it('(negative scenario toggle the selection and string should be in upper case', () => {
|
||||
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
|
||||
expect(replaceSelectionSpy
|
||||
).not.toHaveBeenCalledWith('sTRIng');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function setUpSpies(selectedQueryString, entireQueryString) {
|
||||
getValueSpy = jasmine.createSpy('getValueSpy').and.returnValue(entireQueryString);
|
||||
getSelectionSpy = jasmine.createSpy('getSelectionSpy').and.returnValue(selectedQueryString);
|
||||
replaceSelectionSpy = jasmine.createSpy('replaceSelectionSpy');
|
||||
|
||||
sqlEditorController = {
|
||||
gridView: {
|
||||
@ -449,6 +534,7 @@ describe('queryToolActions', () => {
|
||||
toggleComment: jasmine.createSpy('toggleCommentSpy'),
|
||||
lineComment: jasmine.createSpy('lineCommentSpy'),
|
||||
uncomment: jasmine.createSpy('uncommentSpy'),
|
||||
replaceSelection: replaceSelectionSpy,
|
||||
getCursor: (isFrom) => {
|
||||
return entireQueryString.indexOf(selectedQueryString) + (isFrom ? 0 : selectedQueryString.length);
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user