From 24d2341cf9054bf36d19d2f308f840961b65f639 Mon Sep 17 00:00:00 2001 From: Juliana Rat Date: Sun, 11 Feb 2024 15:37:12 -0500 Subject: [PATCH 1/4] Make port arguments last and optional These changes allow library users to leave out port arguments to instead use current-output-port. * termenv/hyperlink.scm (format-hyperlink): Move port to the end of the argument list and make it default to #t. (format-hyperlink, hyperlink): Make name optional and use link if it is not provided. --- termenv/hyperlink.scm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/termenv/hyperlink.scm b/termenv/hyperlink.scm index 152dbed..5ff9a41 100644 --- a/termenv/hyperlink.scm +++ b/termenv/hyperlink.scm @@ -3,11 +3,11 @@ #:export (format-hyperlink hyperlink)) -(define (format-hyperlink port link name) +(define* (format-hyperlink link #:optional name (port #t)) "Output a hyperlink using OSC8 to the provided port" (format port (hyperlink link name))) -(define (hyperlink link name) +(define* (hyperlink link #:optional name) "Create an OSC8 hyperlink sequence" - (string-append %OSC "8;;" link %ST name %OSC "8;;" %ST)) + (string-append %OSC "8;;" link %ST (or name link) %OSC "8;;" %ST)) From 00e68a9d295de7b4cf366e2ad6c6ca95b85619d7 Mon Sep 17 00:00:00 2001 From: Juliana Rat Date: Mon, 12 Feb 2024 22:08:13 -0500 Subject: [PATCH 2/4] Enable support for more varieties of hexcode strings Enable support for hexcode strings with or without prefixes, and using one or two characters per byte. Additionally, move hex->color to fix a build error. --- termenv/color.scm | 52 +++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/termenv/color.scm b/termenv/color.scm index 478ced5..04e3f53 100644 --- a/termenv/color.scm +++ b/termenv/color.scm @@ -304,6 +304,41 @@ (b color-b) (type color-type)) +(define* (hex->color hex #:optional (type 'foreground)) + (define strlen (string-length hex)) + (define trimmed + (cond + ((and (or (= strlen 4) + (= strlen 7)) + (char=? (string-ref hex 0) #\#)) + (substring/copy hex 1)) + ((and (or (= strlen 5) + (= strlen 8)) + (char=? (string-ref hex 1) #\x)) + (substring/copy hex 2)) + ((or (= strlen 3) + (= strlen 6)) + hex) + (else (error "Invalid hex string: incorrect length")))) + (define width (if (= (string-length trimmed) 3) 1 2)) + + (define r (locale-string->integer + (substring/copy trimmed 0 width) 16)) + (define g (locale-string->integer + (substring/copy trimmed width (* 2 width)) 16)) + (define b (locale-string->integer + (substring/copy trimmed (* 2 width) (* 3 width)) 16)) + + (when (= width 1) + (let ((double-hex + (lambda (v) + (+ (* v #XF) v)))) + (set! r (double-hex r)) + (set! g (double-hex g)) + (set! b (double-hex b)))) + + (make-color r g b type)) + (define %ANSI256-COLORS (map hex->color %ANSI256-HEX)) @@ -371,23 +406,6 @@ (expt (- cie-a1 cie-a2) 2) (expt (- cie-b1 cie-b2) 2)))) -(define* (hex->color str #:optional (type 'foreground)) - (define trimmed (string-trim str #\#)) - (define width (floor (/ (string-length trimmed) 3))) - (unless (or (= 1 width) - (= 2 width)) - (error "Invalid hex: not the right length")) - - (define r (substring/copy trimmed 0 width)) - (define g (substring/copy trimmed width (* 2 width))) - (define b (substring/copy trimmed (* 2 width) (* 3 width))) - - (make-color - (locale-string->integer r 16) - (locale-string->integer g 16) - (locale-string->integer b 16) - type)) - (define (color->ansi color) "Given a full color, convert to the nearest ansi color equivalent" (color->table color %ANSI-COLORS)) From 43b2f86d88f7a6036edb8661eda6a3fda7990fc6 Mon Sep 17 00:00:00 2001 From: Juliana Rat Date: Mon, 12 Feb 2024 22:46:53 -0500 Subject: [PATCH 3/4] Cleanup build infrastructure --- AUTHORS | 3 - ChangeLog | 1 - NEWS | 14 --- bootstrap | 5 -- build-aux/test-driver.scm | 179 -------------------------------------- guile-termenv/hconfig.scm | 35 -------- guix.scm | 65 ++++++++------ hall.scm | 88 +++++++++---------- 8 files changed, 81 insertions(+), 309 deletions(-) delete mode 100644 AUTHORS delete mode 100644 ChangeLog delete mode 100644 NEWS delete mode 100755 bootstrap delete mode 100644 build-aux/test-driver.scm delete mode 100644 guile-termenv/hconfig.scm diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 23a511f..0000000 --- a/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -Contributors to Guile-Termenv 0.1: - - <> diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index 76c33bf..0000000 --- a/ChangeLog +++ /dev/null @@ -1 +0,0 @@ -For a complete log, please see the Git commit log at . diff --git a/NEWS b/NEWS deleted file mode 100644 index 54db4eb..0000000 --- a/NEWS +++ /dev/null @@ -1,14 +0,0 @@ -# -*- mode: org; coding: utf-8; -*- - -#+TITLE: Guile-Termenv NEWS – history of user-visible changes -#+STARTUP: content hidestars - -Copyright © (2024) <> - - Copying and distribution of this file, with or without modification, - are permitted in any medium without royalty provided the copyright - notice and this notice are preserved. - -Please send Guile-Termenv bug reports to . - -* Publication at 0.1 diff --git a/bootstrap b/bootstrap deleted file mode 100755 index 0131994..0000000 --- a/bootstrap +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -autoreconf -vif -./configure -make diff --git a/build-aux/test-driver.scm b/build-aux/test-driver.scm deleted file mode 100644 index 0c555ea..0000000 --- a/build-aux/test-driver.scm +++ /dev/null @@ -1,179 +0,0 @@ -;;;; test-driver.scm - Guile test driver for Automake testsuite harness - -(define script-version "2019-01-15.13") ;UTC - -;;; Copyright © 2015, 2016 Mathieu Lirzin -;;; Copyright © 2019 Alex Sassmannshausen -;;; -;;; This program is free software; you can redistribute it and/or modify it -;;; under the terms of the GNU General Public License as published by -;;; the Free Software Foundation; either version 3 of the License, or (at -;;; your option) any later version. -;;; -;;; This program is distributed in the hope that it will be useful, but -;;; WITHOUT ANY WARRANTY; without even the implied warranty of -;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;;; GNU General Public License for more details. -;;; -;;; You should have received a copy of the GNU General Public License -;;; along with this program. If not, see . - -;;;; Commentary: -;;; -;;; This script provides a Guile test driver using the SRFI-64 Scheme API for -;;; test suites. SRFI-64 is distributed with Guile since version 2.0.9. -;;; -;;; This script is a lightly modified version of the orignal written by -;;; Matthieu Lirzin. The changes make it suitable for use as part of the -;;; guile-hall infrastructure. -;;; -;;;; Code: - -(use-modules (ice-9 getopt-long) - (ice-9 pretty-print) - (srfi srfi-26) - (srfi srfi-64)) - -(define (show-help) - (display "Usage: - test-driver --test-name=NAME --log-file=PATH --trs-file=PATH - [--expect-failure={yes|no}] [--color-tests={yes|no}] - [--enable-hard-errors={yes|no}] [--brief={yes|no}}] [--] - TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS] -The '--test-name', '--log-file' and '--trs-file' options are mandatory. -")) - -(define %options - '((test-name (value #t)) - (log-file (value #t)) - (trs-file (value #t)) - (color-tests (value #t)) - (expect-failure (value #t)) ;XXX: not implemented yet - (enable-hard-errors (value #t)) ;not implemented in SRFI-64 - (brief (value #t)) - (help (single-char #\h) (value #f)) - (version (single-char #\V) (value #f)))) - -(define (option->boolean options key) - "Return #t if the value associated with KEY in OPTIONS is 'yes'." - (and=> (option-ref options key #f) (cut string=? <> "yes"))) - -(define* (test-display field value #:optional (port (current-output-port)) - #:key pretty?) - "Display 'FIELD: VALUE\n' on PORT." - (if pretty? - (begin - (format port "~A:~%" field) - (pretty-print value port #:per-line-prefix "+ ")) - (format port "~A: ~S~%" field value))) - -(define* (result->string symbol #:key colorize?) - "Return SYMBOL as an upper case string. Use colors when COLORIZE is #t." - (let ((result (string-upcase (symbol->string symbol)))) - (if colorize? - (string-append (case symbol - ((pass) "") ;green - ((xfail) "") ;light green - ((skip) "") ;blue - ((fail xpass) "") ;red - ((error) "")) ;magenta - result - "") ;no color - result))) - -(define* (test-runner-gnu test-name #:key color? brief? out-port trs-port) - "Return an custom SRFI-64 test runner. TEST-NAME is a string specifying the -file name of the current the test. COLOR? specifies whether to use colors, -and BRIEF?, well, you know. OUT-PORT and TRS-PORT must be output ports. The -current output port is supposed to be redirected to a '.log' file." - - (define (test-on-test-begin-gnu runner) - ;; Procedure called at the start of an individual test case, before the - ;; test expression (and expected value) are evaluated. - (let ((result (cute assq-ref (test-result-alist runner) <>))) - (format #t "test-name: ~A~%" (result 'test-name)) - (format #t "location: ~A~%" - (string-append (result 'source-file) ":" - (number->string (result 'source-line)))) - (test-display "source" (result 'source-form) #:pretty? #t))) - - (define (test-on-test-end-gnu runner) - ;; Procedure called at the end of an individual test case, when the result - ;; of the test is available. - (let* ((results (test-result-alist runner)) - (result? (cut assq <> results)) - (result (cut assq-ref results <>))) - (unless brief? - ;; Display the result of each test case on the console. - (format out-port "~A: ~A - ~A~%" - (result->string (test-result-kind runner) #:colorize? color?) - test-name (test-runner-test-name runner))) - (when (result? 'expected-value) - (test-display "expected-value" (result 'expected-value))) - (when (result? 'expected-error) - (test-display "expected-error" (result 'expected-error) #:pretty? #t)) - (when (result? 'actual-value) - (test-display "actual-value" (result 'actual-value))) - (when (result? 'actual-error) - (test-display "actual-error" (result 'actual-error) #:pretty? #t)) - (format #t "result: ~a~%" (result->string (result 'result-kind))) - (newline) - (format trs-port ":test-result: ~A ~A~%" - (result->string (test-result-kind runner)) - (test-runner-test-name runner)))) - - (define (test-on-group-end-gnu runner) - ;; Procedure called by a 'test-end', including at the end of a test-group. - (let ((fail (or (positive? (test-runner-fail-count runner)) - (positive? (test-runner-xpass-count runner)))) - (skip (or (positive? (test-runner-skip-count runner)) - (positive? (test-runner-xfail-count runner))))) - ;; XXX: The global results need some refinements for XPASS. - (format trs-port ":global-test-result: ~A~%" - (if fail "FAIL" (if skip "SKIP" "PASS"))) - (format trs-port ":recheck: ~A~%" - (if fail "yes" "no")) - (format trs-port ":copy-in-global-log: ~A~%" - (if (or fail skip) "yes" "no")) - (when brief? - ;; Display the global test group result on the console. - (format out-port "~A: ~A~%" - (result->string (if fail 'fail (if skip 'skip 'pass)) - #:colorize? color?) - test-name)) - #f)) - - (let ((runner (test-runner-null))) - (test-runner-on-test-begin! runner test-on-test-begin-gnu) - (test-runner-on-test-end! runner test-on-test-end-gnu) - (test-runner-on-group-end! runner test-on-group-end-gnu) - (test-runner-on-bad-end-name! runner test-on-bad-end-name-simple) - runner)) - -;;; -;;; Entry point. -;;; - -(define (main . args) - (let* ((opts (getopt-long (command-line) %options)) - (option (cut option-ref opts <> <>))) - (cond - ((option 'help #f) (show-help)) - ((option 'version #f) (format #t "test-driver.scm ~A" script-version)) - (else - (let ((log (open-file (option 'log-file "") "w0")) - (trs (open-file (option 'trs-file "") "wl")) - (out (duplicate-port (current-output-port) "wl"))) - (redirect-port log (current-output-port)) - (redirect-port log (current-warning-port)) - (redirect-port log (current-error-port)) - (test-with-runner - (test-runner-gnu (option 'test-name #f) - #:color? (option->boolean opts 'color-tests) - #:brief? (option->boolean opts 'brief) - #:out-port out #:trs-port trs) - (load-from-path (option 'test-name #f))) - (close-port log) - (close-port trs) - (close-port out)))) - (exit 0))) diff --git a/guile-termenv/hconfig.scm b/guile-termenv/hconfig.scm deleted file mode 100644 index ea2ecb4..0000000 --- a/guile-termenv/hconfig.scm +++ /dev/null @@ -1,35 +0,0 @@ -(define-module - (guile-termenv hconfig) - #:use-module - (srfi srfi-26) - #:export - (%version - %author - %license - %copyright - %gettext-domain - G_ - N_ - init-nls - init-locale)) - -(define %version "0.1") - -(define %author "") - -(define %license 'gpl3+) - -(define %copyright '(2024)) - -(define %gettext-domain "guile-termenv") - -(define G_ identity) - -(define N_ identity) - -(define (init-nls) "Dummy as no NLS is used" #t) - -(define (init-locale) - "Dummy as no NLS is used" - #t) - diff --git a/guix.scm b/guix.scm index c4143ae..7f2f9c2 100644 --- a/guix.scm +++ b/guix.scm @@ -1,16 +1,15 @@ -(use-modules - (gnu packages) - (gnu packages autotools) - (gnu packages guile) - (gnu packages guile-xyz) - (gnu packages pkg-config) - (gnu packages texinfo) - (guix build-system gnu) - (guix download) - (guix gexp) - ((guix licenses) #:prefix license:) - (guix packages) - (srfi srfi-1)) +(use-modules (gnu packages) + (gnu packages autotools) + (gnu packages guile) + (gnu packages guile-xyz) + (gnu packages pkg-config) + (gnu packages texinfo) + (guix build-system gnu) + (guix download) + (guix gexp) + ((guix licenses) #:prefix license:) + (guix packages) + (srfi srfi-1)) (package (name "guile-termenv") @@ -18,21 +17,33 @@ (source (local-file (dirname (current-filename)) - #:recursive? - #t - #:select? - (lambda (file stat) - (not (any (lambda (my-string) - (string-contains file my-string)) - (list ".git" ".dir-locals.el" "guix.scm")))))) + #:recursive? #t + #:select? (lambda (file stat) + (not (any (lambda (my-string) + (string-contains file my-string)) + (list ".git" ".dir-locals.el" "guix.scm")))))) (build-system gnu-build-system) - (arguments `()) - (native-inputs - (list autoconf automake pkg-config texinfo)) + (arguments + (list + #:make-flags + #~(list "GUILE_AUTO_COMPILE=0") + #:phases + #~(modify-phases %standard-phases + (add-before 'bootstrap 'hall + (lambda _ + (system* "hall" "build" "-x"))) + (replace 'bootstrap + (lambda _ + (system* "autoreconf" "-vif")))))) + (native-inputs (list autoconf + automake + guile-hall + pkg-config + texinfo)) (inputs (list guile-3.0)) - (propagated-inputs (list)) - (synopsis "") - (description "") - (home-page "") + (synopsis "Guile port of termenv") + (description + "A library to provide easy control of terminals from Guile using terminal control codes.") + (home-page "https://git.solarpunk.moe/vv/guile-termenv") (license license:gpl3+)) diff --git a/hall.scm b/hall.scm index 3d4cf0f..9a1096f 100644 --- a/hall.scm +++ b/hall.scm @@ -1,46 +1,44 @@ (hall-description - (name "guile-termenv") - (prefix "") - (version "0.1") - (author "") - (email "") - (copyright (2024)) - (synopsis "") - (description "") - (home-page "") - (license gpl3+) - (dependencies `()) - (skip ("bootstrap")) - (features - ((guix #f) - (use-guix-specs-for-dependencies #f) - (native-language-support #f) - (licensing #f))) - (files (libraries - ((directory - "termenv" - ((scheme-file "style") - (scheme-file "unix") - (scheme-file "hyperlink") - (scheme-file "screen") - (scheme-file "color") - (scheme-file "hconfig"))) - (scheme-file "termenv") - (directory - "tests" - ((scheme-file "utils"))))) - (tests ((directory - "tests" - ((scheme-file "test-screen") - (scheme-file "test-style"))))) - (programs ((directory "scripts" ()))) - (documentation - ((org-file "README") - (symlink "README" "README.org") - (text-file "HACKING") - (text-file "COPYING") - (directory "doc" ((texi-file "guile-termenv"))))) - (infrastructure - ((scheme-file "guix") - (text-file ".gitignore") - (scheme-file "hall"))))) + (name "termenv") + (prefix "guile") + (version "0.1") + (author "Vivanne Langdon") + (email "") + (copyright (2024)) + (synopsis "Guile port of termenv") + (description + "A library to provide easy control of terminals from Guile using terminal control codes.") + (home-page "https://git.solarpunk.moe/vv/guile-termenv") + (license gpl3+) + (dependencies `()) + (features + ((guix #t) + (use-guix-specs-for-dependencies #f) + (native-language-support #f) + (licensing #f))) + (files (libraries + ((directory "termenv" + ((scheme-file "style") + (scheme-file "unix") + (scheme-file "hyperlink") + (scheme-file "screen") + (scheme-file "color") + (scheme-file "hconfig"))) + (scheme-file "termenv"))) + (tests ((directory "tests" + ((scheme-file "test-screen") + (scheme-file "test-style"))))) + (documentation + ((org-file "README") + (symlink "README" "README.org") + (text-file "HACKING") + (text-file "COPYING") + (directory "doc" + ((texi-file "guile-termenv"))))) + (programs ()) + (infrastructure + ((scheme-file "guix") + (text-file ".gitignore") + (scheme-file "hall") + (directory "tests" + ((scheme-file "utils"))))))) From b0fc09e3ad2eb6e33f20f9609e61b1738a3645cc Mon Sep 17 00:00:00 2001 From: Juliana Rat Date: Sun, 11 Feb 2024 14:07:12 -0500 Subject: [PATCH 4/4] Add basic documentation --- README.org | 40 +++ doc/guile-termenv.texi | 536 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 567 insertions(+), 9 deletions(-) diff --git a/README.org b/README.org index 0056068..4b7cff9 100644 --- a/README.org +++ b/README.org @@ -2,3 +2,43 @@ #+TITLE: README for Guile-Termenv +~guile-termenv~ is a port of [[https://github.com/muesli/termenv][termenv]] to Guile. It provides a convenient +interface to ANSI control sequences so you can color and style output without +need to bother with arcane symbols, all to the height of your terminal's +capabilities. + +While ~guile-termenv~ is not a 1:1 port of ~termenv~, it does provide much of +the same functionality, and it aims to fill the same niche in the Guile +ecosystem that ~termenv~ does in the Go ecosystem. + +* Building + +~guile-termenv~ is developed using [[https://guix.gnu.org][Guix]] and the simplest way to build it is with +Guix. Running ~guix build -f guix.scm~ will build and test the project, placing +it in the store. Instead using ~guix shell -f guix.scm~ will create an +environment with the project, and ~guix profile -if guix.scm~ will install it. + +If you wish to use a more manual build methodology, you can replicate the build +steps like so: + +#+BEGIN_SRC shell + guix shell -Df guix.scm + hall build -x + autoreconf -vif + ./configure + make -j +#+END_SRC + +Note that it is not advised to install the project this way. + +If you don't have or don't want to use Guix, ~guile-termenv~ requires the +following dependencies to build: + +- autoconf +- automake +- guile-hall +- pkg-config +- texinfo + +With those dependencies installed, the same build commands as above will work, +although the ~guix~ command becomes redundant. diff --git a/doc/guile-termenv.texi b/doc/guile-termenv.texi index 94807f3..c0b770d 100644 --- a/doc/guile-termenv.texi +++ b/doc/guile-termenv.texi @@ -3,14 +3,17 @@ @c %**start of header @setfilename guile-termenv.info -@documentencoding UTF-8 @settitle Guile-Termenv Reference Manual +@documentencoding UTF-8 +@documentlanguage en +@syncodeindex vr fn +@syncodeindex tp fn @c %**end of header @include version.texi @copying -Copyright @copyright{} 2024 +Copyright @copyright{} 2024 Vivianne Langdon Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22,12 +25,13 @@ Documentation License''. @dircategory The Algorithmic Language Scheme @direntry -* Guile-Termenv: (guile-termenv). +* Guile-Termenv: (guile-termenv). ANSI style and color support for +terminal applications. @end direntry @titlepage @title The Guile-Termenv Manual -@author +@author Juliana Rat @page @vskip 0pt plus 1filll @@ -44,17 +48,531 @@ Edition @value{EDITION} @* @top Guile-Termenv This document describes Guile-Termenv version @value{VERSION}. +Guile-Termenv is a Guile port of the Go library +@url{https://github.com/muesli/termenv,termenv}. It analyzes +information about a terminal's ANSI and color support, then uses this +to provide a convenient interface for coloring and styling output. It +is incredibly powerful, and also surprisingly simple. This manual +provides a brief illustrative tutorial followed by API documentation. @menu -* Introduction:: Why Guile-Termenv? +* Tutorial:: An illustrative tutorial +* API:: Documentation for public procedures @end menu @c ********************************************************************* -@node Introduction -@chapter Introduction +@node Tutorial +@chapter Tutorial -INTRODUCTION HERE +TODO -This documentation is a stub. +@c ********************************************************************* +@node API +@chapter API + +The @code{guile-termenv} API aims to be simple and approachable while +allowing functional patterns and composition. + +@menu +* Color:: Procedures to colorize text +* Hyperlink:: Procedures to convert text to hyperlinks +* Screen:: Procedures for manipulating the terminal screen +* Style:: Procedures for styling text +* Unix:: A procedure to determine a terminal's best color profile +@end menu + +@node Color +@section Color + +The @code{(termenv color)} module provides a record type representing +colors, and a set of procedures for creating and using that record. + +Several color-related procedures accept what this documentation refers +to as a @dfn{hexcode}. Hexcodes are hexadecimal representations of +binary data associated with color values. Typically, a hexcode +consists of six hexadecimal digits split into three pairs. The first +pair represents the red value, the second pair represents the green +value, and the third pair represents the blue value. It is also +possible to use a single digit for each value if both digits are the +same. In this case, only one digit may be used per color. + +@code{termenv} accepts hexcodes as strings or as numbers, and it +recommends numbers. If using numbers, it is further recommended to use +Guile's base formatting prefix @code{#X} before the value for clarity. +If using strings, prefixes of any kind are optional and may be either +@code{#} or @code{0x}. + +@deftp {Record} color r g b type + +Record representing a color. This record serves as the central data +type of this module. It has four fields: + +@itemize +@item +@code{r}: Number in the range 0 to 255 representing the red value of +the color. + +@item +@code{g}: Number in the range 0 to 255 representing the green value of +the color. + +@item +@code{b}: Number in the range 0 to 255 representing the blue value of +the color. + +@item +@code{type}: Either @code{'foreground} or @code{'background}. + +@end itemize + +@end deftp + +@deffn {Procedure} color-r color + +Accessor for the @code{r} field of the record @var{color}, +representing its red value. + +@end deffn + +@deffn {Procedure} color-g color + +Accessor for the @code{g} field of the record @var{color}, +representing its green value. + +@end deffn + +@deffn {Procedure} color-b color + +Accessor the @code{b} field of the record @var{color}, representing +its blue value. + +@end deffn + +@deffn {Procedure} color? arg + +Predicate for whether or not @var{arg} is a @code{color}. + +@end deffn + +@deffn {Procedure} make-background hex + +Create a background @code{color} from the hexcode @var{hex}. + +@end deffn + +@deffn {Procedure} make-foreground hex + +Create a foreground @code{color} from the hexcode @var{hex}. + +@end deffn + +@deffn {Procedure} hex->color hex [type] + +Return a @code{color} representing the hexcode @var{hex}, optionally +with the given @var{type} (@code{'foreground} or @code{'background}). + +@end deffn + +@defvr {Parameter} current-color-profile + +Symbol representing the color profile of the current output port. The +possible values are: + +@itemize +@item +@var{true-color}: Port supports 24-bit ``true color'' representing +about 16 million colors. + +@item +@var{ansi256}: Port supports a 256-color palette consisting of 216 +colors, 16 ANSI colors, and 24 shades of gray. Color values are +24-bit. + +@item +@var{ansi}: Port supports 16 colors, bold, italics, and background +coloration. + +@item +@var{ascii}: Port does not support colors or styles. In practice, this +means the output port is not a terminal. + +@end itemize + +@end defvr + +@deffn {Procedure} color->sequence color + +Return a string of terminal control codes representing the +@code{color} record @var{color}. Uses @code{current-color-profile}. + +@end deffn + +@deffn {Procedure} color->ansi color + +Convert the 24-bit ``true color'' @var{color} to the nearest ANSI +color equivalent. + +@end deffn + +@deffn {Procedure} color->ansi256 color + +Convert the 24-bit ``true color'' @var{color} to the nearest 256-color +ANSI equivalent. + +@end deffn + +@node Hyperlink +@section Hyperlink + +The @code{(termenv hyperlink)} module provides procedures to create +active hyperlinks in the terminal. + +@deffn {Procedure} hyperlink link [name] + +Create a terminal control sequence which displays the optional string +@var{name} as a hyperlink to @var{link}. If @var{name} is not +provided, @var{link} is used verbatim. + +@end deffn + +@deffn {Procedure} format-hyperlink link [name] [port (current-output-port)] + +Write the string @var{name} to @var{port}, formatted as a hyperlink to +@var{link}. This is equivalent to: + +@lisp +(format port (hyperlink link name)) +@end lisp + +If @var{name} is not provided, @var{link} is used verbatim. If +@var{port} is not provided, @code{current-output-port} is used. + +@end deffn + +@node Screen +@section Screen + +The @code{(termenv screen)} module provides facilities for controlling +the general state of a terminal. + +@deffn {Procedure} reset [port (current-output-port)] + +Reset @var{port} to its default state, removing any active styles. + +@end deffn + +@deffn {Procedure} set-foreground-color hex [port (current-output-port)] + +Apply the hexcode @var{hex} as the default foreground color for +@var{port}. + +@end deffn + +@deffn {Procedure} set-background-color hex [port (current-output-port)] + +Apply the hexcode @var{hex} as the default background color for +@var{port}. + +@end deffn + +@deffn {Procedure} set-cursor-color hex [port (current-output-port)] + +Apply the hexcode @var{hex} as the default cursor color for +@var{port}. + +@end deffn + +@deffn {Procedure} save-screen [port (current-output-port)] + +Save the state of @var{port} so that it may be restored later with +@code{restore-screen}. + +@end deffn + +@deffn {Procedure} restore-screen [port (current-output-port)] + +Restore @var{port} to a state previously saved with +@code{save-screen}. + +@end deffn + +Terminals provide a facility called an @dfn{alternate screen} which +allows a program to write to a blank slate which is wiped away when +the program terminates. The following procedures allow programmers to +emit control codes entering and exiting this screen. + +@deffn {Procedure} alt-screen [port (current-output-port)] + +Switch @var{port} to the alternate screen buffer. + +@end deffn + +@deffn {Procedure} exit-alt-screen [port (current-output-port)] + +Switch @var{port} from the alternate screen buffer to the main screen +buffer. + +@end deffn + +@deffn {Procedure} hide-cursor [port (current-output-port)] + +Hide the cursor of @var{port}. + +@end deffn + +@deffn {Procedure} show-cursor [port (current-output-port)] + +Show the cursor of @var{port}. + +@end deffn + +@deffn {Procedure} save-cursor-position [port (current-output-port)] + +Save the current position of the cursor of @var{port}. + +@end deffn + +@deffn {Procedure} restore-cursor-position [port (current-output-port)] + +Restore the saved position of the cursor of @var{port}. + +@end deffn + +Terminals have a concept of a @dfn{scrolling region}. This is the +region of a terminal screen which is actively being controlled, and +according to whose coordinates the cursor is moved. Most of the +following procedures operate on the active scrolling region. + +@deffn {Procedure} change-scrolling-region top bottom [port (current-output-port)] + +Set the scrolling region of @var{port} to the area from row number +@var{top} to row number @var{bottom}. + +@end deffn + +@deffn {Procedure} clear-screen [port (current-output-port)] + +Clear the scrolling region of @var{port}. + +@end deffn + +@deffn {Procedure} move-cursor y x [port (current-output-port)] + +Move the cursor of @var{port} to row @var{y} and column @var{x}. Note +that these values are 1-based, so the top left corner is at the +coordinates @samp{1,1}. + +@end deffn + +@deffn {Procedure} scroll-up [amount 1] [port (current-output-port)] + +Scroll @var{port} up by @var{amount} rows. + +@end deffn + +@deffn {Procedure} scroll-down [amount 1] [port (current-output-port)] + +Scroll @var{port} down by @var{amount} rows. + +@end deffn + +@deffn {Procedure} cursor-up [distance 1] [port (current-output-port)] + +Move the cursor of @var{port} up @var{distance} rows. + +@end deffn + +@deffn {Procedure} cursor-down [distance 1] [port (current-output-port)] + +Move the cursor of @var{port} down @var{distance} rows. + +@end deffn + +@deffn {Procedure} cursor-forward [distance 1] [port (current-output-port)] + +Move the cursor of @var{port} forward @var{distance} columns. + +@end deffn + +@deffn {Procedure} cursor-back [distance 1] [port (current-output-port)] + +Move the cursor of @var{port} backwards @var{distance} columns. + +@end deffn + +@deffn {Procedure} cursor-next-line [distance 1] [port (current-output-port)] + +Move the cursor of @var{port} up @var{distance} rows and place it at +the beginning of the line. + +@end deffn + +@deffn {Procedure} cursor-prev-line [distance 1] [port (current-output-port)] + +Move the cursor of @var{port} down @var{distance} rows and place it at +the beginning of the line. + +@end deffn + +@deffn {Procedure} clear-line [port (current-output-port)] + +Clear the current line of @var{port}. + +@end deffn + +@deffn {Procedure} clear-line-left [port (current-output-port)] + +Clear the current line of @var{port} left of its cursor. + +@end deffn + +@deffn {Procedure} clear-line-right [port (current-output-port)] + +Clear the current line of @var{port} right of its cursor. + +@end deffn + +@deffn {Procedure} clear-lines n [port (current-output-port)] + +Clear @var{n} lines of @var{port}. + +@end deffn + +@deffn {Procedure} insert-lines n [port (current-output-port)] + +Insert @var{n} blank rows at the top of the scrolling region of +@var{port}, pushing lower rows down. + +@end deffn + +@deffn {Procedure} delete-lines n [port (current-output-port)] + +Delete @var{n} rows at the top of the scrolling region of @var{port}, +pulling any rows below up. + +@end deffn + +@deffn {Procedure} set-window-title title [port (current-output-port)] + +Set the window title of @var{port} to @var{title}. + +@end deffn + +@node Style +@section Style + +The @code{(termenv style)} module provides procedures for manipulating +the style and color (@pxref{Color}) of text. + +@deffn {Procedure} foreground c s @dots{} + +Return a string of terminal control codes representing the string or +strings @var{s} with the foreground color indicated by the hexcode +@var{c}. + +@end deffn + +@deffn {Procedure} background c s @dots{} + +Return a string of terminal control codes representing the string or +strings @var{s} with the background color indicated by the hexcode +@var{c}. + +@end deffn + +@deffn {Procedure} bold s @dots{} + +Return a string of terminal control codes to render the string or +strings @var{s} in boldface. + +@end deffn + +@deffn {Procedure} faint s @dots{} + +Return a string of terminal control codes to render the string or +strings @var{s} faintly. + +@end deffn + +@deffn {Procedure} italic s @dots{} + +Return a string of terminal control codes to italicize the string or +strings @var{s}. + +@end deffn + +@deffn {Procedure} underline s @dots{} + +Return a string of terminal control codes to underline the string or +strings @var{s}. + +@end deffn + +@deffn {Procedure} overline s @dots{} + +Return a string of terminal control codes to overline the string or +strings @var{s}. + +@end deffn + +@deffn {Procedure} blink s @dots{} + +Return a string of terminal control codes to render the string or +strings @var{s} blinking. + +@end deffn + +@deffn {Procedure} invert s @dots{} + +Return a string of terminal control codes to reverse the string or +strings @var{s}. + +@end deffn + +@deffn {Procedure} cross-out s @dots{} + +Return a string of terminal control codes to cross out the string or +strings @var{s} in boldface. + +@end deffn + +@node Unix +@section Unix + +The @code{(termenv unix)} module provides a single procedure for +determining the color and control code support of a terminal. + +@deffn {Procedure} color-profile port + +Test the characteristics of the terminal indicated by @code{port} and +return a symbol indicating its highest-bit color profile. Returns one +of: + +@itemize +@item +@var{true-color}: Port supports 24-bit ``true color'' representing +about 16 million colors. + +@item +@var{ansi256}: Port supports a 256-color palette consisting of 216 +colors, 16 ANSI colors, and 24 shades of gray. Color values are +24-bit. + +@item +@var{ansi}: Port supports 16 colors, bold, italics, and background +coloration. + +@item +@var{ascii}: Port does not support colors or styles. In practice, this +means the output port is not a terminal. + +@end itemize + +@end deffn + +@node Index +@unnumbered Index + +@printindex fn @bye