Compiler: Ctrl + L doesn't clear Elm REPL

Created on 28 Aug 2018  路  14Comments  路  Source: elm/compiler

Typing ctrl + l doesn't clear the console.

Example:

> 1 + 1
2 : number

-- Now type (CTRL/CMD) + L

-- Nothing happens

Environment

OS: Ubuntu 16.04 LTS / Arch Linux
Elm: 0.19.0

Most helpful comment

The root cause is that the ncurses-static package on Alpine Linux 3.7 is built with:

--with-terminfo-dirs="/etc/terminfo:/usr/share/terminfo"

but some distributions (like Debian and Ubuntu at least) have the terminfo database in /lib/terminfo.

A safer configuration would be:

--with-terminfo-dirs="/etc/terminfo:/lib/terminfo:/usr/share/terminfo:/usr/lib/terminfo"

I will contact the package maintainer to see if this can be improved, else we would have to build ourselves this library with more terminfo directories before linking the elm binary.

Edit: https://bugs.alpinelinux.org/issues/9362

All 14 comments

Did it do this in 0.18? I have not heard of this functionality before.

@evancz On Slack some people said it worked (on both 0.18 and 0.19).

I'm not sure I understand the issue. Can you investigate further, and when you can confirm it exists for other users, open a new issue explaining what you found. I have not used ctrl+l before, but I think I see what you want to do with that.

Usually pressing CTRL-L in a unix terminal clears it, like running the clear command.
This does not work with the 0.19 Linux binary, however it works on other platforms (at least Mac OS X), it works with 0.18, and it also works when building the binary locally dynamically linked (on Ubuntu 18.04).

So this is most likely a side effect of the way the Linux x64 binary is built (using the Alpine Linux environment).
I also noticed that DEL does not work either (CTRL-D and BACKSPACE do though). Other shortcuts seem to work (CTRL-A, CTRL-D, CTRL-K, CTRL-E).

Sorry for that, I should have noticed it during my tests. I am investigating...

Note that the shorcuts available with haskeline are listed there:
https://github.com/judah/haskeline/wiki/KeyBindings

@rlefevre I cannot reproduce the issues you are describing with the latest binary installed using npm on Arch Linux:

$ lsb_release -a
LSB Version:    1.4
Distributor ID: Arch
Description:    Arch Linux
Release:        rolling
Codename:       n/a
$ md5sum node_modules/.bin/elm
8f945459724b4e2b86e583ce787f4f57  node_modules/.bin/elm

Ctrl-L clears the REPL as expected and DEL works for me too.

By the way, I installed 0.19 via the release package available on github.

I'm gonna download it via npm on a Linux Mint and see what happens.

Thank you @hecrj, you're right, CTRL-L works correctly on my Arch Linux too, but it does not on my Ubuntu 18.04 (you can reproduce on arch by using an invalid TERM, for example TERM=badterm elm repl). So the problem is linked to terminfo configuration.

Ok, the problem is that the elm Linux binary does not search for the terminfo database in /lib/terminfo where it is on Ubuntu, as can be seen by the following strace:

