Show More
@@ -0,0 +1,242 b'' | |||||
|
1 | import IPython.ipapi | |||
|
2 | ip = IPython.ipapi.get() | |||
|
3 | ||||
|
4 | import win32api | |||
|
5 | import win32ui | |||
|
6 | import win32console | |||
|
7 | import dde | |||
|
8 | import os | |||
|
9 | import scitedirector | |||
|
10 | ||||
|
11 | # test to write. | |||
|
12 | ||||
|
13 | def set_hook(synchronize_with_editor): | |||
|
14 | """Set the synchronize with editor hook with a callable object. | |||
|
15 | ||||
|
16 | The callable object will be called with the following arguments when | |||
|
17 | IPython wants to synchronize with you favorite editor: | |||
|
18 | ||||
|
19 | - ip: a running IPython instance. | |||
|
20 | ||||
|
21 | - filename: the path of the file the editor is supposed to display. | |||
|
22 | ||||
|
23 | - lineno : the line number of the line the editor is supposed to | |||
|
24 | highlight. | |||
|
25 | ||||
|
26 | - columnno : the column number of the character the editor is supposed | |||
|
27 | to highlight. | |||
|
28 | """ | |||
|
29 | ip.set_hook("synchronize_with_editor", synchronize_with_editor) | |||
|
30 | ||||
|
31 | ||||
|
32 | def find_filename(filename): | |||
|
33 | """Return the filename to synchronize with based on """ | |||
|
34 | filename = os.path.splitext(filename) | |||
|
35 | if filename[1] == ".pyc": | |||
|
36 | filename = (filename[0], ".py") | |||
|
37 | filename = "".join(filename) | |||
|
38 | ||||
|
39 | if not os.path.isabs(filename): | |||
|
40 | filename = os.path.join(os.getcwd(), filename) | |||
|
41 | ||||
|
42 | if os.path.isfile(filename): | |||
|
43 | return filename | |||
|
44 | ||||
|
45 | return "" | |||
|
46 | ||||
|
47 | ||||
|
48 | def run_command(path, command, arguments, asynchronous = True): | |||
|
49 | """Run a shell command and return the exit code of the command""" | |||
|
50 | # This is a thin wrapper around os.system that: | |||
|
51 | # - Let you run command asynchronously. | |||
|
52 | # - Accept spaces in command path. | |||
|
53 | # - Dont throw exception if the command don't exist. | |||
|
54 | line = '' | |||
|
55 | if asynchronous: | |||
|
56 | line += 'start ' | |||
|
57 | ||||
|
58 | try: | |||
|
59 | line += win32api.GetShortPathName(os.path.join(path, command) + ".exe") + " " | |||
|
60 | except: | |||
|
61 | print 'could not find: "%s"' % (os.path.join(path, command) + ".exe") | |||
|
62 | return -1 | |||
|
63 | ||||
|
64 | line += arguments | |||
|
65 | r = os.system(line) | |||
|
66 | return r | |||
|
67 | ||||
|
68 | ||||
|
69 | def sleep(milliseconds): | |||
|
70 | """Wait some milliseconds.""" | |||
|
71 | # This is used to make sure the editor did its job before we reset the focus on the console. | |||
|
72 | win32api.Sleep(milliseconds) | |||
|
73 | ||||
|
74 | ||||
|
75 | def restore_console_focus(): | |||
|
76 | """Restore the focus to the IPython console.""" | |||
|
77 | h = win32console.GetConsoleWindow() | |||
|
78 | console_window = win32ui.CreateWindowFromHandle(h) | |||
|
79 | console_window.SetForegroundWindow() | |||
|
80 | ||||
|
81 | ||||
|
82 | # This is the most simple example of hook: | |||
|
83 | class GVimHook: | |||
|
84 | def __init__(self, path, wakeup_duration): | |||
|
85 | self.path = path | |||
|
86 | self.wakeup_duration = wakeup_duration | |||
|
87 | ||||
|
88 | def __call__(self, ip, filename, lineno, columnno): | |||
|
89 | filename = find_filename(filename) | |||
|
90 | ||||
|
91 | if not filename: | |||
|
92 | return | |||
|
93 | ||||
|
94 | run_command(self.path, 'gvim', '--remote-silent +%d "%s"' % (lineno, filename)) | |||
|
95 | ||||
|
96 | sleep(self.wakeup_duration) | |||
|
97 | ||||
|
98 | restore_console_focus() | |||
|
99 | ||||
|
100 | ||||
|
101 | def gvim(path = r"C:\Program Files\vim\vim71", wakeup_duration = 100): | |||
|
102 | synchronize_with_editor = GVimHook(path, wakeup_duration) | |||
|
103 | set_hook(synchronize_with_editor) | |||
|
104 | ||||
|
105 | ||||
|
106 | class EmacsHook: | |||
|
107 | def __init__(self, path, wakeup_duration, start_duration): | |||
|
108 | self.path = path | |||
|
109 | self.wakeup_duration = wakeup_duration | |||
|
110 | self.start_duration = start_duration | |||
|
111 | ||||
|
112 | def __call__(self, ip, filename, lineno, columnno): | |||
|
113 | filename = find_filename(filename) | |||
|
114 | ||||
|
115 | if not filename: | |||
|
116 | return | |||
|
117 | ||||
|
118 | r = run_command(self.path, "emacsclient", '-n +%d:%d "%s" 2>nul' % (lineno, columnno, filename), False) | |||
|
119 | if r != 0: | |||
|
120 | run_command(self.path, 'runemacs', '--quick -f server-start +%d:%d "%s"' % (lineno, columnno, filename)) | |||
|
121 | sleep(self.start_duration) | |||
|
122 | else: | |||
|
123 | sleep(self.wakeup_duration) | |||
|
124 | ||||
|
125 | restore_console_focus() | |||
|
126 | ||||
|
127 | ||||
|
128 | def emacs(path = r"C:\Program Files\emacs\bin", wakeup_duration = 100, start_duration = 2000): | |||
|
129 | synchronize_with_editor = EmacsHook(path, wakeup_duration, start_duration) | |||
|
130 | set_hook(synchronize_with_editor) | |||
|
131 | ||||
|
132 | ||||
|
133 | class SciteHook: | |||
|
134 | def __init__(self, path, wakeup_duration, start_duration): | |||
|
135 | self.path = path | |||
|
136 | self.wakeup_duration = wakeup_duration | |||
|
137 | self.start_duration = start_duration | |||
|
138 | ||||
|
139 | def __call__(self, ip, filename, lineno, columnno): | |||
|
140 | filename = find_filename(filename) | |||
|
141 | ||||
|
142 | if not filename: | |||
|
143 | return | |||
|
144 | ||||
|
145 | scites = scitedirector.findWindows() | |||
|
146 | if not scites: | |||
|
147 | run_command(self.path, "scite", '"-open:%s" -goto:%d' % (filename.replace("\\", "/"), lineno)) | |||
|
148 | ||||
|
149 | sleep(self.start_duration) | |||
|
150 | restore_console_focus() | |||
|
151 | else: | |||
|
152 | scite = scites[0] | |||
|
153 | scitedirector.sendCommand(scite, 'open:%s' % filename.replace("\\", "/")) | |||
|
154 | scitedirector.sendCommand(scite, "goto:%d" % lineno) | |||
|
155 | ||||
|
156 | ||||
|
157 | def scite(path = r"C:\Program Files\SciTE Source Code Editor", wakeup_duration = 100, start_duration = 500): | |||
|
158 | synchronize_with_editor = SciteHook(path, wakeup_duration, start_duration) | |||
|
159 | set_hook(synchronize_with_editor) | |||
|
160 | ||||
|
161 | ||||
|
162 | class NodePadPlusPlusHook: | |||
|
163 | def __init__(self, path, wakeup_duration): | |||
|
164 | self.path = path | |||
|
165 | self.wakeup_duration = wakeup_duration | |||
|
166 | ||||
|
167 | def __call__(self, ip, filename, lineno, columnno): | |||
|
168 | filename = find_filename(filename) | |||
|
169 | ||||
|
170 | if not filename: | |||
|
171 | return | |||
|
172 | ||||
|
173 | run_command(self.path, "notepad++", '"%s" -n%d' % (filename, lineno)) | |||
|
174 | ||||
|
175 | sleep(self.wakeup_duration) | |||
|
176 | ||||
|
177 | restore_console_focus() | |||
|
178 | ||||
|
179 | ||||
|
180 | def notepadplusplus(path = r"C:\Program Files\Notepad++", wakeup_duration = 100): | |||
|
181 | synchronize_with_editor = NodePadPlusPlusHook(path, wakeup_duration) | |||
|
182 | set_hook(synchronize_with_editor) | |||
|
183 | ||||
|
184 | ||||
|
185 | class PsPadHook: | |||
|
186 | def __init__(self, path, wakeup_duration): | |||
|
187 | self.path = path | |||
|
188 | self.wakeup_duration = wakeup_duration | |||
|
189 | ||||
|
190 | def __call__(self, ip, filename, lineno, columnno): | |||
|
191 | filename = find_filename(filename) | |||
|
192 | ||||
|
193 | if not filename: | |||
|
194 | return | |||
|
195 | ||||
|
196 | run_command(self.path, "pspad", '"%s" -%d' % (filename, lineno)) | |||
|
197 | ||||
|
198 | sleep(self.wakeup_duration) | |||
|
199 | ||||
|
200 | restore_console_focus() | |||
|
201 | ||||
|
202 | ||||
|
203 | def pspad(path = r"C:\Program Files\PSPad editor", wakeup_duration = 100): | |||
|
204 | synchronize_with_editor = PsPadHook(path, wakeup_duration) | |||
|
205 | set_hook(synchronize_with_editor) | |||
|
206 | ||||
|
207 | ||||
|
208 | # This is an example of DDE hook: | |||
|
209 | class UltraEditHook: | |||
|
210 | def __init__(self, path, wakeup_duration, start_duration): | |||
|
211 | self.path = path | |||
|
212 | self.wakeup_duration = wakeup_duration | |||
|
213 | self.start_duration = start_duration | |||
|
214 | ||||
|
215 | def __call__(self, ip, filename, lineno, columnno): | |||
|
216 | filename = find_filename(filename) | |||
|
217 | ||||
|
218 | if not filename: | |||
|
219 | return | |||
|
220 | ||||
|
221 | server = dde.CreateServer() | |||
|
222 | server.Create("myddeserver") | |||
|
223 | conversation = dde.CreateConversation(server) | |||
|
224 | try: | |||
|
225 | conversation.ConnectTo("uedit32", "System") | |||
|
226 | conversation.Exec(r'[open("%s/%d"])' % (filename, lineno)) | |||
|
227 | ||||
|
228 | sleep(self.wakeup_duration) | |||
|
229 | except: | |||
|
230 | run_command(self.path, 'uedit32', '"%s/%d"' % (filename, lineno)) | |||
|
231 | ||||
|
232 | sleep(self.start_duration) | |||
|
233 | ||||
|
234 | server.Shutdown() | |||
|
235 | ||||
|
236 | restore_console_focus() | |||
|
237 | ||||
|
238 | ||||
|
239 | def ultraedit(path = r"C:\Program Files\IDM Computer Solutions\UltraEdit-32", wakeup_duration = 10, start_duration = 2000): | |||
|
240 | synchronize_with_editor = UltraEditHook(path, wakeup_duration, start_duration) | |||
|
241 | set_hook(synchronize_with_editor) | |||
|
242 | No newline at end of file |
@@ -0,0 +1,26 b'' | |||||
|
1 | import win32api | |||
|
2 | import win32gui | |||
|
3 | import win32con | |||
|
4 | ||||
|
5 | import struct | |||
|
6 | import array | |||
|
7 | ||||
|
8 | def findWindows(): | |||
|
9 | ret = [] | |||
|
10 | sdi = win32api.RegisterWindowMessage("SciTEDirectorInterface") | |||
|
11 | w = win32gui.GetWindow(win32gui.GetDesktopWindow(), win32con.GW_CHILD) | |||
|
12 | while w: | |||
|
13 | res = win32gui.SendMessage(w, sdi, 0, 0) | |||
|
14 | if res == sdi: | |||
|
15 | ret.append(w) | |||
|
16 | w = win32gui.GetWindow(w, win32con.GW_HWNDNEXT) | |||
|
17 | ||||
|
18 | return ret | |||
|
19 | ||||
|
20 | def sendCommand(w, message): | |||
|
21 | CopyDataStruct = "IIP" | |||
|
22 | char_buffer = array.array('c', message) | |||
|
23 | char_buffer_address = char_buffer.buffer_info()[0] | |||
|
24 | char_buffer_size = char_buffer.buffer_info()[1] | |||
|
25 | cds = struct.pack(CopyDataStruct, 0, char_buffer_size, char_buffer_address) | |||
|
26 | win32gui.SendMessage(w, win32con.WM_COPYDATA, 0, cds) |
@@ -333,6 +333,12 b' class Pdb(OldPdb):' | |||||
333 | #frame, lineno = frame_lineno |
|
333 | #frame, lineno = frame_lineno | |
334 | print >>Term.cout, self.format_stack_entry(frame_lineno, '', context) |
|
334 | print >>Term.cout, self.format_stack_entry(frame_lineno, '', context) | |
335 |
|
335 | |||
|
336 | # vds: >> | |||
|
337 | frame, lineno = frame_lineno | |||
|
338 | filename = frame.f_code.co_filename | |||
|
339 | __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0) | |||
|
340 | # vds: << | |||
|
341 | ||||
336 | def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3): |
|
342 | def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3): | |
337 | import linecache, repr |
|
343 | import linecache, repr | |
338 |
|
344 | |||
@@ -496,6 +502,12 b' class Pdb(OldPdb):' | |||||
496 | last = first + 10 |
|
502 | last = first + 10 | |
497 | self.print_list_lines(self.curframe.f_code.co_filename, first, last) |
|
503 | self.print_list_lines(self.curframe.f_code.co_filename, first, last) | |
498 |
|
504 | |||
|
505 | # vds: >> | |||
|
506 | lineno = first | |||
|
507 | filename = self.curframe.f_code.co_filename | |||
|
508 | __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0) | |||
|
509 | # vds: << | |||
|
510 | ||||
499 | do_l = do_list |
|
511 | do_l = do_list | |
500 |
|
512 | |||
501 | def do_pdef(self, arg): |
|
513 | def do_pdef(self, arg): |
@@ -53,10 +53,12 b' from pprint import PrettyPrinter' | |||||
53 |
|
53 | |||
54 | # List here all the default hooks. For now it's just the editor functions |
|
54 | # List here all the default hooks. For now it's just the editor functions | |
55 | # but over time we'll move here all the public API for user-accessible things. |
|
55 | # but over time we'll move here all the public API for user-accessible things. | |
56 | __all__ = ['editor', 'fix_error_editor', 'result_display', |
|
56 | # vds: >> | |
|
57 | __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', 'result_display', | |||
57 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', |
|
58 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', | |
58 | 'generate_prompt', 'generate_output_prompt','shell_hook', |
|
59 | 'generate_prompt', 'generate_output_prompt','shell_hook', | |
59 | 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook'] |
|
60 | 'show_in_pager','pre_prompt_hook', 'pre_runcode_hook'] | |
|
61 | # vds: << | |||
60 |
|
62 | |||
61 | pformat = PrettyPrinter().pformat |
|
63 | pformat = PrettyPrinter().pformat | |
62 |
|
64 | |||
@@ -107,6 +109,10 b' def fix_error_editor(self,filename,linenum,column,msg):' | |||||
107 | finally: |
|
109 | finally: | |
108 | t.close() |
|
110 | t.close() | |
109 |
|
111 | |||
|
112 | # vds: >> | |||
|
113 | def synchronize_with_editor(self, filename, linenum, column): | |||
|
114 | pass | |||
|
115 | # vds: << | |||
110 |
|
116 | |||
111 | class CommandChainDispatcher: |
|
117 | class CommandChainDispatcher: | |
112 | """ Dispatch calls to a chain of commands until some func can handle it |
|
118 | """ Dispatch calls to a chain of commands until some func can handle it |
@@ -490,6 +490,11 b' class ListTB(TBTools):' | |||||
490 | Colors.Normal, s)) |
|
490 | Colors.Normal, s)) | |
491 | else: |
|
491 | else: | |
492 | list.append('%s\n' % str(stype)) |
|
492 | list.append('%s\n' % str(stype)) | |
|
493 | ||||
|
494 | # vds:>> | |||
|
495 | __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0) | |||
|
496 | # vds:<< | |||
|
497 | ||||
493 | return list |
|
498 | return list | |
494 |
|
499 | |||
495 | def _some_str(self, value): |
|
500 | def _some_str(self, value): | |
@@ -801,6 +806,15 b' class VerboseTB(TBTools):' | |||||
801 | for name in names: |
|
806 | for name in names: | |
802 | value = text_repr(getattr(evalue, name)) |
|
807 | value = text_repr(getattr(evalue, name)) | |
803 | exception.append('\n%s%s = %s' % (indent, name, value)) |
|
808 | exception.append('\n%s%s = %s' % (indent, name, value)) | |
|
809 | ||||
|
810 | # vds: >> | |||
|
811 | if records: | |||
|
812 | frame, file, lnum, func, lines, index = records[-1] | |||
|
813 | #print "file:", str(file), "linenb", str(lnum) | |||
|
814 | file = abspath(file) | |||
|
815 | __IPYTHON__.hooks.synchronize_with_editor(file, lnum, 0) | |||
|
816 | # vds: << | |||
|
817 | ||||
804 | # return all our info assembled as a single string |
|
818 | # return all our info assembled as a single string | |
805 | return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) ) |
|
819 | return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) ) | |
806 |
|
820 |
General Comments 0
You need to be logged in to leave comments.
Login now