diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,9 +3,28 @@
 `hslua-module-doclayout` uses [PVP Versioning][1].
 The changelog is available [on GitHub][2].
 
+## 1.0.2
+
+Released 2022-02-05.
+
+-   Modify functions, ensuring that the main document is always
+    the first argument. This allows convenient use of these
+    functions as methods.
+
+-   Improved documentation.
+
+## 1.0.1
+
+Released 2022-01-31.
+
+-   Updated to hslua-2.1.
+
+-   Functions that take a `Doc` as the first argument are added as
+    methods to `Doc` values.
+
 ## 1.0.0
 
-Released 2021-10-24
+Released 2021-10-24.
 
 * Upgraded to hslua-2.0.
 * Switched module name from `Foreign.Lua.Module.DocLayout` to
diff --git a/hslua-module-doclayout.cabal b/hslua-module-doclayout.cabal
--- a/hslua-module-doclayout.cabal
+++ b/hslua-module-doclayout.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.0
 name:                hslua-module-doclayout
-version:             1.0.1
+version:             1.0.2
 synopsis:            Lua module wrapping Text.DocLayout.
 description:         Lua module wrapping @Text.DocLayout@.
 homepage:            https://github.com/hslua/hslua-module-doclayout
diff --git a/src/HsLua/Module/DocLayout.hs b/src/HsLua/Module/DocLayout.hs
--- a/src/HsLua/Module/DocLayout.hs
+++ b/src/HsLua/Module/DocLayout.hs
@@ -208,17 +208,25 @@
       [ method before_non_blank
       , method braces
       , method brackets
+      , method cblock
       , method chomp
       , method double_quotes
       , method is_empty
       , method flush
+      , method hang
       , method height
+      , method inside
+      , method lblock
       , method min_offset
+      , method nest
       , method nestle
       , method nowrap
       , method offset
       , method parens
+      , method prefixed
       , method quotes
+      , method rblock
+      , method render
       , method update_column
       , method vfill
       ]
@@ -236,7 +244,7 @@
 render = defun "render"
   ### liftPure2 (flip Doc.render)
   <#> docParam "doc"
-  <#> opt (integralParam "colwidth" "")
+  <#> opt (integralParam "colwidth" "planned maximum line length")
   =#> functionResult pushText "Doc" "rendered doc"
   #? ("Render a @'Doc'@. The text is reflowed on breakable spaces" <>
       "to match the given line length. Text is not reflowed if the" <>
@@ -278,7 +286,7 @@
 update_column = defun "update_column"
   ### liftPure2 Doc.updateColumn
   <#> docParam "doc"
-  <#> integralParam "i" ""
+  <#> integralParam "i" "start column"
   =#> integralResult "column number"
   #? ("Returns the column that would be occupied by the last " <>
       "laid out character.")
@@ -298,7 +306,7 @@
 real_length :: DocumentedFunction e
 real_length = defun "real_length"
   ### liftPure Doc.realLength
-  <#> textParam "str" ""
+  <#> textParam "str" "UTF-8 string to measure"
   =#> integralResult "text length"
   #? ("Returns the real length of a string in a monospace font: " <>
       "0 for a combining chaeracter, 1 for a regular character, " <>
@@ -313,10 +321,12 @@
 after_break :: LuaError e => DocumentedFunction e
 after_break = defun "after_break"
   ### liftPure Doc.afterBreak
-  <#> textParam "text" ""
+  <#> textParam "text" "content to include when placed after a break"
   =#> docResult "new doc"
-  #? ("Creates a `Doc` which is conditionally included only if it" <>
-      "comes at the beginning of a line.")
+  #? ("Creates a `Doc` which is conditionally included only if it " <>
+      "comes at the beginning of a line.\n\n" <>
+      "An example where this is useful is for escaping line-initial " <>
+      "`.` in roff man.")
 
 -- | Conditionally includes the given @'Doc'@ unless it is
 -- followed by a blank space.
@@ -332,7 +342,7 @@
 blanklines :: LuaError e => DocumentedFunction e
 blanklines = defun "blanklines"
   ### liftPure Doc.blanklines
-  <#> integralParam "n" ""
+  <#> integralParam "n" "number of blank lines"
   =#> docResult "conditional blank lines"
   #? "Inserts blank lines unless they exist already."
 
@@ -355,9 +365,9 @@
 -- | Like @'lblock'@ but aligned centered.
 cblock :: LuaError e => DocumentedFunction e
 cblock = defun "cblock"
-  ### liftPure2 Doc.cblock
-  <#> parameter peekIntegral "integer" "width" "block width in chars"
+  ### liftPure2 (flip Doc.cblock)
   <#> docParam "doc"
+  <#> integralParam "width" "block width in chars"
   =#> docResult ("doc, aligned centered in a block with max" <>
                  "`width` chars per line.")
   #? ("Creates a block with the given width and content, " <>
@@ -377,7 +387,7 @@
   ### liftPure2 (\docs optSep -> mconcat $
                   maybe docs (`intersperse` docs) optSep)
   <#> parameter (peekList peekDoc) "`{Doc,...}`" "docs" "list of Docs"
