suplemon-editor 0.3.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 (72) hide show
  1. suplemon/__init__.py +0 -0
  2. suplemon/__main__.py +3 -0
  3. suplemon/cli.py +65 -0
  4. suplemon/config/defaults.json +153 -0
  5. suplemon/config/keymap.json +63 -0
  6. suplemon/config.py +324 -0
  7. suplemon/cursor.py +135 -0
  8. suplemon/editor.py +568 -0
  9. suplemon/file.py +193 -0
  10. suplemon/help.py +327 -0
  11. suplemon/helpers.py +104 -0
  12. suplemon/hex2xterm.py +23 -0
  13. suplemon/key_mappings.py +239 -0
  14. suplemon/lexer.py +88 -0
  15. suplemon/line.py +51 -0
  16. suplemon/linelight/__init__.py +0 -0
  17. suplemon/linelight/color_map.py +9 -0
  18. suplemon/linelight/css.py +21 -0
  19. suplemon/linelight/diff.py +17 -0
  20. suplemon/linelight/html.py +19 -0
  21. suplemon/linelight/js.py +21 -0
  22. suplemon/linelight/json.py +15 -0
  23. suplemon/linelight/lua.py +10 -0
  24. suplemon/linelight/md.py +19 -0
  25. suplemon/linelight/php.py +27 -0
  26. suplemon/linelight/py.py +27 -0
  27. suplemon/logger.py +90 -0
  28. suplemon/main.py +771 -0
  29. suplemon/module_loader.py +98 -0
  30. suplemon/modules/application_state.py +84 -0
  31. suplemon/modules/autocomplete.py +114 -0
  32. suplemon/modules/autodocstring.py +142 -0
  33. suplemon/modules/battery.py +118 -0
  34. suplemon/modules/bulk_delete.py +75 -0
  35. suplemon/modules/clock.py +22 -0
  36. suplemon/modules/comment.py +59 -0
  37. suplemon/modules/config.py +20 -0
  38. suplemon/modules/date.py +22 -0
  39. suplemon/modules/diff.py +42 -0
  40. suplemon/modules/eval.py +43 -0
  41. suplemon/modules/hostname.py +34 -0
  42. suplemon/modules/input_test.py +23 -0
  43. suplemon/modules/keymap.py +20 -0
  44. suplemon/modules/linter.py +274 -0
  45. suplemon/modules/lower.py +21 -0
  46. suplemon/modules/lstrip.py +20 -0
  47. suplemon/modules/paste.py +49 -0
  48. suplemon/modules/reload.py +16 -0
  49. suplemon/modules/replace_all.py +23 -0
  50. suplemon/modules/reverse.py +22 -0
  51. suplemon/modules/rstrip.py +19 -0
  52. suplemon/modules/save.py +16 -0
  53. suplemon/modules/save_all.py +19 -0
  54. suplemon/modules/sort_lines.py +41 -0
  55. suplemon/modules/strip.py +19 -0
  56. suplemon/modules/system_clipboard.py +121 -0
  57. suplemon/modules/tabstospaces.py +18 -0
  58. suplemon/modules/toggle_whitespace.py +18 -0
  59. suplemon/modules/upper.py +21 -0
  60. suplemon/prompt.py +319 -0
  61. suplemon/suplemon_module.py +210 -0
  62. suplemon/themes/8colors.tmTheme +179 -0
  63. suplemon/themes/monokai.tmTheme +284 -0
  64. suplemon/themes.py +201 -0
  65. suplemon/ui.py +656 -0
  66. suplemon/viewer.py +1004 -0
  67. suplemon_editor-0.3.0.dist-info/METADATA +515 -0
  68. suplemon_editor-0.3.0.dist-info/RECORD +72 -0
  69. suplemon_editor-0.3.0.dist-info/WHEEL +5 -0
  70. suplemon_editor-0.3.0.dist-info/entry_points.txt +3 -0
  71. suplemon_editor-0.3.0.dist-info/licenses/LICENSE +21 -0
  72. suplemon_editor-0.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,59 @@
