README.md
1<!-- README.md is generated from README.Rmd. Please edit that file
2library(rmarkdown)
3render('README.Rmd', output_format=md_document())
4render('README.Rmd', output_format=html_document())
5 -->
6fansi - ANSI Control Sequence Aware String Functions
7====================================================
8
9[![R build
10status](https://github.com/brodieG/fansi/workflows/R-CMD-check/badge.svg)](https://github.com/brodieG/fansi/actions)
11[![](https://codecov.io/gh/brodieG/fansi/branch/master/graphs/badge.svg?branch=master)](https://codecov.io/github/brodieG/fansi?branch=master)
12[![](http://www.r-pkg.org/badges/version/fansi)](https://cran.r-project.org/package=fansi)
13[![Dependencies
14direct/recursive](https://tinyverse.netlify.app/badge/fansi)](https://tinyverse.netlify.app/)
15
16Counterparts to R string manipulation functions that account for the
17effects of ANSI text formatting control sequences.
18
19Formatting Strings with Control Sequences
20-----------------------------------------
21
22Many terminals will recognize special sequences of characters in strings
23and change display behavior as a result. For example, on my terminal the
24sequence `"\033[42m"` turns text background green:
25
26![hello
27world](https://raw.githubusercontent.com/brodieG/fansi/rc/extra/images/hello.png)
28
29The sequence itself is not shown, but the text display changes.
30
31This type of sequence is called an ANSI CSI SGR control sequence. Most
32\*nix terminals support them, and newer versions of Windows and Rstudio
33consoles do too. You can check whether your display supports them by
34running `term_cap_test()`.
35
36Whether the `fansi` functions behave as expected depends on many
37factors, including how your particular display handles Control
38Sequences. See `?fansi` for details, particularly if you are getting
39unexpected results.
40
41Control Sequences Require Special Handling
42------------------------------------------
43
44ANSI control characters and sequences (*Control Sequences* hereafter)
45break the relationship between byte/character position in a string and
46display position.
47
48For example, in `"Hello \033[42mWorld, Good\033[m Night Moon!"` the
49space after “World,” is thirteenth displayed character, but the
50eighteenth actual character (“\\033” is a single character, the ESC). If
51we try to split the string after the space with `substr` things go wrong
52in several ways:
53
54![bad
55substring](https://raw.githubusercontent.com/brodieG/fansi/master/extra/images/substr.png)
56
57We end up cutting up our string in the middle of “World”, and worse the
58formatting bleeds out of our string into the prompt line. Compare to
59what happens when we use `substr_ctl`, the *Control Sequence* aware
60version of `substr`:
61
62![good
63substring](https://raw.githubusercontent.com/brodieG/fansi/master/extra/images/substr_ctl.png)
64
65Functions
66---------
67
68`fansi` provides counterparts to the following string functions:
69
70- `substr`
71- `strsplit`
72- `strtrim`
73- `strwrap`
74- `nchar` / `nzchar`
75
76These are drop-in replacements that behave (almost) identically to the
77base counterparts, except for the *Control Sequence* awareness.
78
79`fansi` also includes improved versions of some of those functions, such
80as `substr2_ctl` which allows for width based substrings. There are also
81utility functions such as `strip_ctl` to remove *Control Sequences* and
82`has_ctl` to detect whether strings contain them.
83
84Most of `fansi` is written in C so you should find performance of the
85`fansi` functions to be comparable to the base functions. `strwrap_ctl`
86is much faster, and `strsplit_ctl` is somewhat slower than the
87corresponding base functions.
88
89HTML Translation
90----------------
91
92You can translate ANSI CSI SGR formatted strings into their HTML
93counterparts with `sgr_to_html`:
94
95![translate to
96html](https://raw.githubusercontent.com/brodieG/fansi/master/extra/images/sgr_to_html.png)
97
98Rmarkdown
99---------
100
101It is possible to set `knitr` hooks such that R output that contains
102ANSI CSI SGR is automatically converted to the HTML formatted equivalent
103and displayed as intended. See the
104[vignette](https://htmlpreview.github.io/?https://raw.githubusercontent.com/brodieG/fansi/issue61/doc/sgr-in-rmd.html)
105for details.
106
107Installation
108------------
109
110This package is available on CRAN:
111
112 install.packages('fansi')
113
114It has no runtime dependencies.
115
116For the development version use
117`remotes::install_github('brodieg/fansi@development')` or:
118
119 f.dl <- tempfile()
120 f.uz <- tempfile()
121 github.url <- 'https://github.com/brodieG/fansi/archive/development.zip'
122 download.file(github.url, f.dl)
123 unzip(f.dl, exdir=f.uz)
124 install.packages(file.path(f.uz, 'fansi-development'), repos=NULL, type='source')
125 unlink(c(f.dl, f.uz))
126
127There is no guarantee that development versions are stable or even
128working. The master branch typically mirrors CRAN and should be stable.
129
130Related Packages and References
131-------------------------------
132
133- [crayon](https://github.com/r-lib/crayon), the library that started
134 it all.
135- [ansistrings](https://github.com/r-lib/ansistrings/), which
136 implements similar functionality.
137- [ECMA-48 - Control Functions For Coded Character
138 Sets](https://www.ecma-international.org/publications-and-standards/standards/ecma-48/),
139 in particular pages 10-12, and 61.
140- [CCITT Recommendation
141 T.416](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.416-199303-I!!PDF-E&type=items)
142- [ANSI Escape Code -
143 Wikipedia](https://en.wikipedia.org/wiki/ANSI_escape_code) for a
144 gentler introduction.
145
146Acknowledgments
147---------------
148
149- R Core for developing and maintaining such a wonderful language.
150- CRAN maintainers, for patiently shepherding packages onto CRAN and
151 maintaining the repository, and Uwe Ligges in particular for
152 maintaining [Winbuilder](http://win-builder.r-project.org/).
153- [Gábor Csárdi](https://github.com/gaborcsardi) for getting me
154 started on the journey ANSI control sequences, and for many of the
155 ideas on how to process them.
156- [Jim Hester](https://github.com/jimhester) for
157 [covr](https://cran.r-project.org/package=covr), and with Rstudio
158 for [r-lib/actions](https://github.com/r-lib/actions).
159- [Dirk Eddelbuettel](https://github.com/eddelbuettel) and [Carl
160 Boettiger](https://github.com/cboettig) for the
161 [rocker](https://github.com/rocker-org/rocker) project, and [Gábor
162 Csárdi](https://github.com/gaborcsardi) and the
163 [R-consortium](https://www.r-consortium.org/) for
164 [Rhub](https://github.com/r-hub), without which testing bugs on
165 R-devel and other platforms would be a nightmare.
166- [Tomas Kalibera](https://github.com/kalibera) for
167 [rchk](https://github.com/kalibera/rchk) and the accompanying
168 vagrant image, and rcnst to help detect errors in compiled code.
169- [Winston Chang](https://github.com/wch) for the
170 [r-debug](https://hub.docker.com/r/wch1/r-debug/) docker container,
171 in particular because of the valgrind level 2 instrumented version
172 of R.
173- [Hadley Wickham](https://github.com/hadley/) and [Peter
174 Danenberg](https://github.com/klutometis) for
175 [roxygen2](https://cran.r-project.org/package=roxygen2).
176- [Yihui Xie](https://github.com/yihui) for
177 [knitr](https://cran.r-project.org/package=knitr) and [J.J.
178 Allaire](https://github.com/jjallaire) et al. for
179 [rmarkdown](https://cran.r-project.org/package=rmarkdown), and by
180 extension John MacFarlane for [pandoc](https://pandoc.org/).
181- [Gábor Csárdi](https://github.com/gaborcsardi), the
182 [R-consortium](https://www.r-consortium.org/), et al. for
183 [revdepcheck](https://github.com/r-lib/revdepcheck) to simplify
184 reverse dependency checks.
185- Olaf Mersmann for
186 [microbenchmark](https://cran.r-project.org/package=microbenchmark),
187 because microsecond matter, and [Joshua
188 Ulrich](https://github.com/joshuaulrich) for making it lightweight.
189- All open source developers out there that make their work freely
190 available for others to use.
191- [Github](https://github.com/), [Travis-CI](https://travis-ci.org/),
192 [Codecov](https://about.codecov.io/),
193 [Vagrant](https://www.vagrantup.com/),
194 [Docker](https://www.docker.com/), [Ubuntu](https://ubuntu.com/),
195 [Brew](https://brew.sh/) for providing infrastructure that greatly
196 simplifies open source development.
197- [Free Software Foundation](https://www.fsf.org/) for developing the
198 GPL license and promotion of the free software movement.
199