Slicing
-------

The definition of slicing is split into forward and backwards slicing:
using both methods together and we get a full slice. Currently only
forward slicing is implemented which returns all line numbers depending
on the current line number.

Slicing Forward
~~~~~~~~~~~~~~~

Given a simple program:

>>> program = u"""
... def main():
...     foo = 1
...     bar = 1
...     baz = foo + bar
...     print(baz)
... 
... if __name__ == "__main__":
...     main()
... """

To see which lines depend on line 3, use the :py:meth:`slice_string` method:

>>> from programslice import slice_string
>>> slice_string('foo', 3, 4, program, 'myprogram')
['foo,3,4', 'foo,5,10', 'baz,5,4', 'baz,6,10']

Shebangs and Encoding declarations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sometimes programs use encoding declarations, which need to removed
before the program can be parsed. The slicing will not cause an error:

>>> encprogram = u'#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n{program}'.format(program=program)
>>> ignored = slice_string('bar', 4, 4, encprogram, 'myprogram')
>>> encprogram = u'#!/usr/bin/env python\n#\n# vim: set fileencoding=utf-8 :\n{program}'.format(program=program)
>>> ignored = slice_string('baz', 5, 4, encprogram, 'myprogram')

Text Output
~~~~~~~~~~~

Instead of returning line numbers, we can filter the buffer as well. The
`slice_string` function can be given a custom formatter class. It
defaults to :py:class:`LineFormatter` to just render the line numbers:

>>> from programslice.formatter import TextOutputFormatter
>>> result = slice_string('bar', 4, 4, program, 'myprogram', formatter=TextOutputFormatter)
>>> print('\n'.join(result))    # doctest: +NORMALIZE_WHITESPACE
    bar = 1
    baz = foo + bar
    print(baz)
