Repository: Qiskit/qiskit

Issue:
Add an eASCII/Unicode drawer
### What is the expected behavior?
Something along these lines, with minimal or non dependencies.
```
       ┌───┐
q[0] ──┤ H ├──·───m
       └───┘  │   ║
q[1] ─────────┼───╫──m
              │   ║  ║
q[2] ────────(+)──╫──╫──m
                  ║  ║  ║
c[0] ─────────────╨──╫──╫──
                     ║  ║
c[1] ────────────────╨──╫──
                        ║
c[2] ───────────────────╨──
```


Discussion:

Resolving patch:
diff --git a/qiskit/tools/visualization/__init__.py b/qiskit/tools/visualization/__init__.py
--- a/qiskit/tools/visualization/__init__.py
+++ b/qiskit/tools/visualization/__init__.py
@@ -10,7 +10,7 @@
 import sys
 from qiskit._util import _has_connection
 from ._circuit_visualization import circuit_drawer, plot_circuit, generate_latex_source,\
-    latex_circuit_drawer, matplotlib_circuit_drawer, qx_color_scheme
+    latex_circuit_drawer, matplotlib_circuit_drawer, _text_circuit_drawer, qx_color_scheme
 from ._error import VisualizationError
 from ._state_visualization import plot_bloch_vector
 from ._dag_visualization import dag_drawer
diff --git a/qiskit/tools/visualization/_circuit_visualization.py b/qiskit/tools/visualization/_circuit_visualization.py
--- a/qiskit/tools/visualization/_circuit_visualization.py
+++ b/qiskit/tools/visualization/_circuit_visualization.py
@@ -9,6 +9,7 @@
 
 """
 Two quantum circuit drawers based on:
+    0. Ascii art
     1. LaTeX
     2. Matplotlib
 """
@@ -37,6 +38,7 @@
 from qiskit.dagcircuit import DAGCircuit
 from qiskit.tools.visualization._error import VisualizationError
 from qiskit.transpiler import transpile
+from .text import TextDrawing
 
 logger = logging.getLogger(__name__)
 
@@ -64,9 +66,10 @@ def circuit_drawer(circuit,
                    filename=None,
                    style=None,
                    output=None,
-                   interactive=False):
-    """Draw a quantum circuit, via 2 methods (try 1st, if unsuccessful, 2nd):
-
+                   interactive=False,
+                   line_length=None):
+    """Draw a quantum circuit to different formats (set by output parameter):
+    0. text: ASCII art string
     1. latex: high-quality images, but heavy external software dependencies
     2. matplotlib: purely in Python with no external dependencies
 
@@ -79,16 +82,19 @@ def circuit_drawer(circuit,
         filename (str): file path to save image to
         style (dict or str): dictionary of style or file name of style file
         output (str): Select the output method to use for drawing the circuit.
-            Valid choices are `latex`, `latex_source`, `mpl`. Note if one is
-            not specified it will use latex and if that fails fallback to
+            Valid choices are `text`, `latex`, `latex_source`, `mpl`. Note if one
+            is not specified it will use latex and if that fails fallback to
             mpl. However this behavior is deprecated and in a future release
             the default will change.
         interactive (bool): when set true show the circuit in a new window
             (cannot inline in Jupyter). Note when used with the latex_source
             output type this has no effect
-
+        line_length (int): sets the length of the lines generated by `text`
     Returns:
-        PIL.Image: an in-memory representation of the circuit diagram
+        PIL.Image: (outputs `latex` and `python`) an in-memory representation of
+                   the circuit diagram.
+        String: (outputs `text` and `latex_source`). The ascii art or the LaTeX
+                source code.
 
     Raises:
         VisualizationError: when an invalid output method is selected
@@ -99,18 +105,17 @@ def circuit_drawer(circuit,
         warnings.warn('The current behavior for the default output will change'
                       ' in a future release. Instead of trying latex and '
                       'falling back to mpl on failure it will just use '
-                      'mpl by default', DeprecationWarning)
+                      '"text" by default', DeprecationWarning)
         try:
             im = _latex_circuit_drawer(circuit, basis, scale, filename, style)
-        except (OSError, subprocess.CalledProcessError):
+        except (OSError, subprocess.CalledProcessError, FileNotFoundError):
             im = _matplotlib_circuit_drawer(circuit, basis, scale, filename,
                                             style)
     else:
-        if output not in ['latex', 'latex_source', 'mpl']:
-            raise VisualizationError(
-                'Invalid output type %s selected. The only valid choices are '
-                'latex, latex_source, and mpl' % output)
-        if output == 'latex':
+        if output == 'text':
+            return _text_circuit_drawer(circuit, filename=filename, basis=basis,
+                                        line_length=line_length)
+        elif output == 'latex':
             im = _latex_circuit_drawer(circuit, basis=basis, scale=scale,
                                        filename=filename, style=style)
         elif output == 'latex_source':
@@ -120,6 +125,9 @@ def circuit_drawer(circuit,
         elif output == 'mpl':
             im = _matplotlib_circuit_drawer(circuit, basis=basis, scale=scale,
                                             filename=filename, style=style)
+        else:
+            raise VisualizationError('Invalid output type %s selected. The only valid choices '
+                                     'are latex, latex_source, text, and mpl' % output)
     if im and interactive:
         im.show()
     return im
@@ -292,6 +300,36 @@ def qx_color_scheme():
     }
 
 
+# -----------------------------------------------------------------------------
+# _text_circuit_drawer
+# -----------------------------------------------------------------------------
+
+
+def _text_circuit_drawer(circuit, filename=None,
+                         basis="id,u0,u1,u2,u3,x,y,z,h,s,sdg,t,tdg,rx,ry,rz,"
+                               "cx,cy,cz,ch,crz,cu1,cu3,swap,ccx,cswap", line_length=None):
+    """
+    Draws a circuit using ascii art.
+    Args:
+        circuit (QuantumCircuit): Input circuit
+        filename (str): optional filename to write the result
+        basis (str): Optional. Comma-separated list of gate names
+        line_length (int): Optional. Sometimes, your console is too small of the drawing. Give me
+                           you maximum line length your console supports.
+    Returns:
+        String: The drawing in a loooong string.
+    """
+    dag_circuit = DAGCircuit.fromQuantumCircuit(circuit, expand_gates=False)
+    json_circuit = transpile(dag_circuit, basis_gates=basis, format='json')
+
+    text = "\n".join(TextDrawing(json_circuit).lines(line_length))
+
+    if filename:
+        with open(filename, mode='w', encoding="utf8") as text_file:
+            text_file.write(text)
+    return text
+
+
 # -----------------------------------------------------------------------------
 # latex_circuit_drawer
 # -----------------------------------------------------------------------------
@@ -413,7 +451,7 @@ def _trim(im):
 
 def generate_latex_source(circuit, filename=None,
                           basis="id,u0,u1,u2,u3,x,y,z,h,s,sdg,t,tdg,rx,ry,rz,"
-                          "cx,cy,cz,ch,crz,cu1,cu3,swap,ccx,cswap",
+                                "cx,cy,cz,ch,crz,cu1,cu3,swap,ccx,cswap",
                           scale=0.7, style=None):
     """Convert QuantumCircuit to LaTeX string.
 
@@ -437,7 +475,7 @@ def generate_latex_source(circuit, filename=None,
 
 def _generate_latex_source(circuit, filename=None,
                            basis="id,u0,u1,u2,u3,x,y,z,h,s,sdg,t,tdg,rx,ry,rz,"
-                           "cx,cy,cz,ch,crz,cu1,cu3,swap,ccx,cswap",
+                                 "cx,cy,cz,ch,crz,cu1,cu3,swap,ccx,cswap",
                            scale=0.7, style=None):
     """Convert QuantumCircuit to LaTeX string.
 
@@ -469,6 +507,7 @@ class QCircuitImage(object):
 
     Thanks to Eric Sabo for the initial implementation for QISKit.
     """
+
     def __init__(self, circuit, scale, style=None):
         """
         Args:
@@ -638,7 +677,7 @@ def latex(self, aliases=None):
                 if j != self.img_depth:
                     output.write(" & ")
                 else:
-                    output.write(r'\\'+'\n')
+                    output.write(r'\\' + '\n')
         output.write('\t }\n')
         output.write('\\end{equation*}\n\n')
         output.write('\\end{document}')
@@ -687,7 +726,7 @@ def _get_image_depth(self, aliases=None):
         Raises:
             QISKitError: if trying to draw unsupported gates
         """
-        columns = 2     # wires in the beginning and end
+        columns = 2  # wires in the beginning and end
         is_occupied = [False] * self.img_width
         max_column_width = {}
         for op in self.circuit['instructions']:
@@ -894,7 +933,7 @@ def _get_image_depth(self, aliases=None):
         # the qubit/cbit labels plus initial states is 2 more
         # the wires poking out at the ends is 2 more
         sum_column_widths = sum(1 + v / 3 for v in max_column_width.values())
-        return columns+1, ceil(sum_column_widths)+4
+        return columns + 1, ceil(sum_column_widths) + 4
 
     def _get_beamer_page(self):
         """Get height, width & scale attributes for the beamer page.
@@ -1052,12 +1091,13 @@ def _build_latex_array(self, aliases=None):
                             self._latex[pos_1][columns] = "\\gate{U_1(%s)}" % (
                                 op["texparams"][0])
                         elif nm == "u2":
-                            self._latex[pos_1][columns] =\
+                            self._latex[pos_1][columns] = \
                                 "\\gate{U_2\\left(%s,%s\\right)}" % (
                                     op["texparams"][0], op["texparams"][1])
                         elif nm == "u3":
                             self._latex[pos_1][columns] = "\\gate{U_3(%s,%s,%s)}" \
-                                % (op["texparams"][0], op["texparams"][1], op["texparams"][2])
+                                                          % (op["texparams"][0], op["texparams"][1],
+                                                             op["texparams"][2])
                         elif nm == "rx":
                             self._latex[pos_1][columns] = "\\gate{R_x(%s)}" % (
                                 op["texparams"][0])
@@ -1115,7 +1155,8 @@ def _build_latex_array(self, aliases=None):
                                     op["texparams"][0], op["texparams"][1])
                         elif nm == "u3":
                             self._latex[pos_1][columns] = "\\gate{U_3(%s,%s,%s)}" \
