##// END OF EJS Templates
Merge pull request #10239 from segevfiner/editorhooks-wait-fix...
Thomas Kluyver -
r23296:e311b1db merge
parent child Browse files
Show More
@@ -1,128 +1,128 b''
1 1 """ 'editor' hooks for common editors that work well with ipython
2 2
3 3 They should honor the line number argument, at least.
4 4
5 5 Contributions are *very* welcome.
6 6 """
7 7
8 8 import os
9 9 import pipes
10 10 import shlex
11 11 import subprocess
12 12 import sys
13 13
14 14 from IPython import get_ipython
15 15 from IPython.core.error import TryNext
16 16 from IPython.utils import py3compat
17 17
18 18
19 19 def install_editor(template, wait=False):
20 20 """Installs the editor that is called by IPython for the %edit magic.
21 21
22 22 This overrides the default editor, which is generally set by your EDITOR
23 23 environment variable or is notepad (windows) or vi (linux). By supplying a
24 24 template string `run_template`, you can control how the editor is invoked
25 25 by IPython -- (e.g. the format in which it accepts command line options)
26 26
27 27 Parameters
28 28 ----------
29 29 template : basestring
30 30 run_template acts as a template for how your editor is invoked by
31 31 the shell. It should contain '{filename}', which will be replaced on
32 32 invokation with the file name, and '{line}', $line by line number
33 33 (or 0) to invoke the file with.
34 34 wait : bool
35 35 If `wait` is true, wait until the user presses enter before returning,
36 36 to facilitate non-blocking editors that exit immediately after
37 37 the call.
38 38 """
39 39
40 40 # not all editors support $line, so we'll leave out this check
41 41 # for substitution in ['$file', '$line']:
42 42 # if not substitution in run_template:
43 43 # raise ValueError(('run_template should contain %s'
44 44 # ' for string substitution. You supplied "%s"' % (substitution,
45 45 # run_template)))
46 46
47 47 def call_editor(self, filename, line=0):
48 48 if line is None:
49 49 line = 0
50 50 cmd = template.format(filename=pipes.quote(filename), line=line)
51 51 print(">", cmd)
52 52 # pipes.quote doesn't work right on Windows, but it does after splitting
53 53 if sys.platform.startswith('win'):
54 54 cmd = shlex.split(cmd)
55 55 proc = subprocess.Popen(cmd, shell=True)
56 if wait and proc.wait() != 0:
56 if proc.wait() != 0:
57 57 raise TryNext()
58 58 if wait:
59 59 py3compat.input("Press Enter when done editing:")
60 60
61 61 get_ipython().set_hook('editor', call_editor)
62 62 get_ipython().editor = template
63 63
64 64
65 65 # in these, exe is always the path/name of the executable. Useful
66 66 # if you don't have the editor directory in your path
67 67 def komodo(exe=u'komodo'):
68 68 """ Activestate Komodo [Edit] """
69 69 install_editor(exe + u' -l {line} {filename}', wait=True)
70 70
71 71
72 72 def scite(exe=u"scite"):
73 73 """ SciTE or Sc1 """
74 74 install_editor(exe + u' {filename} -goto:{line}')
75 75
76 76
77 77 def notepadplusplus(exe=u'notepad++'):
78 78 """ Notepad++ http://notepad-plus.sourceforge.net """
79 79 install_editor(exe + u' -n{line} {filename}')
80 80
81 81
82 82 def jed(exe=u'jed'):
83 83 """ JED, the lightweight emacsish editor """
84 84 install_editor(exe + u' +{line} {filename}')
85 85
86 86
87 87 def idle(exe=u'idle'):
88 88 """ Idle, the editor bundled with python
89 89
90 90 Parameters
91 91 ----------
92 92 exe : str, None
93 93 If none, should be pretty smart about finding the executable.
94 94 """
95 95 if exe is None:
96 96 import idlelib
97 97 p = os.path.dirname(idlelib.__filename__)
98 98 # i'm not sure if this actually works. Is this idle.py script
99 99 # guarenteed to be executable?
100 100 exe = os.path.join(p, 'idle.py')
101 101 install_editor(exe + u' {filename}')
102 102
103 103
104 104 def mate(exe=u'mate'):
105 105 """ TextMate, the missing editor"""
106 106 # wait=True is not required since we're using the -w flag to mate
107 107 install_editor(exe + u' -w -l {line} {filename}')
108 108
109 109
110 110 # ##########################################
111 111 # these are untested, report any problems
112 112 # ##########################################
113 113
114 114
115 115 def emacs(exe=u'emacs'):
116 116 install_editor(exe + u' +{line} {filename}')
117 117
118 118
119 119 def gnuclient(exe=u'gnuclient'):
120 120 install_editor(exe + u' -nw +{line} {filename}')
121 121
122 122
123 123 def crimson_editor(exe=u'cedt.exe'):
124 124 install_editor(exe + u' /L:{line} {filename}')
125 125
126 126
127 127 def kate(exe=u'kate'):
128 128 install_editor(exe + u' -u -l {line} {filename}')
@@ -1,33 +1,34 b''
1 1 """Test installing editor hooks"""
2 2 import sys
3 3 from unittest import mock
4 4
5 5 import nose.tools as nt
6 6
7 7 from IPython import get_ipython
8 8 from IPython.lib import editorhooks
9 9
10 10 def test_install_editor():
11 11 called = []
12 12 def fake_popen(*args, **kwargs):
13 13 called.append({
14 14 'args': args,
15 15 'kwargs': kwargs,
16 16 })
17 return mock.MagicMock(**{'wait.return_value': 0})
17 18 editorhooks.install_editor('foo -l {line} -f {filename}', wait=False)
18 19
19 20 with mock.patch('subprocess.Popen', fake_popen):
20 21 get_ipython().hooks.editor('the file', 64)
21 22
22 23 nt.assert_equal(len(called), 1)
23 24 args = called[0]['args']
24 25 kwargs = called[0]['kwargs']
25 26
26 27 nt.assert_equal(kwargs, {'shell': True})
27 28
28 29 if sys.platform.startswith('win'):
29 30 expected = ['foo', '-l', '64', '-f', 'the file']
30 31 else:
31 32 expected = "foo -l 64 -f 'the file'"
32 33 cmd = args[0]
33 34 nt.assert_equal(cmd, expected)
General Comments 0
You need to be logged in to leave comments. Login now