randy3k / radian

A 21 century R console
MIT License
1.99k stars 75 forks source link

vi mode-dependent cursor shape #220

Open mskar opened 3 years ago

mskar commented 3 years ago

I would like radian to have a beam cursor (|) in vi insert mode and a block cursor in vi navigation (normal) mode.

Since both radian and IPython use prompt-toolkit, I think it will be helpful to link to the relevant prompt-toolkit issue. By including the code from the issue in my ipython_config.py file, i was able to set up IPython with a vi mode-dependent cursor:

How could I do something similar in my .radian_profile?

YlanAllouche commented 3 years ago

Similarly, would it be possible to decide the apperance of the vi mode indicator? Ideally, this would be done by having two different prompt or a function that return different string depending on the current mode. For the latter, I do not know if this is something R could access though.

mskar commented 3 years ago

@YlanAllouche, I found the answer in a related issue:

options(
    radian.vi_mode_prompt = list(
        "ins" = "(I) ",
        "nav" = "(N) ",
        "rep" = "(R) "
    )
)

As for cursor shape, it might be possible to use another example from that same issue to adapt my ipython_config.py to radian. cc @petobens

mskar commented 3 years ago

Wow, I just pasted the relevant code from my ipython_config.py into radian/settings.py and it works! 😄

image image image

Is settings.py the right place for it? Or is it better for this to be handled by a config file?

Should I submit a pull request? I think everyone who uses the radian vi mode will want this.

import sys

from prompt_toolkit.application.current import get_app
from prompt_toolkit.key_binding.vi_state import InputMode, ViState

def get_input_mode(self):
    if sys.version_info[0] == 3:
        # Decrease input flush timeout from 500ms to 10ms.
        app = get_app()
        app.ttimeoutlen = 0.01
        app.timeoutlen = 0.2

    return self._input_mode

def set_input_mode(self, mode):
    shape = {InputMode.NAVIGATION: 2, InputMode.REPLACE: 4}.get(mode, 6)
    cursor = "\x1b[{} q".format(shape)

    if hasattr(sys.stdout, "_cli"):
        write = sys.stdout._cli.output.write_raw
    else:
        write = sys.stdout.write

    write(cursor)
    sys.stdout.flush()

    self._input_mode = mode

ViState._input_mode = InputMode.INSERT
ViState.input_mode = property(get_input_mode, set_input_mode)
mskar commented 3 years ago

I submitted a pull request #222.

If anyone wants to install the change to try it out, run the line below.

python -m pip install git+https://github.com/mskar/radian.git@cursor

The change is a small addition to the apply_settings() function in radian/session.py.

YlanAllouche commented 3 years ago

Thanks a lot for the tip for the vi mode prompt. I tried to rebuild Radian in a container with this PR and I cannot see the cursor shape change between modes. Does it require extra configuration post installation?

I tried in both Xterm and Kitty to make sure it was not a terminal compatibility problem.

mskar commented 3 years ago

@YlanAllouche, thanks for giving it a try. Sorry to hear it didn't work for you.

There should be no additional setup required. \ Just in case, here is the .radian_profile I am using.

In addition to using a container, you could also try a virtual environment.

Click here for minimal virtual environment example that I hope will be reproducible🤞 ```sh bash --norc --noprofile mkdir cursor cd cursor python -m venv ./venv source ./venv/bin/activate python -m pip install git+https://github.com/mskar/radian.git@cursor ./venv/bin/radian ```
Click here for the result of pip list after the virtual environment is activated ``` Package Version ---------- ------- cffi 1.14.3 lineedit 0.1.5 pip 19.2.3 pycparser 2.20 Pygments 2.7.1 radian 0.5.8 rchitect 0.3.28 setuptools 41.2.0 six 1.15.0 wcwidth 0.2.5 ```

The only requirements for creating the environment should be bash and python (for venv and pip). Could you give this a try and see if it works for you?

