magics.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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 (if available)."""
  73. self.shell.set_autoindent()
  74. print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
  75. @line_magic
  76. def cpaste(self, parameter_s=''):
  77. """Paste & execute a pre-formatted code block from clipboard.
  78. You must terminate the block with '--' (two minus-signs) or Ctrl-D
  79. alone on the line. You can also provide your own sentinel with '%paste
  80. -s %%' ('%%' is the new sentinel for this operation).
  81. The block is dedented prior to execution to enable execution of method
  82. definitions. '>' and '+' characters at the beginning of a line are
  83. ignored, to allow pasting directly from e-mails, diff files and
  84. doctests (the '...' continuation prompt is also stripped). The
  85. executed block is also assigned to variable named 'pasted_block' for
  86. later editing with '%edit pasted_block'.
  87. You can also pass a variable name as an argument, e.g. '%cpaste foo'.
  88. This assigns the pasted block to variable 'foo' as string, without
  89. dedenting or executing it (preceding >>> and + is still stripped)
  90. '%cpaste -r' re-executes the block previously entered by cpaste.
  91. '%cpaste -q' suppresses any additional output messages.
  92. Do not be alarmed by garbled output on Windows (it's a readline bug).
  93. Just press enter and type -- (and press enter again) and the block
  94. will be what was just pasted.
  95. IPython statements (magics, shell escapes) are not supported (yet).
  96. See also
  97. --------
  98. paste: automatically pull code from clipboard.
  99. Examples
  100. --------
  101. ::
  102. In [8]: %cpaste
  103. Pasting code; enter '--' alone on the line to stop.
  104. :>>> a = ["world!", "Hello"]
  105. :>>> print " ".join(sorted(a))
  106. :--
  107. Hello world!
  108. """
  109. opts, name = self.parse_options(parameter_s, 'rqs:', mode='string')
  110. if 'r' in opts:
  111. self.rerun_pasted()
  112. return
  113. quiet = ('q' in opts)
  114. sentinel = opts.get('s', u'--')
  115. block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet))
  116. self.store_or_execute(block, name)
  117. @line_magic
  118. def paste(self, parameter_s=''):
  119. """Paste & execute a pre-formatted code block from clipboard.
  120. The text is pulled directly from the clipboard without user
  121. intervention and printed back on the screen before execution (unless
  122. the -q flag is given to force quiet mode).
  123. The block is dedented prior to execution to enable execution of method
  124. definitions. '>' and '+' characters at the beginning of a line are
  125. ignored, to allow pasting directly from e-mails, diff files and
  126. doctests (the '...' continuation prompt is also stripped). The
  127. executed block is also assigned to variable named 'pasted_block' for
  128. later editing with '%edit pasted_block'.
  129. You can also pass a variable name as an argument, e.g. '%paste foo'.
  130. This assigns the pasted block to variable 'foo' as string, without
  131. executing it (preceding >>> and + is still stripped).
  132. Options:
  133. -r: re-executes the block previously entered by cpaste.
  134. -q: quiet mode: do not echo the pasted text back to the terminal.
  135. IPython statements (magics, shell escapes) are not supported (yet).
  136. See also
  137. --------
  138. cpaste: manually paste code into terminal until you mark its end.
  139. """
  140. opts, name = self.parse_options(parameter_s, 'rq', mode='string')
  141. if 'r' in opts:
  142. self.rerun_pasted()
  143. return
  144. try:
  145. block = self.shell.hooks.clipboard_get()
  146. except TryNext as clipboard_exc:
  147. message = getattr(clipboard_exc, 'args')
  148. if message:
  149. error(message[0])
  150. else:
  151. error('Could not get text from the clipboard.')
  152. return
  153. except ClipboardEmpty:
  154. raise UsageError("The clipboard appears to be empty")
  155. # By default, echo back to terminal unless quiet mode is requested
  156. if 'q' not in opts:
  157. write = self.shell.write
  158. write(self.shell.pycolorize(block))
  159. if not block.endswith('\n'):
  160. write('\n')
  161. write("## -- End pasted text --\n")
  162. self.store_or_execute(block, name)
  163. # Class-level: add a '%cls' magic only on Windows
  164. if sys.platform == 'win32':
  165. @line_magic
  166. def cls(self, s):
  167. """Clear screen.
  168. """
  169. os.system("cls")