Skip to content

Commit 9be091e

Browse files
committed
Add support for styling commands
1 parent 0b14f4d commit 9be091e

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed

src/HsLua/Module/DocLayout.hs

+80
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ module HsLua.Module.DocLayout (
6363
, real_length
6464
, update_column
6565

66+
-- * Styling
67+
, bold
68+
, italic
69+
, underlined
70+
, strikeout
71+
, fg
72+
, bg
73+
6674
-- * Marshaling
6775
, peekDoc
6876
, pushDoc
@@ -188,6 +196,13 @@ functions =
188196
, offset
189197
, real_length
190198
, update_column
199+
-- styling
200+
, bold
201+
, italic
202+
, underlined
203+
, strikeout
204+
, fg
205+
, bg
191206
]
192207

193208
typeDoc :: LuaError e => DocumentedType e (Doc Text)
@@ -538,6 +553,54 @@ vfill = defun "vfill"
538553
"expands to the height of the box. Strings cycle through the " <>
539554
"list provided.")
540555

556+
--
557+
-- Styling
558+
--
559+
560+
bold :: LuaError e => DocumentedFunction e
561+
bold = defun "bold"
562+
### liftPure Doc.bold
563+
<#> docParam "doc"
564+
=#> docResult "bolded Doc"
565+
#? "Puts a [[Doc]] in boldface."
566+
567+
italic :: LuaError e => DocumentedFunction e
568+
italic = defun "italic"
569+
### liftPure Doc.italic
570+
<#> docParam "doc"
571+
=#> docResult "styled Doc"
572+
#? "Puts a [[Doc]] in italics."
573+
574+
underlined :: LuaError e => DocumentedFunction e
575+
underlined = defun "underlined"
576+
### liftPure Doc.underlined
577+
<#> docParam "doc"
578+
=#> docResult "styled Doc"
579+
#? "Underlines a [[Doc]]."
580+
581+
strikeout :: LuaError e => DocumentedFunction e
582+
strikeout = defun "strikeout"
583+
### liftPure Doc.strikeout
584+
<#> docParam "doc"
585+
=#> docResult "styled Doc"
586+
#? "Puts a line through the [[Doc]]."
587+
588+
fg :: LuaError e => DocumentedFunction e
589+
fg = defun "fg"
590+
### liftPure2 (flip Doc.fg)
591+
<#> docParam "doc"
592+
<#> colorParam
593+
=#> docResult "styled Doc"
594+
#? "Set the foreground color."
595+
596+
bg :: LuaError e => DocumentedFunction e
597+
bg = defun "bg"
598+
### liftPure2 (flip Doc.bg)
599+
<#> docParam "doc"
600+
<#> colorParam
601+
=#> docResult "styled Doc"
602+
#? "Set the background color."
603+
541604
--
542605
-- Marshaling
543606
--
@@ -571,6 +634,23 @@ instance Pushable (Doc Text) where
571634
docParam :: LuaError e => Text -> Parameter e (Doc Text)
572635
docParam name = parameter peekDoc "Doc" name "document"
573636

637+
-- | @Color@ function parameter
638+
colorParam :: Parameter e Doc.Color
639+
colorParam = parameter peekColor "string" "color"
640+
("One of 'black', 'red', 'green', 'yellow', 'blue', 'magenta' " <>
641+
"'cyan', or 'white'.")
642+
where
643+
peekColor idx = peekByteString idx >>= \case
644+
"black" -> pure Doc.black
645+
"red" -> pure Doc.red
646+
"green" -> pure Doc.green
647+
"yellow" -> pure Doc.yellow
648+
"blue" -> pure Doc.blue
649+
"magenta" -> pure Doc.magenta
650+
"cyan" -> pure Doc.cyan
651+
"white" -> pure Doc.white
652+
color -> failPeek $ "Unknown color: " <> color
653+
574654
--
575655
-- Results
576656
--

test/test-doclayout.lua

+73
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ local group = tasty.test_group
88
local test = tasty.test_case
99
local assert = tasty.assert
1010

11+
local function renderANSI (doc, cols)
12+
return doclayout.render(doc, cols, true)
13+
end
14+
1115
-- Check existence static fields
1216
return {
1317
group 'constructors' {
@@ -244,6 +248,75 @@ return {
244248
end)
245249
},
246250

251+
-- Styling happens per-character, so the output is quite verbose, and
252+
-- includes additional commands to reset all attributes.
253+
-- We just look for the right escape sequences instead of matching
254+
-- the whole output.
255+
group 'styling' {
256+
test('bold', function ()
257+
assert.is_truthy(
258+
renderANSI(doclayout.bold('a')):match('\027%[1m')
259+
)
260+
end),
261+
262+
test('italics', function ()
263+
assert.is_truthy(
264+
renderANSI(doclayout.italic('a')):match('\027%[3m')
265+
)
266+
end),
267+
268+
test('underlined', function ()
269+
assert.is_truthy(
270+
renderANSI(doclayout.underlined('a')):match('\027%[4m')
271+
)
272+
end),
273+
274+
test('strikeout', function ()
275+
assert.is_truthy(
276+
renderANSI(doclayout.strikeout('a')):match('\027%[9m')
277+
)
278+
end),
279+
280+
test('fg', function ()
281+
assert.is_truthy(
282+
renderANSI(doclayout.fg('a', 'red')):match('\027%[31m')
283+
)
284+
end),
285+
286+
test('bg', function ()
287+
assert.is_truthy(
288+
renderANSI(doclayout.bg('a', 'red')):match('\027%[41m')
289+
)
290+
end),
291+
292+
group 'colors' {
293+
test('black', function ()
294+
renderANSI(doclayout.bg('a', 'black')):match('\027%[40m')
295+
end),
296+
test('red', function ()
297+
renderANSI(doclayout.bg('a', 'red')):match('\027%[41m')
298+
end),
299+
test('green', function ()
300+
renderANSI(doclayout.bg('a', 'green')):match('\027%[42m')
301+
end),
302+
test('yellow', function ()
303+
renderANSI(doclayout.bg('a', 'yellow')):match('\027%[43m')
304+
end),
305+
test('blue', function ()
306+
renderANSI(doclayout.bg('a', 'blue')):match('\027%[44m')
307+
end),
308+
test('magenta', function ()
309+
renderANSI(doclayout.bg('a', 'magenta')):match('\027%[45m')
310+
end),
311+
test('cyan', function ()
312+
renderANSI(doclayout.bg('a', 'cyan')):match('\027%[46m')
313+
end),
314+
test('white', function ()
315+
renderANSI(doclayout.bg('a', 'white')):match('\027%[47m')
316+
end),
317+
}
318+
},
319+
247320
group 'Doc type' {
248321
test('empty strings equal the empty Doc', function ()
249322
assert.are_equal(doclayout.empty .. '', doclayout.empty)

0 commit comments

Comments
 (0)