magics.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. """Extra magics for terminal use."""
  2. # Copyright (c) IPython Development Team.
  3. # Distributed under the terms of the Modified BSD License.
  4. from __future__ import print_function
  5. from logging import error
  6. import os
  7. import sys
  8. from IPython.core.error import TryNext, UsageError
  9. from IPython.core.inputsplitter import IPythonInputSplitter
  10. from IPython.core.magic import Magics, magics_class, line_magic
  11. from IPython.lib.clipboard import ClipboardEmpty
  12. from IPython.utils.text import SList, strip_email_quotes
  13. from IPython.utils import py3compat
  14. def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False):
  15. """ Yield pasted lines until the user enters the given sentinel value.
  16. """
  17. if not quiet:
  18. print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
  19. % sentinel)
  20. prompt = ":"
  21. else:
  22. prompt = ""
  23. while True:
  24. try:
  25. l = py3compat.str_to_unicode(l_input(prompt))
  26. if l == sentinel:
  27. return
  28. else:
  29. yield l
  30. except EOFError:
  31. print('<EOF>')
  32. return
  33. @magics_class
  34. class TerminalMagics(Magics):
  35. def __init__(self, shell):
  36. super(TerminalMagics, self).__init__(shell)
  37. self.input_splitter = IPythonInputSplitter()
  38. def store_or_execute(self, block, name):
  39. """ Execute a block, or store it in a variable, per the user's request.
  40. """
  41. if name:
  42. # If storing it for further editing
  43. self.shell.user_ns[name] = SList(block.splitlines())
  44. print("Block assigned to '%s'" % name)
  45. else:
  46. b = self.preclean_input(block)
  47. self.shell.user_ns['pasted_block'] = b
  48. self.shell.using_paste_magics = True
  49. try:
  50. self.shell.run_cell(b)
  51. finally:
  52. self.shell.using_paste_magics = False
  53. def preclean_input(self, block):
  54. lines = block.splitlines()
  55. while lines and not lines[0].strip():
  56. lines = lines[1:]
  57. return strip_email_quotes('\n'.join(lines))
  58. def rerun_pasted(self, name='pasted_block'):
  59. """ Rerun a previously pasted command.
  60. """
  61. b = self.shell.user_ns.get(name)
  62. # Sanity checks
  63. if b is None:
  64. raise UsageError('No previous pasted block available')
  65. if not isinstance(b, py3compat.string_types):
  66. raise UsageError(
  67. "Variable 'pasted_block' is not a string, can't execute")
  68. print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
  69. self.shell.run_cell(b)
  70. @line_magic
  71. def autoindent(self, parameter_s = ''):
  72. """Toggle autoindent on/off (deprecated)"""
  73. print("%autoindent is deprecated since IPython 5: you can now paste "
  74. "multiple lines without turning autoindentation off.")
  75. self.shell.set_autoindent()
  76. print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
  77. @line_magic
  78. def cpaste(self, parameter_s=''):
  79. """Paste & execute a pre-formatted code block from clipboard.
  80. You must terminate the block with '--' (two minus-signs) or Ctrl-D
  81. alone on the line. You can also provide your own sentinel with '%paste
  82. -s %%' ('%%' is the new sentinel for this operation).
  83. The block is dedented prior to execution to enable execution of method
  84. definitions. '>' and '+' characters at the beginning of a line are
  85. ignored, to allow pasting directly from e-mails, diff files and
  86. doctests (the '...' continuation prompt is also stripped). The
  87. executed block is also assigned to variable named 'pasted_block' for
  88. later editing with '%edit pasted_block'.
  89. You can also pass a variable name as an argument, e.g. '%cpaste foo'.
  90. This assigns the pasted block to variable 'foo' as string, without
  91. dedenting or executing it (preceding >>> and + is still stripped)
  92. '%cpaste -r' re-executes the block previously entered by cpaste.
  93. '%cpaste -q' suppresses any additional output messages.
  94. Do not be alarmed by garbled output on Windows (it's a readline bug).
  95. Just press enter and type -- (and press enter again) and the block
  96. will be what was just pasted.
  97. IPython statements (magics, shell escapes) are not supported (yet).
  98. See also
  99. --------
  100. paste: automatically pull code from clipboard.
  101. Examples
  102. --------
  103. ::
  104. In [8]: %cpaste
  105. Pasting code; enter '--' alone on the line to stop.
  106. :>>> a = ["world!", "Hello"]
  107. :>>> print " ".join(sorted(a))
  108. :--
  109. Hello world!
  110. """
  111. opts, name = self.parse_options(parameter_s, 'rqs:', mode='string')
  112. if 'r' in opts:
  113. self.rerun_pasted()
  114. return
  115. quiet = ('q' in opts)
  116. sentinel = opts.get('s', u'--')
  117. block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet))
  118. self.store_or_execute(block, name)
  119. @line_magic
  120. def paste(self, parameter_s=''):
  121. """Paste & execute a pre-formatted code block from clipboard.
  122. The text is pulled directly from the clipboard without user
  123. intervention and printed back on the screen before execution (unless
  124. the -q flag is given to force quiet mode).
  125. The block is dedented prior to execution to enable execution of method
  126. definitions. '>' and '+' characters at the beginning of a line are
  127. ignored, to allow pasting directly from e-mails, diff files and
  128. doctests (the '...' continuation prompt is also stripped). The
  129. executed block is also assigned to variable named 'pasted_block' for
  130. later editing with '%edit pasted_block'.
  131. You can also pass a variable name as an argument, e.g. '%paste foo'.
  132. This assigns the pasted block to variable 'foo' as string, without
  133. executing it (preceding >>> and + is still stripped).
  134. Options:
  135. -r: re-executes the block previously entered by cpaste.
  136. -q: quiet mode: do not echo the pasted text back to the terminal.
  137. IPython statements (magics, shell escapes) are not supported (yet).
  138. See also
  139. --------
  140. cpaste: manually paste code into terminal until you mark its end.
  141. """
  142. opts, name = self.parse_options(parameter_s, 'rq', mode='string')
  143. if 'r' in opts:
  144. self.rerun_pasted()
  145. return
  146. try:
  147. block = self.shell.hooks.clipboard_get()
  148. except TryNext as clipboard_exc:
  149. message = getattr(clipboard_exc, 'args')
  150. if message:
  151. error(message[0])
  152. else:
  153. error('Could not get text from the clipboard.')
  154. return
  155. except ClipboardEmpty:
  156. raise UsageError("The clipboard appears to be empty")
  157. # By default, echo back to terminal unless quiet mode is requested
  158. if 'q' not in opts:
  159. write = self.shell.write
  160. write(self.shell.pycolorize(block))
  161. if not block.endswith('\n'):
  162. write('\n')
  163. write("## -- End pasted text --\n")
  164. self.store_or_execute(block, name)
  165. # Class-level: add a '%cls' magic only on Windows
  166. if sys.platform == 'win32':
  167. @line_magic
  168. def cls(self, s):
  169. """Clear screen.
  170. """
  171. os.system("cls")