Giter Club home page Giter Club logo

notty's Introduction

Notty — Declaring terminals

Notty is a declarative terminal library for OCaml structured around a notion of composable images. It tries to abstract away the basic terminal programming model, providing something simpler and more expressive.

The core layout engine and IO codecs are pure platform-independent OCaml. Distribution includes modules with input and output facilities for Unix, and Lwt on Unix.

As an attempt to redefine terminal programming, Notty has to be opinionated. It assumes Unicode throughout, does not have universal support for various terminals out there, and has a peculiar programming and rendering model.

Notty's core API was heavily influenced by Haskell's Vty.

Where to start

Check out the documentation, examples, or peek directly into the interface file.

Building with dune build @ex will produce several little example programs that also double as tests.

(* Game of Life with ZX Spectrum kitsch. *)

let dot : image = I.uchar A.(fg lightred) (Uchar.of_int 0x25cf) 1 1

let background step (n, m) =
  let k = 24. *. sin (float (step + m + n) /. 10.) |> truncate in
  if k > 0 then I.char A.(fg (gray k)) '.' 1 1 else I.void 1 1

let render (w, h) step life : image =
  I.tabulate w (h - 1) @@ fun x y ->
    let pt = (x, y) in
    if CSet.mem pt life then dot else background step pt

What?

  • Notty?

    Terminals are tedious to program for. Notty tries to abstract the tedium away, leaving you with a more pleasant programming surface that's quite unlike a TTY. Hence, No-TTY.

  • A new kind of Rust terminal?

    This Notty has no connection to any other body of code named Notty.

  • Why make yet another terminal output library?

    Because:

    • It allows one to describe what should be seen, as opposed to commanding a terminal.
    • It's pretty compact. Both bells and whistles can be implemented separately.
    • Core is easy to glue onto various IO backends.
    • Pure platform-independent OCaml.

notty's People

Contributors

bcc32 avatar kit-ty-kate avatar pqwy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

notty's Issues

Bell character support

From the documentation:

{2:ctrls Control characters}