-  <#> opt (parameter peekDoc "Doc" "sep" "separator")
+  <#> opt (parameter peekDoc "Doc" "sep" "separator (default: none)")
   =#> docResult "concatenated doc"
   #? "Concatenates a list of `Doc`s."
 
@@ -400,10 +410,10 @@
 -- | Creates a hanging indent.
 hang :: LuaError e => DocumentedFunction e
 hang = defun "hang"
-  ### liftPure3 Doc.hang
-  <#> parameter peekIntegral "integer" "ind" "indentation width"
-  <#> docParam "start"
+  ### liftPure3 (\doc ind start -> Doc.hang ind start doc)
   <#> docParam "doc"
+  <#> integralParam "ind" "indentation width"
+  <#> docParam "start"
   =#> docResult ("`doc` prefixed by `start` on the first line, " <>
                  "subsequent lines indented by `ind` spaces.")
   #? "Creates a hanging indent."
@@ -411,10 +421,10 @@
 -- | Encloses a @'Doc'@ inside a start and end @'Doc'@.
 inside :: LuaError e => DocumentedFunction e
 inside = defun "inside"
-  ### liftPure3 Doc.inside
+  ### liftPure3 (\contents start end -> Doc.inside start end contents)
+  <#> docParam "contents"
   <#> docParam "start"
   <#> docParam "end"
-  <#> docParam "contents"
   =#> docResult "enclosed contents"
   #? "Encloses a `Doc` inside a start and end `Doc`."
 
@@ -422,9 +432,9 @@
 -- the left.
 lblock :: LuaError e => DocumentedFunction e
 lblock = defun "lblock"
-  ### liftPure2 Doc.lblock
-  <#> parameter peekIntegral "integer" "width" "block width in chars"
+  ### liftPure2 (flip Doc.lblock)
   <#> docParam "doc"
+  <#> integralParam "width" "block width in chars"
   =#> docResult "doc put into block with max `width` chars per line."
   #? ("Creates a block with the given width and content, " <>
       "aligned to the left.")
@@ -433,16 +443,16 @@
 literal :: LuaError e => DocumentedFunction e
 literal = defun "literal"
   ### liftPure Doc.literal
-  <#> textParam "string" ""
+  <#> textParam "text" "literal value"
   =#> docResult "doc contatining just the literal string"
   #? "Creates a `Doc` from a string."
 
 -- | Indents a @'Doc'@ by the specified number of spaces.
 nest :: LuaError e => DocumentedFunction e
 nest = defun "nest"
-  ### liftPure2 Doc.nest
-  <#> parameter peekIntegral "integer" "ind" "indentation size"
+  ### liftPure2 (flip Doc.nest)
   <#> docParam "doc"
+  <#> integralParam "ind" "indentation size"
   =#> docResult "`doc` indented by `ind` spaces"
   #? "Indents a `Doc` by the specified number of spaces."
 
@@ -476,9 +486,9 @@
 -- the line).
 prefixed :: LuaError e => DocumentedFunction e
 prefixed = defun "prefixed"
-  ### liftPure2 Doc.prefixed
-  <#> parameter peekString "string" "prefix" "prefix for each line"
+  ### liftPure2 (flip Doc.prefixed)
   <#> docParam "doc"
+  <#> stringParam "prefix" "prefix for each line"
   =#> docResult "prefixed `doc`"
   #? ("Uses the specified string as a prefix for every line of " <>
       "the inside document (except the first, if not at the " <>
@@ -495,9 +505,9 @@
 -- | Like @'rblock'@ but aligned to the right.
 rblock :: LuaError e => DocumentedFunction e
 rblock = defun "rblock"
-  ### liftPure2 Doc.rblock
-  <#> parameter peekIntegral "integer" "width" "block width in chars"
+  ### liftPure2 (flip Doc.rblock)
   <#> docParam "doc"
+  <#> integralParam "width" "block width in chars"
   =#> docResult ("doc, right aligned in a block with max" <>
                  "`width` chars per line.")
   #? ("Creates a block with the given width and content, " <>
@@ -509,7 +519,7 @@
 vfill :: LuaError e => DocumentedFunction e
 vfill = defun "vfill"
   ### liftPure Doc.vfill
-  <#> textParam "border" ""
+  <#> textParam "border" "vertically expanded characters"
   =#> docResult "automatically expanding border Doc"
   #? ("An expandable border that, when placed next to a box, " <>
       "expands to the height of the box.  Strings cycle through the " <>
@@ -546,7 +556,7 @@
 
 -- | @Doc@ typed function parameter.
 docParam :: LuaError e => Text -> Parameter e (Doc Text)
-docParam name = parameter peekDoc "Doc" name ""
+docParam name = parameter peekDoc "Doc" name "document"
 
 --
 -- Results
diff --git a/test/test-doclayout.lua b/test/test-doclayout.lua
--- a/test/test-doclayout.lua
+++ b/test/test-doclayout.lua
@@ -50,7 +50,7 @@
       test('inside', function ()
         local doc = doclayout.literal 'Hello,' + 'World!'
         assert.are_equal(
-          doclayout.inside('Yo! ', ' Wassup?', doc),
+          doclayout.inside(doc, 'Yo! ', ' Wassup?'),
           'Yo! ' .. doc .. ' Wassup?'
         )
       end),
