|
2 | 2 | # SPDX-FileCopyrightText: 2021 The Elixir Team
|
3 | 3 | # SPDX-FileCopyrightText: 2012 Plataformatec
|
4 | 4 |
|
5 |
| -defmodule IO.ANSI.Sequence do |
6 |
| - @moduledoc false |
7 |
| - |
8 |
| - defmacro defsequence(name, code, terminator \\ "m") do |
9 |
| - quote bind_quoted: [name: name, code: code, terminator: terminator] do |
10 |
| - @spec unquote(name)() :: String.t() |
11 |
| - def unquote(name)() do |
12 |
| - "\e[#{unquote(code)}#{unquote(terminator)}" |
13 |
| - end |
14 |
| - |
15 |
| - defp format_sequence(unquote(name)) do |
16 |
| - unquote(name)() |
17 |
| - end |
18 |
| - end |
19 |
| - end |
20 |
| -end |
21 |
| - |
22 | 5 | defmodule IO.ANSI do
|
23 | 6 | @moduledoc """
|
24 | 7 | Functionality to render ANSI escape sequences.
|
@@ -53,8 +36,6 @@ defmodule IO.ANSI do
|
53 | 36 | In case ANSI is disabled, the ANSI escape sequences are simply discarded.
|
54 | 37 | """
|
55 | 38 |
|
56 |
| - import IO.ANSI.Sequence |
57 |
| - |
58 | 39 | @type ansicode :: atom
|
59 | 40 | @type ansilist ::
|
60 | 41 | maybe_improper_list(char | ansicode | binary | ansilist, binary | ansicode | [])
|
@@ -129,104 +110,121 @@ defmodule IO.ANSI do
|
129 | 110 | color_background(16 + 36 * r + 6 * g + b)
|
130 | 111 | end
|
131 | 112 |
|
| 113 | + defsequence = fn name, code, terminator -> |
| 114 | + @spec unquote(name)() :: String.t() |
| 115 | + def unquote(name)() do |
| 116 | + "\e[#{unquote(code)}#{unquote(terminator)}" |
| 117 | + end |
| 118 | + |
| 119 | + defp format_sequence(unquote(name)) do |
| 120 | + unquote(name)() |
| 121 | + end |
| 122 | + end |
| 123 | + |
132 | 124 | @doc "Resets all attributes."
|
133 |
| - defsequence(:reset, 0) |
| 125 | + defsequence.(:reset, 0, "m") |
134 | 126 |
|
135 | 127 | @doc "Bright (increased intensity) or bold."
|
136 |
| - defsequence(:bright, 1) |
| 128 | + defsequence.(:bright, 1, "m") |
137 | 129 |
|
138 | 130 | @doc "Faint (decreased intensity). Not widely supported."
|
139 |
| - defsequence(:faint, 2) |
| 131 | + defsequence.(:faint, 2, "m") |
140 | 132 |
|
141 | 133 | @doc "Italic: on. Not widely supported. Sometimes treated as inverse."
|
142 |
| - defsequence(:italic, 3) |
| 134 | + defsequence.(:italic, 3, "m") |
143 | 135 |
|
144 | 136 | @doc "Underline: single."
|
145 |
| - defsequence(:underline, 4) |
| 137 | + defsequence.(:underline, 4, "m") |
146 | 138 |
|
147 | 139 | @doc "Blink: slow. Less than 150 per minute."
|
148 |
| - defsequence(:blink_slow, 5) |
| 140 | + defsequence.(:blink_slow, 5, "m") |
149 | 141 |
|
150 | 142 | @doc "Blink: rapid. MS-DOS ANSI.SYS; 150 per minute or more; not widely supported."
|
151 |
| - defsequence(:blink_rapid, 6) |
| 143 | + defsequence.(:blink_rapid, 6, "m") |
152 | 144 |
|
153 | 145 | @doc "Image: negative. Swap foreground and background."
|
154 |
| - defsequence(:inverse, 7) |
| 146 | + defsequence.(:inverse, 7, "m") |
155 | 147 |
|
156 | 148 | @doc "Image: negative. Swap foreground and background."
|
157 |
| - defsequence(:reverse, 7) |
| 149 | + defsequence.(:reverse, 7, "m") |
158 | 150 |
|
159 | 151 | @doc "Conceal. Not widely supported."
|
160 |
| - defsequence(:conceal, 8) |
| 152 | + defsequence.(:conceal, 8, "m") |
161 | 153 |
|
162 | 154 | @doc "Crossed-out. Characters legible, but marked for deletion. Not widely supported."
|
163 |
| - defsequence(:crossed_out, 9) |
| 155 | + defsequence.(:crossed_out, 9, "m") |
164 | 156 |
|
165 | 157 | @doc "Sets primary (default) font."
|
166 |
| - defsequence(:primary_font, 10) |
| 158 | + defsequence.(:primary_font, 10, "m") |
167 | 159 |
|
168 | 160 | for font_n <- [1, 2, 3, 4, 5, 6, 7, 8, 9] do
|
169 | 161 | @doc "Sets alternative font #{font_n}."
|
170 |
| - defsequence(:"font_#{font_n}", font_n + 10) |
| 162 | + defsequence.(:"font_#{font_n}", font_n + 10, "m") |
171 | 163 | end
|
172 | 164 |
|
173 | 165 | @doc "Normal color or intensity."
|
174 |
| - defsequence(:normal, 22) |
| 166 | + defsequence.(:normal, 22, "m") |
175 | 167 |
|
176 | 168 | @doc "Not italic."
|
177 |
| - defsequence(:not_italic, 23) |
| 169 | + defsequence.(:not_italic, 23, "m") |
178 | 170 |
|
179 | 171 | @doc "Underline: none."
|
180 |
| - defsequence(:no_underline, 24) |
| 172 | + defsequence.(:no_underline, 24, "m") |
181 | 173 |
|
182 | 174 | @doc "Blink: off."
|
183 |
| - defsequence(:blink_off, 25) |
| 175 | + defsequence.(:blink_off, 25, "m") |
184 | 176 |
|
185 | 177 | @doc "Image: positive. Normal foreground and background."
|
186 |
| - defsequence(:inverse_off, 27) |
| 178 | + defsequence.(:inverse_off, 27, "m") |
187 | 179 |
|
188 | 180 | @doc "Image: positive. Normal foreground and background."
|
189 |
| - defsequence(:reverse_off, 27) |
| 181 | + defsequence.(:reverse_off, 27, "m") |
190 | 182 |
|
191 | 183 | colors = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white]
|
192 | 184 |
|
193 | 185 | for {color, code} <- Enum.with_index(colors) do
|
194 | 186 | @doc "Sets foreground color to #{color}."
|
195 |
| - defsequence(color, code + 30) |
| 187 | + defsequence.(color, code + 30, "m") |
196 | 188 |
|
197 | 189 | @doc "Sets foreground color to light #{color}."
|
198 |
| - defsequence(:"light_#{color}", code + 90) |
| 190 | + defsequence.(:"light_#{color}", code + 90, "m") |
199 | 191 |
|
200 | 192 | @doc "Sets background color to #{color}."
|
201 |
| - defsequence(:"#{color}_background", code + 40) |
| 193 | + defsequence.(:"#{color}_background", code + 40, "m") |
202 | 194 |
|
203 | 195 | @doc "Sets background color to light #{color}."
|
204 |
| - defsequence(:"light_#{color}_background", code + 100) |
| 196 | + defsequence.(:"light_#{color}_background", code + 100, "m") |
205 | 197 | end
|
206 | 198 |
|
207 | 199 | @doc "Default text color."
|
208 |
| - defsequence(:default_color, 39) |
| 200 | + defsequence.(:default_color, 39, "m") |
209 | 201 |
|
210 | 202 | @doc "Default background color."
|
211 |
| - defsequence(:default_background, 49) |
| 203 | + defsequence.(:default_background, 49, "m") |
212 | 204 |
|
213 | 205 | @doc "Framed."
|
214 |
| - defsequence(:framed, 51) |
| 206 | + defsequence.(:framed, 51, "m") |
215 | 207 |
|
216 | 208 | @doc "Encircled."
|
217 |
| - defsequence(:encircled, 52) |
| 209 | + defsequence.(:encircled, 52, "m") |
218 | 210 |
|
219 | 211 | @doc "Overlined."
|
220 |
| - defsequence(:overlined, 53) |
| 212 | + defsequence.(:overlined, 53, "m") |
221 | 213 |
|
222 | 214 | @doc "Not framed or encircled."
|
223 |
| - defsequence(:not_framed_encircled, 54) |
| 215 | + defsequence.(:not_framed_encircled, 54, "m") |
224 | 216 |
|
225 | 217 | @doc "Not overlined."
|
226 |
| - defsequence(:not_overlined, 55) |
| 218 | + defsequence.(:not_overlined, 55, "m") |
| 219 | + |
| 220 | + @doc "Clears screen." |
| 221 | + defsequence.(:clear, "2", "J") |
| 222 | + |
| 223 | + @doc "Clears line." |
| 224 | + defsequence.(:clear_line, "2", "K") |
227 | 225 |
|
228 | 226 | @doc "Sends cursor home."
|
229 |
| - defsequence(:home, "", "H") |
| 227 | + defsequence.(:home, "", "H") |
230 | 228 |
|
231 | 229 | @doc """
|
232 | 230 | Sends cursor to the absolute position specified by `line` and `column`.
|
@@ -255,12 +253,6 @@ defmodule IO.ANSI do
|
255 | 253 | @spec cursor_left(pos_integer) :: String.t()
|
256 | 254 | def cursor_left(columns \\ 1) when is_integer(columns) and columns >= 1, do: "\e[#{columns}D"
|
257 | 255 |
|
258 |
| - @doc "Clears screen." |
259 |
| - defsequence(:clear, "2", "J") |
260 |
| - |
261 |
| - @doc "Clears line." |
262 |
| - defsequence(:clear_line, "2", "K") |
263 |
| - |
264 | 256 | defp format_sequence(other) do
|
265 | 257 | raise ArgumentError, "invalid ANSI sequence specification: #{inspect(other)}"
|
266 | 258 | end
|
|
0 commit comments