These are taken to be characters in the ranges [0x00-0x1f] ({b C0}) and
[0x80-0x9f] ({b C1}), and [0x7f] (BACKSPACE). This is the
{{: http://unicode.org/reports/tr44/#General_Category_Values}Unicode
general category} {b Cc}.

As control characters directly influence the cursor positioning, they
cannot be used to create images.

Since the bell character (0x07) does not change the cursor position, it should be allowed in images,
and/or there should be a bell attribute that prints it.

Terminal state is not properly restored on Ctrl-C

When using Notty_unix.Term, The state of the terminal is not properly restored on Ctrl-C (while it is well restored when just exiting the program).

This code "solves" it, but I think it should be done directly by notty.

  Sys.(set_signal sigint @@ Signal_handle (fun _ -> Term.release t)) ;

Not all examples will be built

Get an error message, that unmark.cli is not avaialable.
Removing that entry in the dune-file, next err-msg is, that unmark is not available.
So I can't compile all examples.
Only six examples will be built.

[OCaml 5.0] Eio compatibility

Hi, with the upcoming release of OCaml 5.00 eio seems to be the new reference library for IO.

@talex5 began investigating on its own here, but an "official" new IO module adding support for eio would be nice.

API addition/change

First of all, let me say that notty is very nice to use and the result are terrific! Thank you for making this library.

After using it on a few projects, this request came to me.

In the "Additional Combinators" section, there's a function called tile which lays out images in a grid. I would recommend renaming it to grid, since it defines a finite grid. Next, I request that in the "Primitives" section, you add a function called tile:

val tile : image -> image

which takes an image and infinitely tiles it vertically and horizontally. You use a cropping function to limit the tiling.

I don't know how easy/difficult this would be to implement. I may take a crack at implementing myself, if you think it'd be a good addition to the library.

Respond to SIGTSTP/SIGSTOP nicely

I'm trying to make a tool with notty that suspends properly on Ctrl-Z and struggling. When I send SIGSTOP or SIGTSTP to a hello world program and continue with fg, there are a couple of problems: it doesn't continue instantly (first it prints the program name and then I have to press enter), and after continuing my keypresses are echoed at the bottom of the screen. Is there something I need to do to fix this?

Windows support

It does not like notty is supported for windows. It would be great to add support for windows.

possible issue with Notty.I.strf

I wanted to add tab space in a string image like with Format.astring with :

I.(strf ~attr:A.(fg lightred ++ bg lightblack) "\t %s : %s" title artist)

but it makes my program stop without any warnings, when I remove the "\t" part, everything is fine.

If I add a backslash to try to escape,

I.(strf ~attr:A.(fg lightred ++ bg lightblack) "\\t %s : %s" title artist)

my program does not crash but it displays something like:

"\ta_title : an artist" which is not the same behavior that Format.astring as it is said in the documentation

pretty-prints like Format.asprintf format ..., but returns an image.

Regards.

Unable to build the keys.ml example

I have been able to build all the others examples but I have an error with the keys.ml file:
Here is the error message:

ocamlbuild -pkg notty keys.native
+ /usr/bin/ocamlc.opt -c -I /home/cedlemo/.opam/system/lib/bytes -I /home/cedlemo/.opam/system/lib/notty -I /home/cedlemo/.opam/system/lib/result -I /home/cedlemo/.opam/system/lib/uucp -I /home/cedlemo/.opam/system/lib/uuseg -I /home/cedlemo/.opam/system/lib/uutf -o keys.cmo keys.ml
File "keys.ml", line 61, characters 16-33:
Error: Unbound type constructor Unescape.special
Command exited with code 2.
Hint: Recursive traversal of subdirectories was not enabled for this build,
  as the working directory does not look like an ocamlbuild project (no
  '_tags' or 'myocamlbuild.ml' file). If you have modules in subdirectories,
  you should add the option "-r" or create an empty '_tags' file.

  To enable recursive traversal for some subdirectories only, you can use the
  following '_tags' file:

      true: -traverse
      <dir1> or <dir2>: traverse

Compilation unsuccessful after building 4 targets (2 cached) in 00:00:00.

I have not found any references to Unescape.special in the other files (sources or examples) :

~/Projets/Ocaml/notty · (master)
⟩ find -type f | xargs grep Unescape.special
./examples/keys.ml:        | `Key (#Unescape.special as k, mods) ->

Am I doing something wrong?

Terminal state not cleaned up?

After the execution of the following program, I have to enter reset the terminal, to restore it's behavior (echo, etc.).

If I un-comment the two commented line, it works OK. Is it expected?

open Lwt.Infix

let main () =
  (* let original_attr = Unix.tcgetattr Unix.stdout in (\* ADDED TO STORE TERM STATE *\) *)
  let t = Notty_lwt.Term.create ~dispose:true ~mouse:false ~bpaste:false () in
  let loop =
    Lwt.return t
    >>= Notty_lwt.Term.release
    >>= fun () -> Printf.printf "Ciao!\n%!"; Lwt.return_unit in

  Lwt_main.run loop
  (* ;Unix.tcsetattr Unix.stdout Unix.TCSANOW original_attr (\* ADDED TO RESET TERM STATE *\) *)

let () = main ()

The version I used:

$ opam show notty

=-=- notty: information on all versions -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
name                   notty
all-installed-versions 0.2.1 [4.06.1+flambda]
all-versions           0.1.0  0.1.1  0.2.0  0.2.1

=-=- Version-specific details -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
version       0.2.1
repository    default
url.src:      https://github.com/pqwy/notty/releases/download/v0.2.1/notty-0.2.1.tbz
url.checksum: md5=f85f6d0099483230b2b60335ab4496d1
homepage:     https://github.com/pqwy/notty
bug-reports:  https://github.com/pqwy/notty/issues
dev-repo:     git+https://github.com/pqwy/notty.git
authors:      David Kaloper <[email protected]>
maintainer:   David Kaloper <[email protected]>
license:      ISC
depends:      "ocaml" {>= "4.03.0"}
              "ocamlbuild" {build}
              "ocamlfind" {build}
              "topkg" {build}
              "ocb-stubblr" {build & >= "0.1.0"}
              "uchar"
              "uucp" {>= "2.0.0"}
              "uuseg" {>= "1.0.0"}
              "uutf" {>= "1.0.0"}
depopts:      "lwt"
conflicts:    "ocb-stubblr" {< "0.1.0"} "lwt" {< "2.5.2"}
synopsis      Declaring terminals.
description   Notty is a declarative terminal library for OCaml structured around a notion
              of composable images. It tries to abstract away the basic terminal programming
              model, providing a simpler and a more expressive one.

Thanks: I'm having fun playing with notty

Vertical stacking on WSL (Ubuntu subsystem on Windows 10) does not work.

See this issue.

To repeat:
Given the following code:

open Notty
open Notty_unix

(*
 * ocamlbuild -pkg notty -pkg notty.unix basics_wow.native
 *)
let () =
let wow = I.string A.(fg lightred) "Wow!" in
I.(wow <-> (void 2 0 <|> wow))
|> Notty_unix.eol
|> Notty_unix.output_image

and the following two commands:
ocamlbuild -pkg notty -pkg notty.unix basics_wow.native
./basics_wow.native

I get this image:

Wow!s next to each other instead of above one another

I'm on Windows 10, running this through the terminal for my Ubuntu subsystem.

build script fails due to missing 'unmark' package

The build script fails to compile the benchmarks due to the missing package unmark:

ocamlfind ocamldep -package unmark -package 'uchar uucp uuseg uutf' -modules benchmarks/speed.ml > benchmarks/speed.ml.depends         
+ ocamlfind ocamldep -package unmark -package 'uchar uucp uuseg uutf' -modules benchmarks/speed.ml > benchmarks/speed.ml.depends        
ocamlfind: Package `unmark' not found                                                                                   
Command exited with code 2.                                                                                             
pkg.ml: [ERROR] cmd ['ocamlbuild' '-use-ocamlfind' '-classic-display' '-j' '4' '-tag' 'debug'                           
     '-build-dir' '_build' '-plugin-tag' 'package(ocb-stubblr)' 'opam'                                                  
     'pkg/META' 'CHANGES.md' 'LICENSE.md' 'README.md' 'src/notty.a'                                                     
     'src/notty.cmxs' 'src/notty.cmxa' 'src/notty.cma' 'src/notty.cmx'                                                  
     'src/notty.cmi' 'src/notty.mli' 'src/notty_top.a' 'src/notty_top.cmxs'                                             
     'src/notty_top.cmxa' 'src/notty_top.cma' 'src/notty_top.cmx'                                                       
     'src/notty_top_init.ml' 'unix/notty_unix.a' 'unix/notty_unix.cmxs'                                                 
     'unix/notty_unix.cmxa' 'unix/notty_unix.cma' 'unix/notty_unix.cmx'                                                 
     'unix/notty_unix.cmi' 'unix/notty_unix.mli' 'lwt/notty_lwt.a'                                                      
     'lwt/notty_lwt.cmxs' 'lwt/notty_lwt.cmxa' 'lwt/notty_lwt.cma'                                                      
     'lwt/notty_lwt.cmx' 'lwt/notty_lwt.cmi' 'lwt/notty_lwt.mli'                                                        
     'unix/dllnotty_unix_stubs.so' 'unix/libnotty_unix_stubs.a'                                                         
     'benchmarks/speed.native' 'examples/testpatterns.native'                                                           
     'examples/letters.native' 'examples/keys.native'                                                                   
     'examples/colors.native' 'examples/sierpinski.native'                                                              
     'examples/cuts.native' 'examples/thisbig.native' 'examples/runes.native'                                           
     'examples/crops.native' 'examples/mouse.native' 'examples/cursor.native'                                                                                                
     'examples/emoji.native' 'examples/inline.native' 'examples/rain.native'                                                                                               
     'examples/almondbread.native' 'examples/sierpinski_lwt.native'                                                                                                               
     'examples/life.native' 'examples/linear.native']: exited with 10  

Unfortunately I wasn't able to find any module/package named unmark in opam or various web search results.

The README does clearly state to use ./pkg/pkg.ml but developers will assume they can just run ./build and it will build everything. If this is not the case, then to avoid confusion, it seems like a good idea to make one of the below changes to build

  1. Add a check for the unmark package and build with --benchmarks false if not present
  2. Update to match the command mentioned in README.md
  3. Remove it

circular dependency between unmark.cli and notty

I tried to run the benchmark, which depends on the 'unmark' package that is not on opam.
I tried pinning it, which went fine:
opam pin add unmark https://github.com/pqwy/unmark.git

Then tried running the benchmark:

dune exec ./speed.exe
Entering directory '/var/home/edwin/git/notty'
Error: Conflict between the following libraries:
- "notty" in _build/default/src
- "notty" in /var/home/edwin/.opam/5.0.0/lib/notty
  -> required by library "unmark.cli" in
     /var/home/edwin/.opam/5.0.0/lib/unmark
-> required by executable speed in benchmarks/dune:2
-> required by _build/default/benchmarks/speed.exe

Lets try removing notty and use the one I'm just building locally with dune, but that removes unmark too:

opam remove notty
[WARNING] Opam package conf-gles2.1 depends on the following system package that can no longer be found: mesa-libGLES-devel
cd ..
The following actions will be performed:
  ⊘ remove unmark ~dev* [uses notty]
  ⊘ remove notty  0.2.3
===== ⊘ 2 =====
Do you want to continue? [Y/n] y

And since unmark doesn't use dune I can't just drop it in a subdir to build it together.

Is there a way to break the cycle?

Possible extensions to the image combinators

One issue I see with the current image combinators is that the ability to overlay them seems limited. In particular, it's often natural to want to overlay some property over an existing image. For example, it would be nice to highlight a range of text by setting the background color attribute on some range of an existing image.

The current combinators offer no way of doing this cleanly, as far as I understand. To make it work, you basically need to get the correct attributes in when constructing the original image.

Would there be any interesting in adding some calls that would allow this kind of thing by operating more directly on images?

Dune support

Would a PR that migrates the project to using Dune be welcomed? I've been playing around with writing a notty_unix package, and I've run into some problems linking things that I was able to resolve by moving things to Dune.

If you're happy with it, I'll go ahead and make the PR.

some alignment issues

Hi, first of all thanks for that amazing library. It's like magic, but better.

When running ./runes.native I got some alignement issues:

screen shot 2016-02-11 at 07 43 48

Anything special to report to help debugging that? I'm running on OSX 10.10.5 and notty is built from master.

`pending` seems to not work using unix backend

I tried to write something like:

(* main loop …*)
   render;
   while Notty_unix.Term.pending() do
     match Notty_unix.Term.event () withdone

but the code would never process any event. If I remove the pending() loop, the whole UI becomes blocking, but works properly. However, that's not very convenient when one wants to both react to events, and draw some UI that can change in other ways (e.g. a clock).

Converting rgb_888 to rgb

In my program, I have a series of RGB values that are suited for the A.rgb_888 function (range 0-255), but not all terminal applications support True Color mode. Is there a way to convert those values so they can be used with the A.rgb function (range 0-5)?

Add mouse movement

I was thinking that having the ability to track the movement of the mouse would be quite nice, so I tried digging a bit and it seems that it can be done quite easily by de-commenting the move inputs in the event_of_control_code function and using the mode 1003 instead of 1002 (which activates the tracking of all mouse input even without any button pressed).

However it might have an impact on the performances & other secondary effects I am not aware off (I have very little knowledge on the subject). What do you think of it @pqwy ? Maybe it can be added but toggled off by default ?

Here is the diff file:
diff.txt

Merging attributes

It would be nice, when overlaying one image on another, that if the upper image doesn't specify a background, it uses the lower image's background. Right now, it seems the upper image will have a black background (unless I missed an important operator or combinator.) Maybe a new operator <//> to overlay and blend the two images?

Something like that would make it easy to do things like:

open Notty
open Notty.Infix

let progress_bar w pcnt =
  let pcnt = max 0.0 (min 1.0 pcnt) in
  let w' = truncate (float w *. pcnt) in
  I.(hsnap w (strf ~attr:A.(fg yellow) "%.0f%%" (pcnt *. 100.))) </>
    I.((char A.(bg cyan) ' ' w' 1) <|> (char A.(bg blue) ' ' (w - w') 1))

