4

I would like to add some syntax changes to (my installation of) IPython. For example, I might want to use \+ to mean operator.add. I imagine that I can insert some code that would process the input and turn it into actual (I)Python, and then IPython can do its own processing. But I don't know where to put that code.

(Disclaimer: Don't do it for production code, or code that's intended for other people to see/use.)

Community
  • 1
  • 1
leewz
  • 3,201
  • 1
  • 18
  • 38
  • Any reasoning for the "too broad" votes? It's asking where to insert some string processing code. (Too broad: "There are either too many possible answers, or good answers would be too long for this format.) – leewz Jun 14 '15 at 21:56
  • 1
    This is not done by adding a couple of lines of string processing code to a file. Changing the syntax of a language is far from trivial. A solution certainly does not fit into an answer in this format. – cel Jun 14 '15 at 22:13
  • @cel I'm asking about IPython, not Python. Are you familiar with how IPython works? – leewz Jun 14 '15 at 22:28
  • And if I were asking about Python, what you said is false. In decreasing size: [A StackOverflow answer about hacking Python's syntax](http://stackoverflow.com/q/214881/2963903). [A blogpost about adding constants](http://blaag.haard.se/Using-the-AST-to-hack-constants-into-Python/). [A short post about adding implicit return](http://webcache.googleusercontent.com/search?q=cache:CVP06GG_MQEJ:blog.marcbelmont.com/2011/09/hacking-python-syntax-implicit-return.html+&cd=7&hl=en&ct=clnk&gl=us) (Google cache, so it will expire). An answer could link to something like this and give a short summary. – leewz Jun 14 '15 at 22:29
  • 1
    Actually, this is pretty easy using IPython input transformers, but as long as it is put on hold, I can't make a valid answer ... – Kiwi Jun 14 '15 at 22:30
  • @Kiwi, thanks. That's enough to get me started. I'll hope for a reopen so you can answer. If not, then for anyone else reading, here's the link to the docs on input transformers. https://ipython.org/ipython-doc/dev/config/inputtransforms.html – leewz Jun 14 '15 at 22:34
  • Just to be sure, you want something that turns "\+ a b" to "a + b" right ? – Kiwi Jun 14 '15 at 22:45
  • I'm voting for reopening, IPython does define custom syntax. ( != , %, %%) the question is legit. – Matt Jun 14 '15 at 22:51
  • @Kiwi, I want to experiment with many things. For example, infix syntax for adding two lists element-wise (which can be done with Numpy and `+`, but I'm interested in syntax, not objects). In my previous example, I would want to be able to do `addition = \+`. – leewz Jun 14 '15 at 23:08
  • Another blogpost, in case anyone comes to this question and is satisfied with hacking Python itself. ["Hacking Python without hacking Python"](http://stupidpythonideas.blogspot.com/2015/06/hacking-python-without-hacking-python.html) describes hacking at multiple points of the import process. – leewz Jun 14 '15 at 23:33
  • @Kiwi The question has been reopened, if you'd like to post an answer. – leewz Jun 15 '15 at 00:40

1 Answers1

2

Here is an example of how to transform "\+ a b" to "a + b".

from IPython.core.inputtransformer import StatelessInputTransformer

@StatelessInputTransformer.wrap
def my_filter(line):
    words = line.split()
    if line.startswith(r'\+ ') and len(words) == 3:
        return '{} + {}'.format(*words[1:])
    return line

ip = get_ipython()
ip.input_transformer_manager.physical_line_transforms.insert(0, my_filter())

Note that this is all string based. This hook executes in an unevaluated context. It means that you can't do conditional transformation based on which value is a or b. A magic would best suit your need in that case.

Moreover, you have to be careful when parsing input string. In my example, the following is broken \+ (a * b) c because of the split. In that case, you will need a tokenization tool. IPython provides one with TokenInputTransformer. It works like StatelessInputTransformer but it is called with a list of tokens instead of the whole line.

Simply run this code to add the filter. If you want it to be available as you start IPython, you can save it as a .py or .ipy file and put it in ~/.ipython/profile_*/startup

https://ipython.org/ipython-doc/dev/config/inputtransforms.html

Kiwi
  • 2,698
  • 16
  • 15