##// END OF EJS Templates
Merge pull request #11734 from Carreau/autoformat-black...
Matthias Bussonnier -
r25249:17e9ca62 merge
parent child Browse files
Show More
@@ -0,0 +1,24 b''
1 Code autoformatting
2 ===================
3
4 The IPython terminal can now auto format your code just before entering a new
5 line or executing a command. To do so use the
6 ``--TerminalInteractiveShell.autoformatter`` option and set it to ``'black'``;
7 if black is installed IPython will use black to format your code when possible.
8
9 IPython cannot always properly format your code; in particular it will
10 auto formatting with *black* will only work if:
11
12 - Your code does not contains magics or special python syntax.
13
14 - There is no code after your cursor.
15
16 The Black API is also still in motion; so this may not work with all versions of
17 black.
18
19 It should be possible to register custom reformatter, though the API is till in
20 flux.
21
22
23
24
@@ -87,6 +87,14 b' else:'
87 87
88 88 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
89 89
90 def black_reformat_handler(text_before_cursor):
91 import black
92 formatted_text = black.format_str(text_before_cursor, mode=black.FileMode())
93 if not text_before_cursor.endswith('\n') and formatted_text.endswith('\n'):
94 formatted_text = formatted_text[:-1]
95 return formatted_text
96
97
90 98 class TerminalInteractiveShell(InteractiveShell):
91 99 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
92 100 'to reserve for the completion menu'
@@ -120,6 +128,11 b' class TerminalInteractiveShell(InteractiveShell):'
120 128 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
121 129 ).tag(config=True)
122 130
131 autoformatter = Unicode(None,
132 help="Autoformatter to reformat Terminal code. Can be `'black'` or `None`",
133 allow_none=True
134 ).tag(config=True)
135
123 136 mouse_support = Bool(False,
124 137 help="Enable mouse support in the prompt\n(Note: prevents selecting text with the mouse)"
125 138 ).tag(config=True)
@@ -150,6 +163,16 b' class TerminalInteractiveShell(InteractiveShell):'
150 163 if self.pt_app:
151 164 self.pt_app.editing_mode = u_mode
152 165
166 @observe('autoformatter')
167 def _autoformatter_changed(self, change):
168 formatter = change.new
169 if formatter is None:
170 self.reformat_handler = lambda x:x
171 elif formatter == 'black':
172 self.reformat_handler = black_reformat_handler
173 else:
174 raise ValueError
175
153 176 @observe('highlighting_style')
154 177 @observe('colors')
155 178 def _highlighting_style_changed(self, change):
@@ -44,6 +44,15 b' def create_ipython_shortcuts(shell):'
44 44 & insert_mode
45 45 ))(return_handler)
46 46
47 def reformat_and_execute(event):
48 reformat_text_before_cursor(event.current_buffer, event.current_buffer.document, shell)
49 event.current_buffer.validate_and_handle()
50
51 kb.add('escape', 'enter', filter=(has_focus(DEFAULT_BUFFER)
52 & ~has_selection
53 & insert_mode
54 ))(reformat_and_execute)
55
47 56 kb.add('c-\\')(force_exit)
48 57
49 58 kb.add('c-p', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
@@ -86,7 +95,17 b' def create_ipython_shortcuts(shell):'
86 95 return kb
87 96
88 97
98 def reformat_text_before_cursor(buffer, document, shell):
99 text = buffer.delete_before_cursor(len(document.text[:document.cursor_position]))
100 try:
101 formatted_text = shell.reformat_handler(text)
102 buffer.insert_text(formatted_text)
103 except Exception as e:
104 buffer.insert_text(text)
105
106
89 107 def newline_or_execute_outer(shell):
108
90 109 def newline_or_execute(event):
91 110 """When the user presses return, insert a newline or execute the code."""
92 111 b = event.current_buffer
@@ -107,7 +126,12 b' def newline_or_execute_outer(shell):'
107 126 else:
108 127 check_text = d.text[:d.cursor_position]
109 128 status, indent = shell.check_complete(check_text)
110
129
130 # if all we have after the cursor is whitespace: reformat current text
131 # before cursor
132 after_cursor = d.text[d.cursor_position:]
133 if not after_cursor.strip():
134 reformat_text_before_cursor(b, d, shell)
111 135 if not (d.on_last_line or
112 136 d.cursor_position_row >= d.line_count - d.empty_line_count_at_the_end()
113 137 ):
@@ -118,6 +142,7 b' def newline_or_execute_outer(shell):'
118 142 return
119 143
120 144 if (status != 'incomplete') and b.accept_handler:
145 reformat_text_before_cursor(b, d, shell)
121 146 b.validate_and_handle()
122 147 else:
123 148 if shell.autoindent:
General Comments 0
You need to be logged in to leave comments. Login now