## Copyright (C) Brodie Gaslam ## ## This file is part of "fansi - ANSI Control Sequence Aware String Functions" ## ## 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 2 or 3 of the License. ## ## 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. ## ## Go to for copies of the licenses. library(unitizer) library(fansi) unitizer_sect("term_cap_test", { tct <- term_cap_test() tct fansi_lines(LETTERS, step=6) # should only be one warning at index 1 local({ tc <- getOption('fansi.term.cap') col <- Sys.getenv('COLORTERM', unset=NA) on.exit({ options(fansi.term.cap=tc) if(is.na(col)) suppressWarnings(Sys.unsetenv("COLORTERM")) else Sys.setenv(COLORTERM=col) }) options(fansi.term.cap=NULL) suppressWarnings(Sys.unsetenv("COLORTERM")) string <- "a\033[38;2;50;50;50m" substr_ctl(c(string, ""), 1, 10) Sys.setenv(COLORTERM="truecolor") substr_ctl(c("", string), 1, 10) }) }) unitizer_sect("add_int", { fansi:::add_int(1, 1) fansi:::add_int(2^31 - 1, 1) fansi:::add_int(2^31 - 1, 0) fansi:::add_int(-2^31 + 1, 0) fansi:::add_int(-2^31 + 1, -1) }) unitizer_sect("unhandled", { # example string.0 <- c( "\033[41mhello world\033[m", "foo\033[22>m", "\033[999mbar", "baz \033[31#3m", "a\033[31k", "hello\033m world" ) unhandled_ctl(string.0) # some more interesting cases string.1 <- c( "foo\033[22>mhello\033[9999m", "a\033[31k", "hello\033m \033[180mworld \033" ) unhandled_ctl(string.1) # A malformed ESCape unhandled_ctl("hello\033\033\033[45p wor\ald") # Specifying term cap unhandled_ctl("\033[38;5;220mworld\033[m", "bright") unhandled_ctl("\033[38;2;10;20;30mworld\033[m", "bright") unhandled_ctl("\033[38;2;10;20;30mworld\033[m", "bri") unhandled_ctl("\033[38;2;10;20;30mworld\033[m", NULL) # Malformed in sequences unhandled_ctl("AB\033[34m\033]9\033\\\033[1m\033[2LCD") # Unterminated OSC consumes everything unhandled_ctl("AB\033[34m\033]9\033[1m\033[2LCD") # Non-SGR and SGR bad tokens unhandled_ctl("A\033[45#1pB\033[256pC\033[256mD") # Abruptly ending 256/truecolor unhandled_ctl("\033[38m") }) unitizer_sect("strtrim", { strtrim_ctl(" hello world", 7) strtrim_ctl("\033[42m hello world\033[m", 7) strtrim_ctl(" hello\nworld", 7) strtrim_ctl("\033[42m hello\nworld\033[m", 7) strtrim_ctl("\nhello\nworld", 7) strtrim_ctl("\033[42m\nhello\nworld\033[m", 7) strtrim_ctl("\thello\rworld foobar", 12) strtrim_ctl("\033[42m\thello\rworld\033[m foobar", 12) strtrim2_ctl("\033[42m\thello world\033[m foobar", 12, tabs.as.spaces=TRUE) strtrim_sgr("\033[42m\the\allo world\033[m foobar", 12, warn=FALSE) strtrim2_sgr( "\033[42m\the\allo world\033[m foobar", 12, tabs.as.spaces=TRUE, warn=FALSE, tab.stops=2 ) # NA handling identical( strtrim_ctl(c("AB", NA_character_, "CD"), 1), strtrim(c("AB", NA_character_, "CD"), 1) ) strtrim_ctl(c("AB", NA_character_, "CD"), 1, carry=TRUE) # bad args hello2.0 <- "\033[42m\thello world\033[m foobar" strtrim_ctl(1:3, width=10) strtrim_ctl(hello2.0, width="35") strtrim_ctl(hello2.0, width=NA_integer_) strtrim_ctl(hello2.0, width=10, warn=NULL) strtrim_ctl(hello2.0, width=10, ctl=0) strtrim_ctl(hello2.0, width=10, ctl='bananas') strtrim2_ctl(1:3, width=10) strtrim2_ctl(hello2.0, width="35") strtrim2_ctl(hello2.0, width=NA_integer_) strtrim2_ctl(hello2.0, width=10, warn=NULL) strtrim2_ctl(hello2.0, width=10, tabs.as.spaces=NA) strtrim2_ctl(hello2.0, width=10, tabs.as.spaces=1:3) strtrim2_ctl(hello2.0, width=10, tab.stops=-(1:3)) strtrim2_ctl(hello2.0, width=10, tab.stops=0) strtrim2_ctl(hello2.0, width=10, ctl=0) strtrim2_ctl(hello2.0, width=10, ctl='bananas') }) unitizer_sect("enc check", { x <- y <- "He\x9f" Encoding(x) <- "latin1" fansi:::check_enc(x, 1) Encoding(y) <- "bytes" fansi:::check_enc(y, 1) fansi:::check_enc("hello", 1) }) unitizer_sect("what as int", { fansi:::ctl_as_int(c(1, 2, 3, 4, 5)) fansi:::ctl_as_int(c(2, 3, 4, 5)) fansi:::ctl_as_int(c(1, 2, 3, 9)) fansi:::ctl_as_int(c(2, 3, 9)) }) unitizer_sect("HTML helper", { html_esc(character()) html_esc(1:10) html_esc(NA_character_) html_esc("") html_esc("ow&wo") html_esc(c("hello", "wors", NA, "")) html_esc(c("he'l\"lo", "wors", NA, "")) html_esc("<<<<") html_esc("<123hello>") txt <- c( "day > night", "hello world" ) html_code_block(character()) html_code_block(txt) html_code_block(1:10) html_code_block(txt, class=c('not-fansi', 'plain')) html_code_block(txt, class=NULL) html_esc(c("h&e'l\"lo", "wors", NA, ""), "<>") html_esc(c("h&e'l\"lo", "wors", NA, ""), "><") html_esc(c("h&e'l\"lo", "wors", NA, ""), "<&>") html_esc(c("h&e'l\"lo", "wors", NA, ""), "'<&>") html_esc(c("h&e'l\"lo", "wors", NA, ""), "'<&>\"") html_esc(c("h&e'l\"lo", "wors", NA, ""), "'&>\"<") html_esc(c("h&e'l\"lo", "wors", NA, ""), "") ## repeated chars okay html_esc(c("h&e'l\"lo", "wors", NA, ""), "'<&>\"<") ## Errors html_esc(c("h&e'l\"lo", "wors", NA, ""), character()) html_esc(c("h&e'l\"lo", "wors", NA, ""), NA_character_) html_esc(c("h&e'l\"lo", "wors", NA, ""), 1:5) html_esc(c("h&e'l\"lo", "wors", NA, ""), "'<&><") html_esc(c("h&e'l\"lo", "wors", NA, ""), "'x><") }) unitizer_sect("hooks", { h.1 <- list( set=function(...) cat("Set hooks: ", names(list(...)), "\n"), get=function(...) function(...) "old.hook" ) h.2 <- list( set=function(...) cat("Set hooks: ", names(list(...)), "\n"), get=function(...) "not a function" ) h.3 <- list( set=function(...) cat("Set hooks: ", names(list(...)), "\n"), get=function(...) stop("error in get") ) h.4 <- list( set=function(...) stop("error in set"), get=function(...) function() "old.hook" ) ## Works set_knit_hooks(list(1, 2)) set_knit_hooks(list(function() NULL, function() NULL)) res1 <- set_knit_hooks(h.1, .test=TRUE) res1[['new.hooks']][['output']]("hello") res1[['new.hooks']][['output']]("hello\033[31m world") ## split.nl works res1a <- set_knit_hooks(h.1, split.nl=TRUE, .test=TRUE) res1a[['new.hooks']][['output']]("hello\033[31m wo\nrld") p.f.2 <- function(x, y) NULL p.f.3 <- function(x, class) sprintf("new proc fun, '%s'", class) p.f.4 <- function(x, class) stop("new proc fun") ## bad inputs set_knit_hooks(h.1, split.nl='banana') set_knit_hooks(h.1, proc.fun=p.f.2) set_knit_hooks(h.1, which="hello") set_knit_hooks(h.1, which=NULL) ## works res2 <- set_knit_hooks( h.1, which=c('output', 'message'), class=c('f-output', 'f-message'), proc.fun=p.f.3, .test=TRUE ) res2[['new.hooks']][['message']]("hello") res2[['new.hooks']][['message']]("hello\033[31m world") res2[['new.hooks']][['output']]("hello\033[31m world") ## error in proc.fun res3 <- set_knit_hooks( h.1, which=c('message', 'warning'), proc.fun=p.f.4, .test=TRUE ) res3[['new.hooks']][['warning']]("hello") res3[['new.hooks']][['warning']]("hello\033[31mworld") ## hook errors set_knit_hooks(h.2) set_knit_hooks(h.3) set_knit_hooks(h.4) ## Other errors set_knit_hooks(h.1, style=NULL) set_knit_hooks(h.1, class=1:10) set_knit_hooks(h.1, class=letters) set_knit_hooks(h.1, which=c('output', 'message', 'output')) }) unitizer_sect("output funs", { fansi_lines(1:3) fansi_lines(1:3, step='hello') capture.output(fwl("\033[43mhello")) }) unitizer_sect("validation", { fansi:::VAL_IN_ENV(booboo="error") })