The progress is displayed using the background attribute. I'd like it to continue behind the numeric string but, instead, the background of the text is always black. And it's not necessarily easy to implement what I want using the current combinators. I'd have to keep the string and conditionally cut it up so half can be displayed with one background the other half with the other background. I'd also have to stop using hsnap since I'd have to carefully control how it's centered to make sure the backgrounds lined up properly.

New version in opam

Is it hard to mint a new opam version that includes the val I.attr, which seems to be in the master branch? If it's hard or simply time consuming for the maintainers, I'd be happy to lend my time as well.

Also happy holidays! 🎄 Please ignore me until you're back in the normal flow of things :)

Time for a new release on OPAM?

The version on opam is pretty old at this point, and is not compatible with the most recent uutf. It's possible to build without downgrading by pinning to the dev version, but making a release and putting it on opam would be lovely.

Type error when building: Uchar.t / int clash

I'm attempting to track down the source of the problem, but thought it might be useful to make note of hurdle here.

I wonder if this is perhaps a package conflict, or conflict in version. I see there is a definition of module Uchar in notty.ml, and I wonder if this is perhaps coming in to conflict with with the module Uchar in the 4.04 std library. Or perhaps it is built with an older version of some package?

System

$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.11.6
BuildVersion: 15G1217

Output

