Shells in OCaml
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

Use bruit

Switches our use of linenoise to bruit, a port of linenoise to OCaml.

+45 -2557
+3
.gitmodules
··· 1 + [submodule "vendor/bruit"] 2 + path = vendor/bruit 3 + url = https://tangled.org/patrick.sirref.org/bruit
+1 -1
src/lib/dune
··· 12 12 morbig 13 13 yojson 14 14 ppxlib 15 - linenoise 15 + bruit 16 16 fpath 17 17 cmdliner 18 18 merry.glob))
+41 -28
src/lib/interactive.ml
··· 29 29 (Fpath.normalize @@ S.cwd state |> subst_tilde |> Fpath.to_string); 30 30 Format.flush_str_formatter () 31 31 32 - let file_path_completitions () = 33 - let complete path completions = 34 - let completions from_path = 35 - match (Unix.stat from_path).st_kind with 36 - | S_DIR -> 37 - let entries = Sys.readdir from_path in 38 - Array.iter 39 - (fun e -> 40 - LNoise.add_completion completions (Filename.concat from_path e)) 41 - entries 42 - | S_REG -> LNoise.add_completion completions path 43 - | _ -> () 44 - | exception Unix.Unix_error (Unix.ENOENT, _, _) -> () 45 - in 46 - match Unix.(stat path).st_kind with 47 - | exception Unix.Unix_error (Unix.ENOENT, _, _) -> 48 - let dirname = Filename.dirname path in 49 - completions dirname 50 - | S_DIR -> completions path 51 - | _ -> () 32 + let complete path = 33 + let rest, last_arg = 34 + String.split_on_char ' ' path |> List.rev |> function 35 + | [] -> ([], None) 36 + | x :: rest -> (List.rev rest, Some x) 37 + in 38 + let completions from_path basename = 39 + match (Unix.stat from_path).st_kind with 40 + | S_DIR -> 41 + let entries = Sys.readdir from_path |> Array.to_list in 42 + List.filter_map 43 + (fun e -> 44 + match basename with 45 + | None -> Some e 46 + | Some prefix -> 47 + if String.starts_with ~prefix e then Some e else None) 48 + entries 49 + |> List.map (fun e -> Filename.concat from_path e) 50 + |> List.map (fun p -> String.concat " " (rest @ [ p ])) 51 + | S_REG -> [ String.concat " " (rest @ [ path ]) ] 52 + | _ -> [] 53 + | exception Unix.Unix_error (Unix.ENOENT, _, _) -> [] 52 54 in 53 - LNoise.set_completion_callback complete 55 + match last_arg with 56 + | None -> [] 57 + | Some path -> ( 58 + match Unix.(stat path).st_kind with 59 + | exception Unix.Unix_error (Unix.ENOENT, _, _) -> 60 + let dirname = Filename.dirname path in 61 + let basename = 62 + match Filename.basename path with "." | "" -> None | p -> Some p 63 + in 64 + completions dirname basename 65 + | S_DIR -> completions path None 66 + | _ -> []) 54 67 55 68 let run ?(prompt = default_prompt) initial_ctx = 56 69 Sys.set_signal Sys.sigttou Sys.Signal_ignore; 57 70 Sys.set_signal Sys.sigttin Sys.Signal_ignore; 58 71 Sys.set_signal Sys.sigtstp Sys.Signal_ignore; 59 - file_path_completitions (); 60 72 let rec loop (ctx : Eval.ctx Exit.t) = 61 73 Option.iter (Fmt.epr "%s%!") 62 74 (S.lookup (Exit.value ctx).state ~param:"PS1" 63 75 |> Option.map Ast.word_components_to_string); 64 76 let p = prompt ctx in 65 77 Fmt.pr "%s\r%!" p; 66 - match LNoise.linenoise "" with 67 - | None -> 78 + match Bruit.bruit ~complete "" with 79 + | String None -> 68 80 Fmt.pr "exit\n%!"; 69 81 exit 0 70 - | Some c -> 71 - let ast = Ast.of_string c in 82 + | String (Some c) -> 83 + (* Fmt.epr ">>> [%s]\n%!" c; *) 84 + let ast = Ast.of_string (String.trim c) in 72 85 let ctx', _ast = Eval.run ctx ast in 73 86 (* TODO: Make better History abstraction *) 74 - let _ : (unit, string) result = LNoise.history_add c in 87 + (* let _ : (unit, string) result = LNoise.history_add c in *) 75 88 loop ctx' 76 - | exception Sys.Break -> 89 + | Ctrl_c -> 77 90 let c = Exit.value ctx in 78 91 loop (Exit.nonzero c 130) 79 92 in
-1
vendor/ocaml-linenoise/.github/CODEOWNERS
··· 1 - * @c-cube
-49
vendor/ocaml-linenoise/.github/workflows/main.yml
··· 1 - name: build 2 - on: 3 - push: 4 - branches: 5 - - main 6 - pull_request: 7 - jobs: 8 - run: 9 - name: build 10 - strategy: 11 - fail-fast: false 12 - matrix: 13 - os: 14 - - ubuntu-latest 15 - - macos-latest 16 - - macos-13 17 - setup-version: 18 - - v2 19 - - v3 20 - ocaml-compiler: 21 - - 4.06.x 22 - - 4.14.x 23 - - 5.1.x 24 - exclude: 25 - - os: ubuntu-latest 26 - setup-version: v2 27 - - os: macos-13 28 - setup-version: v3 29 - - os: macos-latest 30 - setup-version: v2 31 - - os: macos-latest 32 - ocaml-compiler: 4.06.x 33 - runs-on: ${{ matrix.os }} 34 - steps: 35 - - uses: actions/checkout@v4 36 - - uses: ocaml/setup-ocaml@v2 37 - if: matrix.setup-version == 'v2' 38 - with: 39 - ocaml-compiler: ${{ matrix.ocaml-compiler }} 40 - allow-prerelease-opam: true 41 - - uses: ocaml/setup-ocaml@v3 42 - if: matrix.setup-version == 'v3' 43 - with: 44 - ocaml-compiler: ${{ matrix.ocaml-compiler }} 45 - allow-prerelease-opam: true 46 - - run: opam pin -n . 47 - - run: opam install -t . --deps-only 48 - - run: opam exec -- dune build --ignore-promoted-rules 49 - - run: opam exec -- dune runtest --ignore-promoted-rules
-15
vendor/ocaml-linenoise/.gitignore
··· 1 - _build 2 - *.docdir 3 - 4 - history.txt 5 - *.cmi 6 - *.cmt 7 - *.cmo 8 - *.cma 9 - *.cmx 10 - *.o 11 - T 12 - setup.data 13 - setup.log 14 - *.install 15 - .merlin
-10
vendor/ocaml-linenoise/CHANGES.md
··· 1 - # 1.5.1 2 - 3 - - fix a deadlock from 1.5 4 - 5 - # 1.5 6 - 7 - - release runtime lock when calling `lnoise` 8 - - fix potential memleaks and use of deprecate parts of 9 - the OCaml C API 10 - - remove dependency on `result`
-19
vendor/ocaml-linenoise/Makefile
··· 1 - 2 - all: build test 3 - 4 - build: 5 - @dune build @install 6 - 7 - test: 8 - @dune runtest --no-buffer --force 9 - 10 - example: 11 - @dune exec examples/show_off.exe 12 - 13 - clean: 14 - @dune clean 15 - 16 - doc: 17 - @dune build @doc 18 - 19 - .PHONY: all build test example clean doc
-70
vendor/ocaml-linenoise/README.md
··· 1 - Linenoise in OCaml 2 - -------------------- 3 - 4 - [![build](https://github.com/ocaml-community/ocaml-linenoise/actions/workflows/main.yml/badge.svg)](https://github.com/ocaml-community/ocaml-linenoise/actions/workflows/main.yml) 5 - 6 - # Benefits 7 - 1. BSD licensed. 8 - 2. No system dependencies, no need for `readline` on your machine. 9 - 3. Related to 2, these bindings are self-contained, the source for 10 - `linenoise` is in this repo and compiled all together with the 11 - `OCaml`. 12 - 4. Written in OCaml + C. 13 - 5. Pretty cool hints feature, see the gif. 14 - 6. Additional features compared to linenoise, such as history search 15 - 16 - # Installation 17 - 18 - It is easy with `opam` 19 - 20 - ```shell 21 - $ opam install linenoise 22 - ``` 23 - 24 - See the pretty 25 - documentation [here](https://ocaml-community.github.io/ocaml-linenoise/) 26 - 27 - # Example code 28 - This example is also included in the repo under examples: 29 - 30 - <p align="center" style='min-width:100%'> 31 - <img style='min-width:100%' src='example.gif'/> 32 - </p> 33 - 34 - 35 - ```ocaml 36 - let rec user_input prompt cb = 37 - match LNoise.linenoise prompt with 38 - | None -> () 39 - | Some v -> 40 - cb v; 41 - user_input prompt cb 42 - 43 - let () = 44 - (* LNoise.set_multiline true; *) 45 - LNoise.set_hints_callback (fun line -> 46 - if line <> "git remote add " then None 47 - else Some (" <this is the remote name> <this is the remote URL>", 48 - LNoise.Yellow, 49 - true) 50 - ); 51 - LNoise.history_load ~filename:"history.txt" |> ignore; 52 - LNoise.history_set ~max_length:100 |> ignore; 53 - LNoise.set_completion_callback begin fun line_so_far ln_completions -> 54 - if line_so_far <> "" && line_so_far.[0] = 'h' then 55 - ["Hey"; "Howard"; "Hughes";"Hocus"] 56 - |> List.iter (LNoise.add_completion ln_completions); 57 - end; 58 - ["These are OCaml bindings to linenoise"; 59 - "get tab completion with <TAB>, type h then hit <TAB>"; 60 - "type quit to exit gracefully"; 61 - "By Edgar Aroutiounian\n"] 62 - |> List.iter print_endline; 63 - (fun from_user -> 64 - if from_user = "quit" then exit 0; 65 - LNoise.history_add from_user |> ignore; 66 - LNoise.history_save ~filename:"history.txt" |> ignore; 67 - Printf.sprintf "Got: %s" from_user |> print_endline 68 - ) 69 - |> user_input "test_program> " 70 - ```
-2
vendor/ocaml-linenoise/dune-project
··· 1 - (lang dune 1.1) 2 - (name linenoise)
vendor/ocaml-linenoise/example.gif

This is a binary file and will not be displayed.

-4
vendor/ocaml-linenoise/examples/dune
··· 1 - (executable 2 - (name show_off) 3 - (libraries linenoise) 4 - )
-34
vendor/ocaml-linenoise/examples/show_off.ml
··· 1 - let rec user_input prompt cb = 2 - match LNoise.linenoise prompt with 3 - | None -> () 4 - | Some v -> 5 - cb v; 6 - user_input prompt cb 7 - 8 - let () = 9 - (* LNoise.set_multiline true; *) 10 - LNoise.set_hints_callback (fun line -> 11 - if line <> "git remote add " then None 12 - else Some (" <this is the remote name> <this is the remote URL>", 13 - LNoise.Yellow, 14 - true) 15 - ); 16 - LNoise.history_load ~filename:"history.txt" |> ignore; 17 - LNoise.history_set ~max_length:100 |> ignore; 18 - LNoise.set_completion_callback begin fun line_so_far ln_completions -> 19 - if line_so_far <> "" && line_so_far.[0] = 'h' then 20 - ["Hey"; "Howard"; "Hughes";"Hocus"] 21 - |> List.iter (LNoise.add_completion ln_completions); 22 - end; 23 - ["These are OCaml bindings to linenoise"; 24 - "get tab completion with <TAB>, type h then hit <TAB>"; 25 - "type quit to exit gracefully"; 26 - "By Edgar Aroutiounian\n"] 27 - |> List.iter print_endline; 28 - (fun from_user -> 29 - if from_user = "quit" then exit 0; 30 - LNoise.history_add from_user |> ignore; 31 - LNoise.history_save ~filename:"history.txt" |> ignore; 32 - Printf.sprintf "Got: %s" from_user |> print_endline 33 - ) 34 - |> user_input "test_program> "
-20
vendor/ocaml-linenoise/linenoise.opam
··· 1 - opam-version: "2.0" 2 - name: "linenoise" 3 - version: "1.5.1" 4 - synopsis: "Lightweight readline alternative" 5 - maintainer: "Simon Cruanes" 6 - authors: [ "Edgar Aroutiounian <edgar.factorial@gmail.com>" "Simon Cruanes" ] 7 - license: "BSD-3-clause" 8 - homepage: "https://github.com/ocaml-community/ocaml-linenoise" 9 - dev-repo: "git+https://github.com/ocaml-community/ocaml-linenoise.git" 10 - bug-reports: "https://github.com/ocaml-community/ocaml-linenoise/issues" 11 - build: [ 12 - ["dune" "build" "@install" "-p" name "-j" jobs] 13 - ["dune" "runtest" "-p" name] {with-test} 14 - ["dune" "build" "@doc" "-p" name] {with-doc} 15 - ] 16 - depends: [ 17 - "dune" { >= "1.1" } 18 - "ocaml" { >= "4.06.0" } 19 - "odoc" {with-doc} 20 - ]
-8
vendor/ocaml-linenoise/src/dune
··· 1 - 2 - (library 3 - (name linenoise) 4 - (public_name linenoise) 5 - (modules LNoise) 6 - (wrapped false) 7 - (flags :standard -warn-error -3) 8 - (c_names linenoise_src utf8 linenoise_stubs))
-57
vendor/ocaml-linenoise/src/lNoise.ml
··· 1 - 2 - type completions 3 - 4 - external add_completion : completions -> string -> unit = "ml_add_completion" 5 - 6 - external linenoise : string -> string option = "ml_linenoise" 7 - 8 - external history_add_ : string -> int = "ml_history_add" 9 - external history_set_ : max_length:int -> int = "ml_history_set_maxlen" 10 - external history_save_ : filename:string -> int = "ml_history_save" 11 - external history_load_ : filename:string -> int = "ml_history_load" 12 - 13 - external catch_break : bool -> unit = "ml_catch_break" 14 - 15 - external setup_bridges : unit -> unit = "ml_setup_bridges" 16 - 17 - type hint_color = Red | Green | Yellow | Blue | Magenta | Cyan | White 18 - 19 - let completion_cb = ref (fun _ _ -> ()) 20 - let hints_cb = ref (fun _ -> None) 21 - 22 - let set_completion_callback (f:string->completions->unit) : unit = 23 - completion_cb := f; 24 - Callback.register "lnoise_completion_cb" f 25 - 26 - let set_hints_callback (f:string -> (string*hint_color*bool) option) : unit = 27 - hints_cb := f; 28 - Callback.register "lnoise_hints_cb" f 29 - 30 - (* initialization: register [Sys.Break] and enable catch-break *) 31 - let () = 32 - setup_bridges(); 33 - set_completion_callback !completion_cb; 34 - set_hints_callback !hints_cb; 35 - Callback.register_exception "sys_break" Sys.Break; 36 - catch_break true 37 - 38 - let history_add h = 39 - if history_add_ h = 0 then Error "Couldn't add to history" 40 - else Ok () 41 - 42 - let history_set ~max_length = 43 - if history_set_ ~max_length = 0 44 - then Error "Couldn't set the max length of history" 45 - else Ok () 46 - 47 - let history_save ~filename = 48 - if history_save_ ~filename = 0 then Ok () 49 - else Error "Couldn't save" 50 - 51 - let history_load ~filename = 52 - if history_load_ ~filename = 0 then Ok () 53 - else Error "Couldn't load the file" 54 - 55 - external clear_screen : unit -> unit = "ml_clearscreen" 56 - external set_multiline : bool -> unit = "ml_set_multiline" 57 - external print_keycodes : unit -> unit = "ml_printkeycodes"
-65
vendor/ocaml-linenoise/src/lNoise.mli
··· 1 - (** OCaml bindings to linenoise, functions that can fail use result 2 - type *) 3 - 4 - (** Abstract type of completions, given to your completion callback *) 5 - type completions 6 - 7 - (** This function is used by the callback function registered by the 8 - user in order to add completion options given the input string 9 - when the user typed <TAB>. *) 10 - val add_completion : completions -> string -> unit 11 - 12 - (** Register the callback function that is called for upon 13 - tab-completion, aka when <TAB> is hit in the terminal *) 14 - val set_completion_callback : (string -> completions -> unit) -> unit 15 - 16 - (** The high level function that is the main API of the linenoise 17 - library. This function checks if the terminal has basic 18 - capabilities, just checking for a blacklist of stupid terminals, 19 - and later either calls the line editing function or uses dummy 20 - fgets() so that you will be able to type something even in the 21 - most desperate of the conditions. *) 22 - val linenoise : string -> string option 23 - 24 - (** Add a string to the history *) 25 - val history_add : string -> (unit, string) result 26 - 27 - (** Set the maximum length for the history. This function can be 28 - called even if there is already some history, the function will 29 - make sure to retain just the latest 'len' elements if the new 30 - history length value is smaller than the amount of items already 31 - inside the history. *) 32 - val history_set : max_length:int -> (unit, string) result 33 - 34 - (** Save the history in the specified file *) 35 - val history_save : filename:string -> (unit, string) result 36 - 37 - (** Load the history from the specified file. *) 38 - val history_load : filename:string -> (unit, string) result 39 - 40 - (** Clear the screen; used to handle CTRL+L *) 41 - val clear_screen : unit -> unit 42 - 43 - (** If [true], [ctrl-c] during a call to {!linenoise} 44 - will raise [Sys.Break] instead of returning an empty string. 45 - @since 1.1 *) 46 - val catch_break : bool -> unit 47 - 48 - (** Set if to use or not use the multi line mode. *) 49 - val set_multiline : bool -> unit 50 - 51 - (** This special mode is used by linenoise in order to print scan 52 - codes on screen for debugging / development purposes. *) 53 - val print_keycodes : unit -> unit 54 - 55 - (** What color you want the hints to be. *) 56 - type hint_color = Red | Green | Yellow | Blue | Magenta | Cyan | White 57 - 58 - (** Set a hints callback, callback gets a string, aka the line input, 59 - and you get a chance to give a hint to the user. Example, imagine 60 - if user types git remote add, then you can give a hint of <this is 61 - where you add a remote name> <this is where you add the remote's 62 - URL>, see animated gif in source repo for clear example. Returned 63 - tuple represents the hint message, color, and whether it ought to 64 - be bold. *) 65 - val set_hints_callback : (string -> (string * hint_color * bool) option) -> unit
-1388
vendor/ocaml-linenoise/src/linenoise_src.c
··· 1 - /* linenoise.c -- guerrilla line editing library against the idea that a 2 - * line editing lib needs to be 20,000 lines of C code. 3 - * 4 - * You can find the latest source code at: 5 - * 6 - * http://github.com/antirez/linenoise 7 - * 8 - * Does a number of crazy assumptions that happen to be true in 99.9999% of 9 - * the 2010 UNIX computers around. 10 - * 11 - * ------------------------------------------------------------------------ 12 - * 13 - * Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com> 14 - * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com> 15 - * 16 - * All rights reserved. 17 - * 18 - * Redistribution and use in source and binary forms, with or without 19 - * modification, are permitted provided that the following conditions are 20 - * met: 21 - * 22 - * * Redistributions of source code must retain the above copyright 23 - * notice, this list of conditions and the following disclaimer. 24 - * 25 - * * Redistributions in binary form must reproduce the above copyright 26 - * notice, this list of conditions and the following disclaimer in the 27 - * documentation and/or other materials provided with the distribution. 28 - * 29 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 - * 41 - * ------------------------------------------------------------------------ 42 - * 43 - * References: 44 - * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html 45 - * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html 46 - * 47 - * Todo list: 48 - * - Filter bogus Ctrl+<char> combinations. 49 - * - Win32 support 50 - * 51 - * List of escape sequences used by this program, we do everything just 52 - * with three sequences. In order to be so cheap we may have some 53 - * flickering effect with some slow terminal, but the lesser sequences 54 - * the more compatible. 55 - * 56 - * EL (Erase Line) 57 - * Sequence: ESC [ n K 58 - * Effect: if n is 0 or missing, clear from cursor to end of line 59 - * Effect: if n is 1, clear from beginning of line to cursor 60 - * Effect: if n is 2, clear entire line 61 - * 62 - * CUF (CUrsor Forward) 63 - * Sequence: ESC [ n C 64 - * Effect: moves cursor forward n chars 65 - * 66 - * CUB (CUrsor Backward) 67 - * Sequence: ESC [ n D 68 - * Effect: moves cursor backward n chars 69 - * 70 - * The following is used to get the terminal width if getting 71 - * the width with the TIOCGWINSZ ioctl fails 72 - * 73 - * DSR (Device Status Report) 74 - * Sequence: ESC [ 6 n 75 - * Effect: reports the current cusor position as ESC [ n ; m R 76 - * where n is the row and m is the column 77 - * 78 - * When multi line mode is enabled, we also use an additional escape 79 - * sequence. However multi line editing is disabled by default. 80 - * 81 - * CUU (Cursor Up) 82 - * Sequence: ESC [ n A 83 - * Effect: moves cursor up of n chars. 84 - * 85 - * CUD (Cursor Down) 86 - * Sequence: ESC [ n B 87 - * Effect: moves cursor down of n chars. 88 - * 89 - * When linenoiseClearScreen() is called, two additional escape sequences 90 - * are used in order to clear the screen and position the cursor at home 91 - * position. 92 - * 93 - * CUP (Cursor position) 94 - * Sequence: ESC [ H 95 - * Effect: moves the cursor to upper left corner 96 - * 97 - * ED (Erase display) 98 - * Sequence: ESC [ 2 J 99 - * Effect: clear the whole screen 100 - * 101 - */ 102 - 103 - #include <termios.h> 104 - #include <unistd.h> 105 - #include <stdlib.h> 106 - #include <stdio.h> 107 - #include <errno.h> 108 - #include <string.h> 109 - #include <stdlib.h> 110 - #include <ctype.h> 111 - #include <sys/stat.h> 112 - #include <sys/types.h> 113 - #include <sys/ioctl.h> 114 - #include <unistd.h> 115 - #include "linenoise_src.h" 116 - 117 - #define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 118 - #define LINENOISE_MAX_LINE 4096 119 - static char *unsupported_term[] = {"dumb","cons25","emacs",NULL}; 120 - static linenoiseCompletionCallback *completionCallback = NULL; 121 - static linenoiseHintsCallback *hintsCallback = NULL; 122 - static linenoiseFreeHintsCallback *freeHintsCallback = NULL; 123 - 124 - static struct termios orig_termios; /* In order to restore at exit.*/ 125 - static int rawmode = 0; /* For atexit() function to check if restore is needed*/ 126 - static int mlmode = 0; /* Multi line mode. Default is single line. */ 127 - static int atexit_registered = 0; /* Register atexit just 1 time. */ 128 - static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; 129 - static int history_len = 0; 130 - static char **history = NULL; 131 - 132 - int linenoiseWasInterrupted = 0; 133 - 134 - /* The linenoiseState structure represents the state during line editing. 135 - * We pass this state to functions implementing specific editing 136 - * functionalities. */ 137 - struct linenoiseState { 138 - int ifd; /* Terminal stdin file descriptor. */ 139 - int ofd; /* Terminal stdout file descriptor. */ 140 - char *buf; /* Edited line buffer. */ 141 - size_t buflen; /* Edited line buffer size. */ 142 - const char *prompt; /* Prompt to display. */ 143 - size_t plen; /* Prompt length. */ 144 - size_t pos; /* Current cursor position. */ 145 - size_t oldpos; /* Previous refresh cursor position. */ 146 - size_t len; /* Current edited line length. */ 147 - size_t cols; /* Number of columns in terminal. */ 148 - size_t maxrows; /* Maximum num of rows used so far (multiline mode) */ 149 - int history_index; /* The history index we are currently editing. */ 150 - }; 151 - 152 - enum KEY_ACTION{ 153 - KEY_NULL = 0, /* NULL */ 154 - CTRL_A = 1, /* Ctrl+a */ 155 - CTRL_B = 2, /* Ctrl-b */ 156 - CTRL_C = 3, /* Ctrl-c */ 157 - CTRL_D = 4, /* Ctrl-d */ 158 - CTRL_E = 5, /* Ctrl-e */ 159 - CTRL_F = 6, /* Ctrl-f */ 160 - CTRL_G = 7, /* Ctrl-g */ 161 - CTRL_H = 8, /* Ctrl-h */ 162 - TAB = 9, /* Tab */ 163 - CTRL_K = 11, /* Ctrl+k */ 164 - CTRL_L = 12, /* Ctrl+l */ 165 - ENTER = 13, /* Enter */ 166 - CTRL_N = 14, /* Ctrl-n */ 167 - CTRL_P = 16, /* Ctrl-p */ 168 - CTRL_R = 18, /* Ctrl-r */ 169 - CTRL_T = 20, /* Ctrl-t */ 170 - CTRL_U = 21, /* Ctrl+u */ 171 - CTRL_W = 23, /* Ctrl+w */ 172 - ESC = 27, /* Escape */ 173 - BACKSPACE = 127 /* Backspace */ 174 - }; 175 - 176 - static void linenoiseAtExit(void); 177 - int linenoiseHistoryAdd(const char *line); 178 - static void refreshLine(struct linenoiseState *l); 179 - static void refreshLinePrompt(struct linenoiseState *l, const char *prompt); 180 - 181 - /* Debugging macro. */ 182 - #if 0 183 - FILE *lndebug_fp = NULL; 184 - #define lndebug(...) \ 185 - do { \ 186 - if (lndebug_fp == NULL) { \ 187 - lndebug_fp = fopen("/tmp/lndebug.txt","a"); \ 188 - fprintf(lndebug_fp, \ 189 - "[%d %d %d] p: %d, rows: %d, rpos: %d, max: %d, oldmax: %d\n", \ 190 - (int)l->len,(int)l->pos,(int)l->oldpos,plen,rows,rpos, \ 191 - (int)l->maxrows,old_rows); \ 192 - } \ 193 - fprintf(lndebug_fp, ", " __VA_ARGS__); \ 194 - fflush(lndebug_fp); \ 195 - } while (0) 196 - #else 197 - #define lndebug(fmt, ...) 198 - #endif 199 - 200 - /* ======================= Low level terminal handling ====================== */ 201 - 202 - /* Set if to use or not the multi line mode. */ 203 - void linenoiseSetMultiLine(int ml) { 204 - mlmode = ml; 205 - } 206 - 207 - /* Return true if the terminal name is in the list of terminals we know are 208 - * not able to understand basic escape sequences. */ 209 - static int isUnsupportedTerm(void) { 210 - char *term = getenv("TERM"); 211 - int j; 212 - 213 - if (term == NULL) return 0; 214 - for (j = 0; unsupported_term[j]; j++) 215 - if (!strcasecmp(term,unsupported_term[j])) return 1; 216 - return 0; 217 - } 218 - 219 - /* Raw mode: 1960 magic shit. */ 220 - static int enableRawMode(int fd) { 221 - struct termios raw; 222 - 223 - if (!isatty(STDIN_FILENO)) goto fatal; 224 - if (!atexit_registered) { 225 - atexit(linenoiseAtExit); 226 - atexit_registered = 1; 227 - } 228 - if (tcgetattr(fd,&orig_termios) == -1) goto fatal; 229 - 230 - raw = orig_termios; /* modify the original mode */ 231 - /* input modes: no break, no CR to NL, no parity check, no strip char, 232 - * no start/stop output control. */ 233 - raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); 234 - /* output modes - disable post processing */ 235 - raw.c_oflag &= ~(OPOST); 236 - /* control modes - set 8 bit chars */ 237 - raw.c_cflag |= (CS8); 238 - /* local modes - choing off, canonical off, no extended functions, 239 - * no signal chars (^Z,^C) */ 240 - raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); 241 - /* control chars - set return condition: min number of bytes and timer. 242 - * We want read to return every single byte, without timeout. */ 243 - raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */ 244 - 245 - /* put terminal in raw mode after flushing */ 246 - if (tcsetattr(fd,TCSADRAIN,&raw) < 0) goto fatal; 247 - rawmode = 1; 248 - return 0; 249 - 250 - fatal: 251 - errno = ENOTTY; 252 - return -1; 253 - } 254 - 255 - static void disableRawMode(int fd) { 256 - /* Don't even check the return value as it's too late. */ 257 - if (rawmode && tcsetattr(fd,TCSADRAIN,&orig_termios) != -1) 258 - rawmode = 0; 259 - } 260 - 261 - /* Use the ESC [6n escape sequence to query the horizontal cursor position 262 - * and return it. On error -1 is returned, on success the position of the 263 - * cursor. */ 264 - static int getCursorPosition(int ifd, int ofd) { 265 - char buf[32]; 266 - int cols, rows; 267 - unsigned int i = 0; 268 - 269 - /* Report cursor location */ 270 - if (write(ofd, "\x1b[6n", 4) != 4) return -1; 271 - 272 - /* Read the response: ESC [ rows ; cols R */ 273 - while (i < sizeof(buf)-1) { 274 - if (read(ifd,buf+i,1) != 1) break; 275 - if (buf[i] == 'R') break; 276 - i++; 277 - } 278 - buf[i] = '\0'; 279 - 280 - /* Parse it. */ 281 - if (buf[0] != ESC || buf[1] != '[') return -1; 282 - if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1; 283 - return cols; 284 - } 285 - 286 - /* Try to get the number of columns in the current terminal, or assume 80 287 - * if it fails. */ 288 - static int getColumns(int ifd, int ofd) { 289 - struct winsize ws; 290 - 291 - if (ioctl(1, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) { 292 - /* ioctl() failed. Try to query the terminal itself. */ 293 - int start, cols; 294 - 295 - /* Get the initial position so we can restore it later. */ 296 - start = getCursorPosition(ifd,ofd); 297 - if (start == -1) goto failed; 298 - 299 - /* Go to right margin and get position. */ 300 - if (write(ofd,"\x1b[999C",6) != 6) goto failed; 301 - cols = getCursorPosition(ifd,ofd); 302 - if (cols == -1) goto failed; 303 - 304 - /* Restore position. */ 305 - if (cols > start) { 306 - char seq[32]; 307 - snprintf(seq,32,"\x1b[%dD",cols-start); 308 - if (write(ofd,seq,strlen(seq)) == -1) { 309 - /* Can't recover... */ 310 - } 311 - } 312 - return cols; 313 - } else { 314 - return ws.ws_col; 315 - } 316 - 317 - failed: 318 - return 80; 319 - } 320 - 321 - /* Clear the screen. Used to handle ctrl+l */ 322 - void linenoiseClearScreen(void) { 323 - if (write(STDOUT_FILENO,"\x1b[H\x1b[2J",7) <= 0) { 324 - /* nothing to do, just to avoid warning. */ 325 - } 326 - } 327 - 328 - /* Beep, used for completion when there is nothing to complete or when all 329 - * the choices were already shown. */ 330 - static void linenoiseBeep(void) { 331 - fprintf(stderr, "\x7"); 332 - fflush(stderr); 333 - } 334 - 335 - /* ============================== Completion ================================ */ 336 - 337 - /* Free a list of completion option populated by linenoiseAddCompletion(). */ 338 - static void freeCompletions(linenoiseCompletions *lc) { 339 - size_t i; 340 - for (i = 0; i < lc->len; i++) 341 - free(lc->cvec[i]); 342 - if (lc->cvec != NULL) 343 - free(lc->cvec); 344 - } 345 - 346 - /* This is an helper function for linenoiseEdit() and is called when the 347 - * user types the <tab> key in order to complete the string currently in the 348 - * input. 349 - * 350 - * The state of the editing is encapsulated into the pointed linenoiseState 351 - * structure as described in the structure definition. */ 352 - static int completeLine(struct linenoiseState *ls) { 353 - linenoiseCompletions lc = { 0, NULL }; 354 - int nread, nwritten; 355 - char c = 0; 356 - 357 - completionCallback(ls->buf,&lc); 358 - if (lc.len == 0) { 359 - linenoiseBeep(); 360 - } else { 361 - size_t stop = 0, i = 0; 362 - 363 - while(!stop) { 364 - /* Show completion or original buffer */ 365 - if (i < lc.len) { 366 - struct linenoiseState saved = *ls; 367 - 368 - ls->len = ls->pos = strlen(lc.cvec[i]); 369 - ls->buf = lc.cvec[i]; 370 - refreshLine(ls); 371 - ls->len = saved.len; 372 - ls->pos = saved.pos; 373 - ls->buf = saved.buf; 374 - } else { 375 - refreshLine(ls); 376 - } 377 - 378 - nread = read(ls->ifd,&c,1); 379 - if (nread <= 0) { 380 - freeCompletions(&lc); 381 - return -1; 382 - } 383 - 384 - switch(c) { 385 - case 9: /* tab */ 386 - i = (i+1) % (lc.len+1); 387 - if (i == lc.len) linenoiseBeep(); 388 - break; 389 - case 27: /* escape */ 390 - /* Re-show original buffer */ 391 - if (i < lc.len) refreshLine(ls); 392 - stop = 1; 393 - break; 394 - default: 395 - /* Update buffer and return */ 396 - if (i < lc.len) { 397 - nwritten = snprintf(ls->buf,ls->buflen,"%s",lc.cvec[i]); 398 - ls->len = ls->pos = nwritten; 399 - } 400 - stop = 1; 401 - break; 402 - } 403 - } 404 - } 405 - 406 - freeCompletions(&lc); 407 - return c; /* Return last read character */ 408 - } 409 - 410 - /* Register a callback function to be called for tab-completion. */ 411 - void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) { 412 - completionCallback = fn; 413 - } 414 - 415 - /* Register a hits function to be called to show hits to the user at the 416 - * right of the prompt. */ 417 - void linenoiseSetHintsCallback(linenoiseHintsCallback *fn) { 418 - hintsCallback = fn; 419 - } 420 - 421 - /* Register a function to free the hints returned by the hints callback 422 - * registered with linenoiseSetHintsCallback(). */ 423 - void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *fn) { 424 - freeHintsCallback = fn; 425 - } 426 - 427 - /* This function is used by the callback function registered by the user 428 - * in order to add completion options given the input string when the 429 - * user typed <tab>. See the example.c source code for a very easy to 430 - * understand example. */ 431 - void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) { 432 - size_t len = strlen(str); 433 - char *copy, **cvec; 434 - 435 - copy = malloc(len+1); 436 - if (copy == NULL) return; 437 - memcpy(copy,str,len+1); 438 - cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1)); 439 - if (cvec == NULL) { 440 - free(copy); 441 - return; 442 - } 443 - lc->cvec = cvec; 444 - lc->cvec[lc->len++] = copy; 445 - } 446 - 447 - /* =========================== Line editing ================================= */ 448 - 449 - /* We define a very simple "append buffer" structure, that is an heap 450 - * allocated string where we can append to. This is useful in order to 451 - * write all the escape sequences in a buffer and flush them to the standard 452 - * output in a single call, to avoid flickering effects. */ 453 - struct abuf { 454 - char *b; 455 - int len; 456 - }; 457 - 458 - static void abInit(struct abuf *ab) { 459 - ab->b = NULL; 460 - ab->len = 0; 461 - } 462 - 463 - static void abAppend(struct abuf *ab, const char *s, int len) { 464 - char *new = realloc(ab->b,ab->len+len); 465 - 466 - if (new == NULL) return; 467 - memcpy(new+ab->len,s,len); 468 - ab->b = new; 469 - ab->len += len; 470 - } 471 - 472 - static void abFree(struct abuf *ab) { 473 - free(ab->b); 474 - } 475 - 476 - /* Helper of refreshSingleLine() and refreshMultiLine() to show hints 477 - * to the right of the prompt. */ 478 - void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) { 479 - char seq[64]; 480 - if (hintsCallback && plen+l->len < l->cols) { 481 - int color = -1, bold = 0; 482 - char *hint = hintsCallback(l->buf,&color,&bold); 483 - if (hint) { 484 - int hintlen = strlen(hint); 485 - int hintmaxlen = l->cols-(plen+l->len); 486 - if (hintlen > hintmaxlen) hintlen = hintmaxlen; 487 - if (bold == 1 && color == -1) color = 37; 488 - if (color != -1 || bold != 0) 489 - snprintf(seq,64,"\033[%d;%d;49m",bold,color); 490 - abAppend(ab,seq,strlen(seq)); 491 - abAppend(ab,hint,hintlen); 492 - if (color != -1 || bold != 0) 493 - abAppend(ab,"\033[0m",4); 494 - /* Call the function to free the hint returned. */ 495 - if (freeHintsCallback) freeHintsCallback(hint); 496 - } 497 - } 498 - } 499 - 500 - /* Single line low level line refresh. 501 - * 502 - * Rewrite the currently edited line accordingly to the buffer content, 503 - * cursor position, and number of columns of the terminal. */ 504 - static void refreshSingleLine(struct linenoiseState *l, const char *prompt) { 505 - char seq[64]; 506 - size_t plen = strlen(prompt); 507 - int fd = l->ofd; 508 - char *buf = l->buf; 509 - size_t len = l->len; 510 - size_t pos = l->pos; 511 - struct abuf ab; 512 - 513 - if (plen >= l->cols) { 514 - len=0; // not enough room 515 - plen = l->cols; 516 - } 517 - 518 - while((plen+pos) >= l->cols && len>0) { 519 - buf++; 520 - len--; 521 - pos--; 522 - } 523 - while (plen+len > l->cols && len>0) { 524 - len--; 525 - } 526 - 527 - abInit(&ab); 528 - /* Cursor to left edge */ 529 - snprintf(seq,64,"\r"); 530 - abAppend(&ab,seq,strlen(seq)); 531 - /* Write the prompt and the current buffer content */ 532 - abAppend(&ab,prompt,plen); 533 - if (len > 0) 534 - abAppend(&ab,buf,len); 535 - /* Show hits if any. */ 536 - refreshShowHints(&ab,l,plen); 537 - /* Erase to right */ 538 - snprintf(seq,64,"\x1b[0K"); 539 - abAppend(&ab,seq,strlen(seq)); 540 - /* Move cursor to original position. */ 541 - snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen)); 542 - abAppend(&ab,seq,strlen(seq)); 543 - if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */ 544 - abFree(&ab); 545 - } 546 - 547 - /* Multi line low level line refresh. 548 - * 549 - * Rewrite the currently edited line accordingly to the buffer content, 550 - * cursor position, and number of columns of the terminal. */ 551 - static void refreshMultiLine(struct linenoiseState *l, const char *prompt) { 552 - char seq[64]; 553 - int plen = strlen(prompt); 554 - int rows = (plen+l->len+l->cols-1)/l->cols; /* rows used by current buf. */ 555 - int rpos = (plen+l->oldpos+l->cols)/l->cols; /* cursor relative row. */ 556 - int rpos2; /* rpos after refresh. */ 557 - int col; /* colum position, zero-based. */ 558 - int old_rows = l->maxrows; 559 - size_t pos = l->pos; 560 - int fd = l->ofd, j; 561 - struct abuf ab; 562 - 563 - /* Update maxrows if needed. */ 564 - if (rows > (int)l->maxrows) l->maxrows = rows; 565 - 566 - /* First step: clear all the lines used before. To do so start by 567 - * going to the last row. */ 568 - abInit(&ab); 569 - if (old_rows-rpos > 0) { 570 - lndebug("go down %d", old_rows-rpos); 571 - snprintf(seq,64,"\x1b[%dB", old_rows-rpos); 572 - abAppend(&ab,seq,strlen(seq)); 573 - } 574 - 575 - /* Now for every row clear it, go up. */ 576 - for (j = 0; j < old_rows-1; j++) { 577 - lndebug("clear+up"); 578 - snprintf(seq,64,"\r\x1b[0K\x1b[1A"); 579 - abAppend(&ab,seq,strlen(seq)); 580 - } 581 - 582 - /* Clean the top line. */ 583 - lndebug("clear"); 584 - snprintf(seq,64,"\r\x1b[0K"); 585 - abAppend(&ab,seq,strlen(seq)); 586 - 587 - /* Write the prompt and the current buffer content */ 588 - abAppend(&ab,prompt,strlen(prompt)); 589 - abAppend(&ab,l->buf,l->len); 590 - 591 - /* Show hits if any. */ 592 - refreshShowHints(&ab,l,plen); 593 - 594 - /* If we are at the very end of the screen with our prompt, we need to 595 - * emit a newline and move the prompt to the first column. */ 596 - if (pos && 597 - pos == l->len && 598 - (pos+plen) % l->cols == 0) 599 - { 600 - lndebug("<newline>"); 601 - abAppend(&ab,"\n",1); 602 - snprintf(seq,64,"\r"); 603 - abAppend(&ab,seq,strlen(seq)); 604 - rows++; 605 - if (rows > (int)l->maxrows) l->maxrows = rows; 606 - } 607 - 608 - /* Move cursor to right position. */ 609 - rpos2 = (plen+pos+l->cols)/l->cols; /* current cursor relative row. */ 610 - lndebug("rpos2 %d", rpos2); 611 - 612 - /* Go up till we reach the expected positon. */ 613 - if (rows-rpos2 > 0) { 614 - lndebug("go-up %d", rows-rpos2); 615 - snprintf(seq,64,"\x1b[%dA", rows-rpos2); 616 - abAppend(&ab,seq,strlen(seq)); 617 - } 618 - 619 - /* Set column. */ 620 - col = (plen+(int)pos) % (int)l->cols; 621 - lndebug("set col %d", 1+col); 622 - if (col) 623 - snprintf(seq,64,"\r\x1b[%dC", col); 624 - else 625 - snprintf(seq,64,"\r"); 626 - abAppend(&ab,seq,strlen(seq)); 627 - 628 - lndebug("\n"); 629 - l->oldpos = pos; 630 - 631 - if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */ 632 - abFree(&ab); 633 - } 634 - 635 - /* Calls the two low level functions refreshSingleLine() or 636 - * refreshMultiLine() according to the selected mode. */ 637 - static void refreshLinePrompt(struct linenoiseState *l, const char *prompt) { 638 - if (mlmode) 639 - refreshMultiLine(l, prompt); 640 - else 641 - refreshSingleLine(l, prompt); 642 - } 643 - 644 - static void refreshLine(struct linenoiseState *l) { 645 - refreshLinePrompt(l, l->prompt); 646 - } 647 - 648 - /* Insert the character 'c' at cursor current position. 649 - * 650 - * On error writing to the terminal -1 is returned, otherwise 0. */ 651 - int linenoiseEditInsert(struct linenoiseState *l, char c) { 652 - if (l->len < l->buflen) { 653 - if (l->len == l->pos) { 654 - l->buf[l->pos] = c; 655 - l->pos++; 656 - l->len++; 657 - l->buf[l->len] = '\0'; 658 - if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) { 659 - /* Avoid a full update of the line in the 660 - * trivial case. */ 661 - if (write(l->ofd,&c,1) == -1) return -1; 662 - } else { 663 - refreshLine(l); 664 - } 665 - } else { 666 - memmove(l->buf+l->pos+1,l->buf+l->pos,l->len-l->pos); 667 - l->buf[l->pos] = c; 668 - l->len++; 669 - l->pos++; 670 - l->buf[l->len] = '\0'; 671 - refreshLine(l); 672 - } 673 - } 674 - return 0; 675 - } 676 - 677 - /* Move cursor on the left. */ 678 - void linenoiseEditMoveLeft(struct linenoiseState *l) { 679 - if (l->pos > 0) { 680 - l->pos--; 681 - refreshLine(l); 682 - } 683 - } 684 - 685 - /* Move cursor on the right. */ 686 - void linenoiseEditMoveRight(struct linenoiseState *l) { 687 - if (l->pos != l->len) { 688 - l->pos++; 689 - refreshLine(l); 690 - } 691 - } 692 - 693 - /* Move cursor on the left */ 694 - void linenoiseEditMovePrevWord(struct linenoiseState *l) { 695 - while (l->pos > 0 && l->buf[l->pos-1] == ' ') 696 - l->pos--; 697 - while (l->pos > 0 && l->buf[l->pos-1] != ' ') 698 - l->pos--; 699 - refreshLine(l); 700 - } 701 - 702 - /* Move cursor on the right. */ 703 - void linenoiseEditMoveNextWord(struct linenoiseState *l) { 704 - while (l->pos < l->len && l->buf[l->pos-1] == ' ') 705 - l->pos++; 706 - while (l->pos < l->len && l->buf[l->pos-1] != ' ') 707 - l->pos++; 708 - refreshLine(l); 709 - } 710 - 711 - /* Move cursor to the start of the line. */ 712 - void linenoiseEditMoveHome(struct linenoiseState *l) { 713 - if (l->pos != 0) { 714 - l->pos = 0; 715 - refreshLine(l); 716 - } 717 - } 718 - 719 - /* Move cursor to the end of the line. */ 720 - void linenoiseEditMoveEnd(struct linenoiseState *l) { 721 - if (l->pos != l->len) { 722 - l->pos = l->len; 723 - refreshLine(l); 724 - } 725 - } 726 - 727 - /* Substitute the currently edited line with the next or previous history 728 - * entry as specified by 'dir'. */ 729 - #define LINENOISE_HISTORY_NEXT 0 730 - #define LINENOISE_HISTORY_PREV 1 731 - void linenoiseEditHistoryNext(struct linenoiseState *l, int dir) { 732 - if (history_len > 1) { 733 - /* Update the current history entry before to 734 - * overwrite it with the next one. */ 735 - free(history[history_len - 1 - l->history_index]); 736 - history[history_len - 1 - l->history_index] = strdup(l->buf); 737 - /* Show the new entry */ 738 - l->history_index += (dir == LINENOISE_HISTORY_PREV) ? 1 : -1; 739 - if (l->history_index < 0) { 740 - l->history_index = 0; 741 - return; 742 - } else if (l->history_index >= history_len) { 743 - l->history_index = history_len-1; 744 - return; 745 - } 746 - strncpy(l->buf,history[history_len - 1 - l->history_index],l->buflen); 747 - l->buf[l->buflen-1] = '\0'; 748 - l->len = l->pos = strlen(l->buf); 749 - refreshLine(l); 750 - } 751 - } 752 - 753 - /* Delete the character at the right of the cursor without altering the cursor 754 - * position. Basically this is what happens with the "Delete" keyboard key. */ 755 - void linenoiseEditDelete(struct linenoiseState *l) { 756 - if (l->len > 0 && l->pos < l->len) { 757 - memmove(l->buf+l->pos,l->buf+l->pos+1,l->len-l->pos-1); 758 - l->len--; 759 - l->buf[l->len] = '\0'; 760 - refreshLine(l); 761 - } 762 - } 763 - 764 - /* Backspace implementation. */ 765 - void linenoiseEditBackspace(struct linenoiseState *l) { 766 - if (l->pos > 0 && l->len > 0) { 767 - memmove(l->buf+l->pos-1,l->buf+l->pos,l->len-l->pos); 768 - l->pos--; 769 - l->len--; 770 - l->buf[l->len] = '\0'; 771 - refreshLine(l); 772 - } 773 - } 774 - 775 - /* Delete the previous word, maintaining the cursor at the start of the 776 - * current word. */ 777 - void linenoiseEditDeletePrevWord(struct linenoiseState *l) { 778 - size_t old_pos = l->pos; 779 - size_t diff; 780 - 781 - while (l->pos > 0 && l->buf[l->pos-1] == ' ') 782 - l->pos--; 783 - while (l->pos > 0 && l->buf[l->pos-1] != ' ') 784 - l->pos--; 785 - diff = old_pos - l->pos; 786 - memmove(l->buf+l->pos,l->buf+old_pos,l->len-old_pos+1); 787 - l->len -= diff; 788 - refreshLine(l); 789 - } 790 - 791 - /* Delete the next word, maintaining the cursor at the same position */ 792 - void linenoiseEditDeleteNextWord(struct linenoiseState *l) { 793 - size_t next_pos = l->pos; 794 - size_t diff; 795 - 796 - while (next_pos < l->len && l->buf[next_pos] == ' ') 797 - next_pos++; 798 - while (next_pos < l->len && l->buf[next_pos] != ' ') 799 - next_pos++; 800 - diff = next_pos - l->pos; 801 - memmove(l->buf+l->pos,l->buf+next_pos,l->len-next_pos+1); 802 - l->len -= diff; 803 - refreshLine(l); 804 - } 805 - 806 - void linenoiseReverseIncrementalSearch(struct linenoiseState *l) { 807 - 808 - char search_buf[LINENOISE_MAX_LINE]; 809 - char search_prompt[LINENOISE_MAX_LINE]; 810 - int search_len = 0; 811 - int search_pos = history_len - 1; 812 - int search_dir = -1; 813 - char* prompt; 814 - 815 - int has_match = 1; 816 - 817 - // backup of current input 818 - char *buf; 819 - { 820 - size_t len = 1+ strlen(l->buf); 821 - buf = malloc(len); 822 - if (buf == NULL) return; 823 - memcpy(buf, l->buf, len); 824 - } 825 - 826 - search_buf[0] = 0; 827 - 828 - while (1) { 829 - 830 - if (!has_match) 831 - prompt = "(failed-reverse-i-search)`%s': "; 832 - else 833 - prompt = "(reverse-i-search)`%s': "; 834 - 835 - if (!snprintf(search_prompt, sizeof(search_prompt), prompt, search_buf)) { 836 - linenoiseBeep(); 837 - break; 838 - } else { 839 - search_prompt[sizeof(search_prompt)-1] = 0; // crop 840 - } 841 - 842 - l->pos = 0; 843 - refreshLinePrompt(l, search_prompt); 844 - 845 - char c; 846 - int new_char = 0; 847 - 848 - if (read(l->ifd, &c, 1) <= 0) { 849 - l->pos = l->len = snprintf(l->buf, l->buflen, "%s", buf); 850 - l->buf[l->buflen-1] = 0; 851 - refreshLine(l); 852 - free(buf); 853 - return; 854 - } 855 - 856 - switch(c) { 857 - case BACKSPACE: 858 - case CTRL_H: 859 - if (search_len > 0) { 860 - search_buf[--search_len] = 0; 861 - search_pos = history_len - 1; 862 - } else 863 - linenoiseBeep(); 864 - break; 865 - case CTRL_N: 866 - case CTRL_R: 867 - search_dir = -1; 868 - if (search_pos >= history_len) 869 - search_pos = history_len - 1; 870 - break; 871 - case CTRL_P: 872 - search_dir = 1; 873 - if (search_pos < 0) 874 - search_pos = 0; 875 - break; 876 - case ESC: 877 - case CTRL_G: 878 - l->pos = l->len = snprintf(l->buf, l->buflen, "%s", buf); 879 - l->buf[l->buflen-1] = 0; 880 - free(buf); 881 - refreshLine(l); 882 - return; 883 - case ENTER: 884 - free(buf); 885 - l->pos = l->len; 886 - refreshLine(l); 887 - return; 888 - default: 889 - new_char = 1; 890 - search_buf[search_len] = c; 891 - search_buf[++search_len] = 0; 892 - search_pos = history_len - 1; 893 - break; 894 - } 895 - 896 - has_match = 0; 897 - 898 - if (strlen(search_buf) > 0) { 899 - for (; search_pos >= 0 && search_pos < history_len; search_pos += search_dir) { 900 - if (strstr(history[search_pos], search_buf) && (new_char || strcmp(history[search_pos], l->buf))) { 901 - has_match = 1; 902 - l->len = snprintf(l->buf, l->buflen, "%s", history[search_pos]); 903 - break; 904 - } 905 - } 906 - if (!has_match) { 907 - linenoiseBeep(); 908 - // forbid writes if the line is too long 909 - if (search_len > 0 && new_char && search_len+1 >= sizeof(search_buf)) 910 - search_buf[--search_len] = 0; 911 - } 912 - } 913 - } 914 - } 915 - 916 - /* This function is the core of the line editing capability of linenoise. 917 - * It expects 'fd' to be already in "raw mode" so that every key pressed 918 - * will be returned ASAP to read(). 919 - * 920 - * The resulting string is put into 'buf' when the user type enter, or 921 - * when ctrl+d is typed. 922 - * 923 - * The function returns the length of the current buffer. */ 924 - static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt) 925 - { 926 - struct linenoiseState l; 927 - 928 - /* Populate the linenoise state that we pass to functions implementing 929 - * specific editing functionalities. */ 930 - l.ifd = stdin_fd; 931 - l.ofd = stdout_fd; 932 - l.buf = buf; 933 - l.buflen = buflen; 934 - l.prompt = prompt; 935 - l.plen = strlen(prompt); 936 - l.oldpos = l.pos = 0; 937 - l.len = 0; 938 - l.cols = getColumns(stdin_fd, stdout_fd); 939 - l.maxrows = 0; 940 - l.history_index = 0; 941 - 942 - /* Buffer starts empty. */ 943 - l.buf[0] = '\0'; 944 - l.buflen--; /* Make sure there is always space for the nulterm */ 945 - 946 - /* The latest history entry is always our current buffer, that 947 - * initially is just an empty string. */ 948 - linenoiseHistoryAdd(""); 949 - 950 - if (write(l.ofd,prompt,l.plen) == -1) return -1; 951 - while(1) { 952 - char c; 953 - int nread; 954 - char seq[5]; 955 - 956 - nread = read(l.ifd,&c,1); 957 - if (nread <= 0) return l.len; 958 - 959 - /* Only autocomplete when the callback is set. It returns < 0 when 960 - * there was an error reading from fd. Otherwise it will return the 961 - * character that should be handled next. */ 962 - if (c == 9 && completionCallback != NULL) { 963 - c = completeLine(&l); 964 - /* Return on errors */ 965 - if (c < 0) return l.len; 966 - /* Read next character when 0 */ 967 - if (c == 0) continue; 968 - } 969 - 970 - switch(c) { 971 - case ENTER: /* enter */ 972 - history_len--; 973 - free(history[history_len]); 974 - if (mlmode) linenoiseEditMoveEnd(&l); 975 - if (hintsCallback) { 976 - /* Force a refresh without hints to leave the previous 977 - * line as the user typed it after a newline. */ 978 - linenoiseHintsCallback *hc = hintsCallback; 979 - hintsCallback = NULL; 980 - refreshLine(&l); 981 - hintsCallback = hc; 982 - } 983 - return (int)l.len; 984 - case CTRL_C: /* ctrl-c */ 985 - errno = EAGAIN; 986 - linenoiseWasInterrupted = 1; 987 - return -1; 988 - case BACKSPACE: /* backspace */ 989 - case 8: /* ctrl-h */ 990 - linenoiseEditBackspace(&l); 991 - break; 992 - case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the 993 - line is empty, act as end-of-file. */ 994 - if (l.len > 0) { 995 - linenoiseEditDelete(&l); 996 - } else { 997 - history_len--; 998 - free(history[history_len]); 999 - return -1; 1000 - } 1001 - break; 1002 - case CTRL_T: /* ctrl-t, swaps current character with previous. */ 1003 - if (l.pos > 0 && l.pos < l.len) { 1004 - int aux = buf[l.pos-1]; 1005 - buf[l.pos-1] = buf[l.pos]; 1006 - buf[l.pos] = aux; 1007 - if (l.pos != l.len-1) l.pos++; 1008 - refreshLine(&l); 1009 - } 1010 - break; 1011 - case CTRL_B: /* ctrl-b */ 1012 - linenoiseEditMoveLeft(&l); 1013 - break; 1014 - case CTRL_F: /* ctrl-f */ 1015 - linenoiseEditMoveRight(&l); 1016 - break; 1017 - case CTRL_P: /* ctrl-p */ 1018 - linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV); 1019 - break; 1020 - case CTRL_R: /* ctrl-r */ 1021 - linenoiseReverseIncrementalSearch(&l); 1022 - break; 1023 - case CTRL_N: /* ctrl-n */ 1024 - linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT); 1025 - break; 1026 - case ESC: /* escape sequence */ 1027 - /* Read the next byte representing the escape sequence */ 1028 - if (read(l.ifd,seq,1) == -1) break; 1029 - 1030 - /* alt-b, alt-f, alt-d, alt-backspace */ 1031 - if (seq[0] == 'b') { 1032 - linenoiseEditMovePrevWord(&l); 1033 - break; 1034 - } else if (seq[0] == 'f') { 1035 - linenoiseEditMoveNextWord(&l); 1036 - break; 1037 - } else if (seq[0] == 'd') { 1038 - linenoiseEditDeleteNextWord(&l); 1039 - break; 1040 - } else if (seq[0] == 127) { /* backspace */ 1041 - linenoiseEditDeletePrevWord(&l); 1042 - break; 1043 - } 1044 - 1045 - /* Read a second byte */ 1046 - if (read(l.ifd,seq+1,1) == -1) break; 1047 - 1048 - /* ESC [ sequences. */ 1049 - if (seq[0] == '[') { 1050 - if (seq[1] >= '0' && seq[1] <= '9') { 1051 - /* Extended escape, read additional byte. */ 1052 - if (read(l.ifd,seq+2,1) == -1) break; 1053 - if (seq[2] == '~') { 1054 - switch(seq[1]) { 1055 - case '3': /* Delete key. */ 1056 - linenoiseEditDelete(&l); 1057 - break; 1058 - } 1059 - } else if (seq[2] == ';') { 1060 - /* read additional 2 bytes */ 1061 - if (read(l.ifd,seq+3,1) == -1) break; 1062 - if (read(l.ifd,seq+4,1) == -1) break; 1063 - if (seq[3] == '5') { 1064 - switch (seq[4]) { 1065 - case 'D': /* ctrl-left */ 1066 - linenoiseEditMovePrevWord(&l); 1067 - break; 1068 - case 'C': /* ctrl-right */ 1069 - linenoiseEditMoveNextWord(&l); 1070 - break; 1071 - } 1072 - } 1073 - } 1074 - } else { 1075 - switch(seq[1]) { 1076 - case 'A': /* Up */ 1077 - linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV); 1078 - break; 1079 - case 'B': /* Down */ 1080 - linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT); 1081 - break; 1082 - case 'C': /* Right */ 1083 - linenoiseEditMoveRight(&l); 1084 - break; 1085 - case 'D': /* Left */ 1086 - linenoiseEditMoveLeft(&l); 1087 - break; 1088 - case 'H': /* Home */ 1089 - linenoiseEditMoveHome(&l); 1090 - break; 1091 - case 'F': /* End*/ 1092 - linenoiseEditMoveEnd(&l); 1093 - break; 1094 - } 1095 - } 1096 - } 1097 - 1098 - /* ESC O sequences. */ 1099 - else if (seq[0] == 'O') { 1100 - switch(seq[1]) { 1101 - case 'H': /* Home */ 1102 - linenoiseEditMoveHome(&l); 1103 - break; 1104 - case 'F': /* End*/ 1105 - linenoiseEditMoveEnd(&l); 1106 - break; 1107 - } 1108 - } 1109 - break; 1110 - default: 1111 - if (linenoiseEditInsert(&l,c)) return -1; 1112 - break; 1113 - case CTRL_U: /* Ctrl+u, delete the whole line. */ 1114 - buf[0] = '\0'; 1115 - l.pos = l.len = 0; 1116 - refreshLine(&l); 1117 - break; 1118 - case CTRL_K: /* Ctrl+k, delete from current to end of line. */ 1119 - buf[l.pos] = '\0'; 1120 - l.len = l.pos; 1121 - refreshLine(&l); 1122 - break; 1123 - case CTRL_A: /* Ctrl+a, go to the start of the line */ 1124 - linenoiseEditMoveHome(&l); 1125 - break; 1126 - case CTRL_E: /* ctrl+e, go to the end of the line */ 1127 - linenoiseEditMoveEnd(&l); 1128 - break; 1129 - case CTRL_L: /* ctrl+l, clear screen */ 1130 - linenoiseClearScreen(); 1131 - refreshLine(&l); 1132 - break; 1133 - case CTRL_W: /* ctrl+w, delete previous word */ 1134 - linenoiseEditDeletePrevWord(&l); 1135 - break; 1136 - } 1137 - } 1138 - return l.len; 1139 - } 1140 - 1141 - /* This special mode is used by linenoise in order to print scan codes 1142 - * on screen for debugging / development purposes. It is implemented 1143 - * by the linenoise_example program using the --keycodes option. */ 1144 - void linenoisePrintKeyCodes(void) { 1145 - char quit[4]; 1146 - 1147 - printf("Linenoise key codes debugging mode.\n" 1148 - "Press keys to see scan codes. Type 'quit' at any time to exit.\n"); 1149 - if (enableRawMode(STDIN_FILENO) == -1) return; 1150 - memset(quit,' ',4); 1151 - while(1) { 1152 - char c; 1153 - int nread; 1154 - 1155 - nread = read(STDIN_FILENO,&c,1); 1156 - if (nread <= 0) continue; 1157 - memmove(quit,quit+1,sizeof(quit)-1); /* shift string to left. */ 1158 - quit[sizeof(quit)-1] = c; /* Insert current char on the right. */ 1159 - if (memcmp(quit,"quit",sizeof(quit)) == 0) break; 1160 - 1161 - printf("'%c' %02x (%d) (type quit to exit)\n", 1162 - isprint(c) ? c : '?', (int)c, (int)c); 1163 - printf("\r"); /* Go left edge manually, we are in raw mode. */ 1164 - fflush(stdout); 1165 - } 1166 - disableRawMode(STDIN_FILENO); 1167 - } 1168 - 1169 - /* This function calls the line editing function linenoiseEdit() using 1170 - * the STDIN file descriptor set in raw mode. */ 1171 - static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) { 1172 - int count; 1173 - 1174 - if (buflen == 0) { 1175 - errno = EINVAL; 1176 - return -1; 1177 - } 1178 - 1179 - if (enableRawMode(STDIN_FILENO) == -1) return -1; 1180 - count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt); 1181 - disableRawMode(STDIN_FILENO); 1182 - printf("\n"); 1183 - return count; 1184 - } 1185 - 1186 - /* This function is called when linenoise() is called with the standard 1187 - * input file descriptor not attached to a TTY. So for example when the 1188 - * program using linenoise is called in pipe or with a file redirected 1189 - * to its standard input. In this case, we want to be able to return the 1190 - * line regardless of its length (by default we are limited to 4k). */ 1191 - static char *linenoiseNoTTY(void) { 1192 - char *line = NULL; 1193 - size_t len = 0, maxlen = 0; 1194 - 1195 - while(1) { 1196 - if (len == maxlen) { 1197 - if (maxlen == 0) maxlen = 16; 1198 - maxlen *= 2; 1199 - char *oldval = line; 1200 - line = realloc(line,maxlen); 1201 - if (line == NULL) { 1202 - if (oldval) free(oldval); 1203 - return NULL; 1204 - } 1205 - } 1206 - int c = fgetc(stdin); 1207 - if (c == EOF || c == '\n') { 1208 - if (c == EOF && len == 0) { 1209 - free(line); 1210 - return NULL; 1211 - } else { 1212 - line[len] = '\0'; 1213 - return line; 1214 - } 1215 - } else { 1216 - line[len] = c; 1217 - len++; 1218 - } 1219 - } 1220 - } 1221 - 1222 - /* The high level function that is the main API of the linenoise library. 1223 - * This function checks if the terminal has basic capabilities, just checking 1224 - * for a blacklist of stupid terminals, and later either calls the line 1225 - * editing function or uses dummy fgets() so that you will be able to type 1226 - * something even in the most desperate of the conditions. */ 1227 - char *linenoise(const char *prompt) { 1228 - char buf[LINENOISE_MAX_LINE]; 1229 - int count; 1230 - 1231 - if (!isatty(STDIN_FILENO)) { 1232 - /* Not a tty: read from file / pipe. In this mode we don't want any 1233 - * limit to the line size, so we call a function to handle that. */ 1234 - return linenoiseNoTTY(); 1235 - } else if (isUnsupportedTerm()) { 1236 - size_t len; 1237 - 1238 - printf("%s",prompt); 1239 - fflush(stdout); 1240 - if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL; 1241 - len = strlen(buf); 1242 - while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) { 1243 - len--; 1244 - buf[len] = '\0'; 1245 - } 1246 - return strdup(buf); 1247 - } else { 1248 - count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt); 1249 - if (count == -1) return NULL; 1250 - return strdup(buf); 1251 - } 1252 - } 1253 - 1254 - /* This is just a wrapper the user may want to call in order to make sure 1255 - * the linenoise returned buffer is freed with the same allocator it was 1256 - * created with. Useful when the main program is using an alternative 1257 - * allocator. */ 1258 - void linenoiseFree(void *ptr) { 1259 - free(ptr); 1260 - } 1261 - 1262 - /* ================================ History ================================= */ 1263 - 1264 - /* Free the history, but does not reset it. Only used when we have to 1265 - * exit() to avoid memory leaks are reported by valgrind & co. */ 1266 - static void freeHistory(void) { 1267 - if (history) { 1268 - int j; 1269 - 1270 - for (j = 0; j < history_len; j++) 1271 - free(history[j]); 1272 - free(history); 1273 - } 1274 - } 1275 - 1276 - /* At exit we'll try to fix the terminal to the initial conditions. */ 1277 - static void linenoiseAtExit(void) { 1278 - disableRawMode(STDIN_FILENO); 1279 - freeHistory(); 1280 - } 1281 - 1282 - /* This is the API call to add a new entry in the linenoise history. 1283 - * It uses a fixed array of char pointers that are shifted (memmoved) 1284 - * when the history max length is reached in order to remove the older 1285 - * entry and make room for the new one, so it is not exactly suitable for huge 1286 - * histories, but will work well for a few hundred of entries. 1287 - * 1288 - * Using a circular buffer is smarter, but a bit more complex to handle. */ 1289 - int linenoiseHistoryAdd(const char *line) { 1290 - char *linecopy; 1291 - 1292 - if (history_max_len == 0) return 0; 1293 - 1294 - /* Initialization on first call. */ 1295 - if (history == NULL) { 1296 - history = malloc(sizeof(char*)*history_max_len); 1297 - if (history == NULL) return 0; 1298 - memset(history,0,(sizeof(char*)*history_max_len)); 1299 - } 1300 - 1301 - /* Don't add duplicated lines. */ 1302 - if (history_len && !strcmp(history[history_len-1], line)) return 0; 1303 - 1304 - /* Add an heap allocated copy of the line in the history. 1305 - * If we reached the max length, remove the older line. */ 1306 - linecopy = strdup(line); 1307 - if (!linecopy) return 0; 1308 - if (history_len == history_max_len) { 1309 - free(history[0]); 1310 - memmove(history,history+1,sizeof(char*)*(history_max_len-1)); 1311 - history_len--; 1312 - } 1313 - history[history_len] = linecopy; 1314 - history_len++; 1315 - return 1; 1316 - } 1317 - 1318 - /* Set the maximum length for the history. This function can be called even 1319 - * if there is already some history, the function will make sure to retain 1320 - * just the latest 'len' elements if the new history length value is smaller 1321 - * than the amount of items already inside the history. */ 1322 - int linenoiseHistorySetMaxLen(int len) { 1323 - char **new; 1324 - 1325 - if (len < 1) return 0; 1326 - if (history) { 1327 - int tocopy = history_len; 1328 - 1329 - new = malloc(sizeof(char*)*len); 1330 - if (new == NULL) return 0; 1331 - 1332 - /* If we can't copy everything, free the elements we'll not use. */ 1333 - if (len < tocopy) { 1334 - int j; 1335 - 1336 - for (j = 0; j < tocopy-len; j++) free(history[j]); 1337 - tocopy = len; 1338 - } 1339 - memset(new,0,sizeof(char*)*len); 1340 - memcpy(new,history+(history_len-tocopy), sizeof(char*)*tocopy); 1341 - free(history); 1342 - history = new; 1343 - } 1344 - history_max_len = len; 1345 - if (history_len > history_max_len) 1346 - history_len = history_max_len; 1347 - return 1; 1348 - } 1349 - 1350 - /* Save the history in the specified file. On success 0 is returned 1351 - * otherwise -1 is returned. */ 1352 - int linenoiseHistorySave(const char *filename) { 1353 - mode_t old_umask = umask(S_IXUSR|S_IRWXG|S_IRWXO); 1354 - FILE *fp; 1355 - int j; 1356 - 1357 - fp = fopen(filename,"w"); 1358 - umask(old_umask); 1359 - if (fp == NULL) return -1; 1360 - chmod(filename,S_IRUSR|S_IWUSR); 1361 - for (j = 0; j < history_len; j++) 1362 - fprintf(fp,"%s\n",history[j]); 1363 - fclose(fp); 1364 - return 0; 1365 - } 1366 - 1367 - /* Load the history from the specified file. If the file does not exist 1368 - * zero is returned and no operation is performed. 1369 - * 1370 - * If the file exists and the operation succeeded 0 is returned, otherwise 1371 - * on error -1 is returned. */ 1372 - int linenoiseHistoryLoad(const char *filename) { 1373 - FILE *fp = fopen(filename,"r"); 1374 - char buf[LINENOISE_MAX_LINE]; 1375 - 1376 - if (fp == NULL) return -1; 1377 - 1378 - while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) { 1379 - char *p; 1380 - 1381 - p = strchr(buf,'\r'); 1382 - if (!p) p = strchr(buf,'\n'); 1383 - if (p) *p = '\0'; 1384 - linenoiseHistoryAdd(buf); 1385 - } 1386 - fclose(fp); 1387 - return 0; 1388 - }
-75
vendor/ocaml-linenoise/src/linenoise_src.h
··· 1 - /* linenoise.h -- VERSION 1.0 2 - * 3 - * Guerrilla line editing library against the idea that a line editing lib 4 - * needs to be 20,000 lines of C code. 5 - * 6 - * See linenoise.c for more information. 7 - * 8 - * ------------------------------------------------------------------------ 9 - * 10 - * Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com> 11 - * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com> 12 - * 13 - * All rights reserved. 14 - * 15 - * Redistribution and use in source and binary forms, with or without 16 - * modification, are permitted provided that the following conditions are 17 - * met: 18 - * 19 - * * Redistributions of source code must retain the above copyright 20 - * notice, this list of conditions and the following disclaimer. 21 - * 22 - * * Redistributions in binary form must reproduce the above copyright 23 - * notice, this list of conditions and the following disclaimer in the 24 - * documentation and/or other materials provided with the distribution. 25 - * 26 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 - */ 38 - 39 - #ifndef __LINENOISE_H 40 - #define __LINENOISE_H 41 - 42 - #ifdef __cplusplus 43 - extern "C" { 44 - #endif 45 - 46 - extern int linenoiseWasInterrupted; /* boolean signalling if last call was ctrl-c */ 47 - 48 - typedef struct linenoiseCompletions { 49 - size_t len; 50 - char **cvec; 51 - } linenoiseCompletions; 52 - 53 - typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); 54 - typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold); 55 - typedef void(linenoiseFreeHintsCallback)(void *); 56 - void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); 57 - void linenoiseSetHintsCallback(linenoiseHintsCallback *); 58 - void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *); 59 - void linenoiseAddCompletion(linenoiseCompletions *, const char *); 60 - 61 - char *linenoise(const char *prompt); 62 - void linenoiseFree(void *ptr); 63 - int linenoiseHistoryAdd(const char *line); 64 - int linenoiseHistorySetMaxLen(int len); 65 - int linenoiseHistorySave(const char *filename); 66 - int linenoiseHistoryLoad(const char *filename); 67 - void linenoiseClearScreen(void); 68 - void linenoiseSetMultiLine(int ml); 69 - void linenoisePrintKeyCodes(void); 70 - 71 - #ifdef __cplusplus 72 - } 73 - #endif 74 - 75 - #endif /* __LINENOISE_H */
-183
vendor/ocaml-linenoise/src/linenoise_stubs.c
··· 1 - // OCaml declarations 2 - #include <caml/alloc.h> 3 - #include <caml/memory.h> 4 - #include <caml/callback.h> 5 - #include <caml/fail.h> 6 - #include <caml/threads.h> 7 - 8 - #include <errno.h> 9 - #include <assert.h> 10 - 11 - #include "linenoise_src.h" 12 - 13 - // Ripped from ctypes 14 - #define Val_none Val_int(0) 15 - #define Some_val(v) Field(v, 0) 16 - 17 - static value Val_some(value v) 18 - { 19 - CAMLparam1(v); 20 - CAMLlocal1(some); 21 - some = caml_alloc(1, 0); 22 - Store_field(some, 0, v); 23 - CAMLreturn(some); 24 - } 25 - 26 - /* if true, raise Sys.Break on ctrl-c */ 27 - static int raise_sys_break = 0; 28 - 29 - CAMLprim value ml_catch_break(value flag) 30 - { 31 - CAMLparam1(flag); 32 - raise_sys_break = Bool_val(flag); 33 - CAMLreturn(Val_unit); 34 - } 35 - 36 - CAMLprim value ml_add_completion(value completions, value new_completion) 37 - { 38 - CAMLparam2(completions, new_completion); 39 - char* c_new_completion = caml_stat_strdup(String_val(new_completion)); 40 - linenoiseAddCompletion((linenoiseCompletions *)completions, c_new_completion); 41 - caml_stat_free(c_new_completion); 42 - CAMLreturn(Val_unit); 43 - } 44 - 45 - // this bridge runs with the runtime lock acquired 46 - static void completion_bridge_inner(const char *buf, linenoiseCompletions *lc) 47 - { 48 - CAMLparam0(); 49 - CAMLlocal1(str_copy); 50 - str_copy = caml_copy_string(buf); 51 - caml_callback2(*caml_named_value("lnoise_completion_cb"), str_copy, (value)lc); 52 - CAMLreturn0; 53 - } 54 - 55 - static void completion_bridge(const char *buf, linenoiseCompletions *lc) 56 - { 57 - caml_acquire_runtime_system(); 58 - completion_bridge_inner(buf, lc); 59 - caml_release_runtime_system(); 60 - } 61 - 62 - static char *hints_bridge_inner(const char *buf, int *color, int *bold) 63 - { 64 - CAMLparam0(); 65 - CAMLlocal2(str_copy, cb_result); 66 - 67 - str_copy = caml_copy_string(buf); 68 - 69 - cb_result = caml_callback(*caml_named_value("lnoise_hints_cb"), str_copy); 70 - if (cb_result == Val_none) { 71 - CAMLreturnT(char *,NULL); 72 - } else { 73 - char* msg = caml_stat_strdup(String_val(Field(Field(cb_result, 0), 0))); 74 - *color = Int_val(Field(Field(cb_result, 0), 1)) + 31; 75 - *bold = Bool_val(Field(Field(cb_result, 0), 2)); 76 - CAMLreturnT(char *,msg); 77 - } 78 - } 79 - 80 - static char *hints_bridge(const char *buf, int *color, int *bold) 81 - { 82 - caml_acquire_runtime_system(); 83 - char* res = hints_bridge_inner(buf, color, bold); 84 - caml_release_runtime_system(); 85 - return res; 86 - } 87 - 88 - 89 - static void free_hints_bridge(void* data) { 90 - caml_acquire_runtime_system(); 91 - caml_stat_free(data); 92 - caml_release_runtime_system(); 93 - } 94 - 95 - __attribute__((constructor)) 96 - void set_free_hints(void) { linenoiseSetFreeHintsCallback(free); } 97 - 98 - CAMLprim value ml_setup_bridges(value unit) { 99 - CAMLparam1(unit); 100 - linenoiseSetCompletionCallback(completion_bridge); 101 - linenoiseSetHintsCallback(hints_bridge); 102 - linenoiseSetFreeHintsCallback(free_hints_bridge); 103 - CAMLreturn(Val_unit); 104 - } 105 - 106 - CAMLprim value ml_linenoise(value prompt) 107 - { 108 - CAMLparam1(prompt); 109 - CAMLlocal1(lnoise_result); 110 - 111 - linenoiseWasInterrupted = 0; // reset 112 - char* c_prompt = caml_stat_strdup(String_val(prompt)); 113 - 114 - caml_release_runtime_system(); 115 - const char *result = linenoise(c_prompt); 116 - caml_acquire_runtime_system(); 117 - 118 - caml_stat_free(c_prompt); 119 - if (!result) { 120 - if (linenoiseWasInterrupted && raise_sys_break) { 121 - caml_raise_constant(*caml_named_value("sys_break")); 122 - } else { 123 - CAMLreturn(Val_none); 124 - } 125 - } 126 - lnoise_result = caml_copy_string(result); 127 - linenoiseFree((void*)result); 128 - CAMLreturn(Val_some(lnoise_result)); 129 - } 130 - 131 - CAMLprim value ml_history_add(value line) 132 - { 133 - CAMLparam1(line); 134 - char* c_line = caml_stat_strdup(String_val(line)); 135 - int res = linenoiseHistoryAdd(c_line); 136 - caml_stat_free(c_line); 137 - CAMLreturn(Val_int(res)); 138 - } 139 - 140 - CAMLprim value ml_history_set_maxlen(value max) 141 - { 142 - CAMLparam1(max); 143 - CAMLreturn(Val_int(linenoiseHistorySetMaxLen(Int_val(max)))); 144 - } 145 - 146 - CAMLprim value ml_history_save(value filename) 147 - { 148 - CAMLparam1(filename); 149 - char* c_filename = caml_stat_strdup(String_val(filename)); 150 - int res = linenoiseHistorySave(c_filename); 151 - caml_stat_free(c_filename); 152 - CAMLreturn(Val_int(res)); 153 - } 154 - 155 - CAMLprim value ml_history_load(value filename) 156 - { 157 - CAMLparam1(filename); 158 - char* c_filename= caml_stat_strdup(String_val(filename)); 159 - int res = linenoiseHistoryLoad(c_filename); 160 - caml_stat_free(c_filename); 161 - CAMLreturn(Val_int(res)); 162 - } 163 - 164 - CAMLprim value ml_clearscreen(__attribute__((unused))value unit) 165 - { 166 - CAMLparam0(); 167 - linenoiseClearScreen(); 168 - CAMLreturn(Val_unit); 169 - } 170 - 171 - CAMLprim value ml_set_multiline(value use_multiline) 172 - { 173 - CAMLparam1(use_multiline); 174 - linenoiseSetMultiLine(Bool_val(use_multiline)); 175 - CAMLreturn(Val_unit); 176 - } 177 - 178 - CAMLprim value ml_printkeycodes(void) 179 - { 180 - CAMLparam0(); 181 - linenoisePrintKeyCodes(); 182 - CAMLreturn(Val_unit); 183 - }
-473
vendor/ocaml-linenoise/src/utf8.c
··· 1 - /* encoding/utf8.c -- VERSION 1.0 2 - * 3 - * Guerrilla line editing library against the idea that a line editing lib 4 - * needs to be 20,000 lines of C code. 5 - * 6 - * You can find the latest source code at: 7 - * 8 - * http://github.com/antirez/linenoise 9 - * 10 - * Does a number of crazy assumptions that happen to be true in 99.9999% of 11 - * the 2010 UNIX computers around. 12 - * 13 - * ------------------------------------------------------------------------ 14 - * 15 - * Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com> 16 - * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com> 17 - * 18 - * All rights reserved. 19 - * 20 - * Redistribution and use in source and binary forms, with or without 21 - * modification, are permitted provided that the following conditions are 22 - * met: 23 - * 24 - * * Redistributions of source code must retain the above copyright 25 - * notice, this list of conditions and the following disclaimer. 26 - * 27 - * * Redistributions in binary form must reproduce the above copyright 28 - * notice, this list of conditions and the following disclaimer in the 29 - * documentation and/or other materials provided with the distribution. 30 - * 31 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 37 - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 38 - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 39 - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 41 - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 - */ 43 - 44 - #include <unistd.h> 45 - #include <stdio.h> 46 - 47 - #define UNUSED(x) (void)(x) 48 - 49 - /* ============================ UTF8 utilities ============================== */ 50 - 51 - static unsigned long wideCharTable[][2] = { 52 - { 0x1100, 0x115F }, { 0x231A, 0x231B }, { 0x2329, 0x232A }, { 0x23E9, 0x23EC }, 53 - { 0x23F0, 0x23F0 }, { 0x23F3, 0x23F3 }, { 0x25FD, 0x25FE }, { 0x2614, 0x2615 }, 54 - { 0x2630, 0x2637 }, { 0x2648, 0x2653 }, { 0x267F, 0x267F }, { 0x268A, 0x268F }, 55 - { 0x2693, 0x2693 }, { 0x26A1, 0x26A1 }, { 0x26AA, 0x26AB }, { 0x26BD, 0x26BE }, 56 - { 0x26C4, 0x26C5 }, { 0x26CE, 0x26CE }, { 0x26D4, 0x26D4 }, { 0x26EA, 0x26EA }, 57 - { 0x26F2, 0x26F3 }, { 0x26F5, 0x26F5 }, { 0x26FA, 0x26FA }, { 0x26FD, 0x26FD }, 58 - { 0x2705, 0x2705 }, { 0x270A, 0x270B }, { 0x2728, 0x2728 }, { 0x274C, 0x274C }, 59 - { 0x274E, 0x274E }, { 0x2753, 0x2755 }, { 0x2757, 0x2757 }, { 0x2795, 0x2797 }, 60 - { 0x27B0, 0x27B0 }, { 0x27BF, 0x27BF }, { 0x2B1B, 0x2B1C }, { 0x2B50, 0x2B50 }, 61 - { 0x2B55, 0x2B55 }, { 0x2E80, 0x2E99 }, { 0x2E9B, 0x2EF3 }, { 0x2F00, 0x2FD5 }, 62 - { 0x2FF0, 0x303E }, { 0x3041, 0x3096 }, { 0x3099, 0x30FF }, { 0x3105, 0x312F }, 63 - { 0x3131, 0x318E }, { 0x3190, 0x31E5 }, { 0x31EF, 0x321E }, { 0x3220, 0x3247 }, 64 - { 0x3250, 0xA48C }, { 0xA490, 0xA4C6 }, { 0xA960, 0xA97C }, { 0xAC00, 0xD7A3 }, 65 - { 0xF900, 0xFAFF }, { 0xFE10, 0xFE19 }, { 0xFE30, 0xFE52 }, { 0xFE54, 0xFE66 }, 66 - { 0xFE68, 0xFE6B }, { 0xFF01, 0xFF60 }, { 0xFFE0, 0xFFE6 }, { 0x16FE0, 0x16FE4 }, 67 - { 0x16FF0, 0x16FF1 }, { 0x17000, 0x187F7 }, { 0x18800, 0x18CD5 }, { 0x18CFF, 0x18D08 }, 68 - { 0x1AFF0, 0x1AFF3 }, { 0x1AFF5, 0x1AFFB }, { 0x1AFFD, 0x1AFFE }, { 0x1B000, 0x1B122 }, 69 - { 0x1B132, 0x1B132 }, { 0x1B150, 0x1B152 }, { 0x1B155, 0x1B155 }, { 0x1B164, 0x1B167 }, 70 - { 0x1B170, 0x1B2FB }, { 0x1D300, 0x1D356 }, { 0x1D360, 0x1D376 }, { 0x1F004, 0x1F004 }, 71 - { 0x1F0CF, 0x1F0CF }, { 0x1F18E, 0x1F18E }, { 0x1F191, 0x1F19A }, { 0x1F200, 0x1F202 }, 72 - { 0x1F210, 0x1F23B }, { 0x1F240, 0x1F248 }, { 0x1F250, 0x1F251 }, { 0x1F260, 0x1F265 }, 73 - { 0x1F300, 0x1F320 }, { 0x1F32D, 0x1F335 }, { 0x1F337, 0x1F37C }, { 0x1F37E, 0x1F393 }, 74 - { 0x1F3A0, 0x1F3CA }, { 0x1F3CF, 0x1F3D3 }, { 0x1F3E0, 0x1F3F0 }, { 0x1F3F4, 0x1F3F4 }, 75 - { 0x1F3F8, 0x1F43E }, { 0x1F440, 0x1F440 }, { 0x1F442, 0x1F4FC }, { 0x1F4FF, 0x1F53D }, 76 - { 0x1F54B, 0x1F54E }, { 0x1F550, 0x1F567 }, { 0x1F57A, 0x1F57A }, { 0x1F595, 0x1F596 }, 77 - { 0x1F5A4, 0x1F5A4 }, { 0x1F5FB, 0x1F64F }, { 0x1F680, 0x1F6C5 }, { 0x1F6CC, 0x1F6CC }, 78 - { 0x1F6D0, 0x1F6D2 }, { 0x1F6D5, 0x1F6D7 }, { 0x1F6DC, 0x1F6DF }, { 0x1F6EB, 0x1F6EC }, 79 - { 0x1F6F4, 0x1F6FC }, { 0x1F7E0, 0x1F7EB }, { 0x1F7F0, 0x1F7F0 }, { 0x1F90C, 0x1F93A }, 80 - { 0x1F93C, 0x1F945 }, { 0x1F947, 0x1F9FF }, { 0x1FA70, 0x1FA7C }, { 0x1FA80, 0x1FA89 }, 81 - { 0x1FA8F, 0x1FAC6 }, { 0x1FACE, 0x1FADC }, { 0x1FADF, 0x1FAE9 }, { 0x1FAF0, 0x1FAF8 }, 82 - { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }, 83 - }; 84 - 85 - static size_t wideCharTableSize = sizeof(wideCharTable) / sizeof(wideCharTable[0]); 86 - 87 - static unsigned long combiningCharTable[] = { 88 - 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 89 - 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F, 90 - 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, 91 - 0x0318, 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, 92 - 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, 93 - 0x0328, 0x0329, 0x032A, 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, 94 - 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, 95 - 0x0338, 0x0339, 0x033A, 0x033B, 0x033C, 0x033D, 0x033E, 0x033F, 96 - 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345, 0x0346, 0x0347, 97 - 0x0348, 0x0349, 0x034A, 0x034B, 0x034C, 0x034D, 0x034E, 0x034F, 98 - 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, 99 - 0x0358, 0x0359, 0x035A, 0x035B, 0x035C, 0x035D, 0x035E, 0x035F, 100 - 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, 101 - 0x0368, 0x0369, 0x036A, 0x036B, 0x036C, 0x036D, 0x036E, 0x036F, 102 - 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0591, 0x0592, 0x0593, 103 - 0x0594, 0x0595, 0x0596, 0x0597, 0x0598, 0x0599, 0x059A, 0x059B, 104 - 0x059C, 0x059D, 0x059E, 0x059F, 0x05A0, 0x05A1, 0x05A2, 0x05A3, 105 - 0x05A4, 0x05A5, 0x05A6, 0x05A7, 0x05A8, 0x05A9, 0x05AA, 0x05AB, 106 - 0x05AC, 0x05AD, 0x05AE, 0x05AF, 0x05B0, 0x05B1, 0x05B2, 0x05B3, 107 - 0x05B4, 0x05B5, 0x05B6, 0x05B7, 0x05B8, 0x05B9, 0x05BA, 0x05BB, 108 - 0x05BC, 0x05BD, 0x05BF, 0x05C1, 0x05C2, 0x05C4, 0x05C5, 0x05C7, 109 - 0x0610, 0x0611, 0x0612, 0x0613, 0x0614, 0x0615, 0x0616, 0x0617, 110 - 0x0618, 0x0619, 0x061A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 111 - 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0656, 0x0657, 112 - 0x0658, 0x0659, 0x065A, 0x065B, 0x065C, 0x065D, 0x065E, 0x065F, 113 - 0x0670, 0x06D6, 0x06D7, 0x06D8, 0x06D9, 0x06DA, 0x06DB, 0x06DC, 114 - 0x06DF, 0x06E0, 0x06E1, 0x06E2, 0x06E3, 0x06E4, 0x06E7, 0x06E8, 115 - 0x06EA, 0x06EB, 0x06EC, 0x06ED, 0x0711, 0x0730, 0x0731, 0x0732, 116 - 0x0733, 0x0734, 0x0735, 0x0736, 0x0737, 0x0738, 0x0739, 0x073A, 117 - 0x073B, 0x073C, 0x073D, 0x073E, 0x073F, 0x0740, 0x0741, 0x0742, 118 - 0x0743, 0x0744, 0x0745, 0x0746, 0x0747, 0x0748, 0x0749, 0x074A, 119 - 0x07A6, 0x07A7, 0x07A8, 0x07A9, 0x07AA, 0x07AB, 0x07AC, 0x07AD, 120 - 0x07AE, 0x07AF, 0x07B0, 0x07EB, 0x07EC, 0x07ED, 0x07EE, 0x07EF, 121 - 0x07F0, 0x07F1, 0x07F2, 0x07F3, 0x07FD, 0x0816, 0x0817, 0x0818, 122 - 0x0819, 0x081B, 0x081C, 0x081D, 0x081E, 0x081F, 0x0820, 0x0821, 123 - 0x0822, 0x0823, 0x0825, 0x0826, 0x0827, 0x0829, 0x082A, 0x082B, 124 - 0x082C, 0x082D, 0x0859, 0x085A, 0x085B, 0x0897, 0x0898, 0x0899, 125 - 0x089A, 0x089B, 0x089C, 0x089D, 0x089E, 0x089F, 0x08CA, 0x08CB, 126 - 0x08CC, 0x08CD, 0x08CE, 0x08CF, 0x08D0, 0x08D1, 0x08D2, 0x08D3, 127 - 0x08D4, 0x08D5, 0x08D6, 0x08D7, 0x08D8, 0x08D9, 0x08DA, 0x08DB, 128 - 0x08DC, 0x08DD, 0x08DE, 0x08DF, 0x08E0, 0x08E1, 0x08E3, 0x08E4, 129 - 0x08E5, 0x08E6, 0x08E7, 0x08E8, 0x08E9, 0x08EA, 0x08EB, 0x08EC, 130 - 0x08ED, 0x08EE, 0x08EF, 0x08F0, 0x08F1, 0x08F2, 0x08F3, 0x08F4, 131 - 0x08F5, 0x08F6, 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, 0x08FC, 132 - 0x08FD, 0x08FE, 0x08FF, 0x0900, 0x0901, 0x0902, 0x093A, 0x093C, 133 - 0x0941, 0x0942, 0x0943, 0x0944, 0x0945, 0x0946, 0x0947, 0x0948, 134 - 0x094D, 0x0951, 0x0952, 0x0953, 0x0954, 0x0955, 0x0956, 0x0957, 135 - 0x0962, 0x0963, 0x0981, 0x09BC, 0x09C1, 0x09C2, 0x09C3, 0x09C4, 136 - 0x09CD, 0x09E2, 0x09E3, 0x09FE, 0x0A01, 0x0A02, 0x0A3C, 0x0A41, 137 - 0x0A42, 0x0A47, 0x0A48, 0x0A4B, 0x0A4C, 0x0A4D, 0x0A51, 0x0A70, 138 - 0x0A71, 0x0A75, 0x0A81, 0x0A82, 0x0ABC, 0x0AC1, 0x0AC2, 0x0AC3, 139 - 0x0AC4, 0x0AC5, 0x0AC7, 0x0AC8, 0x0ACD, 0x0AE2, 0x0AE3, 0x0AFA, 140 - 0x0AFB, 0x0AFC, 0x0AFD, 0x0AFE, 0x0AFF, 0x0B01, 0x0B3C, 0x0B3F, 141 - 0x0B41, 0x0B42, 0x0B43, 0x0B44, 0x0B4D, 0x0B55, 0x0B56, 0x0B62, 142 - 0x0B63, 0x0B82, 0x0BC0, 0x0BCD, 0x0C00, 0x0C04, 0x0C3C, 0x0C3E, 143 - 0x0C3F, 0x0C40, 0x0C46, 0x0C47, 0x0C48, 0x0C4A, 0x0C4B, 0x0C4C, 144 - 0x0C4D, 0x0C55, 0x0C56, 0x0C62, 0x0C63, 0x0C81, 0x0CBC, 0x0CBF, 145 - 0x0CC6, 0x0CCC, 0x0CCD, 0x0CE2, 0x0CE3, 0x0D00, 0x0D01, 0x0D3B, 146 - 0x0D3C, 0x0D41, 0x0D42, 0x0D43, 0x0D44, 0x0D4D, 0x0D62, 0x0D63, 147 - 0x0D81, 0x0DCA, 0x0DD2, 0x0DD3, 0x0DD4, 0x0DD6, 0x0E31, 0x0E34, 148 - 0x0E35, 0x0E36, 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0x0E47, 0x0E48, 149 - 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0EB1, 0x0EB4, 150 - 0x0EB5, 0x0EB6, 0x0EB7, 0x0EB8, 0x0EB9, 0x0EBA, 0x0EBB, 0x0EBC, 151 - 0x0EC8, 0x0EC9, 0x0ECA, 0x0ECB, 0x0ECC, 0x0ECD, 0x0ECE, 0x0F18, 152 - 0x0F19, 0x0F35, 0x0F37, 0x0F39, 0x0F71, 0x0F72, 0x0F73, 0x0F74, 153 - 0x0F75, 0x0F76, 0x0F77, 0x0F78, 0x0F79, 0x0F7A, 0x0F7B, 0x0F7C, 154 - 0x0F7D, 0x0F7E, 0x0F80, 0x0F81, 0x0F82, 0x0F83, 0x0F84, 0x0F86, 155 - 0x0F87, 0x0F8D, 0x0F8E, 0x0F8F, 0x0F90, 0x0F91, 0x0F92, 0x0F93, 156 - 0x0F94, 0x0F95, 0x0F96, 0x0F97, 0x0F99, 0x0F9A, 0x0F9B, 0x0F9C, 157 - 0x0F9D, 0x0F9E, 0x0F9F, 0x0FA0, 0x0FA1, 0x0FA2, 0x0FA3, 0x0FA4, 158 - 0x0FA5, 0x0FA6, 0x0FA7, 0x0FA8, 0x0FA9, 0x0FAA, 0x0FAB, 0x0FAC, 159 - 0x0FAD, 0x0FAE, 0x0FAF, 0x0FB0, 0x0FB1, 0x0FB2, 0x0FB3, 0x0FB4, 160 - 0x0FB5, 0x0FB6, 0x0FB7, 0x0FB8, 0x0FB9, 0x0FBA, 0x0FBB, 0x0FBC, 161 - 0x0FC6, 0x102D, 0x102E, 0x102F, 0x1030, 0x1032, 0x1033, 0x1034, 162 - 0x1035, 0x1036, 0x1037, 0x1039, 0x103A, 0x103D, 0x103E, 0x1058, 163 - 0x1059, 0x105E, 0x105F, 0x1060, 0x1071, 0x1072, 0x1073, 0x1074, 164 - 0x1082, 0x1085, 0x1086, 0x108D, 0x109D, 0x135D, 0x135E, 0x135F, 165 - 0x1712, 0x1713, 0x1714, 0x1732, 0x1733, 0x1752, 0x1753, 0x1772, 166 - 0x1773, 0x17B4, 0x17B5, 0x17B7, 0x17B8, 0x17B9, 0x17BA, 0x17BB, 167 - 0x17BC, 0x17BD, 0x17C6, 0x17C9, 0x17CA, 0x17CB, 0x17CC, 0x17CD, 168 - 0x17CE, 0x17CF, 0x17D0, 0x17D1, 0x17D2, 0x17D3, 0x17DD, 0x180B, 169 - 0x180C, 0x180D, 0x180F, 0x1885, 0x1886, 0x18A9, 0x1920, 0x1921, 170 - 0x1922, 0x1927, 0x1928, 0x1932, 0x1939, 0x193A, 0x193B, 0x1A17, 171 - 0x1A18, 0x1A1B, 0x1A56, 0x1A58, 0x1A59, 0x1A5A, 0x1A5B, 0x1A5C, 172 - 0x1A5D, 0x1A5E, 0x1A60, 0x1A62, 0x1A65, 0x1A66, 0x1A67, 0x1A68, 173 - 0x1A69, 0x1A6A, 0x1A6B, 0x1A6C, 0x1A73, 0x1A74, 0x1A75, 0x1A76, 174 - 0x1A77, 0x1A78, 0x1A79, 0x1A7A, 0x1A7B, 0x1A7C, 0x1A7F, 0x1AB0, 175 - 0x1AB1, 0x1AB2, 0x1AB3, 0x1AB4, 0x1AB5, 0x1AB6, 0x1AB7, 0x1AB8, 176 - 0x1AB9, 0x1ABA, 0x1ABB, 0x1ABC, 0x1ABD, 0x1ABF, 0x1AC0, 0x1AC1, 177 - 0x1AC2, 0x1AC3, 0x1AC4, 0x1AC5, 0x1AC6, 0x1AC7, 0x1AC8, 0x1AC9, 178 - 0x1ACA, 0x1ACB, 0x1ACC, 0x1ACD, 0x1ACE, 0x1B00, 0x1B01, 0x1B02, 179 - 0x1B03, 0x1B34, 0x1B36, 0x1B37, 0x1B38, 0x1B39, 0x1B3A, 0x1B3C, 180 - 0x1B42, 0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 181 - 0x1B72, 0x1B73, 0x1B80, 0x1B81, 0x1BA2, 0x1BA3, 0x1BA4, 0x1BA5, 182 - 0x1BA8, 0x1BA9, 0x1BAB, 0x1BAC, 0x1BAD, 0x1BE6, 0x1BE8, 0x1BE9, 183 - 0x1BED, 0x1BEF, 0x1BF0, 0x1BF1, 0x1C2C, 0x1C2D, 0x1C2E, 0x1C2F, 184 - 0x1C30, 0x1C31, 0x1C32, 0x1C33, 0x1C36, 0x1C37, 0x1CD0, 0x1CD1, 185 - 0x1CD2, 0x1CD4, 0x1CD5, 0x1CD6, 0x1CD7, 0x1CD8, 0x1CD9, 0x1CDA, 186 - 0x1CDB, 0x1CDC, 0x1CDD, 0x1CDE, 0x1CDF, 0x1CE0, 0x1CE2, 0x1CE3, 187 - 0x1CE4, 0x1CE5, 0x1CE6, 0x1CE7, 0x1CE8, 0x1CED, 0x1CF4, 0x1CF8, 188 - 0x1CF9, 0x1DC0, 0x1DC1, 0x1DC2, 0x1DC3, 0x1DC4, 0x1DC5, 0x1DC6, 189 - 0x1DC7, 0x1DC8, 0x1DC9, 0x1DCA, 0x1DCB, 0x1DCC, 0x1DCD, 0x1DCE, 190 - 0x1DCF, 0x1DD0, 0x1DD1, 0x1DD2, 0x1DD3, 0x1DD4, 0x1DD5, 0x1DD6, 191 - 0x1DD7, 0x1DD8, 0x1DD9, 0x1DDA, 0x1DDB, 0x1DDC, 0x1DDD, 0x1DDE, 192 - 0x1DDF, 0x1DE0, 0x1DE1, 0x1DE2, 0x1DE3, 0x1DE4, 0x1DE5, 0x1DE6, 193 - 0x1DE7, 0x1DE8, 0x1DE9, 0x1DEA, 0x1DEB, 0x1DEC, 0x1DED, 0x1DEE, 194 - 0x1DEF, 0x1DF0, 0x1DF1, 0x1DF2, 0x1DF3, 0x1DF4, 0x1DF5, 0x1DF6, 195 - 0x1DF7, 0x1DF8, 0x1DF9, 0x1DFA, 0x1DFB, 0x1DFC, 0x1DFD, 0x1DFE, 196 - 0x1DFF, 0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 197 - 0x20D7, 0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20E1, 0x20E5, 198 - 0x20E6, 0x20E7, 0x20E8, 0x20E9, 0x20EA, 0x20EB, 0x20EC, 0x20ED, 199 - 0x20EE, 0x20EF, 0x20F0, 0x2CEF, 0x2CF0, 0x2CF1, 0x2D7F, 0x2DE0, 200 - 0x2DE1, 0x2DE2, 0x2DE3, 0x2DE4, 0x2DE5, 0x2DE6, 0x2DE7, 0x2DE8, 201 - 0x2DE9, 0x2DEA, 0x2DEB, 0x2DEC, 0x2DED, 0x2DEE, 0x2DEF, 0x2DF0, 202 - 0x2DF1, 0x2DF2, 0x2DF3, 0x2DF4, 0x2DF5, 0x2DF6, 0x2DF7, 0x2DF8, 203 - 0x2DF9, 0x2DFA, 0x2DFB, 0x2DFC, 0x2DFD, 0x2DFE, 0x2DFF, 0x302A, 204 - 0x302B, 0x302C, 0x302D, 0x3099, 0x309A, 0xA66F, 0xA674, 0xA675, 205 - 0xA676, 0xA677, 0xA678, 0xA679, 0xA67A, 0xA67B, 0xA67C, 0xA67D, 206 - 0xA69E, 0xA69F, 0xA6F0, 0xA6F1, 0xA802, 0xA806, 0xA80B, 0xA825, 207 - 0xA826, 0xA82C, 0xA8C4, 0xA8C5, 0xA8E0, 0xA8E1, 0xA8E2, 0xA8E3, 208 - 0xA8E4, 0xA8E5, 0xA8E6, 0xA8E7, 0xA8E8, 0xA8E9, 0xA8EA, 0xA8EB, 209 - 0xA8EC, 0xA8ED, 0xA8EE, 0xA8EF, 0xA8F0, 0xA8F1, 0xA8FF, 0xA926, 210 - 0xA927, 0xA928, 0xA929, 0xA92A, 0xA92B, 0xA92C, 0xA92D, 0xA947, 211 - 0xA948, 0xA949, 0xA94A, 0xA94B, 0xA94C, 0xA94D, 0xA94E, 0xA94F, 212 - 0xA950, 0xA951, 0xA980, 0xA981, 0xA982, 0xA9B3, 0xA9B6, 0xA9B7, 213 - 0xA9B8, 0xA9B9, 0xA9BC, 0xA9BD, 0xA9E5, 0xAA29, 0xAA2A, 0xAA2B, 214 - 0xAA2C, 0xAA2D, 0xAA2E, 0xAA31, 0xAA32, 0xAA35, 0xAA36, 0xAA43, 215 - 0xAA4C, 0xAA7C, 0xAAB0, 0xAAB2, 0xAAB3, 0xAAB4, 0xAAB7, 0xAAB8, 216 - 0xAABE, 0xAABF, 0xAAC1, 0xAAEC, 0xAAED, 0xAAF6, 0xABE5, 0xABE8, 217 - 0xABED, 0xFB1E, 0xFE00, 0xFE01, 0xFE02, 0xFE03, 0xFE04, 0xFE05, 218 - 0xFE06, 0xFE07, 0xFE08, 0xFE09, 0xFE0A, 0xFE0B, 0xFE0C, 0xFE0D, 219 - 0xFE0E, 0xFE0F, 0xFE20, 0xFE21, 0xFE22, 0xFE23, 0xFE24, 0xFE25, 220 - 0xFE26, 0xFE27, 0xFE28, 0xFE29, 0xFE2A, 0xFE2B, 0xFE2C, 0xFE2D, 221 - 0xFE2E, 0xFE2F, 0x101FD, 0x102E0, 0x10376, 0x10377, 0x10378, 0x10379, 222 - 0x1037A, 0x10A01, 0x10A02, 0x10A03, 0x10A05, 0x10A06, 0x10A0C, 0x10A0D, 223 - 0x10A0E, 0x10A0F, 0x10A38, 0x10A39, 0x10A3A, 0x10A3F, 0x10AE5, 0x10AE6, 224 - 0x10D24, 0x10D25, 0x10D26, 0x10D27, 0x10D69, 0x10D6A, 0x10D6B, 0x10D6C, 225 - 0x10D6D, 0x10EAB, 0x10EAC, 0x10EFC, 0x10EFD, 0x10EFE, 0x10EFF, 0x10F46, 226 - 0x10F47, 0x10F48, 0x10F49, 0x10F4A, 0x10F4B, 0x10F4C, 0x10F4D, 0x10F4E, 227 - 0x10F4F, 0x10F50, 0x10F82, 0x10F83, 0x10F84, 0x10F85, 0x11001, 0x11038, 228 - 0x11039, 0x1103A, 0x1103B, 0x1103C, 0x1103D, 0x1103E, 0x1103F, 0x11040, 229 - 0x11041, 0x11042, 0x11043, 0x11044, 0x11045, 0x11046, 0x11070, 0x11073, 230 - 0x11074, 0x1107F, 0x11080, 0x11081, 0x110B3, 0x110B4, 0x110B5, 0x110B6, 231 - 0x110B9, 0x110BA, 0x110C2, 0x11100, 0x11101, 0x11102, 0x11127, 0x11128, 232 - 0x11129, 0x1112A, 0x1112B, 0x1112D, 0x1112E, 0x1112F, 0x11130, 0x11131, 233 - 0x11132, 0x11133, 0x11134, 0x11173, 0x11180, 0x11181, 0x111B6, 0x111B7, 234 - 0x111B8, 0x111B9, 0x111BA, 0x111BB, 0x111BC, 0x111BD, 0x111BE, 0x111C9, 235 - 0x111CA, 0x111CB, 0x111CC, 0x111CF, 0x1122F, 0x11230, 0x11231, 0x11234, 236 - 0x11236, 0x11237, 0x1123E, 0x11241, 0x112DF, 0x112E3, 0x112E4, 0x112E5, 237 - 0x112E6, 0x112E7, 0x112E8, 0x112E9, 0x112EA, 0x11300, 0x11301, 0x1133B, 238 - 0x1133C, 0x11340, 0x11366, 0x11367, 0x11368, 0x11369, 0x1136A, 0x1136B, 239 - 0x1136C, 0x11370, 0x11371, 0x11372, 0x11373, 0x11374, 0x113BB, 0x113BC, 240 - 0x113BD, 0x113BE, 0x113BF, 0x113C0, 0x113CE, 0x113D0, 0x113D2, 0x113E1, 241 - 0x113E2, 0x11438, 0x11439, 0x1143A, 0x1143B, 0x1143C, 0x1143D, 0x1143E, 242 - 0x1143F, 0x11442, 0x11443, 0x11444, 0x11446, 0x1145E, 0x114B3, 0x114B4, 243 - 0x114B5, 0x114B6, 0x114B7, 0x114B8, 0x114BA, 0x114BF, 0x114C0, 0x114C2, 244 - 0x114C3, 0x115B2, 0x115B3, 0x115B4, 0x115B5, 0x115BC, 0x115BD, 0x115BF, 245 - 0x115C0, 0x115DC, 0x115DD, 0x11633, 0x11634, 0x11635, 0x11636, 0x11637, 246 - 0x11638, 0x11639, 0x1163A, 0x1163D, 0x1163F, 0x11640, 0x116AB, 0x116AD, 247 - 0x116B0, 0x116B1, 0x116B2, 0x116B3, 0x116B4, 0x116B5, 0x116B7, 0x1171D, 248 - 0x1171F, 0x11722, 0x11723, 0x11724, 0x11725, 0x11727, 0x11728, 0x11729, 249 - 0x1172A, 0x1172B, 0x1182F, 0x11830, 0x11831, 0x11832, 0x11833, 0x11834, 250 - 0x11835, 0x11836, 0x11837, 0x11839, 0x1183A, 0x1193B, 0x1193C, 0x1193E, 251 - 0x11943, 0x119D4, 0x119D5, 0x119D6, 0x119D7, 0x119DA, 0x119DB, 0x119E0, 252 - 0x11A01, 0x11A02, 0x11A03, 0x11A04, 0x11A05, 0x11A06, 0x11A07, 0x11A08, 253 - 0x11A09, 0x11A0A, 0x11A33, 0x11A34, 0x11A35, 0x11A36, 0x11A37, 0x11A38, 254 - 0x11A3B, 0x11A3C, 0x11A3D, 0x11A3E, 0x11A47, 0x11A51, 0x11A52, 0x11A53, 255 - 0x11A54, 0x11A55, 0x11A56, 0x11A59, 0x11A5A, 0x11A5B, 0x11A8A, 0x11A8B, 256 - 0x11A8C, 0x11A8D, 0x11A8E, 0x11A8F, 0x11A90, 0x11A91, 0x11A92, 0x11A93, 257 - 0x11A94, 0x11A95, 0x11A96, 0x11A98, 0x11A99, 0x11C30, 0x11C31, 0x11C32, 258 - 0x11C33, 0x11C34, 0x11C35, 0x11C36, 0x11C38, 0x11C39, 0x11C3A, 0x11C3B, 259 - 0x11C3C, 0x11C3D, 0x11C3F, 0x11C92, 0x11C93, 0x11C94, 0x11C95, 0x11C96, 260 - 0x11C97, 0x11C98, 0x11C99, 0x11C9A, 0x11C9B, 0x11C9C, 0x11C9D, 0x11C9E, 261 - 0x11C9F, 0x11CA0, 0x11CA1, 0x11CA2, 0x11CA3, 0x11CA4, 0x11CA5, 0x11CA6, 262 - 0x11CA7, 0x11CAA, 0x11CAB, 0x11CAC, 0x11CAD, 0x11CAE, 0x11CAF, 0x11CB0, 263 - 0x11CB2, 0x11CB3, 0x11CB5, 0x11CB6, 0x11D31, 0x11D32, 0x11D33, 0x11D34, 264 - 0x11D35, 0x11D36, 0x11D3A, 0x11D3C, 0x11D3D, 0x11D3F, 0x11D40, 0x11D41, 265 - 0x11D42, 0x11D43, 0x11D44, 0x11D45, 0x11D47, 0x11D90, 0x11D91, 0x11D95, 266 - 0x11D97, 0x11EF3, 0x11EF4, 0x11F00, 0x11F01, 0x11F36, 0x11F37, 0x11F38, 267 - 0x11F39, 0x11F3A, 0x11F40, 0x11F42, 0x11F5A, 0x13440, 0x13447, 0x13448, 268 - 0x13449, 0x1344A, 0x1344B, 0x1344C, 0x1344D, 0x1344E, 0x1344F, 0x13450, 269 - 0x13451, 0x13452, 0x13453, 0x13454, 0x13455, 0x1611E, 0x1611F, 0x16120, 270 - 0x16121, 0x16122, 0x16123, 0x16124, 0x16125, 0x16126, 0x16127, 0x16128, 271 - 0x16129, 0x1612D, 0x1612E, 0x1612F, 0x16AF0, 0x16AF1, 0x16AF2, 0x16AF3, 272 - 0x16AF4, 0x16B30, 0x16B31, 0x16B32, 0x16B33, 0x16B34, 0x16B35, 0x16B36, 273 - 0x16F4F, 0x16F8F, 0x16F90, 0x16F91, 0x16F92, 0x16FE4, 0x1BC9D, 0x1BC9E, 274 - 0x1CF00, 0x1CF01, 0x1CF02, 0x1CF03, 0x1CF04, 0x1CF05, 0x1CF06, 0x1CF07, 275 - 0x1CF08, 0x1CF09, 0x1CF0A, 0x1CF0B, 0x1CF0C, 0x1CF0D, 0x1CF0E, 0x1CF0F, 276 - 0x1CF10, 0x1CF11, 0x1CF12, 0x1CF13, 0x1CF14, 0x1CF15, 0x1CF16, 0x1CF17, 277 - 0x1CF18, 0x1CF19, 0x1CF1A, 0x1CF1B, 0x1CF1C, 0x1CF1D, 0x1CF1E, 0x1CF1F, 278 - 0x1CF20, 0x1CF21, 0x1CF22, 0x1CF23, 0x1CF24, 0x1CF25, 0x1CF26, 0x1CF27, 279 - 0x1CF28, 0x1CF29, 0x1CF2A, 0x1CF2B, 0x1CF2C, 0x1CF2D, 0x1CF30, 0x1CF31, 280 - 0x1CF32, 0x1CF33, 0x1CF34, 0x1CF35, 0x1CF36, 0x1CF37, 0x1CF38, 0x1CF39, 281 - 0x1CF3A, 0x1CF3B, 0x1CF3C, 0x1CF3D, 0x1CF3E, 0x1CF3F, 0x1CF40, 0x1CF41, 282 - 0x1CF42, 0x1CF43, 0x1CF44, 0x1CF45, 0x1CF46, 0x1D167, 0x1D168, 0x1D169, 283 - 0x1D17B, 0x1D17C, 0x1D17D, 0x1D17E, 0x1D17F, 0x1D180, 0x1D181, 0x1D182, 284 - 0x1D185, 0x1D186, 0x1D187, 0x1D188, 0x1D189, 0x1D18A, 0x1D18B, 0x1D1AA, 285 - 0x1D1AB, 0x1D1AC, 0x1D1AD, 0x1D242, 0x1D243, 0x1D244, 0x1DA00, 0x1DA01, 286 - 0x1DA02, 0x1DA03, 0x1DA04, 0x1DA05, 0x1DA06, 0x1DA07, 0x1DA08, 0x1DA09, 287 - 0x1DA0A, 0x1DA0B, 0x1DA0C, 0x1DA0D, 0x1DA0E, 0x1DA0F, 0x1DA10, 0x1DA11, 288 - 0x1DA12, 0x1DA13, 0x1DA14, 0x1DA15, 0x1DA16, 0x1DA17, 0x1DA18, 0x1DA19, 289 - 0x1DA1A, 0x1DA1B, 0x1DA1C, 0x1DA1D, 0x1DA1E, 0x1DA1F, 0x1DA20, 0x1DA21, 290 - 0x1DA22, 0x1DA23, 0x1DA24, 0x1DA25, 0x1DA26, 0x1DA27, 0x1DA28, 0x1DA29, 291 - 0x1DA2A, 0x1DA2B, 0x1DA2C, 0x1DA2D, 0x1DA2E, 0x1DA2F, 0x1DA30, 0x1DA31, 292 - 0x1DA32, 0x1DA33, 0x1DA34, 0x1DA35, 0x1DA36, 0x1DA3B, 0x1DA3C, 0x1DA3D, 293 - 0x1DA3E, 0x1DA3F, 0x1DA40, 0x1DA41, 0x1DA42, 0x1DA43, 0x1DA44, 0x1DA45, 294 - 0x1DA46, 0x1DA47, 0x1DA48, 0x1DA49, 0x1DA4A, 0x1DA4B, 0x1DA4C, 0x1DA4D, 295 - 0x1DA4E, 0x1DA4F, 0x1DA50, 0x1DA51, 0x1DA52, 0x1DA53, 0x1DA54, 0x1DA55, 296 - 0x1DA56, 0x1DA57, 0x1DA58, 0x1DA59, 0x1DA5A, 0x1DA5B, 0x1DA5C, 0x1DA5D, 297 - 0x1DA5E, 0x1DA5F, 0x1DA60, 0x1DA61, 0x1DA62, 0x1DA63, 0x1DA64, 0x1DA65, 298 - 0x1DA66, 0x1DA67, 0x1DA68, 0x1DA69, 0x1DA6A, 0x1DA6B, 0x1DA6C, 0x1DA75, 299 - 0x1DA84, 0x1DA9B, 0x1DA9C, 0x1DA9D, 0x1DA9E, 0x1DA9F, 0x1DAA1, 0x1DAA2, 300 - 0x1DAA3, 0x1DAA4, 0x1DAA5, 0x1DAA6, 0x1DAA7, 0x1DAA8, 0x1DAA9, 0x1DAAA, 301 - 0x1DAAB, 0x1DAAC, 0x1DAAD, 0x1DAAE, 0x1DAAF, 0x1E000, 0x1E001, 0x1E002, 302 - 0x1E003, 0x1E004, 0x1E005, 0x1E006, 0x1E008, 0x1E009, 0x1E00A, 0x1E00B, 303 - 0x1E00C, 0x1E00D, 0x1E00E, 0x1E00F, 0x1E010, 0x1E011, 0x1E012, 0x1E013, 304 - 0x1E014, 0x1E015, 0x1E016, 0x1E017, 0x1E018, 0x1E01B, 0x1E01C, 0x1E01D, 305 - 0x1E01E, 0x1E01F, 0x1E020, 0x1E021, 0x1E023, 0x1E024, 0x1E026, 0x1E027, 306 - 0x1E028, 0x1E029, 0x1E02A, 0x1E08F, 0x1E130, 0x1E131, 0x1E132, 0x1E133, 307 - 0x1E134, 0x1E135, 0x1E136, 0x1E2AE, 0x1E2EC, 0x1E2ED, 0x1E2EE, 0x1E2EF, 308 - 0x1E4EC, 0x1E4ED, 0x1E4EE, 0x1E4EF, 0x1E5EE, 0x1E5EF, 0x1E8D0, 0x1E8D1, 309 - 0x1E8D2, 0x1E8D3, 0x1E8D4, 0x1E8D5, 0x1E8D6, 0x1E944, 0x1E945, 0x1E946, 310 - 0x1E947, 0x1E948, 0x1E949, 0x1E94A, 0xE0100, 0xE0101, 0xE0102, 0xE0103, 311 - 0xE0104, 0xE0105, 0xE0106, 0xE0107, 0xE0108, 0xE0109, 0xE010A, 0xE010B, 312 - 0xE010C, 0xE010D, 0xE010E, 0xE010F, 0xE0110, 0xE0111, 0xE0112, 0xE0113, 313 - 0xE0114, 0xE0115, 0xE0116, 0xE0117, 0xE0118, 0xE0119, 0xE011A, 0xE011B, 314 - 0xE011C, 0xE011D, 0xE011E, 0xE011F, 0xE0120, 0xE0121, 0xE0122, 0xE0123, 315 - 0xE0124, 0xE0125, 0xE0126, 0xE0127, 0xE0128, 0xE0129, 0xE012A, 0xE012B, 316 - 0xE012C, 0xE012D, 0xE012E, 0xE012F, 0xE0130, 0xE0131, 0xE0132, 0xE0133, 317 - 0xE0134, 0xE0135, 0xE0136, 0xE0137, 0xE0138, 0xE0139, 0xE013A, 0xE013B, 318 - 0xE013C, 0xE013D, 0xE013E, 0xE013F, 0xE0140, 0xE0141, 0xE0142, 0xE0143, 319 - 0xE0144, 0xE0145, 0xE0146, 0xE0147, 0xE0148, 0xE0149, 0xE014A, 0xE014B, 320 - 0xE014C, 0xE014D, 0xE014E, 0xE014F, 0xE0150, 0xE0151, 0xE0152, 0xE0153, 321 - 0xE0154, 0xE0155, 0xE0156, 0xE0157, 0xE0158, 0xE0159, 0xE015A, 0xE015B, 322 - 0xE015C, 0xE015D, 0xE015E, 0xE015F, 0xE0160, 0xE0161, 0xE0162, 0xE0163, 323 - 0xE0164, 0xE0165, 0xE0166, 0xE0167, 0xE0168, 0xE0169, 0xE016A, 0xE016B, 324 - 0xE016C, 0xE016D, 0xE016E, 0xE016F, 0xE0170, 0xE0171, 0xE0172, 0xE0173, 325 - 0xE0174, 0xE0175, 0xE0176, 0xE0177, 0xE0178, 0xE0179, 0xE017A, 0xE017B, 326 - 0xE017C, 0xE017D, 0xE017E, 0xE017F, 0xE0180, 0xE0181, 0xE0182, 0xE0183, 327 - 0xE0184, 0xE0185, 0xE0186, 0xE0187, 0xE0188, 0xE0189, 0xE018A, 0xE018B, 328 - 0xE018C, 0xE018D, 0xE018E, 0xE018F, 0xE0190, 0xE0191, 0xE0192, 0xE0193, 329 - 0xE0194, 0xE0195, 0xE0196, 0xE0197, 0xE0198, 0xE0199, 0xE019A, 0xE019B, 330 - 0xE019C, 0xE019D, 0xE019E, 0xE019F, 0xE01A0, 0xE01A1, 0xE01A2, 0xE01A3, 331 - 0xE01A4, 0xE01A5, 0xE01A6, 0xE01A7, 0xE01A8, 0xE01A9, 0xE01AA, 0xE01AB, 332 - 0xE01AC, 0xE01AD, 0xE01AE, 0xE01AF, 0xE01B0, 0xE01B1, 0xE01B2, 0xE01B3, 333 - 0xE01B4, 0xE01B5, 0xE01B6, 0xE01B7, 0xE01B8, 0xE01B9, 0xE01BA, 0xE01BB, 334 - 0xE01BC, 0xE01BD, 0xE01BE, 0xE01BF, 0xE01C0, 0xE01C1, 0xE01C2, 0xE01C3, 335 - 0xE01C4, 0xE01C5, 0xE01C6, 0xE01C7, 0xE01C8, 0xE01C9, 0xE01CA, 0xE01CB, 336 - 0xE01CC, 0xE01CD, 0xE01CE, 0xE01CF, 0xE01D0, 0xE01D1, 0xE01D2, 0xE01D3, 337 - 0xE01D4, 0xE01D5, 0xE01D6, 0xE01D7, 0xE01D8, 0xE01D9, 0xE01DA, 0xE01DB, 338 - 0xE01DC, 0xE01DD, 0xE01DE, 0xE01DF, 0xE01E0, 0xE01E1, 0xE01E2, 0xE01E3, 339 - 0xE01E4, 0xE01E5, 0xE01E6, 0xE01E7, 0xE01E8, 0xE01E9, 0xE01EA, 0xE01EB, 340 - 0xE01EC, 0xE01ED, 0xE01EE, 0xE01EF, 341 - }; 342 - 343 - static unsigned long combiningCharTableSize = sizeof(combiningCharTable) / sizeof(combiningCharTable[0]); 344 - 345 - /* Check if the code is a wide character 346 - */ 347 - static int isWideChar(unsigned long cp) { 348 - size_t i; 349 - for (i = 0; i < wideCharTableSize; i++) 350 - if (wideCharTable[i][0] <= cp && cp <= wideCharTable[i][1]) return 1; 351 - return 0; 352 - } 353 - 354 - /* Check if the code is a combining character 355 - */ 356 - static int isCombiningChar(unsigned long cp) { 357 - size_t i; 358 - for (i = 0; i < combiningCharTableSize; i++) 359 - if (combiningCharTable[i] == cp) return 1; 360 - return 0; 361 - } 362 - 363 - /* Get length of previous UTF8 character 364 - */ 365 - static size_t prevUtf8CharLen(const char* buf, int pos) { 366 - int end = pos--; 367 - while (pos >= 0 && ((unsigned char)buf[pos] & 0xC0) == 0x80) 368 - pos--; 369 - return end - pos; 370 - } 371 - 372 - /* Convert UTF8 to Unicode code point 373 - */ 374 - static size_t utf8BytesToCodePoint(const char* buf, size_t len, int* cp) { 375 - if (len) { 376 - unsigned char byte = buf[0]; 377 - if ((byte & 0x80) == 0) { 378 - *cp = byte; 379 - return 1; 380 - } else if ((byte & 0xE0) == 0xC0) { 381 - if (len >= 2) { 382 - *cp = (((unsigned long)(buf[0] & 0x1F)) << 6) | 383 - ((unsigned long)(buf[1] & 0x3F)); 384 - return 2; 385 - } 386 - } else if ((byte & 0xF0) == 0xE0) { 387 - if (len >= 3) { 388 - *cp = (((unsigned long)(buf[0] & 0x0F)) << 12) | 389 - (((unsigned long)(buf[1] & 0x3F)) << 6) | 390 - ((unsigned long)(buf[2] & 0x3F)); 391 - return 3; 392 - } 393 - } else if ((byte & 0xF8) == 0xF0) { 394 - if (len >= 4) { 395 - *cp = (((unsigned long)(buf[0] & 0x07)) << 18) | 396 - (((unsigned long)(buf[1] & 0x3F)) << 12) | 397 - (((unsigned long)(buf[2] & 0x3F)) << 6) | 398 - ((unsigned long)(buf[3] & 0x3F)); 399 - return 4; 400 - } 401 - } 402 - } 403 - return 0; 404 - } 405 - 406 - /* Get length of next grapheme 407 - */ 408 - size_t linenoiseUtf8NextCharLen(const char* buf, size_t buf_len, size_t pos, size_t *col_len) { 409 - size_t beg = pos; 410 - int cp; 411 - size_t len = utf8BytesToCodePoint(buf + pos, buf_len - pos, &cp); 412 - if (isCombiningChar(cp)) { 413 - /* NOTREACHED */ 414 - return 0; 415 - } 416 - if (col_len != NULL) *col_len = isWideChar(cp) ? 2 : 1; 417 - pos += len; 418 - while (pos < buf_len) { 419 - int cp; 420 - len = utf8BytesToCodePoint(buf + pos, buf_len - pos, &cp); 421 - if (!isCombiningChar(cp)) return pos - beg; 422 - pos += len; 423 - } 424 - return pos - beg; 425 - } 426 - 427 - /* Get length of previous grapheme 428 - */ 429 - size_t linenoiseUtf8PrevCharLen(const char* buf, size_t buf_len, size_t pos, size_t *col_len) { 430 - UNUSED(buf_len); 431 - size_t end = pos; 432 - while (pos > 0) { 433 - size_t len = prevUtf8CharLen(buf, pos); 434 - pos -= len; 435 - int cp; 436 - utf8BytesToCodePoint(buf + pos, len, &cp); 437 - if (!isCombiningChar(cp)) { 438 - if (col_len != NULL) *col_len = isWideChar(cp) ? 2 : 1; 439 - return end - pos; 440 - } 441 - } 442 - /* NOTREACHED */ 443 - return 0; 444 - } 445 - 446 - /* Read a Unicode from file. 447 - */ 448 - size_t linenoiseUtf8ReadCode(int fd, char* buf, size_t buf_len, int* cp) { 449 - if (buf_len < 1) return -1; 450 - size_t nread = read(fd,&buf[0],1); 451 - if (nread <= 0) return nread; 452 - 453 - unsigned char byte = buf[0]; 454 - if ((byte & 0x80) == 0) { 455 - ; 456 - } else if ((byte & 0xE0) == 0xC0) { 457 - if (buf_len < 2) return -1; 458 - nread = read(fd,&buf[1],1); 459 - if (nread <= 0) return nread; 460 - } else if ((byte & 0xF0) == 0xE0) { 461 - if (buf_len < 3) return -1; 462 - nread = read(fd,&buf[1],2); 463 - if (nread <= 0) return nread; 464 - } else if ((byte & 0xF8) == 0xF0) { 465 - if (buf_len < 3) return -1; 466 - nread = read(fd,&buf[1],3); 467 - if (nread <= 0) return nread; 468 - } else { 469 - return -1; 470 - } 471 - 472 - return utf8BytesToCodePoint(buf, buf_len, cp); 473 - }
-55
vendor/ocaml-linenoise/src/utf8.h
··· 1 - /* encodings/utf8.h -- VERSION 1.0 2 - * 3 - * Guerrilla line editing library against the idea that a line editing lib 4 - * needs to be 20,000 lines of C code. 5 - * 6 - * See linenoise.c for more information. 7 - * 8 - * ------------------------------------------------------------------------ 9 - * 10 - * Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com> 11 - * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com> 12 - * 13 - * All rights reserved. 14 - * 15 - * Redistribution and use in source and binary forms, with or without 16 - * modification, are permitted provided that the following conditions are 17 - * met: 18 - * 19 - * * Redistributions of source code must retain the above copyright 20 - * notice, this list of conditions and the following disclaimer. 21 - * 22 - * * Redistributions in binary form must reproduce the above copyright 23 - * notice, this list of conditions and the following disclaimer in the 24 - * documentation and/or other materials provided with the distribution. 25 - * 26 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 - */ 38 - 39 - #ifndef __LINENOISE_ENCODINGS_UTF8_H 40 - #define __LINENOISE_ENCODINGS_UTF8_H 41 - 42 - #ifdef __cplusplus 43 - extern "C" { 44 - #endif 45 - 46 - size_t linenoiseUtf8PrevCharLen(const char* buf, size_t buf_len, size_t pos, size_t *col_len); 47 - size_t linenoiseUtf8NextCharLen(const char* buf, size_t buf_len, size_t pos, size_t *col_len); 48 - size_t linenoiseUtf8ReadCode(int fd, char* buf, size_t buf_len, int* cp); 49 - 50 - #ifdef __cplusplus 51 - } 52 - #endif 53 - 54 - #endif /* __LINENOISE_ENCODINGS_UTF8_H */ 55 -