Click here for a screenshot of how the minimal example above looks for me: ![image](https://user-images.githubusercontent.com/13444106/94732094-cb107180-0333-11eb-9555-ef4c1360ec81.png)
Click here for the text version of the image above Please disregard my zsh prompt (INSERT). ``` INSERT bash --norc --noprofile bash-5.0$ rm -rf cursor/ bash-5.0$ pwd /Users/martinskarzynski bash-5.0$ mkdir cursor bash-5.0$ cd cursor bash-5.0$ python -m venv ./venv bash-5.0$ source ./venv/bin/activate (venv) bash-5.0$ python -m pip install git+https://github.com/mskar/radian.git@cursor Collecting git+https://github.com/mskar/radian.git@cursor Cloning https://github.com/mskar/radian.git (to revision cursor) to /private/var/folders/sb/k_npvt294jd234ltw1cmt77r0000gn/T/pip-req-build-a78pdzku Running command git clone -q https://github.com/mskar/radian.git /private/var/folders/sb/k_npvt294jd234ltw1cmt77r0000gn/T/pip-req-build-a78pdzku Running command git checkout -b cursor --track origin/cursor Switched to a new branch 'cursor' Branch 'cursor' set up to track remote branch 'cursor' from 'origin' by rebasing. Collecting rchitect<0.4.0,>=0.3.28 (from radian==0.5.8) Using cached https://files.pythonhosted.org/packages/7f/6c/bcfa64b8d07e2f1ecc8f1ca6f093b1a5f4a9cbc934c5dd216978824bfe62/rchitect-0.3.28-cp38-cp38-macosx_10_9_x86_64.whl Collecting lineedit<0.2.0,>=0.1.5 (from radian==0.5.8) Using cached https://files.pythonhosted.org/packages/b6/79/042d4fc8bdfd285f61486d9e9505657b7708ea5398597188819764f82ff5/lineedit-0.1.5.tar.gz Collecting six>=1.9.0 (from radian==0.5.8) Using cached https://files.pythonhosted.org/packages/ee/ff/48bde5c0f013094d729fe4b0316ba2a24774b3ff1c52d924a8a4cb04078a/six-1.15.0-py2.py3-none-any.whl Collecting pygments>=2.5.0 (from radian==0.5.8) Using cached https://files.pythonhosted.org/packages/d7/72/49a7db1b245c13d0e38cfdc96c1adf6e3bd16a7a0dceb7b25faa6612353b/Pygments-2.7.1-py3-none-any.whl Collecting cffi>=1.10.0 (from rchitect<0.4.0,>=0.3.28->radian==0.5.8) Using cached https://files.pythonhosted.org/packages/74/9d/bfa10946bcae5d9b922fbdc244d94e89e5b5be3f7539950bc1dc43a89b6b/cffi-1.14.3-2-cp38-cp38-macosx_10_9_x86_64.whl Collecting wcwidth (from lineedit<0.2.0,>=0.1.5->radian==0.5.8) Using cached https://files.pythonhosted.org/packages/59/7c/e39aca596badaf1b78e8f547c807b04dae603a433d3e7a7e04d67f2ef3e5/wcwidth-0.2.5-py2.py3-none-any.whl Collecting pycparser (from cffi>=1.10.0->rchitect<0.4.0,>=0.3.28->radian==0.5.8) Using cached https://files.pythonhosted.org/packages/ae/e7/d9c3a176ca4b02024debf82342dab36efadfc5776f9c8db077e8f6e71821/pycparser-2.20-py2.py3-none-any.whl Installing collected packages: six, pycparser, cffi, rchitect, pygments, wcwidth, lineedit, radian Running setup.py install for lineedit ... done Running setup.py install for radian ... done Successfully installed cffi-1.14.3 lineedit-0.1.5 pycparser-2.20 pygments-2.7.1 radian-0.5.8 rchitect-0.3.28 six-1.15.0 wcwidth-0.2.5 WARNING: You are using pip version 19.2.3, however version 20.2.3 is available. You should consider upgrading via the 'pip install --upgrade pip' command. (venv) bash-5.0$ ./venv/bin/radian R version 4.0.2 (2020-06-22) -- "Taking Off Again" Platform: x86_64-apple-darwin17.0 (64-bit) ```
YlanAllouche commented 3 years ago

Hey @mskar,

Thanks a lot for detailed steps. The issue was my terminal forcing a cursor shape on top of radian. This now works for me

januz commented 9 months ago

@mskar @randy3k It looks as though the associated PR was never merged. Is there a way to get different cursor shapes based on vi mode by modifying .config/radian/profile? Thanks!