-                                % (op["texparams"][0], op["texparams"][1], op["texparams"][2])
+                                                          % (op["texparams"][0], op["texparams"][1],
+                                                             op["texparams"][2])
                         elif nm == "rx":
                             self._latex[pos_1][columns] = "\\gate{R_x(%s)}" % (
                                 op["texparams"][0])
@@ -1192,8 +1233,8 @@ def _build_latex_array(self, aliases=None):
                             self._latex[pos_2][columns] = \
                                 "\\gate{R_z(%s)}" % (op["texparams"][0])
                         elif nm == "cu1":
-                            self._latex[pos_1][columns-1] = "\\ctrl{" + str(pos_2 - pos_1) + "}"
-                            self._latex[pos_2][columns-1] = "\\control\\qw"
+                            self._latex[pos_1][columns - 1] = "\\ctrl{" + str(pos_2 - pos_1) + "}"
+                            self._latex[pos_2][columns - 1] = "\\control\\qw"
                             self._latex[min(pos_1, pos_2)][columns] = \
                                 "\\dstick{%s}\\qw" % (op["texparams"][0])
                             self._latex[max(pos_1, pos_2)][columns] = "\\qw"
@@ -1246,15 +1287,16 @@ def _build_latex_array(self, aliases=None):
                             self._latex[pos_2][columns] = \
                                 "\\gate{R_z(%s)}" % (op["texparams"][0])
                         elif nm == "cu1":
-                            self._latex[pos_1][columns-1] = "\\ctrl{" + str(pos_2 - pos_1) + "}"
-                            self._latex[pos_2][columns-1] = "\\control\\qw"
+                            self._latex[pos_1][columns - 1] = "\\ctrl{" + str(pos_2 - pos_1) + "}"
+                            self._latex[pos_2][columns - 1] = "\\control\\qw"
                             self._latex[min(pos_1, pos_2)][columns] = \
                                 "\\dstick{%s}\\qw" % (op["texparams"][0])
                             self._latex[max(pos_1, pos_2)][columns] = "\\qw"
                         elif nm == "cu3":
                             self._latex[pos_1][columns] = "\\ctrl{" + str(pos_2 - pos_1) + "}"
                             self._latex[pos_2][columns] = "\\gate{U_3(%s,%s,%s)}" \
-                                % (op["texparams"][0], op["texparams"][1], op["texparams"][2])
+                                                          % (op["texparams"][0], op["texparams"][1],
+                                                             op["texparams"][2])
 
                 elif len(qarglist) == 3:
                     pos_1 = self.img_regs[(qarglist[0][0], qarglist[0][1])]
@@ -1285,9 +1327,8 @@ def _build_latex_array(self, aliases=None):
                                 span = re.search('barrier{(.*)}', prev_entry)
                                 if span and any(i in temp for i in range(
                                         item, int(span.group(1)))):
-                                    self._latex[
-                                        item][columns - 1] = prev_entry.replace(
-                                            '\\barrier{', '\\barrier[-0.65em]{')
+                                    self._latex[item][columns - 1] = \
+                                        prev_entry.replace('\\barrier{', '\\barrier[-0.65em]{')
 
                         gap = pos_4 - bottom
                         for i in range(self.cregs[if_reg]):
@@ -1332,9 +1373,8 @@ def _build_latex_array(self, aliases=None):
                                 span = re.search('barrier{(.*)}', prev_entry)
                                 if span and any(i in temp for i in range(
                                         item, int(span.group(1)))):
-                                    self._latex[
-                                        item][columns - 1] = prev_entry.replace(
-                                            '\\barrier{', '\\barrier[-0.65em]{')
+                                    self._latex[item][columns - 1] = \
+                                        prev_entry.replace('\\barrier{', '\\barrier[-0.65em]{')
 
                         if nm == "ccx":
                             self._latex[pos_1][columns] = "\\ctrl{" + str(pos_2 - pos_1) + "}"
@@ -1349,8 +1389,8 @@ def _build_latex_array(self, aliases=None):
 
             elif op["name"] == "measure":
                 assert len(op['clbits']) == 1 and \
-                    len(op['qubits']) == 1 and \
-                    'params' not in op, "bad operation record"
+                       len(op['qubits']) == 1 and \
+                       'params' not in op, "bad operation record"
 
                 if 'conditional' in op:
                     assert False, "If controlled measures currently not supported."
@@ -1385,9 +1425,8 @@ def _build_latex_array(self, aliases=None):
                             span = re.search('barrier{(.*)}', prev_entry)
                             if span and (
                                     item + int(span.group(1))) - pos_1 >= 0:
-                                self._latex[
-                                    item][columns - 1] = prev_entry.replace(
-                                        '\\barrier{', '\\barrier[-1.15em]{')
+                                self._latex[item][columns - 1] = \
+                                    prev_entry.replace('\\barrier{', '\\barrier[-1.15em]{')
 
                     self._latex[pos_2][columns] = \
                         "\\cw \\cwx[-" + str(pos_2 - pos_1) + "]"
@@ -1728,9 +1767,9 @@ def _measure(self, qxy, cxy, cid):
         self.ax.plot([qx, qx + 0.35 * WID], [qy - 0.15 * HIG, qy + 0.20 * HIG],
                      color=self._style.lc, linewidth=1.5, zorder=PORDER_GATE)
         # arrow