# x @ y in ~/Programming/ocaml/consolate/notty on git:master o [3:57:57] C:1
$ ./pkg/pkg.ml build --with-lwt true --examples true --debug true -v -v
pkg.ml: [INFO] topkg v0.8.1, running main
pkg.ml: [EXEC] ['type' 'git' 1>'/dev/null' 2>'/dev/null']
pkg.ml: [INFO] Build configuration:
               pkg-name: notty
               build-dir: _build
               vcs: true
               pinned: false
               tests:
               debug: true
               debugger-support: false
               profile: false
               with-unix: true
               with-lwt: true
               benchmarks: false
               examples: true
pkg.ml: [EXEC] ['ocamlfind' 'ocamlc' '-config' 1>'/var/folders/6y/fszsf5zj6vngmm7l_wrst7t00000gn/T/pkg.mlad2b95topkg']
pkg.ml: [EXEC] ['ocamlbuild' '-use-ocamlfind' '-classic-display' '-tag' 'debug' '-build-dir' '_build' '-plugin-tag' 'package(ocb-stubblr)' 'opam' 'pkg/META' 'CHANGES.md' 'LICENSE.md' 'README.md' 'src/notty.a' 'src/notty.cmxs' 'src/notty.cmxa' 'src/notty.cma' 'src/notty.cmx' 'src/notty.cmi' 'src/notty.mli' 'unix/notty_unix.a' 'unix/notty_unix.cmxs' 'unix/notty_unix.cmxa' 'unix/notty_unix.cma' 'unix/notty_unix.cmx' 'unix/notty_unix.cmi' 'unix/notty_unix.mli' 'lwt/notty_lwt.a' 'lwt/notty_lwt.cmxs' 'lwt/notty_lwt.cmxa' 'lwt/notty_lwt.cma' 'lwt/notty_lwt.cmx' 'lwt/notty_lwt.cmi' 'lwt/notty_lwt.mli' 'unix/dllnotty_unix_stubs.so' 'unix/libnotty_unix_stubs.a' 'examples/testpatterns.native' 'examples/letters.native' 'examples/keys.native' 'examples/colors.native' 'examples/sierpinski.native' 'examples/cuts.native' 'examples/thisbig.native' 'examples/runes.native' 'examples/crops.native' 'examples/mouse.native' 'examples/cursor.native' 'examples/sierpinski_lwt.native' 'examples/life.native' 'examples/linear.native']
ocamlfind ocamlopt -c -g -bin-annot -safe-string -package result -package uucp -package uuseg -package uutf -w A-4-33-40-41-42-43-34-44-48 -color always -I src -I unix -I lwt -o src/notty.cmx src/notty.ml
+ ocamlfind ocamlopt -c -g -bin-annot -safe-string -package result -package uucp -package uuseg -package uutf -w A-4-33-40-41-42-43-34-44-48 -color always -I src -I unix -I lwt -o src/notty.cmx src/notty.ml
File "src/notty.ml", line 154, characters 36-37:
Error: This expression has type Uchar.t
       but an expression was expected of type int
