diff --git a/algorithms/graph/articulations_bridges.cpp b/algorithms/graph/articulations_bridges.cpp
index 2fbb2b63120b75c78962e62ced786756e25f39e5..fd2648439538f0c34b8d8eb5cb6afc40881bf979 100644
--- a/algorithms/graph/articulations_bridges.cpp
+++ b/algorithms/graph/articulations_bridges.cpp
@@ -1,4 +1,4 @@
-/// Articulations and Bridges - Tarjan
+/// Articulations and Bridges
 /// 
 /// Time: O(V + E)
 /// Space: O(V + E)
diff --git a/algorithms/graph/centroid_decomposition.cpp b/algorithms/graph/centroid_decomposition.cpp
index 6cace6113f3fab3a6e40e5a528eb61365de90459..7cb5041607054ed0bbdde6894d67df1533c188dc 100644
--- a/algorithms/graph/centroid_decomposition.cpp
+++ b/algorithms/graph/centroid_decomposition.cpp
@@ -1,13 +1,13 @@
 /// Centroid Decomposition
 ///
 /// Description:
-///   The Centroid Decomposition of a tree is a tree where its root is the 
-/// centroid of the original tree, and its children are the centroid of each 
-/// tree resulting from the removal of the root from the original tree.
-///   The result is a tree with $lg(n)$ height, where the path from $a$ to $b$ 
-/// in the original tree can be decomposed into the path from a to lca($a$,$b$) 
-/// and from lca($a$,$b$) to $b$.
-///   This is useful because each one of the $n^2$ paths of the original tree 
+///   The Centroid Decomposition of a tree is a tree where its root is the
+/// centroid of the original tree, and its children are the centroid of each
+/// tree resulting from the removal of the root from the original tree. \par
+///   The result is a tree with $lg(n)$ height, where the path from $a$ to $b$
+/// in the original tree can be decomposed into the path from a to lca($a$,$b$)
+/// and from lca($a$,$b$) to $b$. \par
+///   This is useful because each one of the $n^2$ paths of the original tree
 /// is the concatenation of two paths in a set of $O(n lg(n))$ paths from a 
 /// node to all its ancestors in the centroid decomposition.
 ///
diff --git a/algorithms/graph/tarjan.cpp b/algorithms/graph/tarjan.cpp
index 0232ee946f81690da7be745cf45b22e024ab2bdf..ecd8f88f953323c0e764ef0cea221e65deaae637 100644
--- a/algorithms/graph/tarjan.cpp
+++ b/algorithms/graph/tarjan.cpp
@@ -1,4 +1,4 @@
-/// Tarjan - Strongly Connected Components (SCC)
+/// Tarjan
 ///
 /// Time: O(V + E)
 /// Space: O(V + E)
@@ -48,7 +48,6 @@ struct Tarjan {
     }
   }
 
