ArtOfWarfare
ArtOfWarfare

Reputation: 21496

Python readline module on OS X lacks set_pre_input_hook

I added the following code to my python startup script. It works great on Windows 7 after I install pyreadline via pip, but it's not working on OS X Yosemite (10.10.2 to be specific).

import readline

def atPrompt():
    import readline
    global freshPrompt
    if freshPrompt:
        freshPrompt = False

    last = readline.get_history_item(readline.get_current_history_length())

    spaces = last[:len(last) - len(last.lstrip())]
    if last.isspace():
        spaces = spaces[:-4]
    elif last and last.strip()[-1] == ':':
        spaces += '    '
    readline.insert_text(spaces)

readline.set_pre_input_hook(atPrompt)

# (I also make it so that when PS1 is called, global freshPrompt is set to True.)

This code automatically indents for me when I'm typing in interactive Python. If the prior line I entered ends in a :, it automatically indents four extra spaces. If the prior line started with spaces but contained more than just spaces, it lines up the new line with that prior one. If the prior line was nothing but spaces, it dedents the new line for me.

Whereas this code works perfectly for me on Windows (with pyreadline from pip), it does nothing on OS X. It doesn't tell me about any modules being missing. I use readline's get_history_item() and get_current_history_length() elsewhere in OS X just fine.

If I insert a print statement at the start of atPrompt, it never appears in OS X but shows up fine in Windows.

This leads me to think that set_pre_input_hook() does nothing in OS X.

I know that the readline module in OS X differs from that on other *nix distributions (for licensing reasons). I've heard that it's possible to install the same module on OS X.

But when I try installing readline via pip, with

pip install readline

I get the following errors:

creating build/lib.macosx-10.10-intel-2.7

cc -bundle -undefined dynamic_lookup -arch x86_64 -arch i386 -Wl,-F. build/temp.macosx-10.10-intel-2.7/Modules/2.x/readline.o readline/libreadline.a readline/libhistory.a -lncurses -o build/lib.macosx-10.10-intel-2.7/readline.so

clang: error: no such file or directory: 'readline/libreadline.a'

clang: error: no such file or directory: 'readline/libhistory.a'

error: command 'cc' failed with exit status 1


Cleaning up... Command /usr/bin/python -c "import setuptools, tokenize;__file__='/private/tmp/pip_build_root/readline/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-FYqn9p-record/install-record.txt --single-version-externally-managed --compile failed with error code 1 in /private/tmp/pip_build_root/readline Storing debug log for failure in /Users/Taylor/Library/Logs/pip.log

(I added backticks around __file__ to keep it from being displayed as file.)

How do I get set_pre_input_hook() to work on OS X? Am I right in thinking I should replace the readline module? If so, how do I get it installed, because simply trying to install it via pip is resulting in the above error messages.

As an extra detail, the Windows machine is running Python 2.7.8. The OS X machine is running Python 2.7.6.

Upvotes: 1

Views: 1461

Answers (1)

ArtOfWarfare
ArtOfWarfare

Reputation: 21496

It seems the best way to do this is to install gnureadline.

pip install gnureadline

Unfortunately, this means for scripts to be compatible across platforms you need to write this:

try:
    import gnureadline as readline
except ImportError:
    import readline

Instead of just this:

import readline

If anyone knows a better, less verbose solution for importing, please share it.

Upvotes: 4

Related Questions