1- defmodule IEx.ANSIDocs do
1+ defmodule IO.ANSI.Docs do
22 @ moduledoc false
33
44 @ bullets [ ?* , ?- , ?+ ]
55
6+ @ default_colors [ enabled: true ,
7+ doc_code: "cyan,bright" ,
8+ doc_inline_code: "cyan" ,
9+ doc_headings: "yellow,bright" ,
10+ doc_title: "reverse,yellow,bright" ,
11+ doc_bold: "bright" ,
12+ doc_underline: "underline" ]
13+
14+ @ shared_print_doc """
15+ In addition to the priting string, takes a truth value for whether to use ANSI
16+ escape codes, and a keyword list for the printing color settings. Supported
17+ keys for the color settings are:
18+
19+ * `:enabled` - toggles coloring on and off (true)
20+ * `:doc_code` - code blocks (cyan, bright)
21+ * `:doc_inline_code` - inline code (cyan)
22+ * `:doc_headings` - h1 and h2 headings (yellow, bright)
23+ * `:doc_title` - top level heading (reverse, yellow, bright)
24+ * `:doc_bold` - bold text (bright)
25+ * `:doc_underline` - underlined text (underline)
26+
27+ Values for the color settings are strings with comma-separated attributes.
28+ Supported attributes are:
29+
30+ * Colors: `black red green yellow blue magenta cyan white`
31+ * Intensity: `normal bright`
32+ * Decoration: `underline reverse`
33+ """
34+
635 @ doc """
7- Prints the head of the documentation (i.e. the function signature)
36+ Prints the head of the documentation (i.e. the function signature).
37+
38+ #{ @ shared_print_doc }
839 """
9- def print_heading ( string , use_ansi // IO.ANSI . terminal? ) do
40+ def print_heading ( string , use_ansi // IO.ANSI . terminal? , colors // @ default_colors ) do
1041 if use_ansi do
11- write_doc_heading ( string )
42+ write_doc_heading ( string , colors )
1243 else
1344 IO . puts "* #{ string } \n "
1445 end
15- IEx . dont_display_result
46+ dont_display_result
1647 end
1748
18- defp write_doc_heading ( heading ) do
49+ defp write_doc_heading ( heading , colors ) do
1950 IO . puts IO.ANSI . reset
2051 width = column_width ( )
2152 padding = div ( width + String . length ( heading ) , 2 )
2253 heading = heading |> String . rjust ( padding ) |> String . ljust ( width )
23- write ( :doc_title , heading )
54+ write ( :doc_title , heading , colors )
2455 end
2556
2657 @ doc """
2758 Prints the documentation body.
59+
60+ #{ @ shared_print_doc }
2861 """
29- def print ( doc , use_ansi // IO.ANSI . terminal? ) do
62+ def print ( doc , use_ansi // IO.ANSI . terminal? , colors // @ default_colors ) do
3063 if use_ansi do
3164 doc
3265 |> String . split ( [ "\r \n " , "\n " ] , trim: false )
3366 |> Enum . map ( & String . rstrip / 1 )
34- |> process ( "" )
67+ |> process ( "" , colors )
3568 else
3669 IO . puts doc
3770 end
38- IEx . dont_display_result
71+ dont_display_result
3972 end
4073
41- defp process ( [ ] , _indent ) , do: nil
74+ defp dont_display_result , do: :"do not show this result in output"
4275
43- defp process ( [ "# " <> heading | rest ] , _indent ) do
44- write_h1 ( String . strip ( heading ) )
45- process ( rest , "" )
76+ defp process ( [ ] , _indent , _colors ) , do: nil
77+
78+ defp process ( [ "# " <> heading | rest ] , _indent , colors ) do
79+ write_h1 ( String . strip ( heading ) , colors )
80+ process ( rest , "" , colors )
4681 end
4782
48- defp process ( [ "## " <> heading | rest ] , _indent ) do
49- write_h2 ( String . strip ( heading ) )
50- process ( rest , "" )
83+ defp process ( [ "## " <> heading | rest ] , _indent , colors ) do
84+ write_h2 ( String . strip ( heading ) , colors )
85+ process ( rest , "" , colors )
5186 end
5287
53- defp process ( [ "### " <> heading | rest ] , indent ) do
54- write_h3 ( String . strip ( heading ) , indent )
55- process ( rest , indent )
88+ defp process ( [ "### " <> heading | rest ] , indent , colors ) do
89+ write_h3 ( String . strip ( heading ) , indent , colors )
90+ process ( rest , indent , colors )
5691 end
5792
58- defp process ( [ "" | rest ] , indent ) do
59- process ( rest , indent )
93+ defp process ( [ "" | rest ] , indent , colors ) do
94+ process ( rest , indent , colors )
6095 end
6196
62- defp process ( [ " " <> line | rest ] , indent ) do
63- process_code ( rest , [ line ] , indent )
97+ defp process ( [ " " <> line | rest ] , indent , colors ) do
98+ process_code ( rest , [ line ] , indent , colors )
6499 end
65100
66- defp process ( [ line | rest ] , indent ) do
101+ defp process ( [ line | rest ] , indent , colors ) do
67102 { stripped , count } = strip_spaces ( line , 0 )
68103 case stripped do
69104 << bullet , ?\s , item :: binary >> when bullet in @ bullets ->
70- process_list ( item , rest , count , indent )
105+ process_list ( item , rest , count , indent , colors )
71106 _ ->
72- process_text ( rest , [ line ] , indent , false )
107+ process_text ( rest , [ line ] , indent , false , colors )
73108 end
74109 end
75110
@@ -83,27 +118,27 @@ defmodule IEx.ANSIDocs do
83118
84119 ## Headings
85120
86- defp write_h1 ( heading ) do
87- write_h2 ( String . upcase ( heading ) )
121+ defp write_h1 ( heading , colors ) do
122+ write_h2 ( String . upcase ( heading ) , colors )
88123 end
89124
90- defp write_h2 ( heading ) do
91- write ( :doc_headings , heading )
125+ defp write_h2 ( heading , colors ) do
126+ write ( :doc_headings , heading , colors )
92127 end
93128
94- defp write_h3 ( heading , indent ) do
129+ defp write_h3 ( heading , indent , colors ) do
95130 IO . write ( indent )
96- write ( :doc_headings , heading )
131+ write ( :doc_headings , heading , colors )
97132 end
98133
99134 ## Lists
100135
101- defp process_list ( line , rest , count , indent ) do
136+ defp process_list ( line , rest , count , indent , colors ) do
102137 IO . write indent <> "• "
103138 { contents , rest , done } = process_list_next ( rest , count , false , [ ] )
104- process_text ( contents , [ line ] , indent <> " " , true )
139+ process_text ( contents , [ line ] , indent <> " " , true , colors )
105140 if done , do: IO . puts ( IO.ANSI . reset )
106- process ( rest , indent )
141+ process ( rest , indent , colors )
107142 end
108143
109144 # Process the thing after a list item entry. It can be either:
@@ -141,35 +176,35 @@ defmodule IEx.ANSIDocs do
141176
142177 ## Text (paragraphs / lists)
143178
144- defp process_text ( doc = [ "" | _ ] , para , indent , from_list ) do
145- write_text ( Enum . reverse ( para ) , indent , from_list )
146- process ( doc , indent )
179+ defp process_text ( doc = [ "" | _ ] , para , indent , from_list , colors ) do
180+ write_text ( Enum . reverse ( para ) , indent , from_list , colors )
181+ process ( doc , indent , colors )
147182 end
148183
149- defp process_text ( [ ] , para , indent , from_list ) do
150- write_text ( Enum . reverse ( para ) , indent , from_list )
184+ defp process_text ( [ ] , para , indent , from_list , colors ) do
185+ write_text ( Enum . reverse ( para ) , indent , from_list , colors )
151186 end
152187
153- defp process_text ( [ line | rest ] , para , indent , true ) do
188+ defp process_text ( [ line | rest ] , para , indent , true , colors ) do
154189 { stripped , count } = strip_spaces ( line , 0 )
155190 case stripped do
156191 << bullet , ?\s , item :: binary >> when bullet in @ bullets ->
157- write_text ( Enum . reverse ( para ) , indent , true )
158- process_list ( item , rest , count , indent )
192+ write_text ( Enum . reverse ( para ) , indent , true , colors )
193+ process_list ( item , rest , count , indent , colors )
159194 _ ->
160- process_text ( rest , [ line | para ] , indent , true )
195+ process_text ( rest , [ line | para ] , indent , true , colors )
161196 end
162197 end
163198
164- defp process_text ( [ line | rest ] , para , indent , from_list ) do
165- process_text ( rest , [ line | para ] , indent , from_list )
199+ defp process_text ( [ line | rest ] , para , indent , from_list , colors ) do
200+ process_text ( rest , [ line | para ] , indent , from_list , colors )
166201 end
167202
168- defp write_text ( lines , indent , from_list ) do
203+ defp write_text ( lines , indent , from_list , colors ) do
169204 lines
170205 |> Enum . join ( " " )
171206 |> handle_links
172- |> handle_inline ( nil , [ ] , [ ] )
207+ |> handle_inline ( nil , [ ] , [ ] , colors )
173208 |> String . split ( % r { \s} )
174209 |> write_with_wrap ( column_width ( ) - size ( indent ) , indent , from_list )
175210
@@ -178,32 +213,32 @@ defmodule IEx.ANSIDocs do
178213
179214 ## Code blocks
180215
181- defp process_code ( [ ] , code , indent ) do
182- write_code ( code , indent )
216+ defp process_code ( [ ] , code , indent , colors ) do
217+ write_code ( code , indent , colors )
183218 end
184219
185220 # Blank line between code blocks
186- defp process_code ( [ "" , " " <> line | rest ] , code , indent ) do
187- process_code ( rest , [ line , "" | code ] , indent )
221+ defp process_code ( [ "" , " " <> line | rest ] , code , indent , colors ) do
222+ process_code ( rest , [ line , "" | code ] , indent , colors )
188223 end
189224
190- defp process_code ( [ " " <> line | rest ] , code , indent ) do
191- process_code ( rest , [ line | code ] , indent )
225+ defp process_code ( [ " " <> line | rest ] , code , indent , colors ) do
226+ process_code ( rest , [ line | code ] , indent , colors )
192227 end
193228
194- defp process_code ( rest , code , indent ) do
195- write_code ( code , indent )
196- process ( rest , indent )
229+ defp process_code ( rest , code , indent , colors ) do
230+ write_code ( code , indent , colors )
231+ process ( rest , indent , colors )
197232 end
198233
199- defp write_code ( code , indent ) do
200- write ( :doc_code , "#{ indent } ┃ #{ Enum . join ( Enum . reverse ( code ) , "\n #{ indent } ┃ " ) } " )
234+ defp write_code ( code , indent , colors ) do
235+ write ( :doc_code , "#{ indent } ┃ #{ Enum . join ( Enum . reverse ( code ) , "\n #{ indent } ┃ " ) } " , colors )
201236 end
202237
203238 ## Helpers
204239
205- defp write ( style , string ) do
206- IO . puts IEx . color ( style , string )
240+ defp write ( style , string , colors ) do
241+ IO . puts color ( style , colors ) <> string <> IO.ANSI . reset
207242 IO . puts IO.ANSI . reset
208243 end
209244
@@ -280,81 +315,77 @@ defmodule IEx.ANSIDocs do
280315 @ spaced [ ?_ , ?* ]
281316
282317 # Clauses for handling spaces
283- defp handle_inline ( << ?* , ?* , ?\s , rest :: binary >> , nil , buffer , acc ) do
284- handle_inline ( rest , nil , [ ?\s , ?* , ?* | buffer ] , acc )
318+ defp handle_inline ( << ?* , ?* , ?\s , rest :: binary >> , nil , buffer , acc , colors ) do
319+ handle_inline ( rest , nil , [ ?\s , ?* , ?* | buffer ] , acc , colors )
285320 end
286321
287- defp handle_inline ( << mark , ?\s , rest :: binary >> , nil , buffer , acc ) when mark in @ spaced do
288- handle_inline ( rest , nil , [ ?\s , mark | buffer ] , acc )
322+ defp handle_inline ( << mark , ?\s , rest :: binary >> , nil , buffer , acc , colors ) when mark in @ spaced do
323+ handle_inline ( rest , nil , [ ?\s , mark | buffer ] , acc , colors )
289324 end
290325
291- defp handle_inline ( << ?\s , ?* , ?* , rest :: binary >> , limit , buffer , acc ) do
292- handle_inline ( rest , limit , [ ?* , ?* , ?\s | buffer ] , acc )
326+ defp handle_inline ( << ?\s , ?* , ?* , rest :: binary >> , limit , buffer , acc , colors ) do
327+ handle_inline ( rest , limit , [ ?* , ?* , ?\s | buffer ] , acc , colors )
293328 end
294329
295- defp handle_inline ( << ?\s , mark , rest :: binary >> , limit , buffer , acc ) when mark in @ spaced do
296- handle_inline ( rest , limit , [ mark , ?\s | buffer ] , acc )
330+ defp handle_inline ( << ?\s , mark , rest :: binary >> , limit , buffer , acc , colors ) when mark in @ spaced do
331+ handle_inline ( rest , limit , [ mark , ?\s | buffer ] , acc , colors )
297332 end
298333
299334 # Clauses for handling escape
300- defp handle_inline ( << ?\\ , ?\\ , rest :: binary >> , limit , buffer , acc ) do
301- handle_inline ( rest , limit , [ ?\\ | buffer ] , acc )
335+ defp handle_inline ( << ?\\ , ?\\ , rest :: binary >> , limit , buffer , acc , colors ) do
336+ handle_inline ( rest , limit , [ ?\\ | buffer ] , acc , colors )
302337 end
303338
304- defp handle_inline ( << ?\\ , ?* , ?* , rest :: binary >> , limit , buffer , acc ) do
305- handle_inline ( rest , limit , [ ?* , ?* | buffer ] , acc )
339+ defp handle_inline ( << ?\\ , ?* , ?* , rest :: binary >> , limit , buffer , acc , colors ) do
340+ handle_inline ( rest , limit , [ ?* , ?* | buffer ] , acc , colors )
306341 end
307342
308343 # A escape is not valid inside `
309- defp handle_inline ( << ?\\ , mark , rest :: binary >> , limit , buffer , acc )
344+ defp handle_inline ( << ?\\ , mark , rest :: binary >> , limit , buffer , acc , colors )
310345 when mark in [ ?_ , ?* , ?` ] and not ( mark == limit and mark == ?` ) do
311- handle_inline ( rest , limit , [ mark | buffer ] , acc )
346+ handle_inline ( rest , limit , [ mark | buffer ] , acc , colors )
312347 end
313348
314349 # Inline start
315- defp handle_inline ( << ?* , ?* , rest :: binary >> , nil , buffer , acc ) when rest != "" do
316- handle_inline ( rest , ?d , [ "**" ] , [ Enum . reverse ( buffer ) | acc ] )
350+ defp handle_inline ( << ?* , ?* , rest :: binary >> , nil , buffer , acc , colors ) when rest != "" do
351+ handle_inline ( rest , ?d , [ "**" ] , [ Enum . reverse ( buffer ) | acc ] , colors )
317352 end
318353
319- defp handle_inline ( << mark , rest :: binary >> , nil , buffer , acc ) when rest != "" and mark in @ single do
320- handle_inline ( rest , mark , [ << mark >> ] , [ Enum . reverse ( buffer ) | acc ] )
354+ defp handle_inline ( << mark , rest :: binary >> , nil , buffer , acc , colors ) when rest != "" and mark in @ single do
355+ handle_inline ( rest , mark , [ << mark >> ] , [ Enum . reverse ( buffer ) | acc ] , colors )
321356 end
322357
323358 # Inline end
324- defp handle_inline ( << ?* , ?* , rest :: binary >> , ?d , buffer , acc ) do
325- handle_inline ( rest , nil , [ ] , [ inline_buffer ( buffer ) | acc ] )
359+ defp handle_inline ( << ?* , ?* , rest :: binary >> , ?d , buffer , acc , colors ) do
360+ handle_inline ( rest , nil , [ ] , [ inline_buffer ( buffer , colors ) | acc ] , colors )
326361 end
327362
328- defp handle_inline ( << mark , rest :: binary >> , mark , buffer , acc ) when mark in @ single do
329- handle_inline ( rest , nil , [ ] , [ inline_buffer ( buffer ) | acc ] )
363+ defp handle_inline ( << mark , rest :: binary >> , mark , buffer , acc , colors ) when mark in @ single do
364+ handle_inline ( rest , nil , [ ] , [ inline_buffer ( buffer , colors ) | acc ] , colors )
330365 end
331366
332- defp handle_inline ( << char , rest :: binary >> , mark , buffer , acc ) do
333- handle_inline ( rest , mark , [ char | buffer ] , acc )
367+ defp handle_inline ( << char , rest :: binary >> , mark , buffer , acc , colors ) do
368+ handle_inline ( rest , mark , [ char | buffer ] , acc , colors )
334369 end
335370
336- defp handle_inline ( << >> , _mark , buffer , acc ) do
371+ defp handle_inline ( << >> , _mark , buffer , acc , _colors ) do
337372 iolist_to_binary Enum . reverse ( [ Enum . reverse ( buffer ) | acc ] )
338373 end
339374
340- defp inline_buffer ( buffer ) do
375+ defp inline_buffer ( buffer , colors ) do
341376 [ h | t ] = Enum . reverse ( [ IO.ANSI . reset | buffer ] )
342- [ color_for ( h ) | t ]
377+ [ color_for ( h , colors ) | t ]
343378 end
344379
345- defp color_for ( "`" ) , do: color ( :doc_inline_code )
346- defp color_for ( "_" ) , do: color ( :doc_underline )
347- defp color_for ( "*" ) , do: color ( :doc_bold )
348- defp color_for ( "**" ) , do: color ( :doc_bold )
349-
350- defp color ( color_name ) do
351- colors = IEx.Options . get ( :colors )
380+ defp color_for ( "`" , colors ) , do: color ( :doc_inline_code , colors )
381+ defp color_for ( "_" , colors ) , do: color ( :doc_underline , colors )
382+ defp color_for ( "*" , colors ) , do: color ( :doc_bold , colors )
383+ defp color_for ( "**" , colors ) , do: color ( :doc_bold , colors )
352384
353- if colors [ :enabled ] do
354- IO.ANSI . escape_fragment ( "%{#{ colors [ color_name ] } }" , true )
355- else
356- ""
357- end
385+ defp color ( style , colors ) do
386+ color = colors [ style ]
387+ enabled = colors [ :enabled ]
388+ IO.ANSI . escape_fragment ( "%{#{ color } }" , enabled )
358389 end
359390
360391 defp column_width ( ) do
0 commit comments