ANSI Control Sequence Aware String Functions

Counterparts to R string manipulation functions that account for the effects of ANSI text formatting control sequences.


Counterparts to R string manipulation functions that account for the effects of ANSI text formatting control sequences.

Formatting Strings with Control Sequences

Many terminals will recognize special sequences of characters in strings and change display behavior as a result. For example, on my terminal the sequence "\033[42m" turns text background green:

helloworld

The sequence itself is not shown, but the text display changes.

This type of sequence is called an ANSI CSI SGR control sequence. Most *nix terminals support them, and newer versions of Windows and Rstudio consoles do too. You can check whether your display supports them by running term_cap_test().

Whether the fansi functions behave as expected depends on many factors, including how your particular display handles Control Sequences. See ?fansi for details, particularly if you are getting unexpected results.

Control Sequences Require Special Handling

ANSI control characters and sequences (Control Sequences hereafter) break the relationship between byte/character position in a string and display position.

For example, in "Hello \033[42mWorld, Good\033[m Night Moon!" the space after "World," is thirteenth displayed character, but the eighteenth actual character ("\033" is a single character, the ESC). If we try to split the string after the space with substr things go wrong in several ways:

bad substring

We end up cutting up our string in the middle of "World", and worse the formatting bleeds out of our string into the prompt line. Compare to what happens when we use substr_ctl, the Control Sequence aware version of substr:

good substring

Functions

fansi provides counterparts to the following string functions:

  • substr
  • strsplit
  • strtrim
  • strwrap
  • nchar / nzchar

These are drop-in replacements that behave (almost) identically to the base counterparts, except for the Control Sequence awareness.

fansi also includes improved versions of some of those functions, such as substr2_ctl which allows for width based substrings. There are also utility functions such as strip_ctl to remove Control Sequences and has_ctl to detect whether strings contain them.

Most of fansi is written in C so you should find performance of the fansi functions to be comparable to the base functions. strwrap_ctl is much faster, and strsplit_ctl is somewhat slower than the corresponding base functions.

HTML Translation

You can translate ANSI CSI SGR formatted strings into their HTML counterparts with sgr_to_html:

translate to html

Rmarkdown

It is possible to set knitr hooks such that R output that contains ANSI CSI SGR is automatically converted to the HTML formatted equivalent and displayed as intended. See the vignette for details.

Installation

This package is available on CRAN:

install.packages('fansi')

It has no runtime dependencies.

For the development version use: devtools::install_github('brodieg/[email protected]') or:

f.dl <- tempfile()
f.uz <- tempfile()
github.url <- 'https://github.com/brodieG/fansi/archive/development.zip'
download.file(github.url, f.dl)
unzip(f.dl, exdir=f.uz)
install.packages(file.path(f.uz, 'fansi-development'), repos=NULL, type='source')
unlink(c(f.dl, f.uz))

There is no guarantee that development versions are stable or even working (Travis build status: ). The master branch typically mirrors CRAN and should be stable.

Related Packages and References

Acknowledgments

News

fansi Release Notes

v0.4.0

  • Systematized which control sequences are handled specially by adding the ctl parameter to most functions. Some functions such as strip_ctl had existing parameters that did the same thing (e.g. strip, or which), and those have been deprecated in favor of ctl. While technically this is a change in the API, it is backwards compatible (addresses #56 among and other things).
  • Added *_sgr version of most *_ctl functions.
  • nzchar_ctl gains the ctl parameter.
  • #57: Correctly detect when CSI sequences are not actually SGR (previously would apply styles from some non-SGR CSI sequences).
  • #55: strsplit_ctl can now work with ctl parameters containing escape sequences provided those sequences are excluded from by the ctl parameter.
  • #54: fix sgr_to_html so that it can handle vector elements with un-terminated SGR sequences (@krlmlr).
  • Fix bug in width computation of first line onwards in strwrap_ctl when indent/exdent/prefix/initial widths vary from first to second line.
  • Fix wrapping in strwrap2_*(..., strip.spaces=FALSE), including a bug when wrap.always=TRUE and a line started in a word-whitespace boundary.
  • Add term.cap parameter to unhandled_ctl.

v0.3.0

  • fansi::set_knit_hooks makes it easy to automatically convert ANSI CSI SGR sequences to HTML in Rmarkdown documents. We also add a vignette that demonstrates how to do this.
  • #53: fix for systems where 'char' is signed (found and fixed by @QuLogic).
  • #52: fix bad compilation under ICC (@kazumits).
  • #51: documentation improvements (@krlmlr).
  • #50: run tests on R 3.1 - 3.4 tests for the rc branch only (@krlmlr).
  • #48: malformed call to error in FANSI_check_enc (@msannell).
  • #47: compatibility with R versions 3.2.0 and 3.2.1 (@andreadega).

v0.2.3

Other minor fixes (#43, #46).

v0.2.2

  • Remove valgrind uninitialized string errors by avoiding strsplit.
  • Reduce R dependency to >= 3.2.x (@gaborcsardi).
  • Update tests to handle potential change in substr behavior starting with R-3.6.

v0.2.1

  • All string inputs are now encoded to UTF-8, not just those that are used in width calculations.
  • UTF-8 tests skipped on Solaris.

v0.2.0

  • Add strsplit_ctl.

v0.1.0

Initial release.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("fansi")

0.4.0 by Brodie Gaslam, 2 months ago


https://github.com/brodieG/fansi


Report a bug at https://github.com/brodieG/fansi/issues


Browse source code at https://github.com/cran/fansi


Authors: Brodie Gaslam [aut, cre] , Elliott Sales De Andrade [ctb] , R Core Team [cph] (UTF8 byte length calcs from src/util.c)


Documentation:   PDF Manual  


GPL (>= 2) license


Suggests unitizer, knitr, rmarkdown


Imported by pillar, pkgdown.

Suggested by cli.


See at CRAN