Repository: ipython/ipython

Issue:
when invoking less, ipython should use -R instead of -r
Currently on posix systems, if `$PAGER` is unset then the default is `less -r`, and if `less` is explicitly requested in `$PAGER` then we go to some lengths to make sure that we pass the `-r` flag (#9256).

Unfortunately, this actually breaks things on my system: I have the `-R` flag in my default less options (`$LESS`), which is the right thing to use, and then IPython overrides it with `-r` :-)

The full docs on these (from `less(1)`):

```
       -r or --raw-control-chars
              Causes "raw" control characters to be displayed.  The default is
              to  display  control  characters  using  the caret notation; for
              example, a control-A (octal 001) is displayed as "^A".  Warning:
              when the -r option is used, less cannot keep track of the actual
              appearance of the screen (since this depends on how  the  screen
              responds to each type of control character).  Thus, various dis‐
              play problems may result, such as long lines being split in  the
              wrong place.

       -R or --RAW-CONTROL-CHARS
              Like  -r,  but  only ANSI "color" escape sequences are output in
              "raw" form.  Unlike -r, the screen appearance is maintained cor‐
              rectly  in  most  cases.   ANSI  "color"  escape  sequences  are
              sequences of the form:

                   ESC [ ... m

              where the "..." is zero or more color  specification  characters
              For  the  purpose  of  keeping  track of screen appearance, ANSI
              color escape sequences are assumed to not move the cursor.   You
              can  make less think that characters other than "m" can end ANSI
              color escape  sequences  by  setting  the  environment  variable
              LESSANSIENDCHARS to the list of characters which can end a color
              escape sequence.  And you can make less  think  that  characters
              other  than the standard ones may appear between the ESC and the
              m by setting the environment variable  LESSANSIMIDCHARS  to  the
              list of characters which can appear.
```

In particular, when I use IPython normally, then help lines that are too long for the terminal and wrap cause weird display issues, because when the `-r` flag is in use then less can't tell which lines have wrapped. For example, if I do `os??` then initially my screen looks like:

```
String form: <module 'os' from '/home/njs/.user-python3.4-64bit/lib/python3.4/os
.py'>
File:        ~/.user-python3.4-64bit/lib/python3.4/os.py
Source:
```

but if I then press downarrow and then uparrow -- which should have no effect -- the screen changes to:

```
Type:        module
.py'>
File:        ~/.user-python3.4-64bit/lib/python3.4/os.py
Source:
```

OTOH if I create a fake pager script that forcibly overrides the `-r` argument and runs `less -R`, then I see:

```
Type:        module
String form: <module 'os' from '/home/njs/.user-python3.4-64bit/lib/python3.4/os
.py'>
File:        ~/.user-python3.4-64bit/lib/python3.4/os.py
Source:
```

and this is presented consistently even if I scroll around down/up/right/left.

when invoking less, ipython should use -R instead of -r
Currently on posix systems, if `$PAGER` is unset then the default is `less -r`, and if `less` is explicitly requested in `$PAGER` then we go to some lengths to make sure that we pass the `-r` flag (#9256).

Unfortunately, this actually breaks things on my system: I have the `-R` flag in my default less options (`$LESS`), which is the right thing to use, and then IPython overrides it with `-r` :-)

The full docs on these (from `less(1)`):

```
       -r or --raw-control-chars
              Causes "raw" control characters to be displayed.  The default is
              to  display  control  characters  using  the caret notation; for
              example, a control-A (octal 001) is displayed as "^A".  Warning:
              when the -r option is used, less cannot keep track of the actual
              appearance of the screen (since this depends on how  the  screen
              responds to each type of control character).  Thus, various dis‐
              play problems may result, such as long lines being split in  the
              wrong place.

       -R or --RAW-CONTROL-CHARS
              Like  -r,  but  only ANSI "color" escape sequences are output in
              "raw" form.  Unlike -r, the screen appearance is maintained cor‐
              rectly  in  most  cases.   ANSI  "color"  escape  sequences  are
              sequences of the form:

                   ESC [ ... m

              where the "..." is zero or more color  specification  characters
              For  the  purpose  of  keeping  track of screen appearance, ANSI
              color escape sequences are assumed to not move the cursor.   You
              can  make less think that characters other than "m" can end ANSI
              color escape  sequences  by  setting  the  environment  variable
              LESSANSIENDCHARS to the list of characters which can end a color
              escape sequence.  And you can make less  think  that  characters
              other  than the standard ones may appear between the ESC and the
              m by setting the environment variable  LESSANSIMIDCHARS  to  the
              list of characters which can appear.
```

In particular, when I use IPython normally, then help lines that are too long for the terminal and wrap cause weird display issues, because when the `-r` flag is in use then less can't tell which lines have wrapped. For example, if I do `os??` then initially my screen looks like:

```
String form: <module 'os' from '/home/njs/.user-python3.4-64bit/lib/python3.4/os
.py'>
File:        ~/.user-python3.4-64bit/lib/python3.4/os.py
Source:
```

but if I then press downarrow and then uparrow -- which should have no effect -- the screen changes to:

```
Type:        module
.py'>
File:        ~/.user-python3.4-64bit/lib/python3.4/os.py
Source:
```

OTOH if I create a fake pager script that forcibly overrides the `-r` argument and runs `less -R`, then I see:

```
Type:        module
String form: <module 'os' from '/home/njs/.user-python3.4-64bit/lib/python3.4/os
.py'>
File:        ~/.user-python3.4-64bit/lib/python3.4/os.py
Source:
```

and this is presented consistently even if I scroll around down/up/right/left.



Discussion:
Change need to be made in `IPython/core/pager.py` and seem pretty easy to do. 
I'll leave that open to see if a new contributor wants to tackle it.

Thanks !

Thanks for working that out, I've been wondering what was screwing up the pager with long lines near the start.

Change need to be made in `IPython/core/pager.py` and seem pretty easy to do. 
I'll leave that open to see if a new contributor wants to tackle it.

Thanks !

Thanks for working that out, I've been wondering what was screwing up the pager with long lines near the start.


Resolving patch:
diff --git a/IPython/core/page.py b/IPython/core/page.py
--- a/IPython/core/page.py
+++ b/IPython/core/page.py
@@ -298,7 +298,7 @@ def get_pager_cmd(pager_cmd=None):
     Makes some attempts at finding an OS-correct one.
     """
     if os.name == 'posix':
-        default_pager_cmd = 'less -r'  # -r for color control sequences
+        default_pager_cmd = 'less -R'  # -R for color control sequences
     elif os.name in ['nt','dos']:
         default_pager_cmd = 'type'
 
@@ -308,8 +308,8 @@ def get_pager_cmd(pager_cmd=None):
         except:
             pager_cmd = default_pager_cmd
     
-    if pager_cmd == 'less' and '-r' not in os.environ.get('LESS', ''):
-        pager_cmd += ' -r'
+    if pager_cmd == 'less' and '-r' not in os.environ.get('LESS', '').lower():
+        pager_cmd += ' -R'
     
     return pager_cmd
 


Test patch: