8

I'm trying to get a handle on the basics of Haskell by creating a Notational Velocity style find-as-you-type file search on the command line. Instead of tackling the whole problem, I'm trying a very basic version of it: There exists a file with 10 lines, and a 3 letter word on each line. After each letter I type, I want to update the display of a list of line numbers that might contain the word I'm typing, based on my input so far.

Can someone demonstrate a Haskell program that does this? I think my problem lies in forcing reevaluation on every character input. Thanks a million in advance.

  • This is less about capabilities of Haskell and more about capabilities of command line. Generally, I don't think your code can know what's written in the command line before user presses [Enter]. – Karolis Juodelė Mar 09 '13 at 11:03
  • 1
    @KarolisJuodelė I think a program can definitely do that - for instance Vim responds to single key inputs without enter being pressed. The way to do this would be to either read a single character at a time from the terminal, and then either update the completions or do some action, depending on whether the key pressed was enter, or to perhaps use some sort of library for making command-line UIs, like ncurses (which is used for many command line programs). –  Mar 09 '13 at 11:14
  • @DarkOtter, that is why I said "generally". I'm aware that it can be done with platform dependent libraries (and their cross platform wrappers). I don't think their use should be encouraged though - if you want a proper UI, use a proper UI toolkit. I fear that beginners might get the idea that console UI is easier, while, in fact, it is usually harder. – Karolis Juodelė Mar 09 '13 at 11:59

2 Answers2

2

I won't try to write the whole Haskell program you're asking for, but here is a very short example showing just the bit you claim to be stuck on at the moment: doing something after every key press. We won't do anything exciting (just bump a number and print it out), but it will show how to do that one small task, and you perhaps can start hacking from there.

The only thing you really need to know that you seem not to is that you can turn off line-buffering on the input.

import System.IO

loop n = do
    c <- getChar
    print n
    -- do whatever recalculation you need to do here, using
    -- n (which can be more complicated than an Integer, as
    -- it is here, of course) and c (which is a Char
    -- representing the key the user whacked)
    -- our recalculation is just to increase n by one
    loop (n+1)

main = do
    hSetBuffering stdin NoBuffering -- do this once before anything else
    loop 0
Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380
  • I Just played with this a little and I'll make two notes. 1) You probably also want to turn buffering off for stdout. 2) It's *very* easy to miss input characters if loop is too slow. Just reprint the char with (putstr [toUpper c]) and bang on the keyboard and you'll see what I mean. – John Tyree Mar 10 '13 at 09:52
1

Studing Reactive programming could be a good starting.
For this a good library seem to be reactive banana
There some base example.

If you want to know more, on FRP, an excellent topic on stack will give you a clear overview.

Community
  • 1
  • 1
zurgl
  • 1,930
  • 1
  • 14
  • 20