spyder-okvim 0.9__0-py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. spyder_okvim/__init__.py +10 -0
  2. spyder_okvim/conftest.py +153 -0
  3. spyder_okvim/executor/__init__.py +8 -0
  4. spyder_okvim/executor/executor_base.py +171 -0
  5. spyder_okvim/executor/executor_colon.py +86 -0
  6. spyder_okvim/executor/executor_easymotion.py +362 -0
  7. spyder_okvim/executor/executor_leader.py +112 -0
  8. spyder_okvim/executor/executor_normal.py +756 -0
  9. spyder_okvim/executor/executor_sub.py +875 -0
  10. spyder_okvim/executor/executor_surround.py +112 -0
  11. spyder_okvim/executor/executor_visual.py +475 -0
  12. spyder_okvim/executor/executor_vline.py +460 -0
  13. spyder_okvim/executor/tests/test_colon.py +130 -0
  14. spyder_okvim/executor/tests/test_easymotion.py +631 -0
  15. spyder_okvim/executor/tests/test_leader_key.py +135 -0
  16. spyder_okvim/executor/tests/test_normal.py +2508 -0
  17. spyder_okvim/executor/tests/test_surround.py +170 -0
  18. spyder_okvim/executor/tests/test_visual.py +1529 -0
  19. spyder_okvim/executor/tests/test_vline.py +1190 -0
  20. spyder_okvim/spyder/__init__.py +0 -0
  21. spyder_okvim/spyder/api.py +57 -0
  22. spyder_okvim/spyder/config.py +42 -0
  23. spyder_okvim/spyder/confpage.py +113 -0
  24. spyder_okvim/spyder/plugin.py +180 -0
  25. spyder_okvim/spyder/tests/test_widgets.py +203 -0
  26. spyder_okvim/spyder/widgets.py +515 -0
  27. spyder_okvim/utils/__init__.py +0 -0
  28. spyder_okvim/utils/easymotion.py +104 -0
  29. spyder_okvim/utils/helper_action.py +684 -0
  30. spyder_okvim/utils/helper_motion.py +1377 -0
  31. spyder_okvim/utils/misc.py +2 -0
  32. spyder_okvim/utils/path_finder.py +243 -0
  33. spyder_okvim/utils/tests/test_path_finder.py +135 -0
  34. spyder_okvim/utils/vim_status.py +998 -0
  35. spyder_okvim-0.9.0.dist-info/METADATA +199 -0
  36. spyder_okvim-0.9.0.dist-info/RECORD +40 -0
  37. spyder_okvim-0.9.0.dist-info/WHEEL +5 -0
  38. spyder_okvim-0.9.0.dist-info/entry_points.txt +2 -0
  39. spyder_okvim-0.9.0.dist-info/licenses/LICENSE +21 -0
  40. spyder_okvim-0.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8 -*-
