! Copyright (C) 2013 John Benediktsson. ! See https://factorcode.org/license.txt for BSD license. USING: accessors assocs combinators formatting endian fry grouping hashtables io io.directories io.encodings.binary io.files io.files.types io.pathnames kernel math math.parser memoize pack sequences sequences.generalizations splitting strings system ; IN: terminfo ! Reads compiled terminfo files ! typically located in any of the directories below. CONSTANT: TERMINFO-DIRS { "~/.terminfo" "/etc/terminfo" "/lib/terminfo" "/usr/share/terminfo" } terminfo-header : read-header ( -- header ) 12 read "ssssss" unpack-le unclip check-magic 5 firstn ; : read-names ( header -- names ) names-bytes>> read but-last "|" split [ >string ] map ; : read-booleans ( header -- booleans ) boolean-bytes>> read [ 1 = ] { } map-as ; : read-shorts ( n -- seq' ) 2 * read 2 [ signed-le> dup 0 < [ drop f ] when ] map ; : align-even-bytes ( header -- ) [ names-bytes>> ] [ boolean-bytes>> ] bi + odd? [ read1 drop ] when ; : read-numbers ( header -- numbers ) [ align-even-bytes ] [ #numbers>> read-shorts ] bi ; : string-offset ( from seq -- str ) 0 2over index-from swap subseq >string ; : read-strings ( header -- strings ) [ #strings>> read-shorts ] [ string-bytes>> read ] bi '[ [ _ string-offset ] [ f ] if* ] map ; TUPLE: terminfo names booleans numbers strings ; C: terminfo : read-terminfo ( -- terminfo ) read-header { [ read-names ] [ read-booleans ] [ read-numbers ] [ read-strings ] } cleave ; PRIVATE> : file>terminfo ( path -- terminfo ) binary [ read-terminfo ] with-file-reader ; HOOK: terminfo-relative-path os ( name -- path ) M: macosx terminfo-relative-path ( name -- path ) [ first >hex ] keep "%s/%s" sprintf ; M: linux terminfo-relative-path ( name -- path ) [ first ] keep "%c/%s" sprintf ; : terminfo-path ( name -- path ) terminfo-relative-path TERMINFO-DIRS [ swap append-path ] with map [ file-exists? ] find nip ; : terminfo-names-for-path ( path -- names ) [ [ type>> +directory+ = ] filter [ name>> directory-files ] map concat ] with-directory-entries ; MEMO: terminfo-names ( -- names ) TERMINFO-DIRS [ file-exists? ] filter [ terminfo-names-for-path ] map concat ; append zip ; PRIVATE> : term-capabilities ( name -- assoc ) terminfo-path file>terminfo { [ booleans>> boolean-names zip-names ] [ numbers>> number-names zip-names ] [ strings>> string-names zip-names ] } cleave 3append >hashtable ;