judah / haskeline Goto Github PK
View Code? Open in Web Editor NEWA Haskell library for line input in command-line programs.
Home Page: https://hackage.haskell.org/package/haskeline
License: BSD 3-Clause "New" or "Revised" License
A Haskell library for line input in command-line programs.
Home Page: https://hackage.haskell.org/package/haskeline
License: BSD 3-Clause "New" or "Revised" License
There's a bunch of issues on GHC's Trac regarding hPutChar crashing on Win32 - which seems to have been solved in Haskeline. Is there any possibility of upstreaming the code in Haskeline to GHC?
Hi!
I'm looking into adopting haskeline for our email client https://github.com/purebred-mua/purebred. It is using brick heavily and I found a great backend implementation done by @rootmos https://github.com/rootmos/haskeline. I don't know if he would be interested getting his code into haskeline (I'd help, thats why I'm filing this issue) or if the haskeline developers would consider opening the API for third party backend developers? What's the best approach from your side to release a new backend which integrates with brick?
The LICENSE
file looks like a 2-clause BSD license, while the cabal-file states it to be a BSD3
license (rather than a BSD2
type)
I'm using both Haskeline and monad-logger and tryin to make my stderr logging play nice with line input, as right now log messages clobber my prompt. Unfortunately, monad-logger deals with ByteString
and the function returned by getExternalPrint
only accepts String. Having monad-logger first build a ByteString each time, and then having to decode + unpack before being able to print is rather inconvenient. Would it be possible to add/extend Haskeline with a way to dump out ByteString directly?
Since Haskeline already has a dependency on ByteString this doesn't seem like it'd expand the dependency footprint any.
I have the following dotfile:
$ cat ~/.haskeline
historyDuplicates: IgnoreConsecutive
However running stack ghci
my settings don't seem to get picked up. I'm on macOS 10.13.6. Any ideas?
I tried using ANSI sequences in the display
field, but it threw off the alignment of the presented completions:
I naively tried inserting a call to stringToGraphemes
in Completion.makeLines
but realized that's a different sort of thing. What do you think about some way to strip out escape sequences or to provide a length directly?
Right now, mapInputT
has the type:
mapInputT :: (forall b. m b -> m b) -> InputT m a -> InputT m a
As I understand it (I'm new to transformers, so correct me if I'm wrong), the type should be:
mapInputT :: (m a -> n b) -> InputT m a -> InputT n b
in order to allow for changing the base monad.
I would like some way to get syntax highlighting in the interactive prompt.
Perhaps by adding a hook that allows processing the output of the interactive prompt before it gets displayed on the terminal. This would require a more structured form of data then string however, at least if we don't want to rely on escape sequences (but even that would be an improvement I think).
My numpad "+" and "*" keys are being ignored at the ghci prompt, but not in any readline program or even in getLine within ghci. Keycodes are 78 (KEY_KPPLUS) and 55 (KEY_KPASTERISK), respectively.
$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 8.2.2
Programs sometimes terminate badly, especially GHCi when you are hacking GHC, or when testing FFI code, and currently the history is lost, which is annoying.
haskeline should save the history after each entered line, before returning it, to be on the safe side.
I found this link over internet and think there's a bug somewhere here:
I've tested almost everything with my new 8.4.3 Haskell installation on Windows 10 and it seems that \ESC[
color sequence works only when \n
finishes the line; in any other situation (if you want to color the prompt without \n
ending) the ghci prompt outputs the ANSI sequence text as it is and does not color the string.
I simply write a ~/.haskeline
file like the following for a test.
bind: home a
bind: end b
It shows that my ghci
seems to ignore my home
and end
press absolutely.
So how could I send home
and end
key to haskline
? I have being suffering from the lack of support for end
key and home
key of ghci
for a long time.
Is any thing wrong with my environment?
My laptop:
Ubuntu 14.04
ghc 7.10.2
haskeline-0.7.2.1
Starting with transformers-0.4.0.0
, ErrorT
was deprecated in favor of ExceptT
. There is currently a MonadException
instance for ErrorT
, but not ExceptT
.
Vim has the ; and , motions in normal mode, to repeat the last f/F/t/T motion. These are also implemented in GNU readline, and would make a great addition to this library.
The GHC 8.6.1 release is quickly approaching and i would like to have all of the submodules finalized in the next few weeks. For this we'll need a new release.
Many applications use Text as the "string" type instead of String. It would be great if Haskeline directly supported IO with Text.
Inspired by #14 . It would be great, if we could rebind Up and Down keys for incremental search. The proposition is to implement simple functions:
parseCommandKeyI :: (Monad m) => String -> Maybe (Command m InsertMode (Maybe String))
parseCommandKeyC :: (Monad m) => String -> Maybe (Command m CommandMode (Maybe String))
with available inputs like "history-incremental-search-backwards" and others. After that, we can replace viKeyCommands
and emacsCommands
with choiceCmd [bindCmd, viKeyCommands]
and choiceCmd [bindCmd, emacsCommands]
in getInputCmdLine
. If you approve this idea, I'll prepare the commit.
The GHC 8.4.1 release is quickly approaching and i would like to have all of the submodules finalized by next alpha. For this we'll need a new release.
When build haskeline-0.7.2.1 by ghc 7.10.1, missing instances.
$ ghci
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
Prelude> import System.Console.Haskeline
Prelude System.Console.Haskeline> import Control.Monad.IO.Class
Prelude System.Console.Haskeline Control.Monad.IO.Class> import Control.Monad.Trans
Prelude System.Console.Haskeline Control.Monad.IO.Class Control.Monad.Trans> :i InputT
type role InputT representational nominal
newtype InputT (m :: * -> *) a
= haskeline-0.7.2.1:System.Console.Haskeline.InputT.InputT {haskeline-0.7.2.1:System.Console.Haskeline.InputT.unInputT :: transformers-0.4.2.0:Control.Monad.Trans.Reader.ReaderT
haskeline-0.7.2.1:System.Console.Haskeline.Term.RunTerm
(transformers-0.4.2.0:Control.Monad.Trans.Reader.ReaderT
(GHC.IORef.IORef
System.Console.Haskeline.History.History)
(transformers-0.4.2.0:Control.Monad.Trans.Reader.ReaderT
(GHC.IORef.IORef
haskeline-0.7.2.1:System.Console.Haskeline.Command.KillRing.KillRing)
(transformers-0.4.2.0:Control.Monad.Trans.Reader.ReaderT
Prefs
(transformers-0.4.2.0:Control.Monad.Trans.Reader.ReaderT
(Settings
m)
m))))
a}
-- Defined in ‘haskeline-0.7.2.1:System.Console.Haskeline.InputT’
instance [overlap ok] Monad m => Monad (InputT m)
-- Defined in ‘haskeline-0.7.2.1:System.Console.Haskeline.InputT’
instance [overlap ok] Monad m => Functor (InputT m)
-- Defined in ‘haskeline-0.7.2.1:System.Console.Haskeline.InputT’
instance [overlap ok] Monad m => Applicative (InputT m)
-- Defined in ‘haskeline-0.7.2.1:System.Console.Haskeline.InputT’
instance [overlap ok] MonadException m => MonadException (InputT m)
-- Defined in ‘haskeline-0.7.2.1:System.Console.Haskeline.InputT’
Prelude System.Console.Haskeline Control.Monad.IO.Class Control.Monad.Trans>
Why do all the Haskeline functions return a Maybe String
rather than a String
? There's no documentation on it, and it seems to me that they should always return String
, like standard getLine
. I have no idea what the interpretation of Nothing
is.
Currently there is getInputChar
, which skips all non-printing inputs. Can the internal mechanism that it uses to get a single input and then check it be exposed directly so that we can do classic terminal things like "press any key to continue"?
It seems to me that Control.Monad.Catch from exceptions already does the job of generalizing exception handling functions, and thus reimplementing it in MonadException only causes Haskeline to be incompatible with libraries that use the exceptions package.
I'm trying to remap escape to "jk" how can this be accomplished?
When I try to cabal install haskeline
, I get
Preprocessing library haskeline-0.7.1.3...
/usr/bin/ld: cannot find -ltinfo
collect2: error: ld returned 1 exit status
linking
dist/dist-sandbox-7d9f4d88/build/System/Console/Haskeline/Directory_hsc_make.o
failed (exit code 1)
Apparently, libncurses and libtinfo used to be a single package, libncurses. Haskeline should fall back to -lncurses if libtinfo is missing but libncurses is present.
Work-around:
After much debugging, the internet suggested symlinking libtinfo.so*
to libncurses.so*
. Because I have no root on the machine I'm using, I had to do this in a local folder, ~/.local64/lib
, and then add ~/.local64/lib
to LD_LIBRARY_PATH
and LIBRARY_PATH
(alternatively, pass cabal install
the options --gcc-options="-L$(readlink -f ~/.local64/lib) -Wl,-L$(readlink -f ~/.local64/lib)" --ghc-options="-L$(readlink -f ~/.local64/lib)"
).
Hi,
This issue looks like #16, but I don't think there is a fix somehow.
So, trying to install haskeline gives the following output on Archlinux:
stack install haskeline
Warning: File listed in haskell-programme.cabal file does not exist: README.md
haskeline-0.7.3.1: configure
haskeline-0.7.3.1: build
-- While building package haskeline-0.7.3.1 using:
/tmp/stack13776/haskeline-0.7.3.1/.stack-work/dist/x86_64-linux/Cabal-1.24.2.0/setup/setup --builddir=.stack-work/dist/x86_64-linux/Cabal-1.24.2.0 build --ghc-options " -ddump-hi -ddump-to-file"
Process exited with code: ExitFailure 1
Logs have been written to: /home/jiehong/Dev/haskell-programme/.stack-work/logs/haskeline-0.7.3.1.log
[1 of 2] Compiling Main ( /tmp/stack13776/haskeline-0.7.3.1/Setup.hs, /tmp/stack13776/haskeline-0.7.3.1/.stack-work/dist/x86_64-linux/Cabal-1.24.2.0/setup/Main.o )
[2 of 2] Compiling StackSetupShim ( /home/jiehong/.stack/setup-exe-src/setup-shim-mPHDZzAJ.hs, /tmp/stack13776/haskeline-0.7.3.1/.stack-work/dist/x86_64-linux/Cabal-1.24.2.0/setup/StackSetupShim.o )
Linking /tmp/stack13776/haskeline-0.7.3.1/.stack-work/dist/x86_64-linux/Cabal-1.24.2.0/setup/setup ...
*** Warning: running on POSIX but not building the terminfo backend. ***
You may need to install the terminfo package manually, e.g. with
"cabal install terminfo"; or, use "-fterminfo" when configuring or
installing this package.
Configuring haskeline-0.7.3.1...
Building haskeline-0.7.3.1...
Preprocessing library haskeline-0.7.3.1...
/usr/bin/ld: cannot find -ltinfo
collect2: error: ld returned 1 exit status
linking .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/System/Console/Haskeline/Directory_hsc_make.o failed (exit code 1)
command was: /usr/bin/gcc .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/System/Console/Haskeline/Directory_hsc_make.o .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/System/Console/Haskeline/Directory_hsc_utils.o -o .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/System/Console/Haskeline/Directory_hsc_make -fno-stack-protector -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/transformers-0.5.2.0 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/transformers-0.5.2.0 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/terminfo-0.4.0.2 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/terminfo-0.4.0.2 -ltinfo -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/process-1.4.3.0 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/process-1.4.3.0 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/directory-1.3.0.0 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/directory-1.3.0.0 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/unix-2.7.2.1 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/unix-2.7.2.1 -lrt -lutil -ldl -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/time-1.6.0.1 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/time-1.6.0.1 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/filepath-1.4.1.1 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/filepath-1.4.1.1 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/containers-0.5.7.1 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/containers-0.5.7.1 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/bytestring-0.10.8.1 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/bytestring-0.10.8.1 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/deepseq-1.4.2.0 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/deepseq-1.4.2.0 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/array-0.5.1.1 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/array-0.5.1.1 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/base-4.9.1.0 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/base-4.9.1.0 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/integer-gmp-1.0.0.1 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/integer-gmp-1.0.0.1 -lgmp -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/ghc-prim-0.5.0.0 -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/ghc-prim-0.5.0.0 -L/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/rts -Wl,-R,/home/jiehong/.stack/programs/x86_64-linux/ghc-8.0.2/lib/ghc-8.0.2/rts -lm -lrt -ldl -lpthread
However, cabal install terminfo
gives the following output:
Resolving dependencies...
All the requested packages are already installed:
terminfo-0.4.0.2
Use --reinstall if you want to reinstall anyway.
Forcing the re-installation does not help at all.
Checking for the lib itself:
ll /usr/lib/libtinfo.so.5
lrwxrwxrwx 1 root root 24 2016-12-28 20:16 '/usr/lib/libtinfo.so.5' -> '/usr/lib/libncurses.so.5'*
I've trying with lts-7.18 instead of lts-8.3 on stack, but still with the same issue.
Could you please help on this issue?
If I redirect stdin so that inputs are read from a file, the input prompts are still displayed to stdout (with newlines chopped off). This looks rather ugly and amateurish. I'd like to be able to configure the prompt functionality to only prompt in interactive mode.
I've moved from Ubuntu 16.0.4 to Mint and want to use vscode
When I do stack install intero I get this error:
-- While building package haskeline-0.7.5.0 using:
/home/kees/.stack/setup-exe-cache/x86_64-linux/Cabal-simple_mPHDZzAJ_2.4.0.1_ghc-8.6.4 --builddir=.stack-work/dist/x86_64-linux/Cabal-2.4.0.1 build --ghc-options " -ddump-hi -ddump-to-file -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
Logs have been written to: /home/kees/freeDB/.stack-work/logs/haskeline-0.7.5.0.log
Configuring haskeline-0.7.5.0...
Preprocessing library for haskeline-0.7.5.0..
/usr/bin/ld.gold: error: cannot find -ltinfo
collect2: error: ld returned 1 exit status
linking .stack-work/dist/x86_64-linux/Cabal-2.4.0.1/build/System/Console/Haskeline/Directory_hsc_make.o failed (exit code 1)
command was: /usr/bin/gcc .stack-work/dist/x86_64-linux/Cabal-2.4.0.1/build/System/Console/Haskeline/Directory_hsc_make.o .stack-work/dist/x86_64-linux/Cabal-2.4.0.1/build/System/Console/Haskeline/Directory_hsc_utils.o -o .stack-work/dist/x86_64-linux/Cabal-2.4.0.1/build/System/Console/Haskeline/Directory_hsc_make -fuse-ld=gold -fno-stack-protector -fuse-ld=gold -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/transformers-0.5.6.2 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/transformers-0.5.6.2 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/terminfo-0.4.1.2 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/terminfo-0.4.1.2 -ltinfo -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/stm-2.5.0.0 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/stm-2.5.0.0 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/process-1.6.5.0 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/process-1.6.5.0 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/directory-1.3.3.0 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/directory-1.3.3.0 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/unix-2.7.2.2 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/unix-2.7.2.2 -lrt -lutil -ldl -lpthread -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/time-1.8.0.2 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/time-1.8.0.2 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/filepath-1.4.2.1 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/filepath-1.4.2.1 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/containers-0.6.0.1 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/containers-0.6.0.1 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/bytestring-0.10.8.2 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/bytestring-0.10.8.2 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/deepseq-1.4.4.0 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/deepseq-1.4.4.0 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/array-0.5.3.0 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/array-0.5.3.0 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/base-4.12.0.0 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/base-4.12.0.0 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/integer-gmp-1.0.2.0 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/integer-gmp-1.0.2.0 -lgmp -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/ghc-prim-0.5.3 -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/ghc-prim-0.5.3 -L/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/rts -Wl,-R,/home/kees/.stack/programs/x86_64-linux/ghc-8.6.4/lib/ghc-8.6.4/rts -lm -lrt -ldl -lpthread
I'am using stack version 1.9.3 and resolver lts-13.16
What can I do?
Kees
This is mostly a reminder for me to send a fix later today
libraries/haskeline/System/Console/Haskeline/Monads.hs:73:10: Warning:
‛StateT’ is an instance of Monad but not Applicative - this will become an error in GHC 7.10, under the Applicative-Monad Proposal.
libraries/haskeline/System/Console/Haskeline/Term.hs:107:16: Warning:
In the use of ‛isEmptyChan’
(imported from Control.Concurrent, but defined in Control.Concurrent.Chan):
Deprecated: "if you need this operation, use Control.Concurrent.STM.TChan instead. See http://hackage.haskell.org/trac/ghc/ticket/4154 for details"
libraries/haskeline/System/Console/Haskeline/Backend/DumbTerm.hs:24:27: Warning:
‛DumbTerm’ is an instance of Monad but not Applicative - this will become an error in GHC 7.10, under the Applicative-Monad Proposal.
libraries/haskeline/System/Console/Haskeline/Backend/Terminfo.hs:106:15: Warning:
‛Draw’ is an instance of Monad but not Applicative - this will become an error in GHC 7.10, under the Applicative-Monad Proposal.
Zsh has a binding called push-line, which I bind to ^e. It pushes the current contents of the command line onto a stack, which is popped when you next hit return. It's useful when you start typing and realize you need to do something else first. Just hit ^e, type the other thing, hit return, and you're back to the original line.
I would like to mix haskeline with the ansi-terminal package to get cross platform colored text support that also has good command line support. However, it seems that the printer function that you obtain from getExternalPrint
is actually only an action to queue text for later printing, so directly mixing it with the setSGR
function from ansi-terminal doesn't work at all.
Example:
-- base
import Control.Monad (forever)
import Control.Concurrent (threadDelay)
-- haskeline
import System.Console.Haskeline
-- async
import Control.Concurrent.Async
-- transformers
import Control.Monad.IO.Class (liftIO)
-- ansi-terminal
import System.Console.ANSI
counter :: (String -> IO ()) -> IO ()
counter printer = go 0 infColorList where
infColorList = cycle [Red,Green,Yellow,Blue,Magenta,Cyan,White]
go n (c:cs) = do
-- This part should print each message 1 second apart, and also in
-- different colors. That's not what happens though. Instead, there are
-- no colors at all. Also, the printing rate is a bit unsteady, but
-- that's more of a secondary problem.
threadDelay 1000000
setSGR [SetColor Foreground Vivid c]
printer $ show n ++ "\n"
setSGR [Reset]
go (n+1) cs
main = runInputT defaultSettings $ do
printer <- getExternalPrint
outputStrLn "Spawning a counting thread..."
(liftIO . async) (counter printer)
loop
where
loop :: InputT IO ()
loop = do
input <- getInputLine "> "
case input of
Nothing -> return ()
Just "quit" -> return ()
Just line -> do
outputStrLn $ "you typed:" ++ line
loop
Now I would ideally like to be able to encode the color changes into the String without using the normal raw escape sequences (which don't work on Windows anyway), ideally in a human-readable way so that users would be able to take advantage of this with their inputs. Then an escape sequence aware printing action can switch colors as it prints out the String. Here's an excerpt of the full example of what I mean.
formatString :: String -> IO ()
formatString [] = setSGR [Reset]
formatString ('@':'@':more) = putChar '@' >> formatString more
formatString ('@':c:more) = do
case c of
'k' -> setSGR [SetColor Foreground Dull Black]
'K' -> setSGR [SetColor Foreground Vivid Black]
'r' -> setSGR [SetColor Foreground Dull Red]
'R' -> setSGR [SetColor Foreground Vivid Red]
-- more colors here, you get the idea
_ -> putChar '@' >> putChar c
formatString more
formatString ('$':'$':more) = putChar '$' >> formatString more
formatString ('$':c:more) = do
case c of
'k' -> setSGR [SetColor Background Dull Black]
'K' -> setSGR [SetColor Background Vivid Black]
'r' -> setSGR [SetColor Background Dull Red]
'R' -> setSGR [SetColor Background Vivid Red]
-- more colors here, you get the idea
_ -> putChar '$' >> putChar c
formatString more
formatString (other:more) = do
putChar other
formatString more
This would probably necessitate that the printer that you get from getExternalPrint
actually do the printing by blocking until the printing happens instead of just queuing it up for later. Or perhaps getExternalPrint
can stay as it is (non-blocking) with updated docs, and then a new blocking printer function can be made available via a new InputT action.
I'm seeing this in GHCi, but I assume its haskeline problem. Please correct me if I'm wrong on that.
I've noticed this minor annoyance for a while but didn't really explore it until now. I was going to do this bug report as an interpretive dance, but i decided an animated GIF was easier.
It seems that if the prompt string has non-printable characters recalling a previous multi line expression, followed by the down arrow key leaves the prompt in a strange state. Hopefully that will be obvious from the GIF. The prompt I'm using is:
:set prompt "\ESC[1;32mλ> \ESC[m"
It would be nice if completion can be case-insensitive. Different behavior in bash prompt and ghci prompt drive me crazy.
Readline has an option: show-mode-in-prompt
that works with editing-mode vi
to give an indicator of the vi editing mode, in the form of the leftmost prompt character showing a '+' in insert mode, and ':' in normal mode, (it removes the character all-together when doing a search with /, I guess if it supports other command-mode commands, it would do the same thing)
It would be great if I could get this in my ghci..
That being said, just because readline does it this way, doesn't mean it makes more sense than having something customizable in the configuration of the prompt itself.
Any thoughts?
As part of another program I am installing, I get the following error:
[rbarden ~]$ stack install haskeline-0.7.4.2
haskeline-0.7.4.2: configure
haskeline-0.7.4.2: build
-- While building custom Setup.hs for package haskeline-0.7.4.2 using:
/home/rbarden/.stack/setup-exe-cache/x86_64-linux/Cabal-simple_mPHDZzAJ_2.0.1.0_ghc-8.2.2 --builddir=.stack-work/dist/x86_64-linux/Cabal-2.0.1.0 build --ghc-options " -ddump-hi -ddump-to-file -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
Logs have been written to: /home/rbarden/.stack/global-project/.stack-work/logs/haskeline-0.7.4.2.log
Configuring haskeline-0.7.4.2...
Preprocessing library for haskeline-0.7.4.2..
/tmp/stack31890/haskeline-0.7.4.2/In file included from .stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/System/Console/Haskeline/Backend/Posix_hsc_make.c:1:0:
Posix.hsc: In function ‘main’:
/tmp/stack31890/haskeline-0.7.4.2/Posix.hsc:70:16: error: ‘TIOCGWINSZ’ undeclared (first use in this function)
/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/template-hsc.h:38:10: note: in definition of macro ‘hsc_const’
if ((x) < 0) \
^
/tmp/stack31890/haskeline-0.7.4.2/Posix.hsc:70:16: note: each undeclared identifier is reported only once for each function it appears in
/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/template-hsc.h:38:10: note: in definition of macro ‘hsc_const’
if ((x) < 0) \
^
compiling .stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/System/Console/Haskeline/Backend/Posix_hsc_make.c failed (exit code 1)
command was: /bin/gcc -c .stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/System/Console/Haskeline/Backend/Posix_hsc_make.c -o .stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/System/Console/Haskeline/Backend/Posix_hsc_make.o -std=gnu99 -fno-stack-protector -std=gnu99 -fno-stack-protector -fPIC -fuse-ld=gold -D__GLASGOW_HASKELL__=802 -Dlinux_BUILD_OS=1 -Dx86_64_BUILD_ARCH=1 -Dlinux_HOST_OS=1 -Dx86_64_HOST_ARCH=1 -Iincludes -DTERMINFO -I.stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/autogen -I.stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/global-autogen -include .stack-work/dist/x86_64-linux/Cabal-2.0.1.0/build/autogen/cabal_macros.h -I/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/process-1.6.1.0/include -I/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/directory-1.3.0.2/include -I/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/unix-2.7.2.2/include -I/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/time-1.8.0.2/include -I/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/bytestring-0.10.8.2/include -I/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/base-4.10.1.0/include -I/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/integer-gmp-1.0.1.0/include -I/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/include -I/home/rbarden/.stack/programs/x86_64-linux/ghc-8.2.2/lib/ghc-8.2.2/include/
[rbarden ~]$ stack --version
Version 1.6.1, Git revision f25811329bbc40b0c21053a8160c56f923e1201b (5435 commits) x86_64 hpack-0.20.0
Having tried to install anything and everything the internet tells me to to get TIOCGWINSZ and not finding anything about the other note, I'm at a loss.
I'd love to be able to set this in my local config file.
Use-cases include debugging a program using this where we want a server to respond within a certain time.
Another use-case is to write a integration test where we want services to respond within a time-frame. In the latter case, a delta from the previous output might be even more practiacal.
Suggested syntax: Similar to docker log -t
which is:
2016-12-21T01:38:57.215005634Z <rest of line>
Consider these testcases:
t1 = getInputLine " \ESC[36m%\ESC[0m "
t2 = getInputLine " \ESC[36m\STX%\ESC[0m\STX "
t3 = getInputLine "\ESC[32m\STX–––\ESC[0m\STX\n \ESC[36m\STX%\ESC[0m\STX "
t4 = getInputLine "\ESC[32m–––\ESC[0m\n \ESC[36m\STX%\ESC[0m\STX "
t5 = getInputLine "\SOH\ESC[32m\STX–––\SOH\ESC[0m\STX\n\SOH\ESC[36m\STX%\SOH\ESC[0m\STX "
runTest = do
runInputT defaultSettings (t1 >> t1) >>= print
runInputT defaultSettings (t2 >> t2) >>= print
runInputT defaultSettings (t3 >> t3) >>= print
runInputT defaultSettings (t4 >> t4) >>= print
Testcase 1 is just to demonstrate why the \STX is needed, just as the wiki says. Enter too many chars, press enter, recall the last entry, pres pos1, edit, press enter, and see that the cursor position was off. So far, nothing new.
Testcase 2 shows the official, working solution.
Testcase 3 uses a multi-line prompt following the official solution. It works, but now weird characters show up in the first line (tested on xfce4-terminal)
Testcase 4 shows what's necessary to combine working cursor positions with multiline prompts. It works, but it is neither consistent nor documented.
Testcase 5 shows that the issue goes further once you need additional control characters. One application is if you want to pipe ghci output through a post processor.
I'm not sure how much of this is a bug and how much of this is just a gap in the documentation.
Example is you are doing fuzzy completion, with drop
completed to Text.drop
and Sequence.drop
. In this case, the common prefix of the completions is the empty string, and the user's input of drop
is deleted (and no suggestions get printed).
Suggested behavior: Don't replace the user input if the common prefix is shorter than the input.
Another possible idea: somehow give the user more control over what happens to the line when completions are chosen (so they can override this behavior).
Hi,
I'm used to using vi mode for pretty much anything I can. The thing is, the way I use vi is by entering Alt+key combinations to go into normal mode instead using the –in my opinion– burdensome Esc key. This works in quite a few terminal emulators including Linux's non-graphical TTYs (usually accessed with Alt+Ctrl+Fn).
However, this trick does not work with haskeline since it interprets Esc instantly followed by a key k
as metaKey k
. This makes haskeline based UIs (in my case, mainly ghci) very cumbersome to use for me, and if I had to guess, a few others too.
I'm currently going around this issue by simply commenting out the part of the code responsible for this behaviour like so:
diff -ur System.orig/Console/Haskeline/Backend/Posix.hsc System/Console/Haskeline/Backend/Posix.hsc
--- System.orig/Console/Haskeline/Backend/Posix.hsc 2014-12-23 03:32:27.000000000 +0100
+++ System/Console/Haskeline/Backend/Posix.hsc 2015-09-20 20:04:31.849770372 +0200
@@ -193,10 +193,10 @@
lexKeys baseMap cs
| Just (k,ds) <- lookupChars baseMap cs
= k : lexKeys baseMap ds
-lexKeys baseMap ('\ESC':cs)
--- TODO: what's the right thing ' to do here?
- | k:ks <- lexKeys baseMap cs
- = metaKey k : ks
+-- lexKeys baseMap ('\ESC':cs)
+-- -- TODO: what's the right thing ' to do here?
+-- | k:ks <- lexKeys baseMap cs
+-- = metaKey k : ks
lexKeys baseMap (c:cs) = simpleChar c : lexKeys baseMap cs
lookupChars :: TreeMap Char Key -> [Char] -> Maybe (Key,[Char])
I then recompile GHC, and, since I don't use any Alt shortcuts anyway, all is fine for me.
Still, I feel it would be nice if there was an option to change this behaviour at runtime, perhaps by letting the user enter a sequence like Ctrl-v + Alt-k
while in insert mode, which would be interpreted "verbatim" as Alt-k
.
Would you be interested in implementing such a functionality, or at least would you be prepared to accept a pull request providing it? Please let me know. In the latter case, I will see what I can do but might have to ask you a few questions for guidance.
A nice to have feature would be multi-line input in interactive mode.
From the api perspective I envision passing a function as part of the configuration.
This function gets called with the input (and possibly some meta information, such as the position of the cursor) every time the user types something at the prompt and then returns a status, indicating whether the input should be considered complete (or partial).
This would for example allow implementing a multi-line mode where the input is accepted when it parses successfully or when a special key sequence is encountered (this would possibly require passing control characters to the envisioned function).
A bizarre discrepancy that I discovered when using GHCi (or any Haskeline-based terminal, actually) on both Windows on Linux. If you have a string which contains sufficiently fancy UTF-8 characters and attempt to copy-and-paste it into Haskeline using a native Windows console, it'll just drop the fancy characters!
For instance, if you have the string "Error: Не удается найти указанный файл" and try to copy-and-paste it into GHCi on PowerShell, you'll get:
(It does paste it some extra whitespace characters, for some bizarre reason...)
But if you paste the same string into, say, MSYS2, it works fine!
So the issue appears to be local to win32Term
.
I'm not intimately familiar with how win32Term
reads input, so I can't say if this is a Haskeline-specific issue or a problem with the way Win32 API calls (e.g., ReadConsoleInput
) are being used.
Between haskeline 0.7.1.0 and 0.7.1.2 you raised the required cabal version from 1.8 to 1.16, which by the way would totally require at least a minor version bump. Seeing that you only used the default-* features it would be enough to require cabal 1.10, since this is when that feature was introduced. The reason I ask for that is of course compatibility. Currently, a travis build of mine unnecessarily fails due to this: https://travis-ci.org/neothemachine/scion-class-browser/jobs/46119820 Lowering the bound makes it work: https://travis-ci.org/neothemachine/haskeline/jobs/46123976 It would be nice if the cabal bound could be lowered, at least to 1.14 in case you don't want to go down to 1.10. Thanks!
Steps to reproduce:
Expected outcome: nothing happens
Real outcome: every now and then, the character f is appended to the command line
No one I asked was able to reproduce this, but I can reproduce it here. I'm on GHCi 8.2.2 on Ubuntu 14.04, 32-bit.
I'd like to use different configuration files (instead of $HOME/.haskeline
) depending on the application in use. For example, I'd like a different set of key bindings for GHCi which doesn't not make sense in the global $HOME/.haskeline
configuration.
Perhaps this could be achieved by modifying readPrefsFromHome
to check for the presence of a .haskeline
file alongside the current executable before falling back to the version in $HOME
.
Is this something that would be useful to other people?
Hello,
I'd like to do something with \BS, but getInputChar
ignores non-printable characters.
How can I do it? Should I build a custom function which acts like getInputChar
returns non-printable ones?
Hey,
while trying to upgrade my version of purescript, which updated it's dependency on haskeline to 0.7.2.0, purescript fails to compile for me, with the following error:
SystemConsoleHaskelineBackendWin32.hsc:263:24:
Not in scope: type constructor or class `Applicative'
Failed to install haskeline-0.7.2.0
cabal: Error: some packages failed to install:
haskeline-0.7.2.0 failed during the building phase. The exception was:
ExitFailure 1
purescript-0.6.9.3 depends on haskeline-0.7.2.0 which failed to install.
Edit: After adapting purescript's dependency .cabal file so it would use haskeline 0.7.1.3, it does compile for me immediately. (Windows 8.1)
I'm using ghci on Windows, and I have migrated some profile path from C: to D: in place for windows reinstallation. But I didn't migrate profile folder itself due to drive failing situation.
Because of directory
package's process, I have to copy .haskeline
file to C:\Users\%USERNAME% each time I reinstall windows.
Some utilities use %HOME% environment variable for this situation. Are you willing to reflect this?
This same issue bit cabal-install
(haskell/cabal#4128), and it affects haskeline
too. Not only is this Windows-specific, but it's also console-specific, as it requires the MSYS2 (or Cygwin) console (as opposed to cmd.exe
or PowerShell, which are exempt from this issue). To reproduce, clone this repo in MSYS2 and run:
$ runghc haskeline/examples/Test.hs
0:password
line 0:password
1:hunter2
line 1:hunter2
2:q
Notice that it echoed my password (hunter2
) when I typed it! This is because sadly, the hGetEcho
and hSetEcho
functions (which getPassword
uses internally) don't work properly on MinTTY consoles like MSYS2. To disable echoing on MinTTY, you have to shell out to stty
.
I fixed the cabal-install
issue by creating my own echo
library, which implements all of the functionality needed to have a withoutInputEcho
function that works properly on all operating systems and consoles, and made cabal-install
depend on it. However, given that haskeline
is a GHC dependency, that probably won't work in this case. Would you object if I inlined the code from echo
into haskeline
to fix getPassword
?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.