old_contents: import os
  
  from invoke import ctask as task, Collection
  
  
  docs_dir = 'docs'
  build_dir = os.path.join(docs_dir, '_build')
  
  
  @task(aliases=['c'])
  def _clean(ctx):
      ctx.run("rm -rf %s" % build_dir)
  
  
  @task(aliases=['b'])
  def _browse(ctx):
      ctx.run("open %s" % os.path.join(build_dir, 'index.html'))
  
  
  @task(default=True)
  def build(ctx, clean=False, browse=False):
      if clean:
          _clean(ctx)
      ctx.run("sphinx-build %s %s" % (docs_dir, build_dir), pty=True)
      if browse:
          _browse(ctx)
  
  ns = Collection(clean=_clean, browse=_browse, build=build)
  
new_contents: import os
  
  from invoke import ctask as task, Collection
  
  
  @task(aliases=['c'])
  def _clean(ctx):
      ctx.run("rm -rf {0}".format(ctx['sphinx.target']))
  
  
  @task(aliases=['b'])
  def _browse(ctx):
      index = os.path.join(ctx['sphinx.target'], 'index.html')
      ctx.run("open {0}".format(index))
  
  
  @task(default=True)
  def build(ctx, clean=False, browse=False):
      if clean:
          _clean(ctx)
      cmd = "sphinx-build {0} {1}".format(
          ctx['sphinx.source'], ctx['sphinx.target']
      )
      ctx.run(cmd, pty=True)
      if browse:
          _browse(ctx)
  
  ns = Collection(clean=_clean, browse=_browse, build=build)
  ns.configure({
      'sphinx.source': 'docs',
      # TODO: allow lazy eval so one attr can refer to another?
      'sphinx.target': os.path.join('docs', '_build'),
  })
  
subject: Make use of new collection config vector