2
+ # -----------------------------------------------------------------------------
3
+ # Copyright (c) Spyder Project Contributors
4
+ #
5
+ # Licensed under the terms of the MIT License
6
+ # (see LICENSE.txt for details)
7
+ # -----------------------------------------------------------------------------
8
+ """Spyder OkVim Plugin."""
9
+
10
+ __version__ = "0.0.1-dev0"
@@ -0,0 +1,153 @@
1
+ """Conftest."""
2
+ # Standard library imports
3
+ import os
4
+ import os.path as osp
5
+ from unittest.mock import Mock
6
+
7
+ # Third party imports
8
+ import pytest
9
+ import requests
10
+ from pytestqt.plugin import QtBot
11
+ from qtpy.QtGui import QFont
12
+ from qtpy.QtWidgets import QVBoxLayout, QWidget
13
+ from spyder.config.manager import CONF
14
+ from spyder.plugins.editor.widgets.editorstack import EditorStack
15
+
16
+ # Local imports
17
+ from spyder_okvim.spyder.config import CONF_DEFAULTS, CONF_SECTION
18
+ from spyder_okvim.spyder.plugin import OkVim
19
+
20
+ LOCATION = osp.realpath(osp.join(os.getcwd(), osp.dirname(__file__)))
21
+
22
+
23
+ class VimTesting(OkVim):
24
+ CONF_FILE = False
25
+ CONF_SECTION = CONF_SECTION
26
+
27
+
28
+ class EditorMock(QWidget):
29
+ """Editor plugin mock."""
30
+
31
+ def __init__(self, editor_stack):
32
+ """Editor Mock constructor."""
33
+ QWidget.__init__(self, None)
34
+ self.editor_stack = editor_stack
35
+ self.editorsplitter = self.editor_stack
36
+ self.open_action = Mock()
37
+ self.new_action = Mock()
38
+ self.save_action = Mock()
39
+ self.close_action = Mock()
40
+
41
+ layout = QVBoxLayout()
42
+ layout.addWidget(self.editor_stack)
43
+ self.setLayout(layout)
44
+
45
+ def get_widget(self):
46
+ """Return self, mimicking Spyder 6 API."""
47
+ return self
48
+
49
+ def get_current_editorstack(self):
50
+ """Return EditorStack instance."""
51
+ return self.editor_stack
52
+
53
+
54
+ class StatusBarMock(QWidget):
55
+ """Stausbar mock."""
56
+
57
+ def __init__(self):
58
+ QWidget.__init__(self, None)
59
+ self.layout = QVBoxLayout()
60
+ self.setLayout(self.layout)
61
+
62
+ def add_status_widget(self, widget):
63
+ self.layout.addWidget(widget)
64
+
65
+
66
+ class MainMock(QWidget):
67
+ """Spyder MainWindow mock."""
68
+
69
+ def __init__(self, editor_stack, qtbot_module):
70
+ """Main Window Mock constructor."""
71
+ QWidget.__init__(self, None)
72
+ self.main = QWidget()
73
+ self.plugin_focus_changed = Mock()
74
+ self.editor = EditorMock(editor_stack)
75
+ self.status_bar = StatusBarMock()
76
+ self.projects = Mock()
77
+ self.open_file = Mock()
78
+ self.projects.get_active_project_path = lambda: None
79
+ layout = QVBoxLayout()
80
+ layout.addWidget(self.editor)
81
+ layout.addWidget(self.status_bar)
82
+ self.setLayout(layout)
83
+
84
+ for name, dict_info in CONF_DEFAULTS:
85
+ if name != CONF_SECTION:
86
+ continue
87
+ for key, val in dict_info.items():
88
+ CONF.set(name, key, val)
89
+
90
+ self.add_dockwidget = Mock()
91
+
92
+ qtbot_module.add_widget(self.main)
93
+ qtbot_module.add_widget(self.editor)
94
+ qtbot_module.add_widget(self.status_bar)
95
+
96
+ def get_plugin(self, dummy, error=True):
97
+ return self.status_bar
98
+
99
+
100
+ @pytest.fixture(scope="session")
101
+ def qtbot_module(qapp, request):
102
+ """Module fixture for qtbot."""
103
+ result = QtBot(request)
104
+ return result
105
+
106
+
107
+ @pytest.fixture(scope="session", autouse=True)
108
+ def vim_bot(qtbot_module):
109
+ """Editorstack pytest fixture."""
110
+ text = (
111
+ " 123\n" "line 1\n" "line 2\n" "line 3\n" "line 4"
112
+ ) # a newline is added at end
113
+ editor_stack = EditorStack(None, [])
114
+
115
+ # Fix the area of the selection
116
+ font = QFont("Courier New")
117
+ font.setPointSize(10)
118
+ editor_stack.set_default_font(font)
119
+ editor_stack.setMinimumWidth(400)
120
+ editor_stack.setMinimumHeight(400)
121
+
122
+ editor_stack.set_find_widget(Mock())
123
+ editor_stack.set_io_actions(Mock(), Mock(), Mock(), Mock())
124
+ finfo0 = editor_stack.new(osp.join(LOCATION, "foo.py"), "utf-8", text)
125
+ finfo1 = editor_stack.new(osp.join(LOCATION, "foo1.py"), "utf-8", text)
126
+ finfo2 = editor_stack.new(osp.join(LOCATION, "foo2.py"), "utf-8", text)
127
+ finfo3 = editor_stack.new(osp.join(LOCATION, "foo3.py"), "utf-8", text)
128
+ main = MainMock(editor_stack, qtbot_module)
129
+
130
+ vim = VimTesting(main, None)
131
+ vim.on_initialize()
132
+
133
+ qtbot_module.addWidget(editor_stack)
134
+ qtbot_module.addWidget(finfo0.editor)
135
+ qtbot_module.addWidget(finfo1.editor)
136
+ qtbot_module.addWidget(finfo2.editor)
137
+ qtbot_module.addWidget(finfo3.editor)
138
+ qtbot_module.addWidget(main)
139
+
140
+ # Show GUI
141
+ main.show()
142
+ yield main, editor_stack, finfo0.editor, vim, qtbot_module
143
+
144
+ finfo0.editor.close()
145
+ finfo1.editor.close()
146
+ finfo2.editor.close()
147
+ finfo3.editor.close()
148
+ finfo0.deleteLater()
149
+ finfo1.deleteLater()
150
+ finfo2.deleteLater()
151
+ finfo3.deleteLater()
152
+ editor_stack.deleteLater()
153
+
@@ -0,0 +1,8 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Excecutor __init__."""
3
+ # %% Import
4
+ # Local imports
5
+ from .executor_normal import ExecutorNormalCmd
6
+ from .executor_visual import ExecutorVisualCmd
7
+ from .executor_vline import ExecutorVlineCmd
8
+ from .executor_leader import ExecutorLeaderKey
@@ -0,0 +1,171 @@
1
+ # -*- coding: utf-8 -*-
2
+ """."""
3
+ # %% Import
4
+ # Standard library imports
5
+ from typing import NamedTuple, Any, List
6
+
7
+ # Local imports
8
+ from spyder_okvim.utils.helper_motion import HelperMotion
9
+ from spyder_okvim.utils.helper_action import HelperAction
10
+
11
+ FUNC_INFO = NamedTuple("FUNC_INFO", [("func", Any), ("has_arg", bool)])
12
+ RETURN_EXECUTOR_METHOD_INFO = NamedTuple(
13
+ "RETURN_EXECUTOR_METHOD_INFO", [("sub_mode", Any), ("clear_command_line", bool)]
14
+ )
15
+
16
+
17
+ class ExecutorBase:
18
+ """Baseclass Executor."""
19
+
20
+ SYMBOLS_REPLACEMENT = {
21
+ "!": "exclamation",
22
+ "?": "question",
23
+ "<": "less",
24
+ ">": "greater",
25
+ "|": "pipe",
26
+ " ": "space",
27
+ "\b": "backspace",
28
+ "\r": "enter",
29
+ "@": "at",
30
+ "$": "dollar",
31
+ "0": "zero",
32
+ "^": "caret",
33
+ '"': "quote",
34
+ "%": "percent",
35
+ "~": "tilde",
36
+ ":": "colon",
37
+ "/": "slash",
38
+ ";": "semicolon",
39
+ ",": "comma",
40
+ ".": "dot",
41
+ "[": "opensquarebracket",
42
+ "]": "closesquarebracket",
43
+ "*": "asterisk",
44
+ "#": "sharp",
45
+ }
46
+
47
+ def __init__(self, vim_status):
48
+ """__init__.
49
+
50
+ Parameters
51
+ ----------
52
+ vim_status : spyder_okvim.utils.vim_status.VimStatus
53
+ vim status
54
+
55
+ """
56
+ self.vim_status = vim_status
57
+ self.get_cursor = vim_status.get_cursor
58
+ self.set_cursor = vim_status.set_cursor
59
+ self.get_editor = vim_status.get_editor
60
+ self.get_editorstack = vim_status.get_editorstack
61
+ self.get_block_no_start_in_selection = (
62
+ vim_status.get_block_no_start_in_selection
63
+ )
64
+ self.get_block_no_end_in_selection = vim_status.get_block_no_end_in_selection
65
+ self.get_pos_start_in_selection = vim_status.get_pos_start_in_selection
66
+ self.get_pos_end_in_selection = vim_status.get_pos_end_in_selection
67
+ self.set_cursor_pos = vim_status.cursor.set_cursor_pos
68
+ self.helper_motion = HelperMotion(vim_status)
69
+ self.helper_action = HelperAction(vim_status)
70
+
71
+ self.has_zero_cmd = True
72
+ self.pattern_cmd = None
73
+ self.allow_leaderkey = True
74
+
75
+ def update_input_cmd_info(self, num_str, cmd, input_txt):
76
+ """Update input cmd to vim_status."""
77
+ self.vim_status.input_cmd_prev.set(self.vim_status.input_cmd)
78
+ self.vim_status.input_cmd.num_str = num_str
79
+ self.vim_status.input_cmd.cmd = cmd
80
+
81
+ def set_parent_info_to_submode(self, submode, num, num_str):
82
+ """Set info to submode."""
83
+ submode.parent_num = [num]
84
+ submode.parent_num_str = [num_str]
85
+
86
+ def __call__(self, txt):
87
+ """Parse txt and executor command.
88
+
89
+ Returns
90
+ -------
91
+ bool
92
+ if return is True, Clear command line
93
+
94
+ """
95
+ if self.has_zero_cmd and txt == "0":
96
+ # Special case to simplify regexp
97
+ key = "0"
98
+ num_str = "1"
99
+ else:
100
+ match = self.pattern_cmd.match(txt)
101
+ if not match:
102
+ if txt.isdigit():
103
+ return False
104
+ else:
105
+ self.vim_status.sub_mode = None
106
+ return True
107
+
108
+ num_str, key = match.groups()
109
+
110
+ num = int(num_str) if num_str else 1
111
+ self.update_input_cmd_info(num_str, key, txt)
112
+
113
+ key = self.SYMBOLS_REPLACEMENT.get(key, key)
114
+
115
+ ret = None
116
+ try:
117
+ method = self.__getattribute__(key)
118
+ except AttributeError:
119
+ print("unknown key", key)
120
+ else:
121
+ ret = method(num=num, num_str=num_str)
122
+
123
+ return self.process_return(ret)
124
+
125
+ def process_return(self, ret: Any):
126
+ """Process return of method."""
127
+ if ret:
128
+ self.vim_status.sub_mode = ret.sub_mode
129
+ return ret.clear_command_line
130
+ else:
131
+ self.vim_status.sub_mode = None
132
+ return True
133
+
134
+
135
+ class ExecutorSubBase(ExecutorBase):
136
+ """Baseclass for submode of executor."""
137
+
138
+ def __init__(self, vim_status):
139
+ super().__init__(vim_status)
140
+
141
+ self.has_zero_cmd = False
142
+ self.parent_num = []
143
+ self.parent_num_str = []
144
+ self.func_list_deferred: List[FUNC_INFO] = []
145
+ self.return_deferred: Any = None
146
+
147
+ def set_parent_info_to_submode(self, submode, num, num_str):
148
+ """Set parent and self into to submode."""
149
+ submode.parent_num = self.parent_num.copy()
150
+ submode.parent_num_str = self.parent_num_str.copy()
151
+
152
+ submode.parent_num.append(num)
153
+ submode.parent_num_str.append(num_str)
154
+
155
+ def set_func_list_deferred(self, f_list: List[FUNC_INFO], ret: Any = None):
156
+ """Set func list."""
157
+ self.func_list_deferred = f_list
158
+ self.return_deferred = ret
159
+
160
+ def execute_func_deferred(self, arg=None):
161
+ """Execute method passed in from previous executor."""
162
+ for func_info in self.func_list_deferred:
163
+ if func_info.has_arg:
164
+ func_info.func(arg)
165
+ else:
166
+ func_info.func()
167
+ return self.return_deferred
168
+
169
+ def update_input_cmd_info(self, num_str, cmd, input_txt):
170
+ """Add input cmd to vim_status."""
171
+ self.vim_status.input_cmd.cmd += input_txt
@@ -0,0 +1,86 @@
1
+ # -*- coding: utf-8 -*-
2
+ """."""
3
+ # Local imports
4
+ from spyder_okvim.executor.executor_base import ExecutorSubBase
5
+
6
+
7
+ class ExecutorColon(ExecutorSubBase):
8
+ """Execute the method by enter."""
9
+
10
+ def __init__(self, vim_status):
11
+ super().__init__(vim_status)
12
+ self.allow_leaderkey = False
13
+
14
+ self.editor_widget = vim_status.editor_widget
15
+
16
+ def __call__(self, txt):
17
+ """Parse txt and executor command.
18
+
19
+ Returns
20
+ -------
21
+ bool
22
+ if return is True, Clear command line
23
+
24
+ """
25
+ if txt[-1] == "\b":
26
+ cmd_line = self.vim_status.cmd_line
27
+ if len(txt) <= 2:
28
+ self.vim_status.sub_mode = None
29
+ return True
30
+ else:
31
+ cmd_line.setText(txt[:-2])
32
+ if txt[-1] != "\r":
33
+ return False
34
+
35
+ if txt[0] != ":" or len(txt) <= 2:
36
+ self.vim_status.sub_mode = None
37
+ return True
38
+
39
+ # ':' is saved to input cmd_info at ExecutorBase.
40
+ # So we need only txt[1:].
41
+ self.update_input_cmd_info(None, None, txt[1:])
42
+
43
+ txt = txt[1:-1] # remove :, \r
44
+ cmd = txt.split(None, 1)
45
+ args = cmd[1] if len(cmd) > 1 else ""
46
+ cmd = cmd[0]
47
+
48
+ for symbol, text in self.SYMBOLS_REPLACEMENT.items():
49
+ cmd = cmd.replace(symbol, text)
50
+
51
+ try:
52
+ method = self.__getattribute__(cmd)
53
+ except AttributeError:
54
+ print("unknown command", cmd)
55
+ else:
56
+ method(args)
57
+
58
+ self.vim_status.sub_mode = None
59
+
60
+ return True
61
+
62
+ def w(self, arg=""):
63
+ """Save current file."""
64
+ self.editor_widget.get_widget().save_action.trigger()
65
+ self.vim_status.cursor.draw_vim_cursor()
66
+
67
+ def q(self, arg=""):
68
+ """Close current file."""
69
+ self.editor_widget.get_widget().close_action.trigger()
70
+ self.vim_status.set_focus_to_vim()
71
+
72
+ def qexclamation(self, arg=""):
73
+ """Close current file without saving."""
74
+ # TODO :
75
+ self.editor_widget.get_widget().close_action.trigger()
76
+ self.vim_status.set_focus_to_vim()
77
+
78
+ def wq(self, arg=""):
79
+ """Save and close current file."""
80
+ self.w(arg)
81
+ self.q()
82
+
83
+ def n(self, args=""):
84
+ """Create new file."""
85
+ self.editor_widget.get_widget().new_action.trigger()
86
+ self.vim_status.set_focus_to_vim()