-  /// Returns number of SCCs.
   int run() {
     init();
     ncomp = ind = 0;
diff --git a/algorithms/structure/disjoint_set.cpp b/algorithms/structure/disjoint_set.cpp
index 176136ec93f344aa5b104dfbcf27c3b832113ef1..b40765aeb1cd66c1aae8553cd93e0673276f1c70 100644
--- a/algorithms/structure/disjoint_set.cpp
+++ b/algorithms/structure/disjoint_set.cpp
@@ -1,6 +1,6 @@
 /// Disjoint-set
 ///
-/// Time: O(1)
+/// Time:
 ///   - make_set:  O(1)
 ///   - find_set:  O(a(n))
 ///   - union_set: O(a(n))
diff --git a/caderno.pdf b/caderno.pdf
index 745b2a84ac3c4bd0096dca4b93bf69495e665084..970826445bf0225f4bacd14f6373a284c0903289 100644
Binary files a/caderno.pdf and b/caderno.pdf differ
diff --git a/gen_notebook b/gen_notebook
index 6f639f7a2dd4f169912174101d2fb00793c66383..394a48cad6c4558f62a4b2a0fee5b92fa32ba76f 100755
--- a/gen_notebook
+++ b/gen_notebook
@@ -4,13 +4,13 @@ if [ "$1" = "DEBUG" ]; then
   tex_file=result.tex
   python3 notebook/gen_latex.py --header=notebook/header.tex --output=$tex_file
 else
-  tex_file=$(mktemp)
+  tex_file=bft_notebook
   python3 notebook/gen_latex.py --header=notebook/header.tex --output=$tex_file
 
   # Lualatex must be used in order to work with the correct font
   lualatex $tex_file -halt-on-error -output-directory . && 
   lualatex $tex_file -halt-on-error -output-directory .
 
-  mv tmp.pdf caderno.pdf
-  rm tmp*
+  mv $tex_file.pdf caderno.pdf
+  rm $tex_file*
 fi
diff --git a/notebook/gen_latex.py b/notebook/gen_latex.py
index 6b8bf33b6acd4c41d73938d6ed2a9e2c04226b79..264a5f00d721be46901e02a399563de884cd2f42 100644
--- a/notebook/gen_latex.py
+++ b/notebook/gen_latex.py
@@ -38,12 +38,116 @@ class Tree:
 
 
 class LatexGenerator:
+
     class SourceFile:
         def __init__(self, path):
-            pass
-
-        def _parse():
-            pass
+            source = open(path, 'r')
+            
+            self.type = path.split('.')[-1]
+            self.comment = '///' if self.type == 'cpp' else '"""'
+
+            self.header = {}
+            self.code, self.raw_header = [], []
+            self.sections = ['Description', 'Time', 'Space', 'Include']
+
+            self._parse_source(source)
+            self._parse_header()
+
+        # Splits content of the file between header and code.
+        def _parse_source(self, source):
+            lines = source.readlines()
+            in_header = True
+
+            for i, line in enumerate(lines):
+                if line[0:3] != self.comment:
+                    in_header = False
+
+                if in_header:
+                    self.raw_header.append(line[4:-1])
+                else:
+                    self.code = lines[(i+1):]
+                    break
+        
+        # Returns section name of line or None if nothing is found.
+        def _get_section(self, line):
+            comm = line.split(':')[0]
+            return comm if comm in self.sections else None
+
+        # Builds header dict by separating the header on the 
+        # found sections.
+        def _parse_header(self):
+            self.name = self.raw_header[0]
+
+            curr = None
+            for i in self.raw_header[1:]:
+                section = self._get_section(i)
+
+                if section != None:
+                    curr = section 
+                    self.header[curr] = []
+
+                    # Add rest of line (right side of section name)
+                    rest = ':'.join(i.split(':')[1:]).strip()
+                    if len(rest) > 0:
+                        self.header[curr].append(rest)
+                else:
+                    if curr != None:
+                        line = i.strip()
+                        if len(line) > 0:
+                            self.header[curr].append(line)
+
+            # Make description a single line
+            if 'Description' in self.header:
+                text = self.header['Description']
+                self.header['Description'] = ' '.join(text)
+
+        # Writes own code to LaTeX output.
+        def output_code(self, write):
+            write('\\begin{lstlisting}[style=custom%s]\n' % self.type)
+            for i in self.code:
+                write(i)
+            write('\\end{lstlisting}\n')
+            write('\n')
+
+        # Writes own header to LaTeX output.
+        def output_header(self, write):
+            write('\\begin{adjustwidth}{5pt}{5pt}\n')
+
+            if 'Description' in self.header:
+                write('\\textbf{\\footnotesize Description: }\n')
+                write('\\footnotesize{\\par %s}' % self.header['Description'])
+                write('\\\\\n')
+                write('~\\\\\n')
+
+            if 'Time' in self.header:
+                write('\\textbf{\\footnotesize Time: }')
+                if len(self.header['Time']) > 1:
+                    write('\n')
+                    write('\\begin{compactitem}\n')
+                    for i in self.header['Time']:
+                        line = i[1:].split(':')
+                        write('\\item{\\footnotesize{%s: $%s$}}\n' % 
+                                (line[0].strip().replace('_', '\\_'), 
+                                 line[1].strip()))
+                    write('\\end{compactitem}\n')
+                else:
+                    write('\\footnotesize{$%s$}\\\\\n' % self.header['Time'][0])
+
+            if 'Space' in self.header:
+                write('\\textbf{\\footnotesize Space: }')
+                if len(self.header['Space']) > 1:
+                    write('\n')
+                    write('\\begin{compactitem}\n')
+                    for i in self.header['Space']:
+                        line = i[1:].split(':')
+                        write('\\item{\\footnotesize{%s: $%s$}}\n' % 
+                                (line[0].strip().replace('_', '\\_'), 
+                                 line[1].strip()))
+                    write('\\end{compactitem}\n')
+                else:
+                    write('\\footnotesize{$%s$}\n' % self.header['Space'][0])
+
+            write('\\end{adjustwidth}\n')
 
     def __init__(self, tree, output, header):
         self.output = open(output, 'w')
@@ -53,11 +157,21 @@ class LatexGenerator:
         self.files = {}
         self.hierarchy = [i*'sub' + 'section' for i in range(3)]
 
+        self._gen_latex()
+
+    # Generates full LaTeX.
+    def _gen_latex(self):
         self._add_header()
-        self._gen_latex(tree)
+
+        self._write('\\begin{document}\n')
+        self._write('\\tableofcontents\n')
+        self._write('\\newpage\n\n')
+
+        self._gen_tree_latex(self.tree)
+
         self._write('\\end{document}\n')
 
-    # Print text to output file
+    # Print text to output file.
     def _write(self, text):
         self.output.write(text)
 
@@ -67,59 +181,40 @@ class LatexGenerator:
         for i in lines:
             self._write(i)
 
-        self._write('\\begin{document}\n')
-        self._write('\\tableofcontents\n')
-        self._write('\\newpage\n')
-        self._write('\n')
-
-    # Prints section title in Latex format.
+    # Prints section title in LaTeX format.
     def _gen_title_latex(self, content, depth):
         self._write('\\%s{%s}\n' % (self.hierarchy[depth], content))
 
-    # Prints code in Latex format.
-    def gen_code_latex(self, path):
-        suffix = path.split('.')[-1]
-        self._write('\\begin{lstlisting}[style=custom%s]\n' % suffix)
-
-        # TODO: Add code parsing funcion to extract text from comments
-        with open(path) as f:
-            lines = f.readlines()
-        for i in lines:
-            self._write(i)
-
-        self._write('\\end{lstlisting}\n')
-        self._write('\n')
+    # Prints code in LaTeX format.
+    def gen_code_latex(self, source):
+        source.output_header(self._write)
+        source.output_code(self._write)
+        self._write('\\hrule\n')
 
-    # Generates Latex for entire tree recursively
-    def _gen_latex(self, sub, path = '', depth = 0):
+    # Generates LaTeX for entire tree recursively.
+    def _gen_tree_latex(self, sub, path = '', depth = 0):
         if type(sub) == list:
             for i in sub:
-                self._gen_title_latex(self._parse_file_name(path + i), depth)
-                self.gen_code_latex(path + i)
+                source = self.SourceFile(path + i)
+                self._gen_title_latex(source.name, depth)
+                self.gen_code_latex(source)
         else:
             if depth == 1:
                 self._write('\\begin{multicols}{3}\n')
-
             for i in sub:
                 self._gen_title_latex(self._parse_dir_name(i), depth)
-                self._gen_latex(sub[i], path + i + '/', depth + 1)
-
+                self._gen_tree_latex(sub[i], path + i + '/', depth + 1)
             if depth == 1:
                 self._write('\\end{multicols}\n')
 
         self._write('\n')
 
-    # Parses name of the section (capitalize)
+    # Parses name of the section (capitalize).
     def _parse_dir_name(self, name):
         return ' '.join(list(map(lambda x : x.capitalize(), name.split('_'))))
 
-    # Parses name of file by getting the first line of the source code.
-    def _parse_file_name(self, name):
-        with open(name) as f:
-            result = f.readline()
-        return result[4:-1]
-
 
+# Parses command line arguments and returns them.
 def get_args():
     parser = argparse.ArgumentParser()
 
diff --git a/notebook/header.tex b/notebook/header.tex
index e03cfb0f3aaa5ca6eb93b80808364072c916e733..871d53e4afcd5d2db54528eb2bf9f4710ffa2ee2 100644
--- a/notebook/header.tex
+++ b/notebook/header.tex
@@ -7,6 +7,9 @@
 \usepackage{multicol}
 \usepackage{titlesec}
 \usepackage{fancyhdr}   
+\usepackage{xcolor}
+\usepackage{changepage}
+\usepackage{paralist}
 
 % 'Fancy pages' adds header with page number and subsection title
 \pagestyle{fancy}
@@ -32,20 +35,24 @@
     left=5mm,
     right=5mm,
     top=20mm,
-    bottom=10mm,
+    bottom=5mm,
 }
 
 % Set sizes for *[sub]section
-\titleformat*{\subsubsection}{\normalsize\bfseries}
-\titleformat*{\subsection}{\large\bfseries}
-\titleformat*{\section}{\Large\bfseries}
+\titleformat*{\subsubsection}{\large\bfseries}
+\titleformat*{\subsection}{\Large\bfseries}
+\titleformat*{\section}{\LARGE\bfseries}
+
+% Set background color used in listings
+\definecolor{light-gray}{gray}{0.95}
 
 % Set style for C++ code
 \lstdefinestyle{customcpp}{
     language=C++,
     basicstyle=\scriptsize\ttfamily,
     tabsize=2,
-    frame=b,
+    backgroundcolor=\color{light-gray},
+%    frame=t,
     breaklines=true,
     morekeywords={int32\_t, ll}
 }
@@ -54,7 +61,7 @@
 \lstdefinestyle{customvim}{
     basicstyle=\scriptsize\ttfamily,
     tabsize=2,
-    frame=b,
+%    frame=t,
     breaklines=true,
     morekeywords={set}
 }