r-lib / cli
1

2
#' Determine the width of the console
3
#'
4
#' It uses the `cli.width` option, if set. Otherwise it tries to
5
#' determine the size of the terminal or console window.
6
#'
7
#' These are the exact rules:
8
#' * If the `cli.width` option is set to a positive integer, it is used.
9
#' * If the `cli.width` option is set, but it is not a positive integer,
10
#'   and error is thrown.
11
#'
12
#' Then we try to determine the size of the terminal or console window:
13
#' * If we are not in RStudio, or we are in an RStudio temrinal,
14
#'   then we try to use the `ps::ps_tty_size()` function to query the
15
#'   terminal size. This might fail if ps is not installed or R is not
16
#'   running in a terminal, but failures are ignored.
17
#' * If we are in the RStudio build pane, then the `RSTUDIO_CONSOLE_WIDTH`
18
#'   environment variable is used. If the build pane is resized, then this
19
#'   environment variable is not accurate any more, and the output might
20
#'   get garbled.
21
#' * We are _not_ using the `RSTUDIO_CONSOLE_WIDTH` environment variable
22
#'   if we are in the RStudio console.
23
#'
24
#' If we cannot determine the size of the terminal or console window, then
25
#' we use the `width` option. If the `width` option is not set, then
26
#' we return 80L.
27
#'
28
#' @return Integer scalar, the console with, in number of characters.
29
#'
30
#' @export
31
#' @examples
32
#' console_width()
33

34
console_width <- function() {
35
  # cli.width option always takes priotity
36 1
  cwopt <- getOption("cli.width")
37 1
  if (!is.null(cwopt)) {
38 0
    if (!is.numeric(cwopt)) stop("options(\"cli.width\") must be integer")
39 0
    if (length(cwopt) != 1) stop("options(\"cli.width\") must be a scalar")
40 0
    if (!is.finite(cwopt)) stop("options(\"cli.width\") must be finite")
41 0
    if (is.na(cwopt)) stop("options(\"cli.width\") cannot be NA")
42 1
    cwopti <- as.integer(cwopt)
43 0
    if (cwopti <= 0) stop("options(\"cli.width\") must be a positive integer")
44 1
    return(cwopti)
45
  }
46

47
  # detect if in RStudio
48 1
  rs <- rstudio$detect()
49 1
  if (rs$type == "not_rstudio") {
50
    # maybe a terminal?
51 1
    width <- terminal_width()
52

53 0
  } else if (rs$type == "rstudio_console_starting") {
54
    # there isn't much we can do here, options and env vars are not set
55 0
    width <- NULL
56

57 0
  } else if (rs$type == "rstudio_console") {
58
    # will just use getOption("width"), in case the user changed it,
59
    # and ignore the RSTUDIO_CONSOLE_WIDTH env var
60 0
    width <- NULL
61

62 0
  } else if (rs$type == "rstudio_build_pane") {
63
    # RStudio explicitly sets this for build pane processes
64
    # It is only good when the build starts, but we cannot do better
65 0
    width <- rs_console_width()
66

67 0
  } else if (rs$type == "rstudio_terminal") {
68
    # Can also be a subprocess of the terminal, with a pty,
69
    # but that's fine, the pty should have a width set up.
70
    # We do not fall back to the RSTUDIO_CONSOLE_WIDTH env var,
71
    # because the user might have changed options("width") and the env
72
    # var is only good when the terminal starts, anyway.
73 0
    width <- terminal_width()
74

75
  } else { # rstudio_subprocess
76 0
    width <- NULL
77
  }
78

79
  # If not set, then use the option
80 1
  width <- width %||% getOption("width") %||% 80L
81

82 1
  width
83
}
84

85
terminal_width <- function() {
86 1
  w <- tryCatch(ps::ps_tty_size()[["width"]], error = function(e) NULL)
87
  # this is probably a pty that does not set the width, use st sensible
88 0
  if (!is.null(w) && w == 0) w <- 80L
89 1
  w
90
}
91

92
rs_console_width <- function() {
93 0
  ev <- as.integer(Sys.getenv("RSTUDIO_CONSOLE_WIDTH", ""))[1]
94 0
  if (!is.na(ev)) ev else NULL
95
}

Read our documentation on viewing source code .

Loading