Skip to content

Commit 7cb0c16

Browse files
committed
Disable ANSI fonts and colors when not on a console
1 parent 6efda58 commit 7cb0c16

File tree

2 files changed

+50
-14
lines changed

2 files changed

+50
-14
lines changed

src/io/aviso/ansi.clj

+44-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,40 @@
11
(ns io.aviso.ansi
22
"Help with generating textual output that includes ANSI escape codes for formatting."
3-
(:import
4-
[java.util.regex Pattern])
5-
(:require
6-
[clojure.string :as str]))
3+
(:require [clojure.string :as str]
4+
[clojure.walk :as walk]))
5+
6+
(def ^:const ansi-output-enabled?
7+
"Determine if ANSI output is enabled. If the environment variable ENABLE_ANSI_COLORS is non-null,
8+
then it sets the value: the value `false` (matched caselessly) disables ANSI colors and fonts,
9+
otherwise they are enabled.
10+
11+
Next, there is an attempt to determine if execution is currently inside an REPL environment,
12+
possibly started from an IDE; a check is made to see if `nrepl.core` namespace is loaded;
13+
if so, then ANSI colors are enabled.
14+
15+
This has been verified to work with Cursive, with `lein repl`, and with `clojure` (or `clj`).
16+
17+
This check is necessary, because often in such cases, there is no console (the next check).
18+
19+
Otherwise, if the system has a console (via `(System/console)`) ANSI output will be enabled;
20+
when Clojure is running in a pipe, or as a background job without a terminal attached, the console
21+
will be nil and ANSI output will be disabled.
22+
23+
When this value is false, all the generated color and font constants return the empty string, and the
24+
color and font functions return the input string unchanged. This is decided during macro expansion when
25+
the ansi namespace is first loaded, so it can't be changed at runtime."
26+
(if-let [value (System/getenv "ENABLE_ANSI_COLORS")]
27+
(not (.equalsIgnoreCase value "false"))
28+
(some?
29+
(or
30+
(contains? (set (loaded-libs)) 'nrepl.core)
31+
(System/console)))))
32+
33+
(defmacro ^:private if-enabled?
34+
[expr]
35+
(if ansi-output-enabled?
36+
expr
37+
""))
738

839
(def ^:const csi
940
"The control sequence initiator: `ESC [`"
@@ -14,27 +45,29 @@
1445
"The Select Graphic Rendition suffix: m"
1546
"m")
1647

17-
(def ^:const
18-
reset-font
48+
(def ^:const reset-font
1949
"Resets the font, clearing bold, italic, color, and background color."
20-
(str csi sgr))
50+
(if-enabled? (str csi sgr)))
2151

2252
(defmacro ^:private def-sgr-const
2353
"Utility for defining a font-modifying constant."
2454
[symbol-name color-name & codes]
2555
`(def ~(vary-meta (symbol symbol-name) assoc :const true)
2656
~(format "Constant for ANSI code to enable %s text." color-name)
27-
(str csi ~(str/join ";" codes) sgr)))
57+
~(if-enabled? (str csi (str/join ";" codes) sgr))))
2858

2959
(defmacro ^:private def-sgr-fn
3060
"Utility for creating a function that enables some combination of SGR codes around some text, but resets
3161
the font after the text."
3262
[fn-name color-name & codes]
33-
(let [arg 'text]
63+
(let [arg 'text
64+
prefix (str csi (str/join ";" codes) sgr)]
3465
`(defn ~(symbol fn-name)
3566
~(format "Wraps the provided text with ANSI codes to render as %s text." color-name)
3667
[~arg]
37-
(str csi ~(str/join ";" codes) sgr ~arg reset-font))))
68+
~(if ansi-output-enabled?
69+
`(str ~prefix ~arg ~reset-font)
70+
arg))))
3871

3972
;;; Define functions and constants for each color. The functions accept a string
4073
;;; and wrap it with the ANSI codes to set up a rendition before the text,
@@ -86,7 +119,7 @@
86119

87120
(define-fonts)
88121

89-
(def ^:const ^:private ansi-pattern (Pattern/compile "\\e\\[.*?m"))
122+
(def ^:const ^:private ansi-pattern #"\e\[.*?m")
90123

91124
(defn ^String strip-ansi
92125
"Removes ANSI codes from a string, returning just the raw text."

src/io/aviso/exception.clj

+6-3
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@
2929
nil)
3030

3131
(def ^:dynamic *fonts*
32-
"Current set of fonts used in exception formatting. This can be overridden to change colors, our bound to nil
33-
to disable fonts. Further, the environment variable DISABLE_DEFAULT_PRETTY_FONTS, if non-nil, will default
34-
this to nil."
32+
"Current set of fonts used in exception formatting. This can be overridden to change colors, or bound to nil
33+
to disable fonts.
34+
35+
~Further, the environment variable DISABLE_DEFAULT_PRETTY_FONTS, if non-nil, will default this to nil.~
36+
37+
Starting in 1.3, ANSI fonts may be disabled; see [[ansi-output-enabled?]]"
3538
(when-not (System/getenv "DISABLE_DEFAULT_PRETTY_FONTS")
3639
default-fonts))
3740

0 commit comments

Comments
 (0)