spyder-okvim 0.9__tar.gz

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 (36) hide show
  1. spyder_okvim-0.9/LICENSE +21 -0
  2. spyder_okvim-0.9/PKG-INFO +29 -0
  3. spyder_okvim-0.9/README.rst +1 -0
  4. spyder_okvim-0.9/setup.cfg +4 -0
  5. spyder_okvim-0.9/setup.py +38 -0
  6. spyder_okvim-0.9/spyder_okvim/__init__.py +10 -0
  7. spyder_okvim-0.9/spyder_okvim/conftest.py +153 -0
  8. spyder_okvim-0.9/spyder_okvim/executor/__init__.py +8 -0
  9. spyder_okvim-0.9/spyder_okvim/executor/executor_base.py +171 -0
  10. spyder_okvim-0.9/spyder_okvim/executor/executor_colon.py +86 -0
  11. spyder_okvim-0.9/spyder_okvim/executor/executor_easymotion.py +362 -0
  12. spyder_okvim-0.9/spyder_okvim/executor/executor_leader.py +112 -0
  13. spyder_okvim-0.9/spyder_okvim/executor/executor_normal.py +756 -0
  14. spyder_okvim-0.9/spyder_okvim/executor/executor_sub.py +875 -0
  15. spyder_okvim-0.9/spyder_okvim/executor/executor_surround.py +112 -0
  16. spyder_okvim-0.9/spyder_okvim/executor/executor_visual.py +475 -0
  17. spyder_okvim-0.9/spyder_okvim/executor/executor_vline.py +460 -0
  18. spyder_okvim-0.9/spyder_okvim/spyder/__init__.py +0 -0
  19. spyder_okvim-0.9/spyder_okvim/spyder/api.py +57 -0
  20. spyder_okvim-0.9/spyder_okvim/spyder/config.py +42 -0
  21. spyder_okvim-0.9/spyder_okvim/spyder/confpage.py +113 -0
  22. spyder_okvim-0.9/spyder_okvim/spyder/plugin.py +180 -0
  23. spyder_okvim-0.9/spyder_okvim/spyder/widgets.py +515 -0
  24. spyder_okvim-0.9/spyder_okvim/utils/__init__.py +0 -0
  25. spyder_okvim-0.9/spyder_okvim/utils/easymotion.py +104 -0
  26. spyder_okvim-0.9/spyder_okvim/utils/helper_action.py +684 -0
  27. spyder_okvim-0.9/spyder_okvim/utils/helper_motion.py +1377 -0
  28. spyder_okvim-0.9/spyder_okvim/utils/misc.py +2 -0
  29. spyder_okvim-0.9/spyder_okvim/utils/path_finder.py +243 -0
  30. spyder_okvim-0.9/spyder_okvim/utils/vim_status.py +998 -0
  31. spyder_okvim-0.9/spyder_okvim.egg-info/PKG-INFO +29 -0
  32. spyder_okvim-0.9/spyder_okvim.egg-info/SOURCES.txt +34 -0
  33. spyder_okvim-0.9/spyder_okvim.egg-info/dependency_links.txt +1 -0
  34. spyder_okvim-0.9/spyder_okvim.egg-info/entry_points.txt +2 -0
  35. spyder_okvim-0.9/spyder_okvim.egg-info/requires.txt +1 -0
  36. spyder_okvim-0.9/spyder_okvim.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 ok97465
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: spyder-okvim
3
+ Version: 0.9
4
+ Summary: A plugin to enable vim keybindings to the spyder editor
5
+ Home-page: https://github.com/ok97465/spyder_okvim
6
+ Author: ok97465
7
+ Author-email: ok97465@kakao.com
8
+ License: MIT license
9
+ Classifier: Operating System :: MacOS
10
+ Classifier: Operating System :: Microsoft :: Windows
11
+ Classifier: Operating System :: POSIX :: Linux
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Education
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Topic :: Scientific/Engineering
18
+ Requires-Python: >=3.9
19
+ License-File: LICENSE
20
+ Requires-Dist: spyder>6
21
+ Dynamic: author
22
+ Dynamic: author-email
23
+ Dynamic: classifier
24
+ Dynamic: home-page
25
+ Dynamic: license
26
+ Dynamic: license-file
27
+ Dynamic: requires-dist
28
+ Dynamic: requires-python
29
+ Dynamic: summary
@@ -0,0 +1 @@
1
+ Spyder Okvim
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env python
2
+ # -----------------------------------------------------------------------------
3
+ # Licensed under the terms of the MIT License
4
+ # (see LICENSE.txt for details)
5
+ # -----------------------------------------------------------------------------
6
+ """Setup script for spyder-okvim."""
7
+ # %% Import
8
+ # Third party imports
9
+ from setuptools import find_packages, setup
10
+
11
+ setup(
12
+ name="spyder-okvim",
13
+ version=0.9,
14
+ author="ok97465",
15
+ author_email="ok97465@kakao.com",
16
+ description="A plugin to enable vim keybindings to the spyder editor",
17
+ license="MIT license",
18
+ url="https://github.com/ok97465/spyder_okvim",
19
+ python_requires=">=3.9",
20
+ install_requires=[
21
+ "spyder>6"
22
+ ],
23
+ packages=find_packages(),
24
+ entry_points={
25
+ "spyder.plugins": ["spyder_okvim = spyder_okvim.spyder.plugin:OkVim"],
26
+ },
27
+ classifiers=[
28
+ "Operating System :: MacOS",
29
+ "Operating System :: Microsoft :: Windows",
30
+ "Operating System :: POSIX :: Linux",
31
+ "Programming Language :: Python :: 3",
32
+ "Development Status :: 5 - Production/Stable",
33
+ "Intended Audience :: Education",
34
+ "Intended Audience :: Science/Research",
35
+ "Intended Audience :: Developers",
36
+ "Topic :: Scientific/Engineering",
37
+ ],
38
+ )
@@ -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()