@@ -87,7 +87,7 @@
         .. doclayout.literal 'How' .. doclayout.space
         .. doclayout.literal 'are' .. doclayout.space
         .. doclayout.literal 'you?'
-      assert.are_equal(doclayout.render(greeting, 7), 'Hi! How\nare\nyou?')
+      assert.are_equal(greeting:render(7), 'Hi! How\nare\nyou?')
     end),
     test('after_break', function ()
       local doc = doclayout.literal 'hi'
@@ -95,7 +95,7 @@
         .. doclayout.after_break '?'
         .. doclayout.literal 'x'
         .. doclayout.after_break '?'
-      assert.are_equal(doclayout.render(doc, 2), 'hi\n!x')
+      assert.are_equal(doc:render(2), 'hi\n!x')
     end),
     test('before_non_blank', function ()
       local doc = doclayout.before_non_blank '!!' .. ' ab'
@@ -120,11 +120,11 @@
       assert.are_equal(doclayout.render(doc), '[1]')
     end),
     test('flush', function ()
-      local doc = doclayout.flush(doclayout.nest(2, 'hi'))
+      local doc = doclayout.flush(doclayout.nest('hi', 2))
       assert.are_equal(doclayout.render(doc), 'hi')
     end),
     test('hang', function ()
-      local doc = doclayout.hang(4, '  - ', 'aa\nbb\ncc')
+      local doc = doclayout.hang('aa\nbb\ncc', 4, '  - ')
       assert.are_equal(
         doclayout.render(doc),
         table.concat{
@@ -135,7 +135,7 @@
       )
     end),
     test('nest', function ()
-      local doc = doclayout.nest(2, 'aa\n\nbb\ncc')
+      local doc = doclayout.nest('aa\n\nbb\ncc', 2)
       assert.are_equal(
         doclayout.render(doc),
         table.concat{
@@ -148,38 +148,45 @@
     end),
     test('nowrap', function()
       local doc = doclayout.nowrap(doclayout.literal 'first' + 'second')
-      assert.are_equal(doclayout.render(doc, 8), 'first second')
+      assert.are_equal(doc:render(8), 'first second')
     end),
     test('parens', function ()
       local doc = doclayout.parens 'lisp'
       assert.are_equal(doclayout.render(doc), '(lisp)')
+      -- as method
+      assert.are_equal(doc:parens():render(), '((lisp))')
     end),
     test('prefixed', function ()
-      local doc = doclayout.prefixed('# ', doclayout.literal 'aa' // 'bb')
+      local doc = doclayout.prefixed(doclayout.literal 'aa' // 'bb', '# ' )
       assert.are_equal(doclayout.render(doc), '# aa\n#\n# bb')
+      -- as method
+      assert.are_equal(
+        (doclayout.literal'aa' // 'bb'):prefixed('# '):render(),
+        '# aa\n#\n# bb'
+      )
     end),
     group 'table helpers' {
       test('cblock', function ()
-        local doc = doclayout.cblock(2, '| ')
-          .. doclayout.cblock(4, 'aa')
-          .. doclayout.cblock(2, ' |')
+        local doc = doclayout.cblock('| ', 2)
+          .. doclayout.cblock('aa', 4)
+          .. doclayout.cblock(' |', 2)
         assert.are_equal(doclayout.render(doc), '|  aa  |')
       end),
       test('lblock', function ()
-        local doc = doclayout.lblock(2, '| ')
-          .. doclayout.lblock(4, 'aa')
-          .. doclayout.lblock(2, ' |')
+        local doc = doclayout.lblock('| ', 2)
+          .. doclayout.lblock('aa', 4)
+          .. doclayout.lblock(' |', 2)
         assert.are_equal(doclayout.render(doc), '| aa   |')
       end),
       test('rblock', function ()
-        local doc = doclayout.rblock(2, '| ')
-          .. doclayout.rblock(4, 'aa')
-          .. doclayout.rblock(2, ' |')
+        local doc = doclayout.rblock('| ', 2)
+          .. doclayout.rblock('aa', 4)
+          .. doclayout.rblock(' |', 2)
         assert.are_equal(doclayout.render(doc), '|   aa |')
       end),
       test('vfill', function ()
         local doc = doclayout.vfill '| '
-          .. doclayout.lblock(4, doclayout.literal 'aa' // 'bbb')
+          .. doclayout.lblock(doclayout.literal 'aa' // 'bbb', 4)
           .. doclayout.vfill(' |')
         assert.are_equal(
           doclayout.render(doc),
@@ -225,6 +232,7 @@
       assert.are_equal(doclayout.real_length('a'), 1)
       assert.are_equal(doclayout.real_length('❄'), 1)
       assert.are_equal(doclayout.real_length('シ'), 2)
+      assert.are_equal(doclayout.real_length('four'), 4)
     end),
 
     test('update_column', function ()
