diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index edbd03739..a147c2c80 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -10,6 +10,7 @@ and this project adheres to http://semver.org/spec/v2.0.0.html[Semantic Versioni
=== Added
+- Added content help pop-up on Text Editor by pressing ``Ctrl-M`` for text at cursor position
- Added Exclude option in context nenu for Test files, previously was only possible for Test Suites folders
- Added exclusion of monitoring filesystem changes for files and directories excluded in Preferences
- Added variables creation shortcuts (``Ctrl-1,2,5``) to fields Arguments in Grid Editor
diff --git a/src/robotide/application/CHANGELOG.html b/src/robotide/application/CHANGELOG.html
index 07a8ef0c9..04352cba5 100644
--- a/src/robotide/application/CHANGELOG.html
+++ b/src/robotide/application/CHANGELOG.html
@@ -1,6 +1,8 @@
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog
and this project adheres to Semantic Versioning.
-
+Added content help pop-up on Text Editor by pressing ``Ctrl-M`` for text at cursor position
+
-
Added Exclude option in context nenu for Test files, previously was only possible for Test Suites folders
-
Added exclusion of monitoring filesystem changes for files and directories excluded in Preferences
diff --git a/src/robotide/application/releasenotes.py b/src/robotide/application/releasenotes.py
index 14f9d464f..bffb03d82 100644
--- a/src/robotide/application/releasenotes.py
+++ b/src/robotide/application/releasenotes.py
@@ -168,6 +168,7 @@ def set_content(self, html_win, content):
New Features and Fixes Highlights
+- Added content help pop-up on Text Editor by pressing Ctrl-M for text at cursor position
- Added Exclude option in context nenu for Test files, previously was only possible for Test Suites folders
- Added exclusion of monitoring filesystem changes for files and directories excluded in Preferences
- Fixed exception when finding GREY color for excluded files and directories in Project Tree
@@ -236,6 +237,6 @@ def set_content(self, html_win, content):
python -m robotide.postinstall -install
-
RIDE {VERSION} was released on 10/Sep/2023.
+
RIDE {VERSION} was released on 18/Sep/2023.
"""
diff --git a/src/robotide/context/__init__.py b/src/robotide/context/__init__.py
index 3872eb86e..97bae4ec9 100644
--- a/src/robotide/context/__init__.py
+++ b/src/robotide/context/__init__.py
@@ -323,6 +323,10 @@ def bind_keys_to_evt_menu(target, actions):
Ctrl-Space or Alt-Space |
Suggestions and auto completion |
+
+
+ CtrlCmd-M |
+ Help for content at cursor |
CtrlCmd-T |
diff --git a/src/robotide/editor/texteditor.py b/src/robotide/editor/texteditor.py
index e4e34cb4a..131d7d7e9 100644
--- a/src/robotide/editor/texteditor.py
+++ b/src/robotide/editor/texteditor.py
@@ -20,7 +20,7 @@
import wx
from wx import stc, Colour
from wx.adv import HyperlinkCtrl, EVT_HYPERLINK
-
+from .popupwindow import HtmlPopupWindow
from .. import robotapi
from ..context import IS_WINDOWS, IS_MAC
from ..controller.ctrlcommands import SetDataFile, INDENTED_START
@@ -57,7 +57,7 @@ def __init__(self, application):
@property
def _editor(self):
if self._editor_component is None:
- self._editor_component = SourceEditor(self.notebook,
+ self._editor_component = SourceEditor(self, self.notebook,
self.title,
DataValidationHandler(self))
self._refresh_timer = wx.Timer(self._editor_component)
@@ -383,7 +383,7 @@ def _txt_data(self, data):
class SourceEditor(wx.Panel):
- def __init__(self, parent, title, data_validator):
+ def __init__(self, plugin, parent, title, data_validator):
wx.Panel.__init__(self, parent)
self.dlg = RIDEDialog()
self.SetBackgroundColour(Colour(self.dlg.color_background))
@@ -392,6 +392,7 @@ def __init__(self, parent, title, data_validator):
self._data_validator = data_validator
self._data_validator.set_editor(self)
self.source_editor_parent = parent
+ self.plugin = plugin
self._title = title
self.tab_size = self.source_editor_parent.app.settings.get(TXT_NUM_SPACES, 4)
self.reformat = self.source_editor_parent.app.settings.get('reformat', False)
@@ -937,6 +938,8 @@ def on_key_down(self, event):
self.delete_cell(event)
else:
self.delete_row(event)
+ elif keycode == ord('M') and event.ControlDown():
+ self.source_editor.show_kw_doc()
else:
event.Skip()
"""
@@ -1484,7 +1487,11 @@ class RobotDataEditor(stc.StyledTextCtrl):
def __init__(self, parent, readonly=False):
stc.StyledTextCtrl.__init__(self, parent)
self.parent = parent
+ self._plugin = parent.plugin
self._settings = parent.source_editor_parent.app.settings
+ self._information_popup = None
+ self.old_position = None
+ self.old_select = []
self.readonly = readonly
self.SetMarginType(self.margin, stc.STC_MARGIN_NUMBER)
self.SetLexer(stc.STC_LEX_CONTAINER)
@@ -1503,21 +1510,38 @@ def __init__(self, parent, readonly=False):
self.RegisterImage(2, wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16, 16)))
self.RegisterImage(3, wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16, 16)))
+ def show_kw_doc(self):
+ cursor_pos = self.GetCurrentPos()
+ if cursor_pos != self.old_position:
+ self.old_position = cursor_pos
+ selected = self.get_selected_or_near_text(keep_cursor_pos=True)
+ if self.old_select != selected:
+ for kw in selected:
+ self._show_keyword_details(kw)
+
def on_key_pressed(self, event):
if self.CallTipActive():
self.CallTipCancel()
+ if self._information_popup:
+ self._information_popup.hide()
key = event.GetKeyCode()
if key == 32 and event.ControlDown():
pos = self.GetCurrentPos()
# Tips
if event.ShiftDown():
+ self.show_kw_doc()
+ """
self.CallTipSetBackground("yellow")
- self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
- 'show some suff, maybe parameters..\n\n'
- 'fubar(param1, param2)')
+ self.CallTipShow(pos, f"lots of of text: blah, blah, blah\n\n"
+ "show some suff, maybe parameters..\n\n"
+ f"fubar(param1, param2)\n\nContext: {selected}"
+ )
+ """
# Code completion
else:
+ if self._information_popup:
+ self._information_popup.hide()
"""
kw = list(keyword.kwlist[:])
kw.append("zzzzzz?2")
@@ -1588,23 +1612,36 @@ def calc_margin_width(self):
width = self.TextWidth(style, str(self.GetLineCount()))
return width + self.TextWidth(style, "1")
- def get_selected_or_near_text(self):
+ def get_selected_or_near_text(self, keep_cursor_pos=False):
content = set()
+ if keep_cursor_pos:
+ restore_cursor_pos = self.GetInsertionPoint()
+ else:
+ restore_cursor_pos = None
# First get selected text
selected = self.GetSelectedText()
if selected:
start_pos = self.GetSelectionStart()
if selected.endswith('.'): # Special cases for libraries prefix
- self.SetInsertionPoint(start_pos + len(selected))
+ if restore_cursor_pos:
+ self.SetInsertionPoint(restore_cursor_pos)
+ else:
+ self.SetInsertionPoint(start_pos + len(selected))
elif len(selected.split('.')) > 1:
parts = selected.split('.')
self.SetSelectionStart(start_pos + len(parts[0]) + 1)
self.SetSelectionEnd(start_pos + len(selected))
- self.SetInsertionPoint(start_pos + len(parts[0]) + 1)
+ if restore_cursor_pos:
+ self.SetInsertionPoint(restore_cursor_pos)
+ else:
+ self.SetInsertionPoint(start_pos + len(parts[0]) + 1)
else:
self.SetSelectionStart(start_pos)
self.SetSelectionEnd(start_pos + len(selected))
- self.SetInsertionPoint(start_pos + len(selected))
+ if restore_cursor_pos:
+ self.SetInsertionPoint(restore_cursor_pos)
+ else:
+ self.SetInsertionPoint(start_pos + len(selected))
content.add(selected.strip())
# Next get text on the left
text = self.GetCurLine()[0]
@@ -1645,16 +1682,25 @@ def get_selected_or_near_text(self):
else:
start_pos = min_pos + pos_in_line
if value.endswith('.'): # Special cases for libraries prefix
- self.SetInsertionPoint(start_pos + len(value))
+ if restore_cursor_pos:
+ self.SetInsertionPoint(restore_cursor_pos)
+ else:
+ self.SetInsertionPoint(start_pos + len(value))
elif len(value.split('.')) > 1:
- parts = value.split('.')
- self.SetSelectionStart(start_pos + len(parts[0]) + 1)
- self.SetSelectionEnd(start_pos + len(value))
- self.SetInsertionPoint(start_pos + len(parts[0]) + 1)
+ if restore_cursor_pos:
+ self.SetInsertionPoint(restore_cursor_pos)
+ else:
+ parts = value.split('.')
+ self.SetSelectionStart(start_pos + len(parts[0]) + 1)
+ self.SetSelectionEnd(start_pos + len(value))
+ self.SetInsertionPoint(start_pos + len(parts[0]) + 1)
else:
- self.SetSelectionStart(start_pos)
- self.SetSelectionEnd(start_pos + len(value))
- self.SetInsertionPoint(start_pos)
+ if restore_cursor_pos:
+ self.SetInsertionPoint(restore_cursor_pos)
+ else:
+ self.SetSelectionStart(start_pos)
+ self.SetSelectionEnd(start_pos + len(value))
+ self.SetInsertionPoint(start_pos)
content.add(value)
return content if content else ['']
@@ -1688,6 +1734,18 @@ def on_update_ui(self, evt):
else:
self.BraceHighlight(brace_at_caret, brace_opposite)
+ def _show_keyword_details(self, value):
+ details = self._plugin.get_keyword_details(value)
+ if details:
+ wpos = self.parent.source_editor_parent.GetPosition()
+ npos = self.parent.GetPosition()
+ position = self.GetCurrentPos()
+ position = self.PointFromPosition(position)
+ position = position + wpos + npos
+ self._information_popup = HtmlPopupWindow(self.parent, (450, 300))
+ self._information_popup.set_content(details, value)
+ self._information_popup.show_at(position)
+
class FromStringIOPopulator(robotapi.populators.FromFilePopulator):
diff --git a/src/robotide/version.py b/src/robotide/version.py
index b3a2eb05c..ae412d3f3 100644
--- a/src/robotide/version.py
+++ b/src/robotide/version.py
@@ -14,4 +14,4 @@
# limitations under the License.
#
# Automatically generated by `tasks.py`.
-VERSION = 'v2.0.8dev11'
+VERSION = 'v2.0.8dev12'
diff --git a/utest/editor/test_texteditor.py b/utest/editor/test_texteditor.py
index 6ffaf96d8..92d8675b4 100644
--- a/utest/editor/test_texteditor.py
+++ b/utest/editor/test_texteditor.py
@@ -129,7 +129,7 @@ def setUp(self):
ShortcutRegistry(self.frame)), settings)
self.app.project = Project(self.app.namespace, self.app.settings)
self.plugin = texteditor.TextEditorPlugin(self.app)
- self.plugin._editor_component = texteditor.SourceEditor(self.app.book, self.plugin.title,
+ self.plugin._editor_component = texteditor.SourceEditor(self.plugin, self.app.book, self.plugin.title,
texteditor.DataValidationHandler(self.plugin))
self.plugin.enable()
self.app.project.load_datafile(datafilereader.TESTCASEFILE_WITH_EVERYTHING, MessageRecordingLoadObserver())
diff --git a/utest/editor/test_z_editor_plugin.py b/utest/editor/test_z_editor_plugin.py
index af3180356..125213842 100644
--- a/utest/editor/test_z_editor_plugin.py
+++ b/utest/editor/test_z_editor_plugin.py
@@ -174,7 +174,7 @@ def setUp(self):
self.app.project = Project(self.app.namespace, self.app.settings)
self.plugin = texteditor.TextEditorPlugin(self.app)
- self.plugin._editor_component = texteditor.SourceEditor(self.app.notebook, self.plugin.title,
+ self.plugin._editor_component = texteditor.SourceEditor(self.plugin, self.app.notebook, self.plugin.title,
texteditor.DataValidationHandler(self.plugin))
self.frame.notebook = self.app.notebook
"""