$ strace ./elm repl 2>&1| grep terminfo
stat("/home/user/.terminfo", 0x2de1320)  = -1 ENOENT (No such file or directory)
stat("/etc/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/usr/share/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
access("/etc/terminfo/x/xterm-256color", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/share/terminfo/x/xterm-256color", R_OK) = -1 ENOENT (No such file or directory)
>

Here is a list of workarounds, choose the one that suits you most:

  1. Add a symbolic link to the terminfo database from the home directory:
ln -s /lib/terminfo ~/.terminfo
  1. Start elm with the TERMINFO environment variable pointing to the correct directory on your system:
TERMINFO=/lib/terminfo elm repl
  1. Export the TERMINFO variable in your ~/.bashrc file:
export TERMINFO=/lib/terminfo

@MatheusRich , could you confirm that this works for you?

The root cause is that the ncurses-static package on Alpine Linux 3.7 is built with:

--with-terminfo-dirs="/etc/terminfo:/usr/share/terminfo"

but some distributions (like Debian and Ubuntu at least) have the terminfo database in /lib/terminfo.

A safer configuration would be:

--with-terminfo-dirs="/etc/terminfo:/lib/terminfo:/usr/share/terminfo:/usr/lib/terminfo"

I will contact the package maintainer to see if this can be improved, else we would have to build ourselves this library with more terminfo directories before linking the elm binary.

Edit: https://bugs.alpinelinux.org/issues/9362

@rlefevre, thank you so much for such a detailed investigation! 鉂わ笍

For the following reasons:

  1. Alpine Linux 3.7 seems to be in maintenance mode, and only security fixes will be accepted, so I don't think we will have a fix there that will help us (and this is more a feature than a bug).
  2. Even with a fix in the Alpine package, the directories could be changed again later in the package (leading to a regression in elm), or we could need to add another one.
  3. We could rebuild the ncurses package ourselves, but this add more complications and we could forget about it later if we change the way we build elm.

I think it is better to fix it in elm itsef. I made this pull-request to offer some directions. Feel free to rewrite it as you wish.

Let me explain why in my opinion, I think this should be fixed in elm instead of asking users to configure it:

1 Additional configuration perception

On a distribution, packages using readline or haskeline (both use terminfo) are usually built on the same distribution, so the compiled-in directories to search for terminal description files are correct by default in the linked ncurses library and the binaries find the terminal description without additional configuration.

The elm Linux binary is actually correctly configured, but only for Alpine Linux on which it is built or distributions using the same directory to store terminfo files.

Therefore asking users to do some additional configuration only for elm when all their other readline/haskeline applications work correctly may not be understood well, will be difficult to explain, and will degrade the first experience of users that are introduced to elm with its REPL (admittedly this is not at all a critical issue either). It can be expected that some users would simply ignore the configuration instructions (if they find them), and get a degraded behaviour.

At last, as elm is distributed as a single binary, it seems to me that it is its responsibility to work on most systems, not the one of the user, who is used to binaries built for its system by the packages maintainers.

2 Impacted Linux users proportion

As you can see in the following table, all Debian derivatives including Ubuntu/Mint ones since Debian 6 are impacted. Unfortunately, according to some statistics, this means that most Linux users would need some additional configuration to have the expected terminal behavior.

| Distribution | Terminal description found | Terminfo directory |
|:-------------|:--------------------------:|:-----------------------:|
| Alpine 3.7 | :heavy_check_mark: | /usr/share/terminfo |
| Arch Linux | :heavy_check_mark: | /usr/share/terminfo |
| Centos 6.6 | :heavy_check_mark: | /usr/share/terminfo |
| Centos 7.5 | :heavy_check_mark: | /usr/share/terminfo |
| Debian 4 etch | :heavy_check_mark: | /usr/share/terminfo |
| Debian 5 lenny | :heavy_check_mark: | /usr/share/terminfo |
| Debian 6 squeeze | :x: | /lib/terminfo |
| Debian 7 wheezy | :x: | /lib/terminfo |
| Debian 9 stretch | :x: | /lib/terminfo |
| Fedora 26 | :heavy_check_mark: | /usr/share/terminfo |
| Fedora 28 | :heavy_check_mark: | /usr/share/terminfo |
| Gentoo | :heavy_check_mark: | /usr/share/terminfo |
| LinuxMint 18.2 | :x: | /lib/terminfo |
| OpenSuse leap 15.0 | :heavy_check_mark: | /usr/share/terminfo |
| Slackware 14.2 | :heavy_check_mark: | /usr/share/terminfo |
| Ubuntu 14.04 | :x: | /lib/terminfo |
| Ubuntu 16.04 | :x: | /lib/terminfo |
| Ubuntu 18.04 | :x: | /lib/terminfo |
| Ubuntu 18.10 (dev) | :x: | /lib/terminfo |

Additional notes

  • the TERMINFO_DIRS environment variable used in the proposed patch is never set on systems as its purpose is to allow the users (not the system) to complement the compiled-in directories searched for whatever reason (this is not an override, the result is a merge of all directories). This is precisely what I propose to do inside the binary (ie: automate the user customization) as the statically compiled-in set of directories is not large enough for all systems (and could change without prior warnings).

  • As far as I can tell, I don't see a way to detect systems on which the binary compiled-in directories are not enough without some code more complex (and likely wrong) versus letting the ncurses/terminfo library do its job. So if we want to propose some additional configuration to the user, it should always be displayed by the binary or put on a website where it would be easy to miss.

  • As I tried to explain, rebuilding the ncurses library with at least the additional Debian path is also a viable solution, but it seems to me that this is more burdensome for releases and the risk of later regression could be more important. The advantage is that this does not require some additional code, and this has strictly no effect on non-Linux systems (the proposed patch would still set the environment variable on other systems, this should have no impact though). All in all, this may be less risky on short term, but more likely to break when the build process is updated. I can provide some directions though if this is a preferred solution.

This issue has been summarized in this new one:

https://github.com/elm/compiler/issues/1774

@rlefevre Remi thank you for your excellent work.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

basickarl picture basickarl  路  3Comments

maxsnew picture maxsnew  路  4Comments

kuon picture kuon  路  3Comments

jvoigtlaender picture jvoigtlaender  路  4Comments

Natim picture Natim  路  3Comments