1
+ # -*- encoding: utf-8
2
+
3
+ from suplemon import helpers
4
+ from suplemon.suplemon_module import Module
5
+
6
+
7
+ class Comment(Module):
8
+ """Toggle line commenting based on current file syntax."""
9
+
10
+ def run(self, app, editor, args):
11
+ """Comment the current line(s)."""
12
+ try:
13
+ # Try to get comment start and end syntax
14
+ comment = editor.syntax.get_comment()
15
+ except AttributeError:
16
+ return False
17
+ line_nums = editor.get_lines_with_cursors()
18
+ # Iterate through lines
19
+ for lnum in line_nums:
20
+ line = editor.lines[lnum]
21
+ if not len(line):
22
+ continue # Skip empty lines
23
+ # Look for comment syntax in stripped line (TODO:Make this smarter)
24
+ target = str(line).strip()
25
+ w = helpers.whitespace(line) # Amount of whitespace at line start
26
+ indent = helpers.leading_whitespace(line) # That whitespace as written
27
+ # If the line starts with comment syntax
28
+ if target.startswith(comment[0]):
29
+ # Reconstruct the whitespace and add the line
30
+ new_line = indent + line[w+len(comment[0]):]
31
+ # If comment end syntax exists
32
+ if comment[1]:
33
+ # Try to remove it from the end of the line
34
+ if new_line.endswith(comment[1]):
35
+ new_line = new_line[:-1*len(comment[1])]
36
+ # Store the modified line
37
+ # editor.lines[lnum] = Line(new_line)
38
+ editor.lines[lnum].set_data(new_line)
39
+ # If the line isn't commented
40
+ else:
41
+ # Slice out the prepended whitespace
42
+ new_line = line[w:]
43
+ # Add the whitespace and starting comment
44
+ new_line = indent + comment[0] + new_line
45
+ if comment[1]:
46
+ # Add comment end syntax if needed
47
+ new_line += comment[1]
48
+ # Store modified line
49
+ # editor.lines[lnum] = Line(new_line)
50
+ editor.lines[lnum].set_data(new_line)
51
+ # Keep cursors under control, same as usual...
52
+ editor.move_cursors()
53
+ editor.store_action_state("comment")
54
+
55
+
56
+ module = {
57
+ "class": Comment,
58
+ "name": "comment",
59
+ }
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8
2
+
3
+ import os
4
+
5
+ from suplemon import config
6
+
7
+
8
+ class SuplemonConfig(config.ConfigModule):
9
+ """Shortcut for openning the config files."""
10
+
11
+ def init(self):
12
+ self.config_name = "defaults.json"
13
+ self.config_default_path = os.path.join(self.app.path, "config", self.config_name)
14
+ self.config_user_path = self.app.config.path()
15
+
16
+
17
+ module = {
18
+ "class": SuplemonConfig,
19
+ "name": "config",
20
+ }
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8
2
+
3
+ import time
4
+
5
+ from suplemon.suplemon_module import Module
6
+
7
+
8
+ class Date(Module):
9
+ """Shows the current date without year in the top status bar."""
10
+
11
+ def get_status(self):
12
+ s = time.strftime("%Y-%m-%d")
13
+ if self.app.config["app"]["use_unicode_symbols"]:
14
+ return "" + s
15
+ return s
16
+
17
+
18
+ module = {
19
+ "class": Date,
20
+ "name": "date",
21
+ "status": "top",
22
+ }
@@ -0,0 +1,42 @@
1
+ # -*- encoding: utf-8
2
+
3
+ import difflib
4
+
5
+ from suplemon.suplemon_module import Module
6
+
7
+
8
+ class Diff(Module):
9
+ """View a diff of the current file compared to it's on disk version."""
10
+
11
+ def run(self, app, editor, args):
12
+ curr_file = app.get_file()
13
+ curr_path = curr_file.get_path()
14
+ if not curr_path:
15
+ self.app.set_status("File hasn't been saved, can't show diff.")
16
+ return False
17
+
18
+ current_data = editor.get_data()
19
+ f = open(curr_path)
20
+ original_data = f.read()
21
+ f.close()
22
+ diff = self.get_diff(original_data, current_data)
23
+
24
+ if not diff:
25
+ self.app.set_status("The file in the editor and on disk are identical.")
26
+ return False
27
+ file = app.new_file()
28
+ file.set_name(curr_file.get_name() + ".diff")
29
+ file.set_data(diff)
30
+ app.switch_to_file(app.last_file_index())
31
+
32
+ def get_diff(self, a, b):
33
+ a = a.splitlines(1)
34
+ b = b.splitlines(1)
35
+ diff = difflib.unified_diff(a, b)
36
+ return "".join(diff)
37
+
38
+
39
+ module = {
40
+ "class": Diff,
41
+ "name": "diff",
42
+ }
@@ -0,0 +1,43 @@
1
+ # -*- encoding: utf-8
2
+
3
+ from suplemon.suplemon_module import Module
4
+
5
+
6
+ class Eval(Module):
7
+ """
8
+ Evaluate a python expression and show the result in the status bar.
9
+
10
+ If no expression is provided the current line(s) are evaluated and
11
+ replaced with the evaluation result.
12
+ """
13
+
14
+ def run(self, app, editor, args):
15
+ if not args:
16
+ return self.evaluate_lines(editor)
17
+ else:
18
+ return self.evaluate_input(args)
19
+
20
+ def evaluate_input(self, inp):
21
+ try:
22
+ value = eval(inp)
23
+ except Exception:
24
+ self.app.set_status("Eval failed.")
25
+ return False
26
+ self.app.set_status("Result:{0}".format(value))
27
+ return True
28
+
29
+ def evaluate_lines(self, editor):
30
+ line_nums = editor.get_lines_with_cursors()
31
+ for num in line_nums:
32
+ line = editor.get_line(num)
33
+ try:
34
+ value = eval(line.get_data())
35
+ except Exception:
36
+ continue
37
+ line.set_data(str(value))
38
+
39
+
40
+ module = {
41
+ "class": Eval,
42
+ "name": "eval",
43
+ }
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8
2
+
3
+ import socket
4
+
5
+ from suplemon.suplemon_module import Module
6
+
7
+
8
+ class Hostname(Module):
9
+ """Shows the machine hostname in the bottom status bar."""
10
+
11
+ def init(self):
12
+ self.hostname = ""
13
+ hostinfo = None
14
+ try:
15
+ hostinfo = socket.gethostbyaddr(socket.gethostname())
16
+ except OSError:
17
+ self.logger.debug("Failed to get hostname.")
18
+ if hostinfo:
19
+ self.hostname = hostinfo[0]
20
+ # Use shorter hostname if available
21
+ if hostinfo[1]:
22
+ self.hostname = hostinfo[1][0]
23
+
24
+ def get_status(self):
25
+ if self.hostname:
26
+ return "host:{0}".format(self.hostname)
27
+ return ""
28
+
29
+
30
+ module = {
31
+ "class": Hostname,
32
+ "name": "hostname",
33
+ "status": "bottom",
34
+ }
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8
2
+
3
+ from suplemon.suplemon_module import Module
4
+
5
+
6
+ class InputTest(Module):
7
+ """
8
+ Input event testing utility.
9
+ """
10
+
11
+ def handler(self, prompt, event):
12
+ self.app.set_status("InputEvent:" + str(event))
13
+ prompt.on_ready()
14
+ return True # Disable normal key handling
15
+
16
+ def run(self, app, editor, args):
17
+ app.ui.query_filtered("Waiting for input...", handler=self.handler)
18
+
19
+
20
+ module = {
21
+ "class": InputTest,
22
+ "name": "input_test",
23
+ }
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8
2
+
3
+ import os
4
+
5
+ from suplemon import config
6
+
7
+
8
+ class KeymapConfig(config.ConfigModule):
9
+ """Shortcut to openning the keymap config file."""
10
+
11
+ def init(self):
12
+ self.config_name = "keymap.json"
13
+ self.config_default_path = os.path.join(self.app.path, "config", self.config_name)
14
+ self.config_user_path = self.app.config.keymap_path()
15
+
16
+
17
+ module = {
18
+ "class": KeymapConfig,
19
+ "name": "keymap",
20
+ }
@@ -0,0 +1,274 @@
1
+ # -*- encoding: utf-8
2
+
3
+ import re
4
+ import os
5
+ import threading
6
+ import subprocess
7
+
8
+ from suplemon.suplemon_module import Module
9
+
10
+
11
+ class Linter(Module):
12
+ """Linter for suplemon."""
13
+
14
+ def init(self):
15
+ self.init_logging(__name__)
16
+
17
+ # TODO: Run linting in a seperate thread to avoid
18
+ # blocking the UI when the app is loading
19
+
20
+ # Lint all files after app is loaded
21
+ self.bind_event_after("app_loaded", self.on_loaded)
22
+ # Show linting messages in status bar
23
+ self.bind_event_after("mainloop", self.mainloop)
24
+ # Re-lint current file when appropriate
25
+ self.bind_event_after("save_file", self.lint_current_file)
26
+ self.bind_event_after("save_file_as", self.lint_current_file)
27
+ self.bind_event_after("reload_file", self.lint_current_file)
28
+ self.bind_event_after("open_file", self.lint_current_file)
29
+
30
+ def run(self, app, editor, args):
31
+ """Run the linting command."""
32
+ editor = self.app.get_file().get_editor()
33
+ count = self.get_msg_count(editor)
34
+ status = "{0} lines with linting errors in this file.".format(str(count))
35
+ self.app.set_status(status)
36
+
37
+ def on_loaded(self, event):
38
+ # Lint all files in a thread since it might take a while
39
+ thread = threading.Thread(target=self.lint_all_files, args=(event,))
40
+ # Use daemon mode to forcefully shutdown the thread on application exit.
41
+ # Python2 doesn't know the boolean daemon keyword argument to the Thread()
42
+ # constructor so we use the .daemon property instead.
43
+ thread.daemon = True
44
+ thread.start()
45
+
46
+ def mainloop(self, event):
47
+ """Run the linting command."""
48
+ file = self.app.get_file()
49
+ editor = file.get_editor()
50
+ cursor = editor.get_cursor()
51
+ if len(editor.cursors) > 1:
52
+ return False
53
+ line_no = cursor.y + 1
54
+ msg = self.get_msgs_on_line(editor, cursor.y)
55
+ if msg:
56
+ self.app.set_status("Line {0}: {1}".format(str(line_no), msg))
57
+
58
+ def lint_current_file(self, event):
59
+ self.lint_file(self.app.get_file())
60
+
61
+ def lint_all_files(self, event):
62
+ """Do linting check for all open files and store results."""
63
+ for file in self.app.files:
64
+ self.lint_file(file)
65
+ return False
66
+
67
+ def lint_file(self, file):
68
+ path = file.get_path()
69
+ if not path: # Unsaved file
70
+ return False
71
+
72
+ ext = file.get_extension().lower()
73
+ linter = False
74
+ if ext == "py":
75
+ linter = PyLint(self.logger)
76
+ elif ext == "js":
77
+ linter = JsLint(self.logger)
78
+ elif ext == "php":
79
+ linter = PhpLint(self.logger)
80
+
81
+ if not linter:
82
+ return False
83
+
84
+ linting = linter.lint(path)
85
+ if linting is False:
86
+ return False
87
+
88
+ editor = file.get_editor()
89
+ for line_no in range(len(editor.lines)):
90
+ line = editor.lines[line_no]
91
+ if line_no+1 in linting.keys():
92
+ line.linting = linting[line_no+1]
93
+ line.set_number_color(1)
94
+ else:
95
+ line.linting = False
96
+ line.reset_number_color()
97
+
98
+ def get_msgs_on_line(self, editor, line_no):
99
+ line = editor.lines[line_no]
100
+ if not hasattr(line, "linting") or not line.linting:
101
+ return False
102
+ return line.linting[0][1]
103
+
104
+ def get_msg_count(self, editor):
105
+ count = 0
106
+ for line in editor.lines:
107
+ if hasattr(line, "linting"):
108
+ if line.linting:
109
+ count += 1
110
+ return count
111
+
112
+
113
+ class BaseLint:
114
+ def __init__(self, logger):
115
+ self.logger = logger
116
+
117
+ def lint(self, path):
118
+ pass
119
+
120
+ def get_file_linting(self, path):
121
+ """Do linting check for given file path."""
122
+ return {}
123
+
124
+ def get_output(self, cmd):
125
+ try:
126
+ fnull = open(os.devnull, "w")
127
+ process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=fnull)
128
+ fnull.close()
129
+ except OSError:
130
+ self.logger.debug("Subprocess failed.")
131
+ return False
132
+ out, err = process.communicate()
133
+ return out
134
+
135
+
136
+ class PyLint(BaseLint):
137
+ def __init__(self, logger):
138
+ BaseLint.__init__(self, logger)
139
+ # Error codes to ignore e.g. 'E501' (line too long)
140
+ self.ignore = []
141
+ # Max length of line
142
+ self.max_line_length = 120 # Default is 79
143
+
144
+ def lint(self, path):
145
+ if not self.has_flake8_support():
146
+ self.logger.warning("Flake8 not available. Can't show linting.")
147
+ return False
148
+ self.logger.debug(self.has_flake8_support())
149
+ return self.get_file_linting(path)
150
+
151
+ def has_flake8_support(self):
152
+ output = self.get_output(["flake8", "--version"])
153
+ return output
154
+
155
+ def get_file_linting(self, path):
156
+ """Do linting check for given file path."""
157
+ output = self.get_output(["flake8", "--max-line-length", str(self.max_line_length), path])
158
+ if output is False:
159
+ self.logger.warning("Failed to get linting for file '{0}'.".format(path))
160
+ return False
161
+ output = output.decode("utf-8")
162
+ # Remove file paths from output
163
+ output = output.replace(path+":", "")
164
+ lines = output.split("\n")
165
+ linting = {}
166
+ for line in lines:
167
+ if not line:
168
+ continue
169
+ try:
170
+ parts = line.split(":")
171
+ line_no = int(parts[0])
172
+ char_no = int(parts[1])
173
+ data = ":".join(parts[2:]).strip()
174
+ err_code = data.split(" ")[0]
175
+ if err_code in self.ignore:
176
+ continue
177
+ if line_no not in linting.keys():
178
+ linting[line_no] = []
179
+ linting[line_no].append((char_no, data, err_code))
180
+ except (IndexError, ValueError):
181
+ self.logger.debug("Failed to parse line:{0}".format(line))
182
+ return linting
183
+
184
+
185
+ class JsLint(BaseLint):
186
+ def __init__(self, logger):
187
+ BaseLint.__init__(self, logger)
188
+
189
+ def lint(self, path):
190
+ return self.get_file_linting(path)
191
+
192
+ def get_file_linting(self, path):
193
+ """Do linting check for given file path."""
194
+ output = self.get_output(["jshint", path])
195
+ if output is False:
196
+ self.logger.warning("Failed to get linting for file '{0}'.".format(path))
197
+ return False
198
+ output = output.decode("utf-8")
199
+ # Remove file paths from output
200
+ output = output.replace(path+": ", "")
201
+ lines = output.split("\n")
202
+ linting = {}
203
+ for line in lines:
204
+ if not line:
205
+ continue
206
+ try:
207
+ parts = line.split(", ")
208
+ if len(parts) < 3:
209
+ continue
210
+ line_no = int(re.sub(r"\D", "", parts[0]))
211
+ char_no = int(re.sub(r"\D", "", parts[1]))
212
+ data = parts[2]
213
+ err_code = None
214
+ if line_no not in linting.keys():
215
+ linting[line_no] = []
216
+ linting[line_no].append((char_no, data, err_code))
217
+ except (IndexError, ValueError):
218
+ self.logger.debug("Failed to parse line:{0}".format(line))
219
+ return linting
220
+
221
+
222
+ class PhpLint(BaseLint):
223
+ def __init__(self, logger):
224
+ BaseLint.__init__(self, logger)
225
+
226
+ def lint(self, path):
227
+ return self.get_file_linting(path)
228
+
229
+ def get_output(self, cmd, errors=False):
230
+ # Need to override this since php reports the errors to stderr
231
+ try:
232
+ fnull = open(os.devnull, "w")
233
+ process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
234
+ fnull.close()
235
+ except OSError:
236
+ self.logger.debug("Subprocess failed.")
237
+ return False
238
+ out, err = process.communicate()
239
+ return err
240
+
241
+ def get_file_linting(self, path):
242
+ """Do linting check for given file path."""
243
+ output = self.get_output(["php", "-l", path])
244
+ if output is False:
245
+ self.logger.warning("Failed to get linting for file '{0}'.".format(path))
246
+ return False
247
+ output = output.decode("utf-8")
248
+ lines = output.split("\n")
249
+ linting = {}
250
+ for line in lines:
251
+ line = line.strip()
252
+ if not line:
253
+ continue
254
+ try:
255
+ parts = line.split(" in {0} on line ".format(path))
256
+ self.logger.debug(parts)
257
+ if len(parts) != 2:
258
+ continue
259
+ line_no = int(parts[1])
260
+ char_no = 0
261
+ data = parts[0]
262
+ err_code = None
263
+ if line_no not in linting.keys():
264
+ linting[line_no] = []
265
+ linting[line_no].append((char_no, data, err_code))
266
+ except (IndexError, ValueError):
267
+ self.logger.debug("Failed to parse line:{0}".format(line))
268
+ return linting
269
+
270
+
271
+ module = {
272
+ "class": Linter,
273
+ "name": "linter",
274
+ }
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8
2
+
3
+ from suplemon.suplemon_module import Module
4
+
5
+
6
+ class Lower(Module):
7
+ """Transform current lines to lower case."""
8
+
9
+ def run(self, app, editor, args):
10
+ line_nums = []
11
+ for cursor in editor.cursors:
12
+ if cursor.y not in line_nums:
13
+ line_nums.append(cursor.y)
14
+ new_data = editor.lines[cursor.y].get_data().lower()
15
+ editor.lines[cursor.y].data = new_data
16
+
17
+
18
+ module = {
19
+ "class": Lower,
20
+ "name": "lower",
21
+ }
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8
2
+
3
+ from suplemon.suplemon_module import Module
4
+
5
+
6
+ class LStrip(Module):
7
+ """Trim whitespace from beginning of current lines."""
8
+
9
+ def run(self, app, editor, args):
10
+ # TODO: move cursors in sync with line contents
11
+ line_nums = editor.get_lines_with_cursors()
12
+ for n in line_nums:
13
+ line = editor.lines[n]
14
+ line.data = line.data.lstrip()
15
+
16
+
17
+ module = {
18
+ "class": LStrip,
19
+ "name": "lstrip",
20
+ }
@@ -0,0 +1,49 @@
1
+ # -*- encoding: utf-8
2
+
3
+ from suplemon.suplemon_module import Module
4
+
5
+
6
+ class Paste(Module):
7
+ """Toggle paste mode (helpful when pasting over SSH if auto indent is enabled)"""
8
+
9
+ def init(self):
10
+ # Flag for paste mode
11
+ self.active = False
12
+ # Initial state of auto indent
13
+ self.auto_indent_active = self.app.config["editor"]["auto_indent_newline"]
14
+ # Listen for config changes
15
+ self.bind_event_after("config_loaded", self.config_loaded)
16
+
17
+ def run(self, app, editor, args):
18
+ # Simply toggle pastemode when the command is run
19
+ self.active = not self.active
20
+ self.set_paste_mode(self.active)
21
+ self.show_confirmation()
22
+ return True
23
+
24
+ def config_loaded(self, e):
25
+ # Refresh the auto indent state when config is reloaded
26
+ self.auto_indent_active = self.app.config["editor"]["auto_indent_newline"]
27
+
28
+ def get_status(self):
29
+ # Return the paste mode status for the statusbar
30
+ return "[PASTEMODE]" if self.active else ""
31
+
32
+ def show_confirmation(self):
33
+ # Show a status message when pastemode is toggled
34
+ state = "activated" if self.active else "deactivated"
35
+ self.app.set_status("Paste mode " + state)
36
+
37
+ def set_paste_mode(self, active):
38
+ # Enable or disable auto indent
39
+ if active:
40
+ self.app.config["editor"]["auto_indent_newline"] = False
41
+ else:
42
+ self.app.config["editor"]["auto_indent_newline"] = self.auto_indent_active
43
+
44
+
45
+ module = {
46
+ "class": Paste,
47
+ "name": "paste",
48
+ "status": "bottom",
49
+ }
@@ -0,0 +1,16 @@
1
+ # -*- encoding: utf-8
2
+
3
+ from suplemon.suplemon_module import Module
4
+
5
+
6
+ class Reload(Module):
7
+ """Reload all add-on modules."""
8
+
9
+ def run(self, app, editor, args):
10
+ self.app.modules.load()
11
+
12
+
13
+ module = {
14
+ "class": Reload,
15
+ "name": "reload",
16
+ }
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8
2
+
3
+ from suplemon.suplemon_module import Module
4
+
5
+
6
+ class ReplaceAll(Module):
7
+ """Replace all occurrences in all files of given text with given replacement."""
8
+
9
+ def run(self, app, editor, args):
10
+ r_from = self.app.ui.query("Replace text:")
11
+ if not r_from:
12
+ return False
13
+ r_to = self.app.ui.query("Replace with:")
14
+ if not r_to:
15
+ return False
16
+ for file in app.get_files():
17
+ file.editor.replace_all(r_from, r_to)
18
+
19
+
20
+ module = {
21
+ "class": ReplaceAll,
22
+ "name": "replace_all",
23
+ }