pax_global_header00006660000000000000000000000064141433323620014513gustar00rootroot0000000000000052 comment=b102082e1e2219882303e752f63c22471c92423b ANSITerminal-0.8.3/000077500000000000000000000000001414333236200137515ustar00rootroot00000000000000ANSITerminal-0.8.3/.github/000077500000000000000000000000001414333236200153115ustar00rootroot00000000000000ANSITerminal-0.8.3/.github/workflows/000077500000000000000000000000001414333236200173465ustar00rootroot00000000000000ANSITerminal-0.8.3/.github/workflows/main.yml000066400000000000000000000024301414333236200210140ustar00rootroot00000000000000name: Continuous Integration on: push: branches: [ master ] pull_request: branches: [ master ] jobs: build: strategy: fail-fast: false matrix: os: - macos-latest - ubuntu-latest - windows-latest ocaml-version: - 4.12.0 include: - ocaml-version: 4.03.0 os: ubuntu-latest skip_test: true - ocaml-version: 4.08.1 os: ubuntu-latest skip_test: true - ocaml-version: 4.11.1 os: ubuntu-latest skip_test: true - ocaml-version: 4.13.0 os: ubuntu-latest skip_test: true - ocaml-version: 4.13.0 arch: armv6 os: ubuntu-latest runs-on: ${{ matrix.os }} env: SKIP_TEST: ${{ matrix.skip_test }} steps: - name: Checkout code uses: actions/checkout@v2 - name: Set up OCaml ${{ matrix.ocaml-version }} uses: ocaml/setup-ocaml@v2 with: ocaml-compiler: ${{ matrix.ocaml-version }} - run: opam install . --deps-only --with-test - run: opam exec -- dune build @install - name: run test suite run: opam exec -- dune build @runtest if: env.SKIP_TEST != 'true' ANSITerminal-0.8.3/.gitignore000066400000000000000000000001531414333236200157400ustar00rootroot00000000000000# OCaml -*-conf-unix-*- *.merlin *.install *.tar.gz _build ANSITerminal-0.8.3/ANSITerminal.opam000066400000000000000000000016151414333236200170600ustar00rootroot00000000000000opam-version: "2.0" maintainer: "Christophe Troestler " authors: [ "Christophe Troestler" "Vincent Hugot" ] license: "LGPL-3.0" # with OCaml linking exception homepage: "https://github.com/Chris00/ANSITerminal" dev-repo: "git+https://github.com/Chris00/ANSITerminal.git" bug-reports: "https://github.com/Chris00/ANSITerminal/issues" doc: "https://Chris00.github.io/ANSITerminal/doc" tags: [ "terminal" ] build: [ ["dune" "subst"] {dev} ["dune" "build" "-p" name "-j" jobs] ["dune" "runtest" "-p" name "-j" jobs] {with-test} ] depends: [ "ocaml" "dune" "base-bytes" "base-unix" ] synopsis: "Basic control of ANSI compliant terminals and the windows shell" description: """ ANSITerminal is a module allowing to use the colors and cursor movements on ANSI terminals. It also works on the windows shell (but this part is currently work in progress).""" ANSITerminal-0.8.3/CHANGES.md000066400000000000000000000007301414333236200153430ustar00rootroot000000000000000.8.3 2021-11-12 ---------------- - Improve the portability on Windows. 0.8.2 2019-12-20 ---------------- - Do not check the terminal at startup for the Windows version — so it can be used in a continuous integration environment. 0.8.1 — 2018-09-27 ------------------ - Port to Dune. - Upgrade to OPAM 2.0. 0.8 — 2017-11-08 ---------------- - Only use escape sequences or Windows calls when the stdout or stderr is a TTY. (issue #1). - Port to jbuilder ANSITerminal-0.8.3/LICENSE.md000066400000000000000000000205451414333236200153630ustar00rootroot00000000000000As a special exception to the GNU Lesser General Public License, you may link, statically or dynamically, a "work that uses the Library" with a publicly distributed version of the Library to produce an executable file containing portions of the Library, and distribute that executable file under terms of your choice, without any of the additional requirements listed in clause 6 of the GNU Library General Public License. By "a publicly distributed version of the Library", we mean either the unmodified Library as distributed by INRIA, or a modified version of the Library that is distributed under the conditions defined in clause 3 of the GNU Library General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. ---------------------------------------------------------------------- GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ANSITerminal-0.8.3/Makefile000066400000000000000000000003271414333236200154130ustar00rootroot00000000000000PKGVERSION = $(shell git describe --always --dirty) build: dune build @install all: build dune build @runtest --force test: all _build/default/tests/test.exe clean: dune clean .PHONY: all build test clean ANSITerminal-0.8.3/README.md000066400000000000000000000014651414333236200152360ustar00rootroot00000000000000![Continuous Integration](https://github.com/Chris00/ANSITerminal/actions/workflows/main.yml/badge.svg) ANSITerminal ============ [ANSITerminal](src/ANSITerminal.mli) provides Basic control of ANSI compliant terminals and the windows shell. ANSITerminal is a module allowing to use the colors and cursor movements on ANSI terminals. It also works on the windows shell (this part is currently work in progress). Install ------- On Unix and OSX, the easier to install this library is to use [opam](http://opam.ocaml.org/): opam install ANSITerminal On Windows, until `opam` and `ocamlbuild` work well on this platform, you clone this repository and compile and install this library by executing: build Documentation ------------- The API may be [read online](http://chris00.github.io/ANSITerminal/doc/). ANSITerminal-0.8.3/build.cmd000066400000000000000000000017021414333236200155350ustar00rootroot00000000000000REM Build ANSITerminal until oasis/ocamlbuild works on Windows cd src ocaml choose_implementation.ml ocamlc -verbose -c ANSITerminal_stubs.c ocamlc -c ANSITerminal.mli ocamlmklib -verbose -o ANSITerminal ANSITerminal_common.ml ANSITerminal.ml ANSITerminal_stubs.obj @echo version = "0.6.5"> META @echo description = "Basic control of the windows shell.">> META @echo requires = "unix">> META @echo archive(byte) = "ANSITerminal.cma">> META @echo archive(byte, plugin) = "ANSITerminal.cma">> META @echo archive(native) = "ANSITerminal.cmxa">> META @echo archive(native, plugin) = "ANSITerminal.cmxs">> META ocamlfind install ANSITerminal ANSITerminal.cmi ANSITerminal.mli ANSITerminal.cma ANSITerminal.cmxa ANSITerminal.cmx ANSITerminal_common.cmx dllANSITerminal.dll libANSITerminal.lib ANSITerminal_stubs.obj META cd ../tests REM ocamlfind list ocamlfind ocamlc -verbose -o showcolors.exe -package ANSITerminal -linkpkg showcolors.ml dir showcolors.exe ANSITerminal-0.8.3/dune-project000066400000000000000000000000441414333236200162710ustar00rootroot00000000000000(lang dune 1.0) (name ANSITerminal) ANSITerminal-0.8.3/src/000077500000000000000000000000001414333236200145405ustar00rootroot00000000000000ANSITerminal-0.8.3/src/ANSITerminal.mli000066400000000000000000000137221414333236200174760ustar00rootroot00000000000000(* File: ANSITerminal.mli Copyright 2004 Troestler Christophe Christophe.Troestler(at)umons.ac.be This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 as published by the Free Software Foundation, with the special exception on linking described in file LICENSE. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file LICENSE for more details. *) (** This module offers basic control of ANSI compliant terminals and the windows shell. The functions below do not send ANSI codes (i.e., do nothing or only print the output) when then output is not connected to a TTY. Functions providing information (such as {!pos_cursor}) fail when in that situation. TTY detection is configurable by changing the value of {!isatty}. This library is not thread safe. @author Christophe Troestler (Christophe.Troestler@umons.ac.be) @author Vincent Hugot (vincent.hugot@gmail.com) *) (** {2 Colors and style} *) (** Available colors. *) type color = | Black | Red | Green | Yellow | Blue | Magenta | Cyan | White | Default (** Default color of the terminal *) (** Various styles for the text. [Blink] and [Hidden] may not work on every terminal. *) type style = | Reset | Bold | Underlined | Blink | Inverse | Hidden | Foreground of color | Background of color val black : style (** Shortcut for [Foreground Black] *) val red : style (** Shortcut for [Foreground Red] *) val green : style (** Shortcut for [Foreground Green] *) val yellow : style (** Shortcut for [Foreground Yellow] *) val blue : style (** Shortcut for [Foreground Blue] *) val magenta : style (** Shortcut for [Foreground Magenta] *) val cyan : style (** Shortcut for [Foreground Cyan] *) val white : style (** Shortcut for [Foreground White] *) val default : style (** Shortcut for [Foreground Default] *) val on_black : style (** Shortcut for [Background Black] *) val on_red : style (** Shortcut for [Background Red] *) val on_green : style (** Shortcut for [Background Green] *) val on_yellow : style (** Shortcut for [Background Yellow] *) val on_blue : style (** Shortcut for [Background Blue] *) val on_magenta : style (** Shortcut for [Background Magenta] *) val on_cyan : style (** Shortcut for [Background Cyan] *) val on_white : style (** Shortcut for [Background White] *) val on_default : style (** Shortcut for [Background Default] *) val set_autoreset : bool -> unit (** Turns the autoreset feature on and off. It defaults to on. *) val print_string : style list -> string -> unit (** [print_string attr txt] prints the string [txt] with the attibutes [attr]. After printing, the attributes are automatically reseted to the defaults, unless autoreset is turned off. *) val prerr_string : style list -> string -> unit (** Like [print_string] but prints on the standard error. *) val printf : style list -> ('a, unit, string, unit) format4 -> 'a (** [printf attr format arg1 ... argN] prints the arguments [arg1],...,[argN] according to [format] with the attibutes [attr]. After printing, the attributes are automatically reseted to the defaults, unless autoreset is turned off. *) val eprintf : style list -> ('a, unit, string, unit) format4 -> 'a (** Same as {!printf} but prints the result on [stderr]. *) val sprintf : style list -> ('a, unit, string) format -> 'a (** Same as {!printf} but returns the result in a string. This only works on ANSI compliant terminals — for which escape sequences are used — and not under Windows — where system calls are required. On Windows, it is identical to the standard [sprintf]. *) (** {2 Erasing} *) type loc = Eol | Above | Below | Screen val erase : loc -> unit (** [erase Eol] clear from the cursor position to the end of the line without moving the cursor. [erase Above] erases everything before the position of the cursor. [erase Below] erases everything after the position of the cursor. [erase Screen] erases the whole screen. This function does not modify the position of the cursor. *) (** {2 Cursor} *) val set_cursor : int -> int -> unit (** [set_cursor x y] puts the cursor at position [(x,y)], [x] indicating the column (the leftmost one being 1) and [y] being the line (the topmost one being 1). If [x <= 0], the [x] coordinate is unchanged; if [y <= 0], the [y] coordinate is unchanged. *) val move_cursor : int -> int -> unit (** [move_cursor x y] moves the cursor by [x] columns (to the right if [x > 0], to the left if [x < 0]) and by [y] lines (downwards if [y > 0] and upwards if [y < 0]). *) val move_bol : unit -> unit (** [move_bol()] moves the cursor to the beginning of the current line. This is useful for progress bars for example. *) val pos_cursor : unit -> int * int (** [pos_cursor()] returns a couple [(x,y)] giving the current position of the cursor, [x >= 1] being the column and [y >= 1] the row. *) val save_cursor : unit -> unit (** [save_cursor()] saves the current position of the cursor. *) val restore_cursor : unit -> unit (** [restore_cursor()] replaces the cursor to the position saved with [save_cursor()]. *) (** {2 Size} *) val resize : int -> int -> unit (** [resize width height] resize the current terminal to the given [width] and [height]. *) val size : unit -> int * int (** [size()] returns a pair [(width, height)] giving the size of the terminal in character cells. *) (** {2 Scrolling} *) val scroll : int -> unit (** [scroll n] scrolls the terminal by [n] lines, up (creating new lines at the bottom) if [n > 0] and down if [n < 0]. *) (** {2 TTY} *) val isatty : (Unix.file_descr -> bool) ref (** Function used to detect whether the current output is connected to a TTY. Defaults to [Unix.isatty]. *) ;; ANSITerminal-0.8.3/src/ANSITerminal_common.ml000066400000000000000000000026521414333236200206750ustar00rootroot00000000000000(* Copyright 2004 by Troestler Christophe Christophe.Troestler(at)umons.ac.be This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 as published by the Free Software Foundation, with the special exception on linking described in file LICENSE. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file LICENSE for more details. *) let autoreset = ref true let set_autoreset b = autoreset := b type color = Black | Red | Green | Yellow | Blue | Magenta | Cyan | White | Default type style = | Reset | Bold | Underlined | Blink | Inverse | Hidden | Foreground of color | Background of color let black = Foreground Black let red = Foreground Red let green = Foreground Green let yellow = Foreground Yellow let blue = Foreground Blue let magenta = Foreground Magenta let cyan = Foreground Cyan let white = Foreground White let default = Foreground Default let on_black = Background Black let on_red = Background Red let on_green = Background Green let on_yellow = Background Yellow let on_blue = Background Blue let on_magenta = Background Magenta let on_cyan = Background Cyan let on_white = Background White let on_default = Background Default type loc = Eol | Above | Below | Screen ANSITerminal-0.8.3/src/ANSITerminal_unix.ml000066400000000000000000000142671414333236200203750ustar00rootroot00000000000000(* File: ANSITerminal_unix.ml Allow colors, cursor movements, erasing,... under Unix shells. ********************************************************************* Copyright 2004 by Troestler Christophe Christophe.Troestler(at)umons.ac.be This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 as published by the Free Software Foundation, with the special exception on linking described in file LICENSE. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file LICENSE for more details. *) (** See the file(s) ctlseqs.* (unix; in Debian package xspecs) CSI = "\027[" (ESC [) man console_codes *) (* man tty(4) *) open Printf open Scanf include ANSITerminal_common let isatty = ref Unix.isatty let is_out_channel_atty ch = !isatty(Unix.descr_of_out_channel ch) (* Cursor *) let set_cursor x y = if is_out_channel_atty stdout then ( if x <= 0 then (if y > 0 then printf "\027[%id%!" y) else (* x > 0 *) if y <= 0 then printf "\027[%iG%!" x else printf "\027[%i;%iH%!" y x ) let move_cursor x y = if is_out_channel_atty stdout then ( if x > 0 then printf "\027[%iC%!" x else if x < 0 then printf "\027[%iD%!" (-x); if y > 0 then printf "\027[%iB%!" y else if y < 0 then printf "\027[%iA%!" (-y) ) let save_cursor () = if is_out_channel_atty stdout then printf "\027[s%!" let restore_cursor () = if is_out_channel_atty stdout then printf "\027[u%!" let move_bol () = print_string "\r"; flush stdout (* Inpired by http://www.ohse.de/uwe/software/resize.c.html and http://qemacs.sourcearchive.com/documentation/0.3.1.cvs.20050713-5/tty_8c-source.html *) let send_and_read_response fdin query fmt f = let alarm = ref false in let set_alarm (_:int) = alarm := true in let old_alarm = Sys.signal Sys.sigalrm (Sys.Signal_handle set_alarm) in let tty = Unix.tcgetattr fdin in Unix.tcsetattr fdin Unix.TCSANOW { tty with Unix.c_ignbrk = false; c_brkint = false; c_parmrk = false; c_istrip = false; c_inlcr = false; c_igncr = false; c_icrnl = false; c_ixon = false; c_opost = true; c_csize = 8; c_parenb = false; c_icanon = false; c_isig = false; c_echo = false; c_echonl = false; c_vmin = 1; c_vtime = 0 }; let restore() = ignore(Unix.alarm 0); Unix.tcsetattr fdin Unix.TCSANOW tty; Sys.set_signal Sys.sigalrm old_alarm in let buf = Bytes.make 127 '\000' in (* FIXME: make it more robust so that it ignores previous key pressed. *) let rec get_answer pos = let l = Unix.read fdin buf pos 1 in let buf = Bytes.unsafe_to_string buf in (* local use only *) try sscanf buf fmt f (* bail out as soon as enough info is present *) with Scan_failure _ -> if !alarm || pos = 126 then failwith "ANSITerminal.input_answer" else if buf.[pos] = '\000' then get_answer pos else get_answer (pos + l) in try ignore(Unix.write fdin query 0 (Bytes.length query)); ignore(Unix.alarm 1); let r = get_answer 0 in restore(); r with e -> restore(); raise e (* Query Cursor Position [6n *) (* Report Cursor Position [{ROW};{COLUMN}R *) let pos_cursor_query = Bytes.of_string "\027[6n" let pos_cursor () = if is_out_channel_atty stdout then ( try send_and_read_response Unix.stdin pos_cursor_query "\027[%d;%dR" (fun y x -> (x,y)) with _ -> failwith "ANSITerminal.pos_cursor" ) else failwith "ANSITerminal.pos_cursor: not a TTY" (* See also the output of 'resize -s x y' (e.g. in an Emacs shell). *) let resize width height = if is_out_channel_atty stdout then ( if width <= 0 then invalid_arg "ANSITerminal.resize: width <= 0"; if height <= 0 then invalid_arg "ANSITerminal.resize: height <= 0"; printf "\027[8;%i;%it%!" height width ) (* FIXME: what about the following recipe: If you run echo -e "\e[18t" then xterm will respond with a line of the form ESC [ 8 ; height ; width t It generates this line as if it were typed input, so it can then be read by your program on stdin. *) external size_ : Unix.file_descr -> int * int = "ANSITerminal_term_size" let size () = if !isatty Unix.stdin then ( size_ Unix.stdin ) else failwith "ANSITerminal.size: not a TTY" (* Erasing *) let erase loc = if is_out_channel_atty stdout then ( print_string (match loc with | Eol -> "\027[K" | Above -> "\027[1J" | Below ->"\027[0J" | Screen -> "\027[2J"); flush stdout ) (* Scrolling *) let scroll lines = if is_out_channel_atty stdout then ( if lines > 0 then printf "\027[%iS%!" lines else if lines < 0 then printf "\027[%iT%!" (- lines) ) let style_to_string = function | Reset -> "0" | Bold -> "1" | Underlined -> "4" | Blink -> "5" | Inverse -> "7" | Hidden -> "8" | Foreground Black -> "30" | Foreground Red -> "31" | Foreground Green -> "32" | Foreground Yellow -> "33" | Foreground Blue -> "34" | Foreground Magenta -> "35" | Foreground Cyan -> "36" | Foreground White -> "37" | Foreground Default -> "39" | Background Black -> "40" | Background Red -> "41" | Background Green -> "42" | Background Yellow -> "43" | Background Blue -> "44" | Background Magenta -> "45" | Background Cyan -> "46" | Background White -> "47" | Background Default -> "49" let print_with pr ~tty style txt = if tty then ( pr "\027["; pr (String.concat ";" (List.map style_to_string style)); pr "m"; ); pr txt; if tty && !autoreset then pr "\027[0m" let print_string style txt = print_with print_string style txt ~tty:(is_out_channel_atty stdout) let prerr_string style txt = print_with prerr_string style txt ~tty:(is_out_channel_atty stderr) let printf style = ksprintf (print_string style) let eprintf style = ksprintf (prerr_string style) let to_string style txt = let s = "\027[" ^ String.concat ";" (List.map style_to_string style) ^ "m" ^ txt in if !autoreset then s ^ "\027[0m" else s let sprintf style = ksprintf (to_string style) ANSITerminal-0.8.3/src/ANSITerminal_unix_stubs.c000066400000000000000000000034451414333236200214230ustar00rootroot00000000000000/* File: ANSITerminal_unix_stubs.c Copyright (C) 2010 Christophe Troestler WWW: http://math.umons.ac.be/an/software/ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 or later as published by the Free Software Foundation. See the file LICENCE for more details. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file LICENSE for more details. */ #include #include #include #include #include #include /* Based on http://www.ohse.de/uwe/software/resize.c.html */ /* Inquire actual terminal size (this it what the kernel thinks - not * was the user on the over end of the phone line has really). */ CAMLexport value ANSITerminal_term_size(value vfd) { CAMLparam1(vfd); CAMLlocal1(vsize); int fd = Int_val(vfd); int x, y; #ifdef TIOCGSIZE struct ttysize win; #elif defined(TIOCGWINSZ) struct winsize win; #endif #ifdef TIOCGSIZE if (ioctl(fd, TIOCGSIZE, &win)) failwith("ANSITerminal.size"); x = win.ts_cols; y = win.ts_lines; #elif defined TIOCGWINSZ if (ioctl(fd, TIOCGWINSZ, &win)) failwith("ANSITerminal.size"); x = win.ws_col; y = win.ws_row; #else { const char *s; s = getenv("LINES"); if (s) y = strtol(s,NULL,10); else y = 25; s = getenv("COLUMNS"); if (s) x = strtol(s,NULL,10); else x = 80; } #endif vsize = caml_alloc_tuple(2); Store_field(vsize, 0, Val_int(x)); Store_field(vsize, 1, Val_int(y)); CAMLreturn(vsize); } ANSITerminal-0.8.3/src/ANSITerminal_win.ml000066400000000000000000000140511414333236200201760ustar00rootroot00000000000000(* File: ANSITerminal_win.ml Copyright 2010 by Vincent Hugot vincent.hugot@gmail.com www.vincent-hugot.com Copyright 2010 by Troestler Christophe Christophe.Troestler@umons.ac.be This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 as published by the Free Software Foundation, with the special exception on linking described in file LICENSE. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file LICENSE for more details. *) open Printf include ANSITerminal_common exception Error of string * string let () = Callback.register_exception "ANSITerminal.Error" (Error("","")) let isatty = ref Unix.isatty let is_out_channel_atty ch = !isatty(Unix.descr_of_out_channel ch) type rgb = R|G|B let rgb_of_color = function | Red -> [R] | Green -> [G] | Blue -> [B] | Default -> [] | White -> [R;G;B] | Cyan -> [B;G] | Magenta -> [B;R] | Yellow -> [R;G] | Black -> [] (* calls to SetConsoleTextAttribute replace one another, so foreground, background and bold must be set in the same action *) type color_state = { fore : rgb list; back : rgb list; bold : bool ; (* could intensify background too, but Unix does not support that so scrapped. *) } let empty = { fore = [R;G;B]; back = [] ; bold = false } let state_of_styles sty = List.fold_left (fun sta style -> match style with | Reset -> empty (* could stop there, but does not, for exact compat with ansi *) | Bold -> {sta with bold = true } | Inverse -> (* simulated inverse... not exact compat *) let oba = sta.back and ofo = sta.fore in {sta with fore = oba; back = ofo } | Foreground c -> {sta with fore = rgb_of_color c } | Background c -> {sta with back = rgb_of_color c } | _ -> sta ) empty sty let int_of_state st = (* Quoth wincon.h #define FOREGROUND_BLUE 1 #define FOREGROUND_GREEN 2 #define FOREGROUND_RED 4 #define FOREGROUND_INTENSITY 8 #define BACKGROUND_BLUE 16 #define BACKGROUND_GREEN 32 #define BACKGROUND_RED 64 #define BACKGROUND_INTENSITY 128 *) let fo = function R -> 4 | G -> 2 | B -> 1 and ba = function R -> 64 | G -> 32 | B -> 16 and sum mode rgb = List.fold_left (lor) 0 (List.map mode rgb) in sum fo st.fore lor sum ba st.back lor (if st.bold then 8 else 0) (* let win_set_style code = printf "<%d>" code let win_unset_style () = printf "" *) external win_set_style : out_channel -> int -> unit = "ANSITerminal_set_style" external win_unset_style : out_channel -> int -> unit = "ANSITerminal_unset_style" (* [win_unset_style] is the same as [win_set_style] except for the error message. *) external win_get_style : out_channel -> int = "ANSITerminal_get_style" let channel_styles = Hashtbl.create 8 let set_style ch styles = let prev_sty = win_get_style ch in Hashtbl.add channel_styles ch prev_sty; let st = int_of_state (state_of_styles styles) in flush ch; win_set_style ch st; flush ch let unset_style ch = flush ch; try win_unset_style ch (Hashtbl.find channel_styles ch); Hashtbl.remove channel_styles ch with Not_found -> () let print ch styles txt = let tty = is_out_channel_atty ch in if tty then set_style ch styles; output_string ch txt; flush ch; if tty && !autoreset then unset_style ch let print_string = print stdout let prerr_string = print stderr let printf style = kprintf (print_string style) let eprintf style = ksprintf (prerr_string style) let sprintf _style = sprintf external set_cursor_ : int -> int -> unit = "ANSITerminal_SetCursorPosition" external pos_cursor : unit -> int * int = "ANSITerminal_pos" external scroll : int -> unit = "ANSITerminal_Scroll" external size : unit -> int * int = "ANSITerminal_size" external resize_ : int -> int -> unit = "ANSITerminal_resize" let set_cursor x y = if is_out_channel_atty stdout then ( let x0, y0 = pos_cursor() in let x = if x <= 0 then x0 else x and y = if y <= 0 then y0 else y in set_cursor_ x y (* FIXME: (x,y) outside the console?? *) ) let move_cursor dx dy = if is_out_channel_atty stdout then ( let x0, y0 = pos_cursor() in let x = x0 + dx and y = y0 + dy in let x = if x <= 0 then 1 else x and y = if y <= 0 then 1 else y in set_cursor_ x y (* FIXME: (x,y) outside the console?? *) ) let move_bol () = if is_out_channel_atty stdout then ( let _, y0 = pos_cursor() in set_cursor_ 1 y0 ) let saved_x = ref 0 let saved_y = ref 0 let save_cursor () = if is_out_channel_atty stdout then ( let x,y = pos_cursor() in saved_x := x; saved_y := y ) let restore_cursor () = if is_out_channel_atty stdout then set_cursor_ !saved_x !saved_y let resize x y = if is_out_channel_atty stdout then ( (* The specified width and height cannot be less than the width and height of the console screen buffer's window. *) let xmin, ymin = size() in let x = if x <= xmin then xmin else x and y = if y <= ymin then ymin else y in resize_ x y ) external fill : out_channel -> char -> n:int -> x:int -> y:int -> int = "ANSITerminal_FillConsoleOutputCharacter" (* Writes the character to the console screen buffer [n] times, beginning at the coordinates [(x,y)]. Returns the number of chars actually written. *) let erase loc = if is_out_channel_atty stdout then ( let w, h = size() in match loc with | Eol -> let x, y = pos_cursor() in ignore(fill stdout ' ' ~n:(w - x + 1) ~x ~y) | Above -> let x, y = pos_cursor() in ignore(fill stdout ' ' ~n:((y - 1) * w + x) ~x:1 ~y:1) | Below -> let x, y = pos_cursor() in ignore(fill stdout ' ' ~n:(w - x + 1 + (h - y) * w) ~x ~y) | Screen -> ignore(fill stdout ' ' ~n:(w * h) ~x:1 ~y:1) ) ;; (* Local Variables: *) (* compile-command: "make ANSITerminal_win.cmo" *) (* End: *) ANSITerminal-0.8.3/src/ANSITerminal_win.mli000077700000000000000000000000001414333236200232722ANSITerminal.mliustar00rootroot00000000000000ANSITerminal-0.8.3/src/ANSITerminal_win_stubs.c000066400000000000000000000204071414333236200212320ustar00rootroot00000000000000/* ANSITerminal; windows API calls Allow colors, cursor movements, erasing,... under Unix and DOS shells. ********************************************************************* Copyright 2010 by Christophe Troestler http://math.umons.ac.be/an/software/ Copyright 2010 by Vincent Hugot vincent.hugot@gmail.com www.vincent-hugot.com This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation, with the special exception on linking described in file LICENSE. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file LICENSE for more details. */ #include #include #include #include #include #include #include #include "io.h" /* From otherlibs/win32unix/channels.c */ extern long _get_osfhandle(int); #define HANDLE_OF_CHAN(vchan) ((HANDLE) _get_osfhandle(Channel(vchan)->fd)) static HANDLE hStdout; static CONSOLE_SCREEN_BUFFER_INFO *csbiInfo = NULL; void raise_error(char *fname, char *msg) { CAMLparam0(); CAMLlocal2(vfname, vmsg); static value *exn = NULL; value args[2]; if (exn == NULL) { /* First time around, look up by name */ exn = caml_named_value("ANSITerminal.Error"); } vfname = caml_copy_string(fname); vmsg = caml_copy_string(msg); args[0] = vfname; args[1] = vmsg; caml_raise_with_args(*exn, 2, args); CAMLnoreturn; } void exn_of_error(char *fname, BOOL cond) { CAMLparam0(); CAMLlocal2(vfname, vmsg); char *msg, *p; LPVOID lpMsgBuf; static value *exn = NULL; value args[2]; if (cond) { if (exn == NULL) { /* First time around, look up by name */ exn = caml_named_value("ANSITerminal.Error"); } FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); vfname = caml_copy_string(fname); msg = (char *) lpMsgBuf; p = msg + strlen(msg) - 1; while(*p == '\n' || *p == '\r') { *p = '\0'; p--; } vmsg = caml_copy_string(msg); LocalFree(lpMsgBuf); args[0] = vfname; args[1] = vmsg; caml_raise_with_args(*exn, 2, args); } CAMLreturn0; } #define SET_CSBI(fname) \ if (! csbiInfo) { \ hStdout = GetStdHandle(STD_OUTPUT_HANDLE); \ if (hStdout == INVALID_HANDLE_VALUE) { \ raise_error(fname, "Invalid stdout handle"); \ } \ exn_of_error(fname, \ ! GetConsoleScreenBufferInfo(hStdout, csbiInfo)); \ } #define SET_STYLE(fname) \ CAMLexport \ value ANSITerminal_ ## fname(value vchan, value vcode) \ { \ HANDLE h = HANDLE_OF_CHAN(vchan); \ int code = Int_val(vcode); \ \ exn_of_error("ANSITerminal." #fname, \ ! SetConsoleTextAttribute(h, code)); \ return Val_unit; \ } SET_STYLE(set_style) SET_STYLE(unset_style) CAMLexport value ANSITerminal_get_style(value vchan) { HANDLE h = HANDLE_OF_CHAN(vchan); CONSOLE_SCREEN_BUFFER_INFO info; /* To save the previous info when setting style */ exn_of_error("ANSITerminal.set_style", ! GetConsoleScreenBufferInfo(h, &info)); return(Val_int(info.wAttributes)); } CAMLexport value ANSITerminal_pos(value vunit) { CAMLparam1(vunit); CAMLlocal1(vpos); SMALL_RECT w; SHORT x, y; exn_of_error("ANSITerminal.pos_cursor", ! GetConsoleScreenBufferInfo(hStdout, csbiInfo)); w = csbiInfo->srWindow; /* The topmost left character has pos (1,1) */ x = csbiInfo->dwCursorPosition.X - w.Left + 1; y = csbiInfo->dwCursorPosition.Y - w.Top + 1; vpos = caml_alloc_tuple(2); Store_field(vpos, 0, Val_int(x)); Store_field(vpos, 1, Val_int(y)); CAMLreturn(vpos); } CAMLexport value ANSITerminal_size(value vunit) { CAMLparam1(vunit); CAMLlocal1(vsize); SMALL_RECT w; /* Update the global var as the terminal may have been be resized */ SET_CSBI("ANSITerminal.size"); exn_of_error("ANSITerminal.size", ! GetConsoleScreenBufferInfo(hStdout, csbiInfo)); w = csbiInfo->srWindow; vsize = caml_alloc_tuple(2); Store_field(vsize, 0, Val_int(w.Right - w.Left + 1)); Store_field(vsize, 1, Val_int(w.Bottom - w.Top + 1)); CAMLreturn(vsize); } CAMLexport value ANSITerminal_resize(value vx, value vy) { /* noalloc */ COORD dwSize; dwSize.X = Int_val(vx); dwSize.Y = Int_val(vy); exn_of_error("ANSITerminal.resize", ! SetConsoleScreenBufferSize(hStdout, dwSize)); return Val_unit; } CAMLexport value ANSITerminal_SetCursorPosition(value vx, value vy) { COORD c; SMALL_RECT w; SET_CSBI("ANSITerminal.set_cursor"); exn_of_error("ANSITerminal.set_cursor", ! GetConsoleScreenBufferInfo(hStdout, csbiInfo)); /* The top lefmost coordinate is (1,1) for ANSITerminal while it is * (0,0) for windows. */ w = csbiInfo->srWindow; c.X = Int_val(vx) - 1 + w.Left; c.Y = Int_val(vy) - 1 + w.Top; // very subtle debugging method... fprintf(stderr,"vx,vy = %d,%d --> [c.X,Y = %d,%d ; L %d R %d T %d B %d]\n", Int_val(vx),Int_val(vy), c.X, c.Y, w.Left, w.Right, w.Top, w.Bottom); if (c.X > w.Right) c.X = w.Right; if (c.Y > w.Bottom) c.Y = w.Bottom; exn_of_error("ANSITerminal.set_cursor", ! SetConsoleCursorPosition(hStdout, c)); return Val_unit; } CAMLexport value ANSITerminal_FillConsoleOutputCharacter( value vchan, value vc, value vlen, value vx, value vy) { CAMLparam1(vchan); HANDLE h = HANDLE_OF_CHAN(vchan); int NumberOfCharsWritten; COORD dwWriteCoord; SET_CSBI("ANSITerminal.erase"); exn_of_error("ANSITerminal.erase", ! GetConsoleScreenBufferInfo(hStdout, csbiInfo)); dwWriteCoord.X = Int_val(vx) - 1 + csbiInfo->srWindow.Left; dwWriteCoord.Y = Int_val(vy) - 1 + csbiInfo->srWindow.Top; exn_of_error("ANSITerminal.erase", !FillConsoleOutputCharacter(h, Int_val(vc), Int_val(vlen), dwWriteCoord, &NumberOfCharsWritten)); CAMLreturn(Val_int(NumberOfCharsWritten)); } CAMLexport value ANSITerminal_Scroll(value vx) { /* noalloc */ INT x = Int_val(vx); SMALL_RECT srctScrollRect, srctClipRect; CHAR_INFO chiFill; COORD coordDest; SET_CSBI("ANSITerminal.scroll"); srctScrollRect.Left = 0; srctScrollRect.Top = 1; srctScrollRect.Right = csbiInfo->dwSize.X - x; srctScrollRect.Bottom = csbiInfo->dwSize.Y - x; // The destination for the scroll rectangle is one row up. coordDest.X = 0; coordDest.Y = 0; // The clipping rectangle is the same as the scrolling rectangle. // The destination row is left unchanged. srctClipRect = srctScrollRect; // Set the fill character and attributes. chiFill.Attributes = FOREGROUND_RED|FOREGROUND_INTENSITY; chiFill.Char.AsciiChar = (char) ' '; exn_of_error("ANSITerminal.scroll", ! ScrollConsoleScreenBuffer( hStdout, // screen buffer handle &srctScrollRect, // scrolling rectangle &srctClipRect, // clipping rectangle coordDest, // top left destination cell &chiFill)); // fill character and color return Val_unit; } ANSITerminal-0.8.3/src/choose_implementation.ml000066400000000000000000000017241414333236200214630ustar00rootroot00000000000000(* Script to choose the unix or windows implementation depending on the platform *) open Printf let copy_file ?(line_directive=false) ?(dir=".") source target = let fh0 = open_in (Filename.concat dir source) in let fh1 = open_out_bin (Filename.concat dir target) in if line_directive then fprintf fh1 "#1 \"%s\"\n" (Filename.concat dir source); let b = Bytes.create 4096 in let n = ref 0 in while n := input fh0 b 0 4096; !n > 0 do output fh1 b 0 !n done; close_in fh0; close_out fh1 let choose_unix () = copy_file "ANSITerminal_unix.ml" "ANSITerminal.ml" ~line_directive:true; copy_file "ANSITerminal_unix_stubs.c" "ANSITerminal_stubs.c" let choose_win () = copy_file "ANSITerminal_win.ml" "ANSITerminal.ml" ~line_directive:true; copy_file "ANSITerminal_win_stubs.c" "ANSITerminal_stubs.c" let () = match Sys.os_type with | "Unix" | "Cygwin" -> choose_unix () | "Win32" -> choose_win() | e -> eprintf "Unknown OS type %S.\n" e ANSITerminal-0.8.3/src/dune000066400000000000000000000010621414333236200154150ustar00rootroot00000000000000(library (name ANSITerminal) (public_name ANSITerminal) (modules ANSITerminal ANSITerminal_common) (c_names ANSITerminal_stubs) (synopsis "Basic control of ANSI compliant terminals and the windows shell") (libraries unix bytes)) (rule (targets ANSITerminal.ml ANSITerminal_stubs.c) (deps ANSITerminal_unix.ml ANSITerminal_win.ml ANSITerminal_unix_stubs.c ANSITerminal_win_stubs.c (:p choose_implementation.exe)) (action (run %{p}))) (executable (name choose_implementation) (modules choose_implementation)) ANSITerminal-0.8.3/src/io.h000066400000000000000000000116121414333236200153210ustar00rootroot00000000000000/**************************************************************************/ /* */ /* OCaml */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 1996 Institut National de Recherche en Informatique et */ /* en Automatique. */ /* */ /* All rights reserved. This file is distributed under the terms of */ /* the GNU Lesser General Public License version 2.1, with the */ /* special exception on linking described in the file LICENSE. */ /* */ /**************************************************************************/ /* Buffered input/output */ #ifndef CAML_IO_H #define CAML_IO_H #include #include #ifndef IO_BUFFER_SIZE #define IO_BUFFER_SIZE 65536 #endif #if defined(_WIN32) typedef __int64 file_offset; #elif defined(HAS_OFF_T) #include typedef off_t file_offset; #else typedef long file_offset; #endif struct channel { int fd; /* Unix file descriptor */ file_offset offset; /* Absolute position of fd in the file */ char * end; /* Physical end of the buffer */ char * curr; /* Current position in the buffer */ char * max; /* Logical end of the buffer (for input) */ void * mutex; /* Placeholder for mutex (for systhreads) */ struct channel * next, * prev;/* Double chaining of channels (flush_all) */ int revealed; /* For Cash only */ int old_revealed; /* For Cash only */ int refcount; /* For flush_all and for Cash */ int flags; /* Bitfield */ char buff[IO_BUFFER_SIZE]; /* The buffer itself */ char * name; /* Optional name (to report fd leaks) */ }; enum { CHANNEL_FLAG_FROM_SOCKET = 1 /* For Windows */ }; /* For an output channel: [offset] is the absolute position of the beginning of the buffer [buff]. For an input channel: [offset] is the absolute position of the logical end of the buffer, [max]. */ /* Functions and macros that can be called from C. Take arguments of type struct channel *. No locking is performed. */ #define putch(channel, ch) do{ \ if ((channel)->curr >= (channel)->end) caml_flush_partial(channel); \ *((channel)->curr)++ = (ch); \ }while(0) #define getch(channel) \ ((channel)->curr >= (channel)->max \ ? caml_refill(channel) \ : (unsigned char) *((channel)->curr)++) CAMLextern struct channel * caml_open_descriptor_in (int); CAMLextern struct channel * caml_open_descriptor_out (int); CAMLextern void caml_close_channel (struct channel *); CAMLextern int caml_channel_binary_mode (struct channel *); CAMLextern value caml_alloc_channel(struct channel *chan); CAMLextern int caml_flush_partial (struct channel *); CAMLextern void caml_flush (struct channel *); CAMLextern void caml_putword (struct channel *, uint32_t); CAMLextern int caml_putblock (struct channel *, char *, intnat); CAMLextern void caml_really_putblock (struct channel *, char *, intnat); CAMLextern unsigned char caml_refill (struct channel *); CAMLextern uint32_t caml_getword (struct channel *); CAMLextern int caml_getblock (struct channel *, char *, intnat); CAMLextern int caml_really_getblock (struct channel *, char *, intnat); /* Extract a struct channel * from the heap object representing it */ #define Channel(v) (*((struct channel **) (Data_custom_val(v)))) /* The locking machinery */ CAMLextern void (*caml_channel_mutex_free) (struct channel *); CAMLextern void (*caml_channel_mutex_lock) (struct channel *); CAMLextern void (*caml_channel_mutex_unlock) (struct channel *); CAMLextern void (*caml_channel_mutex_unlock_exn) (void); CAMLextern struct channel * caml_all_opened_channels; #define Lock(channel) \ if (caml_channel_mutex_lock != NULL) (*caml_channel_mutex_lock)(channel) #define Unlock(channel) \ if (caml_channel_mutex_unlock != NULL) (*caml_channel_mutex_unlock)(channel) #define Unlock_exn() \ if (caml_channel_mutex_unlock_exn != NULL) (*caml_channel_mutex_unlock_exn)() /* Conversion between file_offset and int64_t */ #define Val_file_offset(fofs) caml_copy_int64(fofs) #define File_offset_val(v) ((file_offset) Int64_val(v)) #endif /* CAML_IO_H */ ANSITerminal-0.8.3/tests/000077500000000000000000000000001414333236200151135ustar00rootroot00000000000000ANSITerminal-0.8.3/tests/dune000066400000000000000000000001761414333236200157750ustar00rootroot00000000000000(executables (names showcolors test) (libraries ANSITerminal)) (alias (name runtest) (deps showcolors.exe test.exe)) ANSITerminal-0.8.3/tests/showcolors.ml000066400000000000000000000022461414333236200176530ustar00rootroot00000000000000(* Draw a simple table showing ANSI colors and font effects. Run this in "xterm -fg gray60 -bg gray20". *) module T = ANSITerminal open Printf let colors = [T.Black; T.Red; T.Green; T.Yellow; T.Blue; T.Magenta; T.Cyan; T.White; T.Default] let color_to_string = function | T.Black -> "black" | T.Red -> "red" | T.Green -> "green" | T.Yellow -> "yellow" | T.Blue -> "blue" | T.Magenta -> "magent" | T.Cyan -> "cyan" | T.White -> "white" | T.Default -> "def" let () = (* Table *) let print_line fore = printf "%6s " (color_to_string fore); List.iter (fun back -> T.print_string [T.Foreground fore; T.Background back; ] " !Text! "; ) colors; print_string "\n" in T.erase T.Screen; T.set_cursor 1 1; print_string " "; List.iter (fun back -> printf "%6s " (color_to_string back)) colors; print_string "\n"; List.iter print_line colors; (* Effects *) T.print_string [T.Bold] "Bold "; T.print_string [T.Underlined] "Underlined "; T.print_string [T.Blink] "Blink "; T.print_string [T.Inverse] "Inverse "; T.print_string [T.Hidden] "Hidden"; print_string "<-- hidden\n" ANSITerminal-0.8.3/tests/test.ml000066400000000000000000000013511414333236200164240ustar00rootroot00000000000000 open Printf module T = ANSITerminal let () = printf "Testing ANSITerminal...\n%!"; printf "In 1sec the screen will be cleared and cursor put at (1,1).%!"; Unix.sleep 1; T.erase T.Screen; T.set_cursor 1 1; Unix.sleep 1; let x, y = T.size() in printf "The size of the terminal is (%i,%i).%!" x y; let x, y = T.pos_cursor() in printf "\nThe cursor position was (%i,%i).\n%!" x y; T.set_cursor 3 5; printf "*<--- set_cursor 3 5"; T.set_cursor 1 8; printf "Press ENTER to temporarily move the cursor to (3,6)%!"; ignore(read_line()); T.save_cursor(); T.set_cursor 3 6; printf "*<--- set_cursor 3 6"; T.restore_cursor(); for i = 5 downto 1 do printf "%i%!" i; Unix.sleep 1; T.move_bol(); done