Command exited with code 2.
pkg.ml: [ERROR] cmd ['ocamlbuild' '-use-ocamlfind' '-classic-display' '-tag' 'debug'
     '-build-dir' '_build' '-plugin-tag' 'package(ocb-stubblr)' 'opam'
     'pkg/META' 'CHANGES.md' 'LICENSE.md' 'README.md' 'src/notty.a'
     'src/notty.cmxs' 'src/notty.cmxa' 'src/notty.cma' 'src/notty.cmx'
     'src/notty.cmi' 'src/notty.mli' 'unix/notty_unix.a'
     'unix/notty_unix.cmxs' 'unix/notty_unix.cmxa' 'unix/notty_unix.cma'
     'unix/notty_unix.cmx' 'unix/notty_unix.cmi' 'unix/notty_unix.mli'
     'lwt/notty_lwt.a' 'lwt/notty_lwt.cmxs' 'lwt/notty_lwt.cmxa'
     'lwt/notty_lwt.cma' 'lwt/notty_lwt.cmx' 'lwt/notty_lwt.cmi'
     'lwt/notty_lwt.mli' 'unix/dllnotty_unix_stubs.so'
     'unix/libnotty_unix_stubs.a' 'examples/testpatterns.native'
     'examples/letters.native' 'examples/keys.native'
     'examples/colors.native' 'examples/sierpinski.native'
     'examples/cuts.native' 'examples/thisbig.native' 'examples/runes.native'
     'examples/crops.native' 'examples/mouse.native' 'examples/cursor.native'
     'examples/sierpinski_lwt.native' 'examples/life.native'
     'examples/linear.native']: exited with 10