-        self._line(qxy, [cx, cy+0.35*WID], lc=self._style.cc, ls=self._style.cline)
-        arrowhead = patches.Polygon(((cx-0.20*WID, cy+0.35*WID),
-                                     (cx+0.20*WID, cy+0.35*WID),
+        self._line(qxy, [cx, cy + 0.35 * WID], lc=self._style.cc, ls=self._style.cline)
+        arrowhead = patches.Polygon(((cx - 0.20 * WID, cy + 0.35 * WID),
+                                     (cx + 0.20 * WID, cy + 0.35 * WID),
                                      (cx, cy)),
                                     fc=self._style.cc,
                                     ec=None)
diff --git a/qiskit/tools/visualization/text.py b/qiskit/tools/visualization/text.py
new file mode 100644
--- /dev/null
+++ b/qiskit/tools/visualization/text.py
@@ -0,0 +1,829 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2018, IBM.
+#
+# This source code is licensed under the Apache License, Version 2.0 found in
+# the LICENSE.txt file in the root directory of this source tree.
+
+"""
+A module for drawing circuits in ascii art or some other text representation
+"""
+
+
+class DrawElement():
+    """ An element is an instruction or an operation that need to be drawn."""
+
+    def __init__(self, label=None):
+        self._width = None
+        self.label = self.mid_content = label
+        self.top_format = self.mid_format = self.bot_format = "%s"
+        self.top_connect = self.bot_connect = " "
+        self.top_pad = self._mid_padding = self.bot_pad = " "
+        self.bot_connector = {}
+        self.top_connector = {}
+        self.right_fill = self.left_fill = 0
+
+    @property
+    def top(self):
+        """ Constructs the top line of the element"""
+        ret = self.top_format % self.top_connect.center(
+            self.width - self.left_fill - self.right_fill, self.top_pad)
+        if self.right_fill:
+            ret = ret.ljust(self.right_fill, self.top_pad)
+        if self.left_fill:
+            ret = ret.rjust(self.left_fill, self.top_pad)
+        return ret
+
+    @property
+    def mid(self):
+        """ Constructs the middle line of the element"""
+        ret = self.mid_format % self.mid_content.center(
+            self.width - self.left_fill - self.right_fill, self._mid_padding)
+        if self.right_fill:
+            ret = ret.ljust(self.right_fill, self._mid_padding)
+        if self.left_fill:
+            ret = ret.rjust(self.left_fill, self._mid_padding)
+        return ret
+
+    @property
+    def bot(self):
+        """ Constructs the bottom line of the element"""
+        ret = self.bot_format % self.bot_connect.center(
+            self.width - self.left_fill - self.right_fill, self.bot_pad)
+        if self.right_fill:
+            ret = ret.ljust(self.right_fill, self.bot_pad)
+        if self.left_fill:
+            ret = ret.rjust(self.left_fill, self.bot_pad)
+        return ret
+
+    @property
+    def length(self):
+        """ Returns the length of the element, including the box around."""
+        return max(len(self.top), len(self.mid), len(self.bot))
+
+    @length.setter
+    def length(self, value):
+        """ Adjusts width so the length fits."""
+        self.width = value - max(
+            [len(getattr(self, i) % '') for i in ["bot_format", "mid_format", "top_format"]])
+
+    @property
+    def width(self):
+        """ Returns the width of the label, including padding"""
+        if self._width:
+            return self._width
+        return len(self.mid_content)
+
+    @width.setter
+    def width(self, value):
+        self._width = value
+
+    def connect(self, wire_char, where, label=None):
+        """
+        Connects boxes and elements using wire_char and setting proper connectors.
+        Args:
+            wire_char (char): For example '║' or '│'.
+            where (list["top", "bot"]): Where the connector should be set.
+            label (string): Some connectors have a label (see cu1, for example).
+        """
+        if 'top' in where:
+            self.top_connect = self.top_connector[
+                wire_char] if wire_char in self.top_connector else wire_char
+
+        if 'bot' in where:
+            self.bot_connect = self.bot_connector[
+                wire_char] if wire_char in self.bot_connector else wire_char
+
+        if label:
+            self.top_format = self.top_format[:-1] + (label if label else "")
+
+
+class BoxOnClWire(DrawElement):
+    """ Draws a box on the classical wire
+        top: ┌───┐ ┌───────┐
+        mid: ╡ A ╞ ╡   A   ╞
+        bot: └───┘ └───────┘
+    """
+
+    def __init__(self, label="", top_connect='─', bot_connect='─'):
+        super().__init__(label)
+        self.top_format = "┌─%s─┐"
+        self.mid_format = "╡ %s ╞"
+        self.bot_format = "└─%s─┘"
+        self.top_pad = self.bot_pad = '─'
+        self.top_connect = top_connect
+        self.bot_connect = bot_connect
+        self.mid_content = label
+
+
+class BoxOnQuWire(DrawElement):
+    """ Draws a box on the quantum wire
+        top: ┌───┐ ┌───────┐
+        mid: ┤ A ├ ┤   A   ├
+        bot: └───┘ └───────┘
+    """
+
+    def __init__(self, label="", top_connect='─', bot_connect='─'):
+        super().__init__(label)
+        self.top_format = "┌─%s─┐"
+        self.mid_format = "┤ %s ├"
+        self.bot_format = "└─%s─┘"
+        self.top_pad = self.bot_pad = '─'
+        self.top_connect = top_connect
+        self.bot_connect = bot_connect
+        self.mid_content = label
+        self.top_connector = {"│": '┴'}
+        self.bot_connector = {"│": '┬'}
+
+
+class MeasureTo(DrawElement):
+    """ The element on the classic wire to which the measure is performed
+    top:  ║     ║
+    mid: ═╩═ ═══╩═══
+    bot:
+    """
+
+    def __init__(self):
+        super().__init__()
+        self.top_connect = " ║ "
+        self.mid_content = "═╩═"
+        self.bot_connect = "   "
+        self._mid_padding = "═"
+
+
+class MeasureFrom(BoxOnQuWire):
+    """ The element on the quantum wire in which the measure is performed
+        top: ┌─┐    ┌─┐
+        mid: ┤M├ ───┤M├───
+        bot: └╥┘    └╥┘
+    """
+
+    def __init__(self):
+        super().__init__()
+        self.top_format = self.mid_format = self.bot_format = "%s"
+        self.top_connect = "┌─┐"
+        self.mid_content = "┤M├"
+        self.bot_connect = "└╥┘"
+
+
+class MultiBox(DrawElement):
+    """Elements that is draw on over multiple wires."""
+
+    def center_label(self, input_length, order):
+        """
+        In multi-bit elements, the label is centered vertically.
+        Args:
+            input_length (int): Rhe amount of wires affected.
+            order (int): Which middle element is this one?
+        """
+        location_in_the_box = '*'.center(input_length * 2 - 1).index('*') + 1
+        top_limit = (order - 1) * 2 + 2
+        bot_limit = top_limit + 2
+        if top_limit <= location_in_the_box < bot_limit:
+            if location_in_the_box == top_limit:
+                self.top_connect = self.label
+            elif location_in_the_box == top_limit + 1:
+                self.mid_content = self.label
+            else:
+                self.bot_connect = self.label
+
+
+class BoxOnQuWireTop(MultiBox, BoxOnQuWire):
+    """ Draws the top part of a box that affects more than one quantum wire"""
+
+    def __init__(self, label="", top_connect=None):
+        super().__init__(label)
+        self.mid_content = ""  # The label will be put by some other part of the box.
+        self.bot_format = "│ %s │"
+        self.top_connect = top_connect if top_connect else '─'
+        self.bot_connect = self.bot_pad = " "
+
+
+class BoxOnQuWireMid(MultiBox, BoxOnQuWire):
+    """ Draws the middle part of a box that affects more than one quantum wire"""
+
+    def __init__(self, label, input_length, order):
+        super().__init__(label)
+        self.top_format = "│ %s │"
+        self.bot_format = "│ %s │"
+        self.center_label(input_length, order)
+
+
+class BoxOnQuWireBot(MultiBox, BoxOnQuWire):
+    """ Draws the bottom part of a box that affects more than one quantum wire"""
+
+    def __init__(self, label, input_length):
+        super().__init__(label)
+        self.top_format = "│ %s │"
+
+        self.mid_content = self.bot_connect = self.top_connect = ""
+        if input_length <= 2:
+            self.top_connect = label
+
+
+class BoxOnClWireTop(MultiBox, BoxOnClWire):
+    """ Draws the top part of a conditional box that affects more than one classical wire"""
+
+    def __init__(self, label="", top_connect=None):
+        super().__init__(label)
+        self.mid_content = ""  # The label will be put by some other part of the box.
+        self.bot_format = "│ %s │"
+        self.top_connect = top_connect if top_connect else '─'
+        self.bot_connect = self.bot_pad = " "
+
+
+class BoxOnClWireMid(MultiBox, BoxOnClWire):
+    """ Draws the middle part of a conditional box that affects more than one classical wire"""
+
+    def __init__(self, label, input_length, order):
+        super().__init__(label)
+        self.mid_content = label
+        self.top_format = "│ %s │"
+        self.bot_format = "│ %s │"
+        self.top_pad = self.bot_pad = ' '
+        self.top_connect = self.bot_connect = self.mid_content = ''
+        self.center_label(input_length, order)
+
+
+class BoxOnClWireBot(MultiBox, BoxOnClWire):
+    """ Draws the bottom part of a conditional box that affects more than one classical wire"""
+
+    def __init__(self, label, input_length, bot_connect='─'):
+        super().__init__(label)
+        self.top_format = "│ %s │"
+        self.top_pad = " "
+        self.bot_connect = bot_connect
+
+        self.mid_content = self.top_connect = ""
+        if input_length <= 2:
+            self.top_connect = label
+
+
+class DirectOnQuWire(DrawElement):
+    """
+    Element to the wire (without the box).
+    """
+
+    def __init__(self, label=""):
+        super().__init__(label)
+        self.top_format = ' %s '
+        self.mid_format = '─%s─'
+        self.bot_format = ' %s '
+        self._mid_padding = '─'
+
+
+class Barrier(DirectOnQuWire):
+    """ Draws a barrier.
+        top:  ░     ░
+        mid: ─░─ ───░───
+        bot:  ░     ░
+    """
+
+    def __init__(self, label=""):
+        super().__init__("░")
+        self.top_connect = "░"
+        self.bot_connect = "░"
+
+
+class Ex(DirectOnQuWire):
+    """ Draws an X (usually with a connector). E.g. the top part of a swap gate
+    top:
+    mid: ─X─ ───X───
+    bot:  │     │
+    """
+
+    def __init__(self, bot_connect=" ", top_connect=" "):
+        super().__init__("X")
+        self.bot_connect = bot_connect
+        self.top_connect = top_connect
+
+
+class Reset(DirectOnQuWire):
+    """ Draws a reset gate"""
+
+    def __init__(self):
+        super().__init__("|0>")
+
+
+class Bullet(DirectOnQuWire):
+    """ Draws a bullet (usuallly with a connector). E.g. the top part of a CX gate.
+    top:
+    mid: ─■─  ───■───
+    bot:  │      │
+    """
+
+    def __init__(self, top_connect=" ", bot_connect=" "):
+        super().__init__('■')
+        self.top_connect = top_connect
+        self.bot_connect = bot_connect
+
+
+class EmptyWire(DrawElement):
+    """ This element is just the wire, with no instructions nor operations."""
+
+    def __init__(self, wire):
+        super().__init__(wire)
+        self._mid_padding = wire
+
+    @staticmethod
+    def fillup_layer(layer, first_clbit):
+        """
+        Given a layer, replace the Nones in it with EmptyWire elements.
+        Args:
+            layer (list): The layer that contains Nones.
+            first_clbit (int): The first wire that is classic.
+
+        Returns:
+            list: The new layer, with no Nones.
+        """
+        for nones in [i for i, x in enumerate(layer) if x is None]:
+            layer[nones] = EmptyWire('═') if nones >= first_clbit else EmptyWire('─')
+        return layer
+
+
+class BreakWire(DrawElement):
+    """ This element is used to break the drawing in several pages."""
+
+    def __init__(self, arrow_char):
+        super().__init__()
+        self.top_format = self.mid_format = self.bot_format = "%s"
+        self.top_connect = arrow_char
+        self.mid_content = arrow_char
+        self.bot_connect = arrow_char
+
+    @staticmethod
+    def fillup_layer(layer_length, arrow_char):
+        """
+        Creates a layer with BreakWire elements.
+        Args:
+            layer_length (int): The length of the layer to create
+            arrow_char (char): The char used to create the BreakWire element.
+
+        Returns:
+            list: The new layer.
+        """
+        breakwire_layer = []
+        for _ in range(layer_length):
+            breakwire_layer.append(BreakWire(arrow_char))
+        return breakwire_layer
+
+
+class InputWire(DrawElement):
+    """ This element is the label and the initial value of a wire."""
+
+    def __init__(self, label):
+        super().__init__(label)
+
+    @staticmethod
+    def fillup_layer(names):  # pylint: disable=arguments-differ
+        """
+        Creates a layer with InputWire elements.
+        Args:
+            names (list): List of names for the wires.
+
+        Returns:
+            list: The new layer
+        """
+        longest = max([len(name) for name in names])
+        inputs_wires = []
+        for name in names:
+            inputs_wires.append(InputWire(name.rjust(longest)))
+        return inputs_wires
+
+
+class TextDrawing():
+    """ The text drawing"""
+
+    def __init__(self, json_circuit):
+        self.json_circuit = json_circuit
+
+    def lines(self, line_length=None):
+        """
+        Generates a list with lines. These lines form the text drawing.
+        Args:
+            line_length (int): Optional. When given, breaks the circuit drawing to this length. This
+                               useful when the drawing does not fit in the console.
+
+        Returns:
+            list: A list of lines with the text drawing.
+        """
+        noqubits = self.json_circuit['header']['number_of_qubits']
+        layers = self.build_layers()
+
+        # TODO compress layers
+        # -| H |----------
+        # --------| H |---
+        # should be
+        # -| H |---
+        # -| H |---
+
+        layer_groups = [[]]
+        rest_of_the_line = line_length
+        for layerno, layer in enumerate(layers):
+            # Replace the Nones with EmptyWire
+            layers[layerno] = EmptyWire.fillup_layer(layer, noqubits)
+
+            TextDrawing.normalize_width(layer)
+
+            if line_length is None:
+                # does not page
+                layer_groups[-1].append(layer)
+                continue
+
+            # chop the layer to the line_length (pager)
+            layer_length = layers[layerno][0].length
+
+            if layer_length < rest_of_the_line:
+                layer_groups[-1].append(layer)
+                rest_of_the_line -= layer_length
+            else:
+                layer_groups[-1].append(BreakWire.fillup_layer(len(layer), '»'))
+
+                # New group
+                layer_groups.append([BreakWire.fillup_layer(len(layer), '«')])
+                rest_of_the_line = line_length - layer_groups[-1][-1][0].length
+
+                layer_groups[-1].append(
+                    InputWire.fillup_layer(self.wire_names(with_initial_value=False)))
+                rest_of_the_line -= layer_groups[-1][-1][0].length
+
+                layer_groups[-1].append(layer)
+                rest_of_the_line -= layer_groups[-1][-1][0].length
+
+        lines = []
+        for layer_group in layer_groups:
+            wires = [i for i in zip(*layer_group)]
+            lines += TextDrawing.draw_wires(wires)
+
+        return lines
+
+    def wire_names(self, with_initial_value=True):
+        """
+        Returns a list of names for each wire.
+        Args:
+            with_initial_value (bool): Optional (Default: True). If true, adds the initial value to
+                                       the name.
+
+        Returns:
+            List: The list of wire names.
+        """
+        ret = []
+
+        if with_initial_value:
+            initial_value = {'qubit': '|0>', 'clbit': '0 '}
+        else:
+            initial_value = {'qubit': '', 'clbit': ''}
+
+        header = self.json_circuit['header']
+        for qubit in header['qubit_labels']:
+            ret.append("%s_%s: %s" % (qubit[0], qubit[1], initial_value['qubit']))
+        for creg in header['clbit_labels']:
+            for clbit in range(creg[1]):
+                ret.append("%s_%s: %s" % (creg[0], clbit, initial_value['clbit']))
+        return ret
+
+    @staticmethod
+    def draw_wires(wires):
+        """
+        Given a list of wires, creates a list of lines with the text drawing.
+        Args:
+            wires (list): A list of wires with instructions.
+
+        Returns:
+            list: A list of lines with the text drawing.
+        """
+        lines = []
+        bot_line = None
+        for wire in wires:
+            # TOP
+            top_line = ""
+            for instruction in wire:
+                top_line += instruction.top
+
+            if bot_line is None:
+                lines.append(top_line)
+            else:
+                lines.append(TextDrawing.merge_lines(lines.pop(), top_line))
+
+            # MID
+            mid_line = ""
+            for instruction in wire:
+                mid_line += instruction.mid
+
+            lines.append(TextDrawing.merge_lines(lines[-1], mid_line, icod="bot"))
+
+            # BOT
+            bot_line = ""
+            for instruction in wire:
+                bot_line += instruction.bot
+            lines.append(TextDrawing.merge_lines(lines[-1], bot_line, icod="bot"))
+
+        return lines
+
+    @staticmethod
+    def label_for_conditional(instruction):
+        """ Creates the label for a conditional instruction."""
+        return "%s %s" % ('=', instruction['conditional']['val'])
+
+    @staticmethod
+    def params_for_label(instruction):
+        """Get the params and format them to add them to a label. None of there is no param."""
+        if 'params' in instruction and instruction['params']:
+            return ['%.5g' % i for i in instruction['params']]
+        return None
+
+    @staticmethod
+    def label_for_box(instruction):
+        """ Creates the label for a box."""
+        label = instruction['name'].capitalize()
+        params = TextDrawing.params_for_label(instruction)
+        if params:
+            label += "(%s)" % ','.join(params)
+        return label
+
+    @staticmethod
+    def merge_lines(top, bot, icod="top"):
+        """
+        Merges two lines (top and bot) in the way that the overlapping make senses.
+        Args:
+            top (str): the top line
+            bot (str): the bottom line
+            icod (top or bot): in case of doubt, which line should have priority? Default: "top".
+        Returns:
+            str: The merge of both lines.
+        """
+        ret = ""
+        for topc, botc in zip(top, bot):
+            if topc == botc:
+                ret += topc
+            elif topc in '┼╪' and botc == " ":
+                ret += "│"
+            elif topc == " ":
+                ret += botc
+            elif topc in '┬╥' and botc in " ║│":
+                ret += topc
+            elif topc in '┬│' and botc == "═":
+                ret += '╪'
+            elif topc in '┬│' and botc == "─":
+                ret += '┼'
+            elif topc in '└┘║│░' and botc == " ":
+                ret += topc
+            elif topc in '─═' and botc == " " and icod == "top":
+                ret += topc
+            elif topc in '─═' and botc == " " and icod == "bot":
+                ret += botc
+            elif topc in "║╥" and botc in "═":
+                ret += "╬"
+            elif topc in "║╥" and botc in "─":
+                ret += "╫"
+            elif topc in '╫╬' and botc in " ":
+                ret += "║"
+            elif topc == '└' and botc == "┌":
+                ret += "├"
+            elif topc == '┘' and botc == "┐":
+                ret += "┤"
+            else:
+                ret += botc
+        return ret
+
+    def clbit_index_from_mask(self, mask):
+        """
+        Given a mask, returns a list of classical indexes affected by that mask.
+        Args:
+            mask (int): The mask.
+
+        Returns:
+            list: A list of indexes affected by the mask.
+        """
+        clbit_len = self.json_circuit['header']['number_of_clbits']
+        bit_mask = [bool(mask & (1 << n)) for n in range(clbit_len)]
+        return [i for i, x in enumerate(bit_mask) if x]
+
+    @staticmethod
+    def normalize_width(layer):
+        """
+        When the elements of the layer have different widths, sets the width to the max elements.
+        Args:
+            layer (list): A list of elements.
+        """
+        instructions = [instruction for instruction in filter(lambda x: x is not None, layer)]
+        longest = max([instruction.length for instruction in instructions])
+        for instruction in instructions:
+            instruction.length = longest
+
+    def build_layers(self):
+        """
+        Constructs layers.
+        Returns:
+            list: List of DrawElements.
+        Raises:
+            Exception: When the drawing is, for some reason, impossible to be drawn.
+        """
+        layers = []
+        noqubits = self.json_circuit['header']['number_of_qubits']
+        noclbits = self.json_circuit['header']['number_of_clbits']
+
+        layers.append(InputWire.fillup_layer(self.wire_names(with_initial_value=True)))
+
+        for instruction in self.json_circuit['instructions']:
+            layer = Layer(noqubits, noclbits)
+
+            if instruction['name'] == 'measure':
+                layer.set_qubit(instruction['qubits'][0], MeasureFrom())
+                layer.set_clbit(instruction['clbits'][0], MeasureTo())
+
+            elif instruction['name'] == 'barrier':
+                # barrier
+                for qubit in instruction['qubits']:
+                    layer.qubit_layer[qubit] = Barrier()
+
+            elif instruction['name'] == 'swap':
+                # swap
+                for qubit in instruction['qubits']:
+                    layer.qubit_layer[qubit] = Ex()
+                layer.connect_with("│")
+
+            elif instruction['name'] == 'cswap':
+                # cswap
+                layer.set_qubit(instruction['qubits'][0], Bullet())
+                layer.set_qubit(instruction['qubits'][1], Ex())
+                layer.set_qubit(instruction['qubits'][2], Ex())
+
+                layer.connect_with("│")
+
+            elif instruction['name'] == 'reset':
+                layer.set_qubit(instruction['qubits'][0], Reset())
+
+            elif 'conditional' in instruction:
+                # conditional
+                clbits = self.clbit_index_from_mask(int(instruction['conditional']['mask'], 16))
+                cllabel = TextDrawing.label_for_conditional(instruction)
+                qulabel = TextDrawing.label_for_box(instruction)
+
+                layer.set_cl_multibox(clbits, cllabel, top_connect='┴')
+                layer.set_qubit(instruction['qubits'][0], BoxOnQuWire(qulabel, bot_connect='┬'))
+
+            elif instruction['name'] in ['cx', 'CX', 'ccx']:
+                # cx/ccx
+                for qubit in [qubit for qubit in instruction['qubits'][:-1]]:
+                    layer.set_qubit(qubit, Bullet())
+
+                layer.set_qubit(instruction['qubits'][-1], BoxOnQuWire('X'))
+                layer.connect_with("│")
+
+            elif instruction['name'] == 'cy':
+                # cy
+                layer.set_qubit(instruction['qubits'][0], Bullet())
+                layer.set_qubit(instruction['qubits'][1], BoxOnQuWire('Y'))
+                layer.connect_with("│")
+
+            elif instruction['name'] == 'cz':
+                # cz
+                layer.set_qubit(instruction['qubits'][0], Bullet())
+                layer.set_qubit(instruction['qubits'][1], Bullet())
+                layer.connect_with("│")
+
+            elif instruction['name'] == 'ch':
+                # ch
+                layer.set_qubit(instruction['qubits'][0], Bullet())
+                layer.set_qubit(instruction['qubits'][1], BoxOnQuWire('H'))
+                layer.connect_with("│")
+
+            elif instruction['name'] == 'cu1':
+                # cu1
+                label = TextDrawing.params_for_label(instruction)[0]
+                layer.set_qubit(instruction['qubits'][0], Bullet())
+                layer.set_qubit(instruction['qubits'][1], Bullet())
+                layer.connect_with("│", label)
+
+            elif instruction['name'] == 'cu3':
+                # cu3
+                params = TextDrawing.params_for_label(instruction)
+                layer.set_qubit(instruction['qubits'][0], Bullet())
+                layer.set_qubit(instruction['qubits'][1],
+                                BoxOnQuWire("U3(%s)" % ','.join(params)))
+                layer.connect_with("│")
+
+            elif instruction['name'] == 'crz':
+                # crz
+                label = "Rz(%s)" % TextDrawing.params_for_label(instruction)[0]
+                layer.set_qubit(instruction['qubits'][0], Bullet())
+                layer.set_qubit(instruction['qubits'][1],
+                                BoxOnQuWire(label))
+                layer.connect_with("│")
+
+            elif len(instruction['qubits']) == 1 and 'clbits' not in instruction:
+                # unitary gate
+                layer.set_qubit(instruction['qubits'][0],
+                                BoxOnQuWire(TextDrawing.label_for_box(instruction)))
+
+            elif len(instruction['qubits']) >= 2 and 'clbits' not in instruction:
+                # multiple qubit gate
+                layer.set_qu_multibox(instruction['qubits'], TextDrawing.label_for_box(instruction))
+
+            else:
+                raise Exception("I don't know how to handle this instruction", instruction)
+
+            layers.append(layer.full_layer)
+
+        return layers
+
+
+class Layer:
+    """ A layer is the "column" of the circuit. """
+
+    def __init__(self, noqubits, noclbits):
+        self.qubit_layer = [None] * noqubits
+        self.clbit_layer = [None] * noclbits
+
+    @property
+    def full_layer(self):
+        """
+        Returns the composition of qubits and classic wires.
+        Returns:
+            String: self.qubit_layer + self.clbit_layer
+        """
+        return self.qubit_layer + self.clbit_layer
+
+    def set_qubit(self, qubit, element):
+        """
+        Sets the qubit to the element
+        Args:
+            qubit (int): Qubit index.
+            element (DrawElement): Element to set in the qubit
+        """
+        self.qubit_layer[qubit] = element
+
+    def set_clbit(self, clbit, element):
+        """
+        Sets the clbit to the element
+        Args:
+            clbit (int): Clbit index.
+            element (DrawElement): Element to set in the clbit
+        """
+        self.clbit_layer[clbit] = element
+
+    def _set_multibox(self, wire_type, bits, label, top_connect=None):
+        # pylint: disable=invalid-name
+        bits = sorted(bits)
+        if wire_type == "cl":
+            set_bit = self.set_clbit
+            BoxOnWire = BoxOnClWire
+            BoxOnWireTop = BoxOnClWireTop
+            BoxOnWireMid = BoxOnClWireMid
+            BoxOnWireBot = BoxOnClWireBot
+        elif wire_type == "qu":
+            set_bit = self.set_qubit
+            BoxOnWire = BoxOnQuWire
+            BoxOnWireTop = BoxOnQuWireTop
+            BoxOnWireMid = BoxOnQuWireMid
+            BoxOnWireBot = BoxOnQuWireBot
+
+        # Checks if qubits are consecutive
+        if bits != [i for i in range(bits[0], bits[-1] + 1)]:
+            raise Exception("I don't know how to build a gate with multiple bits when"
+                            "they are not adjacent to each other")
+
+        if len(bits) == 1:
+            set_bit(bits[0], BoxOnWire(label, top_connect=top_connect))
+        else:
+            set_bit(bits[0], BoxOnWireTop(label, top_connect=top_connect))
+            for order, bit in enumerate(bits[1:-1], 1):
+                set_bit(bit, BoxOnWireMid(label, len(bits), order))
+            set_bit(bits[-1], BoxOnWireBot(label, len(bits)))
+
+    def set_cl_multibox(self, bits, label, top_connect='┴'):
+        """
+        Sets the multi clbit box.
+        Args:
+            bits (list[int]): A list of affected bits.
+            label (string): The label for the multi clbit box.
+            top_connect (char): The char to connect the box on the top.
+        """
+        self._set_multibox("cl", bits, label, top_connect=top_connect)
+
+    def set_qu_multibox(self, bits, label):
+        """
+        Sets the multi qubit box.
+        Args:
+            bits (list[int]): A list of affected bits.
+            label (string): The label for the multi qubit box.
+        """
+        self._set_multibox("qu", bits, label)
+
+    def connect_with(self, wire_char, label=None):
+        """
+        Connects the elements in the layer using wire_char.
+        Args:
+            wire_char (char): For example '║' or '│'.
+            label (string): Some connectors have a label (see cu1, for example).
+        """
+        affected_bits = [bit for bit in self.full_layer if bit is not None]
+        affected_bits[0].connect(wire_char, ['bot'])
+        for affected_bit in affected_bits[1:-1]:
+            affected_bit.connect(wire_char, ['bot', 'top'])
+        affected_bits[-1].connect(wire_char, ['top'], label)
+
+        if label:
+            for affected_bit in affected_bits:
+                affected_bit.right_fill = len(label) + len(affected_bit.mid)


Test patch:
diff --git a/test/python/references/text_ref.txt b/test/python/references/text_ref.txt
new file mode 100644
--- /dev/null
+++ b/test/python/references/text_ref.txt
@@ -0,0 +1,13 @@
+              ┌───┐┌───┐┌───┐ ░ ┌───┐┌───┐┌─────┐┌───┐┌─────┐┌────┐     ┌────────────┐┌────────────┐┌────────────┐┌────────────┐┌────────────┐┌───────────────────┐┌──────────────────────────┐                                                                                      ┌─┐
+q_0: |0>──────┤ X ├┤ Y ├┤ Z ├─░─┤ H ├┤ S ├┤ Sdg ├┤ T ├┤ Tdg ├┤ Id ├─|0>─┤ Rx(3.1416) ├┤ Ry(3.1416) ├┤ Rz(3.1416) ├┤ U0(3.1416) ├┤ U1(3.1416) ├┤ U2(3.1416,3.1416) ├┤ U3(3.1416,3.1416,3.1416) ├─X───■────■───■───■───■────────────────────■────────────────────■─────────■───■───────┤M├
+            ░ └───┘└───┘└───┘ ░ └───┘└───┘└─────┘└───┘└─────┘└────┘     └────────────┘└────────────┘└────────────┘└────────────┘└────────────┘└───────────────────┘└──────────────────────────┘ │ ┌─┴─┐┌─┴─┐ │ ┌─┴─┐ │3.1416 ┌────────────┴─────────────┐┌─────┴──────┐  │   │    ┌─┐└╥┘
+q_1: |0>────░───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────X─┤ X ├┤ Y ├─■─┤ H ├─■───────┤ U3(3.1416,3.1416,3.1416) ├┤ Rz(3.1416) ├──■───X────┤M├─╫─
+         ░  ░                                                                                                                                                                                     └───┘└───┘   └───┘         └──────────────────────────┘└────────────┘┌─┴─┐ │ ┌─┐└╥┘ ║ 
+q_2: |0>─░─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ X ├─X─┤M├─╫──╫─
+         ░                                                                                                                                                                                                                                                             └───┘   └╥┘ ║  ║ 
+ c_0: 0 ════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╬══╬══╩═
+                                                                                                                                                                                                                                                                                ║  ║    
+ c_1: 0 ════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╬══╩════
+                                                                                                                                                                                                                                                                                ║       
+ c_2: 0 ════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╩═══════
+                                                                                                                                                                                                                                                                                        
\ No newline at end of file
diff --git a/test/python/test_circuit_text_drawer.py b/test/python/test_circuit_text_drawer.py
new file mode 100644
--- /dev/null
+++ b/test/python/test_circuit_text_drawer.py
@@ -0,0 +1,486 @@
+# -*- coding: utf-8 -*-
+
+# Copyright 2018, IBM.
+#
+# This source code is licensed under the Apache License, Version 2.0 found in
+# the LICENSE.txt file in the root directory of this source tree.
+
+# pylint: disable = no-member
+
+""" `_text_circuit_drawer` "draws" a circuit in "ascii art" """
+
+import unittest
+from math import pi
+from codecs import encode
+from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
+from qiskit.wrapper._circuittoolkit import circuit_from_qasm_string
+from .common import QiskitTestCase
+
+try:
+    from qiskit.tools.visualization import _text_circuit_drawer
+    from qiskit.tools.visualization import text as elements
+
+    VALID_MATPLOTLIB = True
+except (RuntimeError, ImportError):
+    # Under some combinations (travis osx vms, or headless configurations)
+    # matplotlib might not be fully, raising:
+    # RuntimeError: Python is not installed as a framework.
+    # when importing. If that is the case, the full test is skipped.
+    VALID_MATPLOTLIB = False
+
+
+@unittest.skipUnless(VALID_MATPLOTLIB, 'osx matplotlib backend not avaiable')
+class TestTextDrawerElement(QiskitTestCase):
+    """ Draw each element"""
+
+    def assertEqualElement(self, expected, element):
+        """
+        Asserts the top,mid,bot trio
+        Args:
+            expected (list[top,mid,bot]): What is expected.
+            element (DrawElement): The element to check.
+        """
+        try:
+            encode('\n'.join(expected), encoding='cp437')
+        except UnicodeEncodeError:
+            self.fail("_text_circuit_drawer() should only use extended ascii (aka code page 437).")
+
+        self.assertEqual(expected[0], element.top)
+        self.assertEqual(expected[1], element.mid)
+        self.assertEqual(expected[2], element.bot)
+
+    def test_measure_to(self):
+        """ MeasureTo element. """
+        element = elements.MeasureTo()
+        expected = [" ║ ",
+                    "═╩═",
+                    "   "]
+        self.assertEqualElement(expected, element)
+
+    def test_measure_from(self):
+        """ MeasureFrom element. """
+        element = elements.MeasureFrom()
+        expected = ["┌─┐",
+                    "┤M├",
+                    "└╥┘"]
+        self.assertEqualElement(expected, element)
+
+    def test_text_pager(self):
+        """ The pager breaks the circuit when the drawing does not fit in the console."""
+        qr = QuantumRegister(1, 'q')
+        circuit = QuantumCircuit(qr)
+        no_instructions = 50
+        for _ in range(no_instructions):
+            circuit.x(qr[0])
+        self.assertEqual(_text_circuit_drawer(circuit, line_length=10).count('\n'),
+                         no_instructions * 3 + 2)
+
+
+@unittest.skipUnless(VALID_MATPLOTLIB, 'osx matplotlib backend not avaiable')
+class TestTextDrawerGatesInCircuit(QiskitTestCase):
+    """ Gate by gate checks in different settings."""
+
+    def test_text_measure_1(self):
+        """ The measure operator, using 3-bit-length registers. """
+        expected = '\n'.join(["              ┌─┐",
+                              "q_0: |0>──────┤M├",
+                              "           ┌─┐└╥┘",
+                              "q_1: |0>───┤M├─╫─",
+                              "        ┌─┐└╥┘ ║ ",
+                              "q_2: |0>┤M├─╫──╫─",
+                              "        └╥┘ ║  ║ ",
+                              " c_0: 0 ═╬══╬══╩═",
+                              "         ║  ║    ",
+                              " c_1: 0 ═╬══╩════",
+                              "         ║       ",
+                              " c_2: 0 ═╩═══════",
+                              "                 "])
+        qr = QuantumRegister(3, 'q')
+        cr = ClassicalRegister(3, 'c')
+        circuit = QuantumCircuit(qr, cr)
+        circuit.measure(qr, cr)
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_measure_2(self):
+        """ The measure operator, using some registers. """
+        expected = '\n'.join(["               ",
+                              "q1_0: |0>──────",
+                              "               ",
+                              "q1_1: |0>──────",
+                              "            ┌─┐",
+                              "q2_0: |0>───┤M├",
+                              "         ┌─┐└╥┘",
+                              "q2_1: |0>┤M├─╫─",
+                              "         └╥┘ ║ ",
+                              " c1_0: 0 ═╬══╬═",
+                              "          ║  ║ ",
+                              " c1_1: 0 ═╬══╬═",
+                              "          ║  ║ ",
+                              " c2_0: 0 ═╬══╩═",
+                              "          ║    ",
+                              " c2_1: 0 ═╩════",
+                              "               "])
+        qr1 = QuantumRegister(2, 'q1')
+        cr1 = ClassicalRegister(2, 'c1')
+        qr2 = QuantumRegister(2, 'q2')
+        cr2 = ClassicalRegister(2, 'c2')
+        circuit = QuantumCircuit(qr1, qr2, cr1, cr2)
+        circuit.measure(qr2, cr2)
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_swap(self):
+        """ Swap drawing. """
+        expected = '\n'.join(["               ",
+                              "q1_0: |0>────X─",
+                              "             │ ",
+                              "q1_1: |0>─X──┼─",
+                              "          │  │ ",
+                              "q2_0: |0>─┼──X─",
+                              "          │    ",
+                              "q2_1: |0>─X────",
+                              "               "])
+        qr1 = QuantumRegister(2, 'q1')
+        qr2 = QuantumRegister(2, 'q2')
+        circuit = QuantumCircuit(qr1, qr2)
+        circuit.swap(qr1, qr2)
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_cswap(self):
+        """ CSwap drawing. """
+        expected = '\n'.join(["                 ",
+                              "q_0: |0>─■──X──X─",
+                              "         │  │  │ ",
+                              "q_1: |0>─X──■──X─",
+                              "         │  │  │ ",
+                              "q_2: |0>─X──X──■─",
+                              "                 "])
+        qr = QuantumRegister(3, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.cswap(qr[0], qr[1], qr[2])
+        circuit.cswap(qr[1], qr[0], qr[2])
+        circuit.cswap(qr[2], qr[1], qr[0])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_cu3(self):
+        """ cu3 drawing. """
+        expected = '\n'.join(["                                    ┌──────────────────────────┐",
+                              "q_0: |0>─────────────■──────────────┤ U3(1.5708,1.5708,1.5708) ├",
+                              "        ┌────────────┴─────────────┐└────────────┬─────────────┘",
+                              "q_1: |0>┤ U3(1.5708,1.5708,1.5708) ├─────────────┼──────────────",
+                              "        └──────────────────────────┘             │              ",
+                              "q_2: |0>─────────────────────────────────────────■──────────────",
+                              "                                                                "])
+        qr = QuantumRegister(3, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.cu3(pi / 2, pi / 2, pi / 2, qr[0], qr[1])
+        circuit.cu3(pi / 2, pi / 2, pi / 2, qr[2], qr[0])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_crz(self):
+        """ crz drawing. """
+        expected = '\n'.join(["                      ┌────────────┐",
+                              "q_0: |0>──────■───────┤ Rz(1.5708) ├",
+                              "        ┌─────┴──────┐└─────┬──────┘",
+                              "q_1: |0>┤ Rz(1.5708) ├──────┼───────",
+                              "        └────────────┘      │       ",
+                              "q_2: |0>────────────────────■───────",
+                              "                                    "])
+        qr = QuantumRegister(3, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.crz(pi / 2, qr[0], qr[1])
+        circuit.crz(pi / 2, qr[2], qr[0])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_cx(self):
+        """ cx drawing. """
+        expected = '\n'.join(["             ┌───┐",
+                              "q_0: |0>──■──┤ X ├",
+                              "        ┌─┴─┐└─┬─┘",
+                              "q_1: |0>┤ X ├──┼──",
+                              "        └───┘  │  ",
+                              "q_2: |0>───────■──",
+                              "                  "])
+        qr = QuantumRegister(3, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.cx(qr[0], qr[1])
+        circuit.cx(qr[2], qr[0])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_cy(self):
+        """ cy drawing. """
+        expected = '\n'.join(["             ┌───┐",
+                              "q_0: |0>──■──┤ Y ├",
+                              "        ┌─┴─┐└─┬─┘",
+                              "q_1: |0>┤ Y ├──┼──",
+                              "        └───┘  │  ",
+                              "q_2: |0>───────■──",
+                              "                  "])
+        qr = QuantumRegister(3, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.cy(qr[0], qr[1])
+        circuit.cy(qr[2], qr[0])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_cz(self):
+        """ cz drawing. """
+        expected = '\n'.join(["              ",
+                              "q_0: |0>─■──■─",
+                              "         │  │ ",
+                              "q_1: |0>─■──┼─",
+                              "            │ ",
+                              "q_2: |0>────■─",
+                              "              "])
+        qr = QuantumRegister(3, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.cz(qr[0], qr[1])
+        circuit.cz(qr[2], qr[0])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_ch(self):
+        """ ch drawing. """
+        expected = '\n'.join(["             ┌───┐",
+                              "q_0: |0>──■──┤ H ├",
+                              "        ┌─┴─┐└─┬─┘",
+                              "q_1: |0>┤ H ├──┼──",
+                              "        └───┘  │  ",
+                              "q_2: |0>───────■──",
+                              "                  "])
+        qr = QuantumRegister(3, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.ch(qr[0], qr[1])
+        circuit.ch(qr[2], qr[0])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_cu1(self):
+        """ cu1 drawing. """
+        expected = '\n'.join(["                          ",
+                              "q_0: |0>─■────────■───────",
+                              "         │1.5708  │       ",
+                              "q_1: |0>─■────────┼───────",
+                              "                  │1.5708 ",
+                              "q_2: |0>──────────■───────",
+                              "                          "])
+        qr = QuantumRegister(3, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.cu1(pi / 2, qr[0], qr[1])
+        circuit.cu1(pi / 2, qr[2], qr[0])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_ccx(self):
+        """ cx drawing. """
+        expected = '\n'.join(["                  ┌───┐",
+                              "q_0: |0>──■────■──┤ X ├",
+                              "          │  ┌─┴─┐└─┬─┘",
+                              "q_1: |0>──■──┤ X ├──■──",
+                              "        ┌─┴─┐└─┬─┘  │  ",
+                              "q_2: |0>┤ X ├──■────■──",
+                              "        └───┘          "])
+        qr = QuantumRegister(3, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.ccx(qr[0], qr[1], qr[2])
+        circuit.ccx(qr[2], qr[0], qr[1])
+        circuit.ccx(qr[2], qr[1], qr[0])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_reset(self):
+        """ Reset drawing. """
+        expected = '\n'.join(["                        ",
+                              "q1_0: |0>───────────|0>─",
+                              "                        ",
+                              "q1_1: |0>──────|0>──────",
+                              "                        ",
+                              "q2_0: |0>───────────────",
+                              "                        ",
+                              "q2_1: |0>─|0>───────────",
+                              "                        "])
+        qr1 = QuantumRegister(2, 'q1')
+        qr2 = QuantumRegister(2, 'q2')
+        circuit = QuantumCircuit(qr1, qr2)
+        circuit.reset(qr1)
+        circuit.reset(qr2[1])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_single_gate(self):
+        """ Single Qbit gate drawing. """
+        expected = '\n'.join(["                   ┌───┐",
+                              "q1_0: |0>──────────┤ H ├",
+                              "              ┌───┐└───┘",
+                              "q1_1: |0>─────┤ H ├─────",
+                              "              └───┘     ",
+                              "q2_0: |0>───────────────",
+                              "         ┌───┐          ",
+                              "q2_1: |0>┤ H ├──────────",
+                              "         └───┘          "])
+        qr1 = QuantumRegister(2, 'q1')
+        qr2 = QuantumRegister(2, 'q2')
+        circuit = QuantumCircuit(qr1, qr2)
+        circuit.h(qr1)
+        circuit.h(qr2[1])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_barrier(self):
+        """ Barrier drawing. """
+        expected = '\n'.join(["             ░ ",
+                              "q1_0: |0>────░─",
+                              "             ░ ",
+                              "q1_1: |0>────░─",
+                              "             ░ ",
+                              "q2_0: |0>──────",
+                              "          ░    ",
+                              "q2_1: |0>─░────",
+                              "          ░    "])
+        qr1 = QuantumRegister(2, 'q1')
+        qr2 = QuantumRegister(2, 'q2')
+        circuit = QuantumCircuit(qr1, qr2)
+        circuit.barrier(qr1)
+        circuit.barrier(qr2[1])
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_conditional_1(self):
+        """ Conditional drawing with 1-bit-length regs."""
+        qasm_string = """
+        OPENQASM 2.0;
+        include "qelib1.inc";
+        qreg q[1];
+        creg c0[1];
+        creg c1[1];
+        if(c0==1) x q[0];
+        if(c1==1) x q[0];
+        """
+        expected = '\n'.join(["        ┌───────┐┌───────┐",
+                              "q_0: |0>┤   X   ├┤   X   ├",
+                              "        ├───┴───┤└───┬───┘",
+                              "c0_0: 0 ╡ = 0x1 ╞════╪════",
+                              "        └───────┘┌───┴───┐",
+                              "c1_0: 0 ═════════╡ = 0x1 ╞",
+                              "                 └───────┘"])
+        circuit = circuit_from_qasm_string(qasm_string)
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_conditional_2(self):
+        """ Conditional drawing with 2-bit-length regs."""
+        qasm_string = """
+        OPENQASM 2.0;
+        include "qelib1.inc";
+        qreg q[1];
+        creg c0[2];
+        creg c1[2];
+        if(c0==2) x q[0];
+        if(c1==2) x q[0];
+        """
+        expected = '\n'.join(["        ┌───────┐┌───────┐",
+                              "q_0: |0>┤   X   ├┤   X   ├",
+                              "        ├───┴───┤└───┬───┘",
+                              "c0_0: 0 ╡       ╞════╪════",
+                              "        │ = 0x2 │    │    ",
+                              "c0_1: 0 ╡       ╞════╪════",
+                              "        └───────┘┌───┴───┐",
+                              "c1_0: 0 ═════════╡       ╞",
+                              "                 │ = 0x2 │",
+                              "c1_1: 0 ═════════╡       ╞",
+                              "                 └───────┘"])
+        circuit = circuit_from_qasm_string(qasm_string)
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_conditional_3(self):
+        """ Conditional drawing with 3-bit-length regs."""
+        qasm_string = """
+        OPENQASM 2.0;
+        include "qelib1.inc";
+        qreg q[1];
+        creg c0[3];
+        creg c1[3];
+        if(c0==3) x q[0];
+        if(c1==3) x q[0];
+        """
+        expected = '\n'.join(["        ┌───────┐┌───────┐",
+                              "q_0: |0>┤   X   ├┤   X   ├",
+                              "        ├───┴───┤└───┬───┘",
+                              "c0_0: 0 ╡       ╞════╪════",
+                              "        │       │    │    ",
+                              "c0_1: 0 ╡ = 0x3 ╞════╪════",
+                              "        │       │    │    ",
+                              "c0_2: 0 ╡       ╞════╪════",
+                              "        └───────┘┌───┴───┐",
+                              "c1_0: 0 ═════════╡       ╞",
+                              "                 │       │",
+                              "c1_1: 0 ═════════╡ = 0x3 ╞",
+                              "                 │       │",
+                              "c1_2: 0 ═════════╡       ╞",
+                              "                 └───────┘"])
+        circuit = circuit_from_qasm_string(qasm_string)
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_conditional_4(self):
+        """ Conditional drawing with 4-bit-length regs."""
+        qasm_string = """
+        OPENQASM 2.0;
+        include "qelib1.inc";
+        qreg q[1];
+        creg c0[4];
+        creg c1[4];
+        if(c0==4) x q[0];
+        if(c1==4) x q[0];
+        """
+        expected = '\n'.join(["        ┌───────┐┌───────┐",
+                              "q_0: |0>┤   X   ├┤   X   ├",
+                              "        ├───┴───┤└───┬───┘",
+                              "c0_0: 0 ╡       ╞════╪════",
+                              "        │       │    │    ",
+                              "c0_1: 0 ╡       ╞════╪════",
+                              "        │ = 0x4 │    │    ",
+                              "c0_2: 0 ╡       ╞════╪════",
+                              "        │       │    │    ",
+                              "c0_3: 0 ╡       ╞════╪════",
+                              "        └───────┘┌───┴───┐",
+                              "c1_0: 0 ═════════╡       ╞",
+                              "                 │       │",
+                              "c1_1: 0 ═════════╡       ╞",
+                              "                 │ = 0x4 │",
+                              "c1_2: 0 ═════════╡       ╞",
+                              "                 │       │",
+                              "c1_3: 0 ═════════╡       ╞",
+                              "                 └───────┘"])
+        circuit = circuit_from_qasm_string(qasm_string)
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+    def test_text_conditional_5(self):
+        """ Conditional drawing with 5-bit-length regs."""
+        qasm_string = """
+        OPENQASM 2.0;
+        include "qelib1.inc";
+        qreg q[1];
+        creg c0[5];
+        creg c1[5];
+        if(c0==5) x q[0];
+        if(c1==5) x q[0];
+        """
+        expected = '\n'.join(["        ┌───────┐┌───────┐",
+                              "q_0: |0>┤   X   ├┤   X   ├",
+                              "        ├───┴───┤└───┬───┘",
+                              "c0_0: 0 ╡       ╞════╪════",
+                              "        │       │    │    ",
+                              "c0_1: 0 ╡       ╞════╪════",
+                              "        │       │    │    ",
+                              "c0_2: 0 ╡ = 0x5 ╞════╪════",
+                              "        │       │    │    ",
+                              "c0_3: 0 ╡       ╞════╪════",
+                              "        │       │    │    ",
+                              "c0_4: 0 ╡       ╞════╪════",
+                              "        └───────┘┌───┴───┐",
+                              "c1_0: 0 ═════════╡       ╞",
+                              "                 │       │",
+                              "c1_1: 0 ═════════╡       ╞",
+                              "                 │       │",
+                              "c1_2: 0 ═════════╡ = 0x5 ╞",
+                              "                 │       │",
+                              "c1_3: 0 ═════════╡       ╞",
+                              "                 │       │",
+                              "c1_4: 0 ═════════╡       ╞",
+                              "                 └───────┘"])
+        circuit = circuit_from_qasm_string(qasm_string)
+        self.assertEqual(_text_circuit_drawer(circuit), expected)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/test/python/test_visualization_output.py b/test/python/test_visualization_output.py
--- a/test/python/test_visualization_output.py
+++ b/test/python/test_visualization_output.py
@@ -12,13 +12,16 @@
 
 import os
 import unittest
+from codecs import encode
 from math import pi
 from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
 from .common import QiskitTestCase
 
 try:
     from qiskit.tools.visualization import (latex_circuit_drawer,
-                                            matplotlib_circuit_drawer)
+                                            matplotlib_circuit_drawer,
+                                            circuit_drawer)
+
     VALID_MATPLOTLIB = True
 except (RuntimeError, ImportError):
     # Under some combinations (travis osx vms, or headless configurations)
@@ -36,16 +39,13 @@ def _this_directory():
     return os.path.dirname(os.path.abspath(__file__))
 
 
-# TODO: Enable for refactoring purposes and enable by default when we can
-# decide if the backend is available or not.
-@unittest.skip('Useful for refactoring purposes, skipping by default.')
 @unittest.skipIf(not VALID_MATPLOTLIB, 'matplotlib not available.')
 class TestVisualizationImplementation(QiskitTestCase):
     """Visual accuracy of visualization tools outputs tests."""
 
     latex_reference = _path_to_diagram_reference('latex_ref.png')
-
     matplotlib_reference = _path_to_diagram_reference('matplotlib_ref.png')
+    text_reference = _path_to_diagram_reference('text_ref.txt')
 
     def sample_circuit(self):
         """Generate a sample circuit that includes the most common elements of
@@ -88,6 +88,9 @@ def sample_circuit(self):
 
         return circuit
 
+    # TODO: Enable for refactoring purposes and enable by default when we can
+    # decide if the backend is available or not.
+    @unittest.skip('Useful for refactoring purposes, skipping by default.')
     def test_latex_drawer(self):
         filename = self._get_resource_path('current_latex.png')
         qc = self.sample_circuit()
@@ -95,6 +98,9 @@ def test_latex_drawer(self):
         self.assertImagesAreEqual(filename, self.latex_reference)
         os.remove(filename)
 
+    # TODO: Enable for refactoring purposes and enable by default when we can
+    # decide if the backend is available or not.
+    @unittest.skip('Useful for refactoring purposes, skipping by default.')
     def test_matplotlib_drawer(self):
         filename = self._get_resource_path('current_matplot.png')
         qc = self.sample_circuit()
@@ -102,6 +108,25 @@ def test_matplotlib_drawer(self):
         self.assertImagesAreEqual(filename, self.matplotlib_reference)
         os.remove(filename)
 
+    def test_text_drawer(self):
+        filename = self._get_resource_path('current_textplot.txt')
+        qc = self.sample_circuit()
+        output = circuit_drawer(qc, filename=filename, output="text")
+        self.assertFilesAreEqual(filename, self.text_reference)
+        os.remove(filename)
+        try:
+            encode(output, encoding='cp437')
+        except UnicodeEncodeError:
+            self.fail("_text_circuit_drawer() should only use extended ascii (aka code page 437).")
+
+    def assertFilesAreEqual(self, current, expected):
+        """Checks if both file are the same."""
+        self.assertTrue(os.path.exists(current))
+        self.assertTrue(os.path.exists(expected))
+        with open(current, "r", encoding='cp437') as cur,\
+                open(expected, "r", encoding='cp437') as exp:
+            self.assertEqual(cur.read(), exp.read())
+
     def assertImagesAreEqual(self, current, expected, diff_tolerance=0.001):
         """Checks if both images are similar enough to be considered equal.
         Similarity is controlled by the ```diff_tolerance``` argument."""
@@ -115,7 +140,7 @@ def assertImagesAreEqual(self, current, expected, diff_tolerance=0.001):
         diff = ImageChops.difference(expected, current)
         black_pixels = _get_black_pixels(diff)
         total_pixels = diff.size[0] * diff.size[1]
-        similarity_ratio = black_pixels/total_pixels
+        similarity_ratio = black_pixels / total_pixels
         self.assertTrue(
             1 - similarity_ratio < diff_tolerance,
             'The images are different by more than a {}%'