| | """Extra magics for terminal use.""" |
| |
|
| | |
| | |
| |
|
| |
|
| | from logging import error |
| | import os |
| | import sys |
| |
|
| | from IPython.core.error import TryNext, UsageError |
| | from IPython.core.magic import Magics, magics_class, line_magic |
| | from IPython.lib.clipboard import ClipboardEmpty |
| | from IPython.testing.skipdoctest import skip_doctest |
| | from IPython.utils.text import SList, strip_email_quotes |
| | from IPython.utils import py3compat |
| |
|
| | def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False): |
| | """ Yield pasted lines until the user enters the given sentinel value. |
| | """ |
| | if not quiet: |
| | print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \ |
| | % sentinel) |
| | prompt = ":" |
| | else: |
| | prompt = "" |
| | while True: |
| | try: |
| | l = l_input(prompt) |
| | if l == sentinel: |
| | return |
| | else: |
| | yield l |
| | except EOFError: |
| | print('<EOF>') |
| | return |
| |
|
| |
|
| | @magics_class |
| | class TerminalMagics(Magics): |
| | def __init__(self, shell): |
| | super(TerminalMagics, self).__init__(shell) |
| |
|
| | def store_or_execute(self, block, name, store_history=False): |
| | """ Execute a block, or store it in a variable, per the user's request. |
| | """ |
| | if name: |
| | |
| | self.shell.user_ns[name] = SList(block.splitlines()) |
| | print("Block assigned to '%s'" % name) |
| | else: |
| | b = self.preclean_input(block) |
| | self.shell.user_ns['pasted_block'] = b |
| | self.shell.using_paste_magics = True |
| | try: |
| | self.shell.run_cell(b, store_history) |
| | finally: |
| | self.shell.using_paste_magics = False |
| |
|
| | def preclean_input(self, block): |
| | lines = block.splitlines() |
| | while lines and not lines[0].strip(): |
| | lines = lines[1:] |
| | return strip_email_quotes('\n'.join(lines)) |
| |
|
| | def rerun_pasted(self, name='pasted_block'): |
| | """ Rerun a previously pasted command. |
| | """ |
| | b = self.shell.user_ns.get(name) |
| |
|
| | |
| | if b is None: |
| | raise UsageError('No previous pasted block available') |
| | if not isinstance(b, str): |
| | raise UsageError( |
| | "Variable 'pasted_block' is not a string, can't execute") |
| |
|
| | print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b))) |
| | self.shell.run_cell(b) |
| |
|
| | @line_magic |
| | def autoindent(self, parameter_s = ''): |
| | """Toggle autoindent on/off (deprecated)""" |
| | self.shell.set_autoindent() |
| | print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent]) |
| |
|
| | @skip_doctest |
| | @line_magic |
| | def cpaste(self, parameter_s=''): |
| | """Paste & execute a pre-formatted code block from clipboard. |
| | |
| | You must terminate the block with '--' (two minus-signs) or Ctrl-D |
| | alone on the line. You can also provide your own sentinel with '%paste |
| | -s %%' ('%%' is the new sentinel for this operation). |
| | |
| | The block is dedented prior to execution to enable execution of method |
| | definitions. '>' and '+' characters at the beginning of a line are |
| | ignored, to allow pasting directly from e-mails, diff files and |
| | doctests (the '...' continuation prompt is also stripped). The |
| | executed block is also assigned to variable named 'pasted_block' for |
| | later editing with '%edit pasted_block'. |
| | |
| | You can also pass a variable name as an argument, e.g. '%cpaste foo'. |
| | This assigns the pasted block to variable 'foo' as string, without |
| | dedenting or executing it (preceding >>> and + is still stripped) |
| | |
| | '%cpaste -r' re-executes the block previously entered by cpaste. |
| | '%cpaste -q' suppresses any additional output messages. |
| | |
| | Do not be alarmed by garbled output on Windows (it's a readline bug). |
| | Just press enter and type -- (and press enter again) and the block |
| | will be what was just pasted. |
| | |
| | Shell escapes are not supported (yet). |
| | |
| | See Also |
| | -------- |
| | paste : automatically pull code from clipboard. |
| | |
| | Examples |
| | -------- |
| | :: |
| | |
| | In [8]: %cpaste |
| | Pasting code; enter '--' alone on the line to stop. |
| | :>>> a = ["world!", "Hello"] |
| | :>>> print(" ".join(sorted(a))) |
| | :-- |
| | Hello world! |
| | |
| | :: |
| | In [8]: %cpaste |
| | Pasting code; enter '--' alone on the line to stop. |
| | :>>> %alias_magic t timeit |
| | :>>> %t -n1 pass |
| | :-- |
| | Created `%t` as an alias for `%timeit`. |
| | Created `%%t` as an alias for `%%timeit`. |
| | 354 ns ± 224 ns per loop (mean ± std. dev. of 7 runs, 1 loop each) |
| | """ |
| | opts, name = self.parse_options(parameter_s, 'rqs:', mode='string') |
| | if 'r' in opts: |
| | self.rerun_pasted() |
| | return |
| |
|
| | quiet = ('q' in opts) |
| |
|
| | sentinel = opts.get('s', u'--') |
| | block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet)) |
| | self.store_or_execute(block, name, store_history=True) |
| |
|
| | @line_magic |
| | def paste(self, parameter_s=''): |
| | """Paste & execute a pre-formatted code block from clipboard. |
| | |
| | The text is pulled directly from the clipboard without user |
| | intervention and printed back on the screen before execution (unless |
| | the -q flag is given to force quiet mode). |
| | |
| | The block is dedented prior to execution to enable execution of method |
| | definitions. '>' and '+' characters at the beginning of a line are |
| | ignored, to allow pasting directly from e-mails, diff files and |
| | doctests (the '...' continuation prompt is also stripped). The |
| | executed block is also assigned to variable named 'pasted_block' for |
| | later editing with '%edit pasted_block'. |
| | |
| | You can also pass a variable name as an argument, e.g. '%paste foo'. |
| | This assigns the pasted block to variable 'foo' as string, without |
| | executing it (preceding >>> and + is still stripped). |
| | |
| | Options: |
| | |
| | -r: re-executes the block previously entered by cpaste. |
| | |
| | -q: quiet mode: do not echo the pasted text back to the terminal. |
| | |
| | IPython statements (magics, shell escapes) are not supported (yet). |
| | |
| | See Also |
| | -------- |
| | cpaste : manually paste code into terminal until you mark its end. |
| | """ |
| | opts, name = self.parse_options(parameter_s, 'rq', mode='string') |
| | if 'r' in opts: |
| | self.rerun_pasted() |
| | return |
| | try: |
| | block = self.shell.hooks.clipboard_get() |
| | except TryNext as clipboard_exc: |
| | message = getattr(clipboard_exc, 'args') |
| | if message: |
| | error(message[0]) |
| | else: |
| | error('Could not get text from the clipboard.') |
| | return |
| | except ClipboardEmpty as e: |
| | raise UsageError("The clipboard appears to be empty") from e |
| |
|
| | |
| | if 'q' not in opts: |
| | sys.stdout.write(self.shell.pycolorize(block)) |
| | if not block.endswith("\n"): |
| | sys.stdout.write("\n") |
| | sys.stdout.write("## -- End pasted text --\n") |
| |
|
| | self.store_or_execute(block, name, store_history=True) |
| |
|
| | |
| | if sys.platform == 'win32': |
| | @line_magic |
| | def cls(self, s): |
| | """Clear screen. |
| | """ |
| | os.system("cls") |
| |
|