I can't get any of the examples to work

Installed notty from opam. Then tried to follow the 'Basics' instructions.

For example here's what I tried:

─( 19:49:50 )─< command 0 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─
utop # #require "notty";;
─( 19:49:52 )─< command 1 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─
utop # #require "notty.top";;
─( 19:50:03 )─< command 2 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─
utop # I.string A.empty "Rad!";;
- : image = Rad!
─( 19:51:22 )─< command 3 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─
utop # I.string A.empty "Rad!" |> Notty_unix.output_image;;
Line 1:
Error: Reference to undefined global `Notty_unix'
─( 19:51:52 )─< command 4 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─

Support for placing and showing the cursor

Is it possible to specify where the terminal cursor should be placed, as well as showing it? I tried using Notty.show_cursor but didn't seem to work.

What I had in mind is a special combinator cursor : A.attr -> I.image that would have size 1x1 but that would have a special behaviour when overlaid over an image already containing cursor: any underlying cursor would be removed.

`Notty.Unescape.next` doesn't seem to parse Arrow escape sequence

So (in case it matters) typing into my terminal the key sequence "Up, down, right, left" gives:

$ cat
^[[A^[[B^[[C^[[D

I'm hoping to be able to parse these (along with other things like simple keypresses) as Notty.event's. The problem I run into is that I end up parsing ^[ as an 'Escape key event (presumably with [A or something to follow), when I really want it to be parsed as an 'Arrow key event.

The current way I'm doing this looks like:

let events _ =                                                                                                                                                                               
  let unescape = Notty.Unescape.create () in                                                                                                                                                 
  Lwt_stream.from_direct (fun () ->                                                                                                                                                          
      match Stdio.In_channel.input_char stdin with                                                                                                                                           
      | None ->                                                                                                                                                                              
          None                                                                                                                                                                               
      | Some c -> (                                                                                                                                                                          
          Notty.Unescape.input unescape (Bytes.of_char_list [c]) 0 1 ;                                                                                                                       
          match Notty.Unescape.next unescape with                                                                                                                                            
          | `End ->                                                                                                                                                                          
              None                                                                                                                                                                           
          | `Await ->                                                                                                                                                                                                                                                                                                             
              raise (Failure "unimplemented - hasn't happened yet")                                                                                                                          
          | #Notty.Unescape.event as event ->                                                                                                                                                
              Some event ))      

I'm reading from stdin character-by-character and then putting each character into the Unescape.t. Does this seem like a reasonable thing to do? Perhaps there is a different way to get a stream of Notty events.

If this ends up being unimplemented in the parsing mechanism of Notty, I'd be happy to take a stab at trying to improve it!

Notty is incompatible with OCaml 4.06

There was a breaking change to the Format library in 4.06

* GPR#615: Format, add symbolic formatters that output symbolic
  pretty-printing items. New fields have been added to the
  formatter_out_functions record, thus this change will break any code building
  such record from scratch.
  (Richard Bonichon and Pierre Weis, review by Alain Frisch)

notty appears to be affected, according to the logs of my opam-builder instance:

/home/barsac/scherer/opam-builder/4.06.0+beta2+default-unsafe-string/.opam/4.06.0+beta2+default-unsafe-string/bin/ocamlfind ocamlc -c -g -annot -bin-annot -safe-string -w A-4-33-40-41-42-43-34-44-48 -package uutf -package uuseg -package uucp -package result -I src -o src/notty.cmo src/notty.ml
File "src/notty.ml", line 508, characters 41-99:
Error: Some record fields are undefined: out_indent

Would you consider making a release that is compatible with 4.06? (If you have pending features, it would probably make sense to make first a release with the new features compatible with older OCaml versions, and then a minor release that adds nothing but the 4.06 support, so that users of either versions can benefit from the other new notty features.)

combinator for multi-line text

Since I.string does not accept strings with newlines, I propose to add I.text with the same signature but that will split its input on '\n' and position lines vertically (aligned on left, say).
Would that be ok?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.