Example #1
0
    def _writeout(b):
        nonlocal replace_lines

        def to_console(block, replace_lines):
            nonlocal nr
            log_string = "Generating block: " + nr + "\n\n"
            content = reformat(block, margin=args.M) + "\n"
            writeout(log_string + content, False, replace_lines=replace_lines)
            return log_string.count("\n") + content.count("\n")

        try:
            nr = b.nr()
        except:
            nr = ""

        if args.o:
            writeout("Generating block: " + nr, False, replace_lines=1)
            writeout(reformat(b, margin=args.M) + "\n", args.o)
        else:
            replace_lines = to_console(b, replace_lines)
def get_blocks(text, margin=args.M, verbose=False):
    '''Generates a linked list of blocks and returns the first one.
    A block is separated by a newline from another.'''

    def count_empty(i):
        '''Counts empty lines form a location.
        If location is not empty, return 0.'''
        c = 0
        # here this function uses its parent variable <l>
        while not l[i+c] or l[i+c] == '\ufeff':
            c += 1
        return c

    def get_raw_block(i):
        '''Returns the location of nonempty lines from a given index.'''

        # here this function uses its parent variable <l>
        if not l[i]:
            raise EmptyLineForBlockError('Start line of a Block must be nonempty: l{0}.'.format(i+1))

        j = i
        # first we deal with nonempty lines
        while l[j] and j < len(l) - 1:
            j += 1

        # now the empty lines following the block
        c_e = count_empty(j)

        # in case we reached end of document
        if j == len(l) - 1:
            j += 1

        #return Block((i,j), c_e, l_lines=l[i:j])
        return j, c_e

    def subblocks(l_lines):
        '''Joins subblocks to the main linked list of blocks'''

        def indents():
            '''Returns the line indices in l_lines which are indented'''
            # for more sophisticated method we can check if line is longer than margin and ensure zero identification in next line
            result = []
            for i in range(len(l_lines)):
                l = l_lines[i]
                if (0 < len(l) - len(l.lstrip()) <= MAX_INDENT):
                    result.append(i)
            return result

        indices = indents()
        result = []

        # return the whole l_lines if there is no indented lines
        try:
            if indices[0] != 0:
                indices.insert(0,0) # we ensure we start from the beginning
        except:
            result.append(l_lines)
            return result

        # append subblocks
        for i in range(len(indices)):
            st_i = indices[i]
            try:
                en_i = indices[i+1]
            except:
                en_i = len(l_lines)
            result.append(l_lines[st_i:en_i])

        return result

    def get_block(l_lines):
        if len(l_lines) == 1:
            if n == 1: # first block must be the author
                return core.blocks.Author(l_lines, emptyafter)
            elif n == 2: # second block must be the title
                return core.blocks.Title(l_lines, emptyafter)
            elif n == 3 and last_block.emptyafter == 0: # subtitle must be in the very next line of title
                return core.blocks.SubTitle(l_lines, emptyafter)

            elif l_lines[0].lower().find(base_constants['chapter']) > -1:
                return core.blocks.Chapter(l_lines, emptyafter)

            elif l_lines[0].strip() == '***':
                return core.blocks.Break(l_lines, emptyafter)

        return core.blocks.Paragraph(l_lines, emptyafter)

    def last_link(block):
        block = block.dlink
        while block.rlink:
            block = block.rlink
        return block

    if verbose:
        print('Parsing input file:',end='\n\n')

    l = text.splitlines()
    i = 0
    c_e = count_empty(i)

    #we initialize document header which stores the count of empty lines at the beginning of text
    docheader = core.blocks.DocumentHeader(c_e)

    last_block = docheader
    i += c_e
    n = 1

    while i < len(l) - 1:                      # until end of document
        b_loc = get_raw_block(i)               # we separate raw blocks (separated by empty lines)
        l_lines = l[i:b_loc[0]]                # we get the line content for them
        l_blocks = subblocks(l_lines)          # we divide them by subblocks (if any) -- this is for indented paragraphs with no empty line between each other
        while l_blocks:                        # while we have subblock remained
            if len(l_blocks) == 1:
                emptyafter = b_loc[1]          # last one inherits raw_blocks emptyafter
            else:
                emptyafter = 0                 # otherwise zero empty line after the block
            block = get_block(l_blocks.pop(0)) # we create block from the populated first
            if verbose:
                from gntools.filepath import writeout
                writeout('Recognizing blocks: '+str(n), False, replace_lines=1)

            last_block.next = block            # link
            block.prev = last_block            # link
            last_block = block                 # now we have a new last block
            n += 1
        i = b_loc[0] + b_loc[1]                # our new line index value

    if verbose:
        print(' ... done.')
        print('Parsing block hierarchy ... ', end='')

    # now we gonna create the tree of the blocks
    # for this we need to determine the block hierarchy
        # which we gonna program later :)

    current_position = [docheader.frontmatter.titlepage]
    current_block = docheader.next
    while current_block.next:

        if isinstance(current_block, core.blocks.Chapter): # chapter triggers mainmatter
            current_position = [docheader.mainmatter]

        if not current_position[-1].dlink:
            current_position[-1].dlink = current_block
            current_block.ulink = current_position[-1]
        else:
            current_block.llink = last_link(current_position[-1]) # this must be first
            last_link(current_position[-1]).rlink = current_block

        if isinstance(current_block, core.blocks.Chapter): # chapter gets to the end of current position
            current_position.append(current_block)

        current_block = current_block.next

    current_block.llink = last_link(current_position[-1]) # this must be first
    last_link(current_position[-1]).rlink = current_block

    if verbose:
        print('done.')

    return docheader
Example #3
0
 def to_console(block, replace_lines):
     nonlocal nr
     log_string = "Generating block: " + nr + "\n\n"
     content = reformat(block, margin=args.M) + "\n"
     writeout(log_string + content, False, replace_lines=replace_lines)
     return log_string.count("\n") + content.count("\n")