- Type
M-x uniline-mode - Move cursor with the arrow-keys on the keyboard
→ ← ↑ ↓ - Quit
C-c C-c
╷ ╭─────────╮
╰───┤my first ├─╮
│drawing │ ╰───╮
╰─────────╯ │
╭────┬───────╯
╰────╯
Navigating to the relevant section of the info-mode documentation is
now just one or two key-strokes away.
- Under
Hydratype?. - Under
Transienttype??.
The documentation is also reachable from the menu, in the menu-bar at
the top of the screen. The menu is also available by left-clicking on
Uniline on the mode-bar at the bottom of the screen.
Note that there is also a standard description of uniline-mode and its
key-bindings. Just press C-h m or middle-click on Uniline on the
mode-bar at the bottom of the screen.
- Getting started in 10 seconds
- New
- Pure UNICODE text diagrams in Emacs
- A minor mode for drawing
- The <insert> key
- Glyphs ▷ ▶ → □ ◆ ╮─ insertion & modification
- Rectangular actions
- Long range actions: contour and flood-fill
- Macros
- Which fonts?
- Hydra or Transient?
- Customization
- How Uniline behaves with its environment?
- Lisp API
- Mouse support
- Installation
- Related packages
- Author, contributors
- License
pdfjam source.pdf 3-5,9 ╶─────▲────▲────────▲──▲╴ command╶╯ │ │ │ input file╶──╯ │ │ select pages 3,4,5╶───╯ │ and page 9╶──────────────╯
╭───────────────────────╮
╷123╭────▶┤ hundred and something │
╰───╯ ╰───────────────────────╯
╭────▶──╮A╷
╭───╮ ┏━━━┓ ╔═══╗ │ ╰─╯
0╶─→┤ 1 ┝━━━▶┫ 2 ┣═══▷╣ 3 ╟──●────▶──╮B╷
╰───╯ ┗━┯━┛ ╚═╤═╝ │ ╰─╯
╰────←───╯ ╰────▶──╮C╷
╰─╯
╔══════════╗
║ 1 ║ ▐▀▀▀▀▀▀▀▀▜
║ ╭─────╫───╮ ◁──▷ ▐ 3 ▐
╚════╪═════╝ 2 │ ▐▄▄▄▄▄▄▄▄▟
╰─────────╯
┏━━━━━━━━━━━━┓
┃which color?┃
┗━┯━━━━━━━━━━┛
│ ╭──────╮
│ ╭──┤yellow├─▷╮good─choice╭□
▽ │ ╰──────╯ ╰═══════════╯
╰──● ╭───╮ ┏━━━━━┓
├──┤red├───▷┨dark?┠──╮
│ ╰───╯ ┗━━━━━┛ │
│ ╭───◁──────────────╯
│ │ ╭───╮
│ ╰─●─┤yes├▷╮regular─red╭─□
│ │ ╰───╯ ╰═══════════╯
│ │ ╭──╮
│ ╰─┤no├─▷╮pink╭────────□
│ ╰──╯ ╰════╯
│ ╭────╮
├──┤blue├───▷╮next week╭──□
│ ╰────╯ ╰═════════╯
│ ╭─────╮
╰──┤white├──▷╮available╭──□
╰─────╯ ╰═════════╯
╭─╮←─╮
╭╮ │ │ ╰──╴max 235
╭╮││ ╭╯ │
│╰╯│╭─╯ │
╭╮ │ ││ │
╭─╮││╭╮ ╭──╮╭╮ │ ╰╯ ╰╮
╭╯ ╰╯╰╯│ ╭╯ ╰╯╰─╮ │ │ ╭╮
◁─╯ ╰──╯ ╰──╯ ╰─╯╰────▷
◀════════════════════════════════════════▶
╭────────╮
▲ │all time│
┃ ▄ ▗▟█ ←─┤highest │
Qdx █▌ ████ ╰────────╯
┃ ▗▄█▌ █████▙
┃ ▟███████▄█████████▄▄▄ ▗▄
┃▐▄▄████████████████████████████▄▄▖
╺━━━━━━━━━━╸time╺━━━━━━━━━━━━━━━━▶
╭─────────────────────╴G: Einstein tensor
│ ╭────╴κ: Gravitational coupling constant
╭──▽───╮ ╭───▽──╮
┏━┷━━━━━━┷━━━━━━━━┷━━━━━━┷━━━┓
┃ R - gR/2 + Λg = (8πG/c⁴)×T ┃◁╴General Relativity equation
┗━△━━━△△━━━━━△△━━━━━━△━△━━━△━┛
│ ││ ││ │ │ ╭╯
│ ││ ││ │ │ ╰╴Energy-impulsion tensor
│ ││ ││ │ ╰───╴Speed of light
│ ││ ││ ╰─────╴Gravitational constant
│ ││ ╰┴────────────╴Cosmological constant
│ │╰──────┴────────────╴Scalar curvature
│ ╰───────╰────────────╴Metric tensor
╰────────────────────────╴Ricci tensor
╭─────────────────────╴Derivative over time
│ ╭──────────╭────╴State of quantum system at time t
│ │ │ (the square of its absolute value
╭▽─╮ ╭─▽──╮ ╭─▽──╮ is the probability density)
┏━━━━━┷━━┷━┷━━━━┷━━━━━┷━━━━┷━┓
┃ i ħ d/dt |Ψ(t)> = Ĥ |Ψ(t)> ┃◁─╴Schrödinger's equation
┗━△━△━━━━△━━━━△━━━━━△━━━━△━━━┛
│ │ ╰────╰─────┤────╰───╴Time
│ │ ╰────────╴Hamiltonian
│ ╰────────────────────────╴Reduced Plank constant
╰──────────────────────────╴Imaginary number i²=-1
(which language?)
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ the pretty table is standing ┃
┗┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
│ ╭────┬─────┬─────╴radicals
↕ ╭┴╮ ╭┴─╮ ╭┴─╮
┏┷━━━┿━┿━━┿━━┿━━┿━━┿━━━┓
┃ la bela tablo staras ┃
┗━━━━┿━┿△━┿━━┿△━┿━━┿△━━┛
╰─╯│ ╰──╯│ ╰──╯│ ┏━━━━━suffixes━━━━━┓
│ │ ╰──╂╴as: present tense┃
│ │ ┃ os: future tense ┃
│ │ ┃ is: past tense ┃
│ ╰────────╂╴ o: noun ┃
╰──────────────╂╴ a: adjective ┃
┃ e: adverb ┃
┗━━━━━━━━━━━━━━━━━━┛
'(a b c)
┏━━━┳━━━┓ ┏━━━┳━━━┓ ┏━━━┳━━━┓
●━━━▶┫ ● ┃ ●─╂──▷┨ ● ┃ ●─╂──▷┨ ● ┃nil┃
┗━┿━┻━━━┛ ┗━┿━┻━━━┛ ┗━┿━┻━━━┛
│ ╰──────────╮╰╮
│ ╭─────┬───────────╮ │ │
╰─▷┤"a\0"│properties │ │ │
├─────┼───────────┤ │ │
│"b\0"│properties ├◁╯ │
├─────┼───────────┤ │
│"c\0"│properties ├◁──╯
├─────┼───────────┤
│... │... │
╵ ╵ ╵
◀─(-)────────(+)──▶ ~╭──────╮~ ▗──────────────╮ ~~│ ╭~~╮ │~~ ▐ ╰╮ ~│ ╵ ╵ │~ ╭□▐ 1.5 volts ╭╯□╮ ╰─╖ ╓─╯ │ ▝▀▀▀▀▀▀▀▀▀▀▀▀▀▀▘ │ ╠━━╣ │ ╰──────╯ │ ╰─────────────────────────────╯
╶╮ ╭╴ ┏┳┥▒▒▒▒▒▒▒┝╸ ┃┃│▒▒eau▒▒│ ┃┃│▒▒▒▒▒▒▒│ ╔═════╗ ┃┃╰──╮▒╭──╯ ║ ╶╮ ▽ ╭╴ ┃┃ ▒ ║ │ ░ │ ┃┃ ▒ ║ │░░░░░░░░░░░░░░│ ┃┃ ╚═════╝ │░░░░░░░░░░░░░░╞════▷▒▒ ┃┃ │░░░░░akvo░░░░░│ ╶╮ ▒ ╭╴ ┃┃ │░░░░░░░░░░░░░░│ │ ▒ │ ┃┃ ╰─┲┳━━━━━━━━┳┱─╯ │▒▒▒▒▒▒▒▒▒▒▒│ ┃┃ ┃┃ ┃┃ │▒▒▒water▒▒▒│ ┃┃ ┃┃ ┃┃ │▒▒▒▒▒▒▒▒▒▒▒│ ┃┃ ┃┃ ┃┃ ╰───────────╯ ▝▀▀▀▀▀▀▘ ▝▀▘ ▝▀▘ ▀▀▀▀▀▀▀▀▀▀▀▀▀
Those diagrams are pure text. There is nothing graphic. They are achieved using UNICODE characters. Therefore they can be drawn within any text formatted document, like Org Mode, Markdown, txt, comments in any programming language source code (C++, Python, Rust, D, JavaScript, GnuPlot, LaTex, whatever).
Most often, the text file will be encoded as UTF-8. This is becoming the de-facto standard for text and source code files.
Creating such diagrams by hand is painfully slow. Use Uniline to
draw lines while you move the cursor with keyboard arrows.
If you see those diagrams miss-aligned, most likely the font used to display them does not support UNICODE block characters. See bellow the paragraph Which fonts? for details.
If you get misalignment when drawing, this could come from too wide characters. Emojis are an example. Usual characters may also be considered twice as wide as normal under some “language environments”. See the paragraph Language environment for details.
Uniline is a minor mode. Activate it temporarily:
M-x uniline-mode
Exit it with:
C-c C-c
The current major mode is still active underneath uniline-mode.
While in uniline-mode, overwriting is active, as well as long lines
truncation. Also, a hollow cursor is provided (customizable). Those
settings are reset to their previous state when exiting uniline-mode.
Use keyboard arrows to draw lines.
By default, drawing lines only happens over empty space or over other lines. If there is already text, it will not be erased. However, by hitting the control-key while moving, lines overwrite whatever there is.
The buffer is “infinite” in bottom and right directions. Which means that when the cursor ends up outside the buffer, white space characters are automatically added.
The usual numeric prefix is available. For instance, to draw a line 12
characters wide downward, type: M-12 <down>
-single thin line╭─┬─╮+single thick line┏━┳━┓=double line╔═╦═╗#quarter block▙▄▟▀<delete>eraser<return>move without drawing anything
The current brush and the current text direction (see below) are
reflected in the mode-line (at the bottom of the Emacs screen). It
looks like this:
current text current
direction╶────╮ ╭───╴brush
▼ ▼
══════════════════╧═══════╧══════════════
U:** buff (... →Uniline┼ ...)
═════════════════════════════════════════
Usually, inserting text in a buffer moves the cursor to the right. (And
sometimes to the left for some locales). Any of the 4 directions can be
selected under Uniline. Just type any of:
<insert> C-<up><insert> C-<right><insert> C-<down><insert> C-<left>
The current direction is reflected in the mode-line, just before the
word "uniline".
<insert> key is a prefix for other keys:
- for drawing arrows, squares, crosses, o-shapes glyphs,
- for handling rectangles,
- for inserting
# = - +which otherwise change the brush style, - for trying a choice of mono-spaced fonts.
Why <insert>? Because:
Unilinetries to leave their original meaning to as many keys as possible,- the standard meaning of
<insert>is to toggle theoverwrite-mode; butUnilineis already inoverwrite-mode, and de-activating overwrite would breakUniline.
So preempting <insert> does not sacrifices anything.
Customization
Another key may be defined instead of <insert>. Type:
M-x customize-variable uniline-key-insert
Individual character glyphs may be inserted and changed.
- Put the cursor where a glyphs should be edited or inserted.
- Then press
<insert>(this key may be customized, see the “Customization” chapter).
Arrows, squares, circles, crosses may be handled. Also lines may be fine tweaked a single character at a time.
When inserting an arrow, it points in the direction that the line drawing follows.Uniline supports 6 arrows types: ▷ ▶ → ▹ ▸ ↔
□ ╰─◁──▷─╮ □─╮ ╭─╮ ╭─╮ ╭─□ ╭─◀──▶─╯ △ ▲ ↑ ▵ ▴ ↕ ╰─←──→─╮ │ │ │ │ │ │ ╭─◃──▹─╯ ▽ ▼ ↓ ▿ ▾ ↕ ╰─◂──▸─╮ ╰─╯ ╰─╯ ╰─╯ ╭─↔──↔─╯ □
Actually, there are tons of arrows of all styles in the UNICODE
standard. Unfortunately, support by fonts is weak. So Uniline
restrains itself to those six safe arrows.
To insert an arrow, type: <insert> a or <insert> a a or <insert> a a a. (a
cycles through the 6 styles, A cycles backward).
<insert> 4 a is equivalent to <insert> a a a a, which is also equivalent to
<insert> A A A. Those 3 shortcuts insert an arrow of this style: ▵▹▿◃. The
actual direction where the arrow points follows the last movement of
the cursor.
To change the direction of the arrow, use shift-arrow, for example:
S-<up> will change from → to ↑.
To insert a square □ ■ ▫ ▪ ◆ ◊ type:
<insert> s s s... (s cycles, S cycles backward).
To insert a circular shape · ∙ • ● ◦ Ø ø type:
<insert> o o o... (o cycles, O cycles backward).
To insert a cross shape ╳ ╱ ╲ ÷ × ± ¤ type:
<insert> x x x... (x cycles, X cycles backward).
To insert a usual ASCII letter or symbol, just type it.
As the keys - + = # are preempted by uniline-mode, to type them,
prefix them with <insert>. Example: <insert> - inserts a - and
<insert> + inserts a +.
<insert>
│
▼
╭┴╮ ╭───────╮ ╭──────────────────╮
│s├─▶─┤squares├──┤ □ ■ ▫ ▪ ◆ ◊ │
╰┬╯ ╰───────╯ ╰──────────────────╯
╭┴╮ ╭───────╮ ╭─────────────────────╮
│o├─▶─┼circles┼──┤ · ∙ • ● ◦ Ø ø │
╰┬╯ ╰───────╯ ╰─────────────────────╯
╭┴╮ ╭───────╮ ╭───────────────────╮
│x├─▶─┼crosses┼──┤ ╳ ╱ ╲ ÷ × ± ¤ │
╰┬╯ ╰───────╯ ╰───────────────────╯
╭┴╮ ╭───╮
│+├─▶────────────┤ + │
╰┬╯ ╰───╯
╭┴╮ ╭───╮
│-├─▶────────────┤ - │
╰┬╯ ╰───╯
╭┴╮ ╭───╮
│=├─▶────────────┤ = │
╰┬╯ ╰───╯
╭┴╮ ╭───╮
│#├─▶────────────┤ # │
╰─╯ ╰───╯
convert this ═══▶ into that ╭───────────╮ ╭───────────╮ │╶───┬────▷ │ │╶───╮────▷ │ │ │ │ │ │ │ │ │ │ │ │ ▀▀▀ │ │ ▀▟▀ │ ╰───────────╯ ╰───────────╯
At the crossing of lines, it may be appealing to do small adjustments. In the above example, we removed a segment of line which occupies 1/4 of a character. This cannot be achieve with line tracing alone. We also modified a quarter-block line in a non-obvious way.
- Put the point (the cursor) on the character where lines cross each other.
- type
INS S-<right> S-<right>
<right> here refers to the right part of the character under the
point. The 1/4 line segment will cycle through all displayable
forms. On the second stroke, no segment will be displayed, which is
what we want.
Caveat! The UNICODE standard does not define all possible combinations including double line segments. (It does for all combinations of thin and tick lines). So sometimes, when working with double lines, the process may be frustrating.
This works also for lines made of quarter-blocks. There are 4 quarter-blocks in a character, either on or off. Each of the 4 shifted keyboard arrows flips a quarter-block on-and-off.
In the above example, the effect was achieved with:
INS S-<up> S-<down> S-<left>
- Drawing,
- filling,
- moving,
- copying & yanking,
- change line & glyph styles,
those actions may be performed on a rectangular selection.
Select a rectangular region with C-SPC or C-x SPC and move the cursor.
You may also use S-<arrow> (<arrow> being any of the 4
directions) to extend the selection. The buffer grows as needed with
white spaces to accommodate the selection. Selection extension mode is
active when shift-select-mode is non-nil.
Or you may use the mouse to highlight the desired region.
All those region-highlighting are standard in Emacs, and unrelated to
Uniline.
Once you have a region highlighted, press <insert> (this key can be
customized, see the “Customization” chapter). The selection becomes
rectangular if it was not. You are offered a menu of possible actions.
To draw a rectangle in one shot, select a region, press <insert>, then
hit:
rto draw a rectangle inside the selectionS-Rto draw a rectangle outside the selectionC-rto overwrite a rectangle inside the selectionC-S-Rto overwrite a rectangle outside the selection
If needed, change the brush with any of - + = # <delete>
╭───────╮ r: inside╮╭───────╮
│ one │ ▗▄▄▄▄▄▄▖╭┤│▛▀▀▀▀▀▜│
│ ┏━━━━┿━━━━━━┓ ▐╭────╮▌│╰┼▌ ▐│
╰──╂────╯ two ┃ ▐│ │▌│ │▙▄▄▄▄▄▟│
┃ ╔═══════╋═╗ ▐│ ├▌╯ ╰─────┬─╯
┗━━━╋━━━━━━━┛ ║ ▐╰────╯▌────────┴───╮
║ three ║ ▝▀▀▀▀▀▀▘ R: outside╯
╚═════════╝
╭─────────╮
my text I │my text I│
want to ╶─<insert>R─▷ │want to │
box │box │
╰─────────╯
The usual C-_ or C-/ keys may be hit to undo, even with the region
still active visually.
While the rectangular mode is active, press i to fill the
rectangle. You will be asked to choose a character. You have those
options:
- for a regular character like
t, just type it. SPCorDELfor a shade of grey" ░▒▓█"among the 5 available in UNICODE.SPCto make it darker and darker.DELto make the rectangle lighter and lighter.C-yto chose the first character in the top of the kill ring.
The above selection is the same as for the flood-fill action (see the “Flood-fill” chapter).
Select a region, then press<insert>.
Use arrow keys to move the rectangle around. A numeric prefix may be used to move the rectangle that many characters.
- Under
Hydra, be sure to specify the numeric prefix with just digits, without theAltkey. Typing15 <left>moves the rectangle 15 characters to the left.M-15 <left>does not work. - Under
Transient, use theAltkey, like anywhere else inEmacs. TypeM-15 <left>to move the selected rectangle 15 characters to the left.
Press q, <return>, or C-g to stop moving the rectangle.
The C-_ key may also be used to undo the previous movements, even
though the selection is still active.
▲
│
<up>
╭─────┴──────╮
│this is │
│my rectangle│
◀─<left>──┤I want to ├─<right>─▶
│move │
╰─────┬──────╯
<down>
│
▼
A rectangle can be copied or killed, then yanked somewhere else.
Select a region, press <insert>, then:
cto copykto killyto yank (aka paste)
This is similar to the Emacs standard rectangle handling:
C-x r rcopy rectangle to registerC-x r kkill rectangleC-x r yyank killed rectangle
The first difference is that Uniline rectangles, when killed and
yanked, do not move surrounding characters.
The second difference is that the white characters of the yanked rectangle are considered transparent. As a result, only non-blank parts of the yanked rectangle are over-printed.
Uniline and Emacs standard rectangle share the same storage for copied
and killed rectangles, namely the killed-rectangle Lisp variable. So,
a rectangle can be killed one way, and yanked another way.
╭────▷───╮ ┏━━━━▶━━━┓ ╔════▶═══╗ │ ╭─□──╮ │ ┃ ┏━■━━┓ ┃ ║ ╔═■══╗ ║ △ │ │ ▽ ▲ ┃ ┃ ▼ ▲ ║ ║ ▼ │ ╰───◦╯ │ ┃ ┗━━━•┛ ┃ ║ ╚═══•╝ ║ ╰───◁────╯ ┗━━━◀━━━━┛ ╚═══◀════╝ ╭╌╌╌╌▷╌╌╌╮ ┏╍╍╍╍▶╍╍╍┓ ┆ ╭╌□╌╌╮ ┆ ┇ ┏╍■╍╍┓ ┇ △ ┆ ┆ ▽ ▲ ┇ ┇ ▼ ┆ ╰╌╌╌◦╯ ┆ ┇ ┗╍╍╍•┛ ┇ ╰╌╌╌◁╌╌╌╌╯ ┗╍╍╍◀╍╍╍╍┛ ╭┈┈┈┈▷┈┈┈╮ ┏┉┉┉┉▶┉┉┉┓ ┊ ╭┈□┈┈╮ ┊ ┋ ┏┉■┉┉┓ ┋ △ ┊ ┊ ▽ ▲ ┋ ┋ ▼ ┊ ╰┈┈┈◦╯ ┊ ┋ ┗┉┉┉•┛ ┋ ╰┈┈┈◁┈┈┈┈╯ ┗┉┉┉◀┉┉┉┉┛
A base drawing can be converted to dashed lines. Moreover, lines can be made either thin or thick.
- Select the rectangular area you want to operate on (with mouse drag
or
S-<left>,S-<down>and so on as described earlier). - Type
INS, thens(as “style”).
You will be offered a choice of styles:
3: vertical lines will become 3 dashes per character, while horizontal ones will get 2 dashes per character.4: vertical and horizontal lines will get 4 dashes per character.h: thin lines corners, which are usually rounded, become hard angles.+: thin lines and intersections become thick, empty glyphs get filled.-: thick lines and intersections become thin, filled glyphs are emptied.=: thick and thin lines become double lines.0: come back to standard base-lineUnilinestyle: plain, not-dashed lines, thin corner rounded, ASCII art is converted to UNICODE.a: apply theaa2u-rectanglefunction from the unrelatedascii-art-to-unicodepackage, to convert ASCII art to UNICODE (this only works ifascii-art-to-unicodeis already installed).
Converting parts of a drawing from one style to another can produce nice looking sketches.
╭───╮ ╭───╮ ╭───╮
│░░░│ │░░░│ │░░░┝━▶┓ ╭╌╌╌╌╌╮
│░░░╰───╯░░░╰───╯░░░│ ┃ ┆░░░░░╰╌╌╌╌╌╮
□░░░░░░░░░░░░░░░░░░░│ ┗━┥░░░░░░░░░░░┆
│░░░╭───╮░░░╭───╮░░░│ ┆░░░░░╭╌╌╌╌╌╯
╰───╯ ╰─┰─╯ ╰─┰─╯ ╰╌╌┰╌╌╯
▲ ┃ ▼
┗━━━━━━━┻━━━━━━━━━┛
┏━━━┓ ┏━━━┓ ┏━━━┓
┃░░░┃ ┃░░░┃ ┃░░░┠─▷╮ ┏╍╍╍╍╍┓
┃░░░┗━━━┛░░░┗━━━┛░░░┃ │ ┇░░░░░┗╍╍╍╍╍┓
■░░░░░░░░░░░░░░░░░░░┃ ╰─┨░░░░░░░░░░░┇
┃░░░┏━━━┓░░░┏━━━┓░░░┃ ┇░░░░░┏╍╍╍╍╍┛
┗━━━┛ ┗━┯━┛ ┗━┯━┛ ┗╍╍┯╍╍┛
△ │ ▽
╰───────┴─────────╯
The standard base-line Uniline (INS s 0) or aa2u-rectangle (INS s a)
conversions may be used to convert ASCII art to UNICODE. The original
ASCII art may be drawn for instance by the artist-mode or the
picture-mode packages.
To use aa2u-rectangle, install the ascii-art-to-unicode package by
Thien-Thi Nguyen (RIP), available on ELPA. Uniline does not requires a
dependency on this package, by lazy evaluating any call to
aa2u-rectangle.
See https://elpa.gnu.org/packages/ascii-art-to-unicode.html
+-------------+ +--+
| +-->-| +-----+ ASCII art
| 1 +--------+--+ | 3 | made by
+----+--------+ | +----+---+ Artist-mode
| 2 +-<----+
+-----------+
╭─────────────╮ ╭──╮
│ ├──▷─│ ╰─────╮ Converted to
│ 1 ╭────────┼──╮ │ 3 │ Uniline base style
╰────┼────────╯ │ ╰────┬───╯ INS s 0
│ 2 ├─◁────╯
╰───────────╯
┌─────────────┐ ┌──┐
│ ├──>─│ └─────┐ Converted by
│ 1 ┌────────┼──┐ │ 3 │ aa2u-rectangle
└────┼────────┘ │ └────┬───┘ INS s a
│ 2 ├─<────┘
└───────────┘
INS s 0 with selection active calls the uniline-change-style-standard
function. It converts what looks ASCII-art to UNICODE-art. Of course,
there are ambiguities regarding whether a character is part of a
sketch or not.
The heuristic is to consider that a character is part of a sketch if
it is surrounded by at least one other character which is part of a
sketch. So, an isolated - minus character will be left alone, while
two such characters -- will be converted to UNICODE. Conversion will
happens also for <- for instance.
Here is a fairly convoluted ASCII-art example, along with its
conversion by INS s 0:
╭─↔--<-◁-◀--━+ +--->------==+
/----/ Rectangle1 |-----+-----+ Rectangle2 v v
| | <uni^code> ^ " | "quote" +-\ ▼
^^ \------------/ /-+-\ +------------+ " v
| \--+------+--/ | | +----\----/--+ " >▷▶>
\>--\ | | \---/ | | "
v \==<===/ a=b 1=2 a-to-b +----+ ◁==/ >->
╭─↔──◁─◁─◀──━┑ ╭───▷──────══╕
╭────┤ Rectangle1 │─────╥─────┤ Rectangle2 ▽ ▽
│ │ <uni^code> △ ║ │ "quote" ├─╖ ▼
△^ ├────────────┤ ╭─╨─╮ ├────────────┤ ║ ▽
│ ╰──┬──────┬──╯ │ │ ╰────┬────┬──╯ ║ ▷▷▶▷
╰▷──╮ │ │ ╰───╯ │ │ ║
▽ ╘══◁═══╛ a=b 1=2 a-to-b ╰────╯ ◁══╝ ▷─▷
╭──────────────╮
╭─╯A.written.text╰────────╮
│outlined by the.`contour'│
╰─╮function.gets╶┬────────╯
╰╮a.surrounding╰───────╮
╰─╮line.in.the.current│
╰─╮brush.style╭─────╯
╰───────────╯
Choose or change the brush style with any of -,+,=_,#,<delete>. Put
the cursor anywhere on the shape or outside but touching it. Then
type:
<insert> c
A contour line is traced (or erased if brush style is <delete>)
around the contiguous shape close to the cursor.
When hitting capital letter: <insert> S-C the contour is
overwritten. This means that if there was already a different style of
line on the contour path, it is overwritten.
The shape is distinguished because it floats in a blank characters
ocean. For the shake of the contour function, blank characters are
those containing lines as drawn by Uniline (including true blank
characters). Locations outside the buffer are also considered blank.
The algorithm has an upper limit of 10000 steps. This avoids an
infinite loop in which the algorithm may end up in some rare
cases. One of those cases is when the contour crosses a new-page
character, displayed by Emacs as ^L. 10000 steps require a fraction of
a second to run. For shapes really huge, you may launch the contour
command once again, at the point where the previous run ended.
This 10000 steps limit is customizable. Type:
M-x customize-variable uniline-contour-max-steps
this.text.surrounds this.text.surrounds . / .▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒/ . //╶───▷╴.▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒// ... //// ...▒▒▒▒▒▒▒▒▒▒▒▒//// ...a.hole///// ...a.hole/////
A hollow shape is a contiguous region of identical characters (not necessarily blank), surrounded by a boundary of different characters. The end of the buffer in any direction is also considered a boundary.
Put the cursor anywhere in the hole. Then type:
<insert> i
Answer by giving a character to fill the hole.
If instead of a character, SPC or DEL is typed, then a shade of grey
character is picked. SPC selects a darker grey than the one the point
is on, while DEL selects a lighter. There are 5 shades of grey in the
UNICODE standard: " ░▒▓█". Those grey characters are well supported
by the suggested fonts.
C-y is also an option. The first character in the top of the kill
ring will be chosen as the filling character. (The kill ring is filled
by functions like C-k or M-w, unrelated to Uniline).
Typing <return> or C-g aborts the filling operation.
A rectangular shape may also be filled.
- Mark a region
<insert> i- answer which character should be used to fill.
There is no limit on the area to fill. Therefore, the filling operation may flood the entire buffer (but no more).
Uniline adds directional macros to the Emacs standard macros.
Record a macro as usual with C-x ( … C-x ).
Then call it with the usual C-x e. But then, instead of executing
the macro, a menu is offered to execute it in any of the 4 directions.
When a macro is executed in a direction other than the one it was recorded, it is twisted in that direction. This means that recorded hits on the 4 keyboard arrows are rotated. It happens also for shift and control variations of those keys. Direction of text insertion is also rotated.
There is still the classical e option to call the last recorded
macro. So instead of the usual C-x e, type C-x e e. And of course,
the usual repetition typing repeatedly e is available.
Why are directional macros useful? To create fancy lines. For instance, if we want a doted-line instead of the continuous one, we record a macro for one step:
C-x ( ;; begin recording INS o ;; insert a small dot <right> <right> ;; draw a line over 2 characters C-x ) ;; stop recording
Then we call this macro repeatedly in any of the 4 directions:
·─·─·─·─· ╷ ·──·
│ │ │ │
· · · ·
│ │ │ │
· ·─·─·─· ·
│ │
·─·─·─·─·─·─·
We can draw complex shapes by just drawing one step. Hereafter, we call a macro in 4 directions, closing a square:
╭╮╭╮╭╮╭╮╭╮╭╮ △ △ △ △ △ △ ╭─╮ ╭─╮ ╭─╮ ╭─╮ ╭─╮ ╭─╮ ╭─╮ ╭─╮ ╭─╯╰╯╰╯╰╯╰╯╰╯│ ╶╯╶╯╶╯╶╯╶╯╶╯╷ ╭──╯∙╰─╯∙╰─╯∙╰─╯∙│ ▷┤□├▷┤□├▷┤□├▷┤□├▽ ╰╮ ╰╮ ◁╮ ╰▷ │∙ │ ╭┴┼─╯ ╰─╯ ╰─╯ ╰─┼┴╮ ╭╯ ╭╯ ╵ ╷ ╰╮ ╰╮ │□│ │□│ ╰╮ ╰╮ ◁╮ ╰▷ │ ∙│ ╰┬╯ ╰┬╯ ╭╯ ╭╯ ╵ ╷ ╭╯ ╭╯ △ ▽ ╰╮ ╰╮ ◁╮ ╰▷ │∙ │ ╭┴╮ ╭┴╮ ╭╯ ╭╯ ╵ ╷ ╰╮ ╰╮ │□│ │□│ ╰╮ ╰╮ ◁╮ ╰▷ │ ∙│ ╰┬┼─╮ ╭─╮ ╭─╮ ╭─┼┬╯ │╭╮╭╮╭╮╭╮╭╮╭─╯ ╵╭╴╭╴╭╴╭╴╭╴╭╴ │∙╭─╮∙╭─╮∙╭─╮∙╭──╯ △┤□├◁┤□├◁┤□├◁┤□├◁ ╰╯╰╯╰╯╰╯╰╯╰╯ ▽ ▽ ▽ ▽ ▽ ▽ ╰─╯ ╰─╯ ╰─╯ ╰─╯ ╰─╯ ╰─╯ ╰─╯ ╰─╯A mono-space character font must be used. It must also support UNICODE.
Not all fonts are born equal.
(set-frame-font "DejaVu Sans Mono" )(set-frame-font "Unifont" )(set-frame-font "Hack" )(set-frame-font "JetBrains Mono" )(set-frame-font "Cascadia Mono" )(set-frame-font "Agave" )(set-frame-font "JuliaMono" )(set-frame-font "FreeMono" )(set-frame-font "Iosevka Comfy Fixed" )(set-frame-font "Iosevka Comfy Wide Fixed")(set-frame-font "Aporetic Sans Mono" )(set-frame-font "Aporetic Serif Mono" )(set-frame-font "Source Code Pro" )
Those fonts are known to support the required UNICODE characters, AND
display them as mono-space. There are fonts advertised as mono-space
which give arbitrary widths to non-ASCII characters. That is bad for
the kind of drawings done by Uniline.
You may want to try any of the suggested fonts. Just hit the
corresponding entry in the Uniline menu, or type <insert> f. You may
also execute the above Lisp commands like that:
M-: (set-frame-font "DejaVu Sans Mono")
This setting is for the current session only. If you want to make it
permanent, you may use the Emacs customization:
<insert> f *
or
M-x customize-face default
Beware that Emacs tries to compensate for missing UNICODE support by
the current font. Emacs substitutes one font for another, character
per character. The user may not notice until the drawings done under
Emacs are displayed on another text editor or on the Web. Of course,
using the suggested fonts and the UNICODEs drawn by Uniline keeps you
away from those glitches.
To know which font Emacs has chosen for a given character, type:
C-u C-x =
Note that none of those commands downloads a font from the Web. The font should already be available.
The basic usage ofUniline should be easy: just move the point, and lines
are traced. Change brush to draw thicker lines.
More complex actions are summoned by the <insert> key, with or without
selection. This is a single key to remember. Then a textual menu is
displayed, giving the possible keys continuations and their
meaning. All that is achieved by the Hydra or Transient libraries,
which are now part of Emacs (thanks!).
The Hydra and Transient libraries offer similar features. Some users
may prefer one or the other.
Uniline was developed from day one with Hydra. Transient is a late
addition.
Two files are compiled when installing Uniline
uniline-hydra.eluniline-transient.el
One of them should be loaded (but not both). There are several
ways. The cleanest is use-package. Add those lines to your ~/.emacs
file:
(use-package uniline-hydra
:bind ("C-<insert>" . uniline-mode))or:
(use-package uniline-transient
:bind ("C-<insert>" . uniline-mode))Note: there used to be a customizable setting to switch between the two interfaces. This had many issues. One of them is that the native-compiler is blind to all user-customized settings.
There is a third file, uniline-code.elc. Loading uniline-hydra.elc or
uniline-transient.elc automatically loads uniline-core.elc.
It is now possible to switch to less distracting textual menus. They are displayed in the echo-area on a single line.
To do so, type:
C-twithin a sub-mode (glyph insertion mode, rectangle handling, etc.)C-h TABat the top-level.
This will flip between the two sizes of textual menus. It also affects
the welcome message, the one displayed when entering the Uniline minor
mode.
The current size is controlled by the uniline-hint-style variable:
tfor full fledged messages over several lines1for one-liner messages0for no message at all
The variable is “buffer-local”, which means that it can take distinct values on distinct buffers.
Its default value can be customized and saved for future sessions:
M-x customize-variable uniline-hint-style
After customization it can be changed later, on a buffer per buffer
basis, with the C-t or C-h TAB keys.
Transient natively offers a similar setting:
transient-show-popup. (There is no such variable in Hydra). It can be
customized with t, nil, 0 (zero), or a number. This is similar but not
exactly the same as the Hydra behavior and the uniline-hint-style.
the Transient setting stays in effect until the C-t or C-h TAB keys
are not used, . As soon as one of those keys is invoked,
transient-show-popup is toggled (which does not happens in Transient
alone). The change is kept in effect throughout the Uniline session,
but no longer.
Put that in your ~/.emacs file:
(use-package uniline-hydra
:bind ("C-<insert>" . uniline-mode))It has been asked by Transient-only users to avoid installing the
Hydra package. Currently, it is not possible to make dependencies
conditional in Melpa. And removing the Hydra dependency would hurt
Hydra users. Therefore, for the time being, the Hydra package is still
installed when installing Uniline through Melpa.
Put that in your ~/.emacs file:
(use-package uniline-transient
:bind ("C-<insert>" . uniline-mode))Transient interface was added recently to Uniline. This leaded to the
splitting of the single uniline.el file into 4 source
files. Hopefully, the added complexity remains hidden by the Elpa -
Melpa packaging system.
M-x customize-group uniline.
Or Menu bar ⟶ Options ⟶ Customize Emacs ⟶ Specific Group… ⟶ "uniline".
This invokes the standard Emacs customization system. Your settings
will be saved in the file pointed to by the custom-file variable if
set, or your ~/.emacs file. (Along with all your other settings
unrelated to Uniline).
Two settings are special: interface type (obsolete) & the insert key. The other settings are self-explanatory
This switch is obsolete. Choosing between Hydra or Transient interface
is done by loading one or the other sub-package. See “Installation”
for details.
By default, the <insert> or INS key is the prefix for most of the
Uniline actions. Some computers do not have an INS key, or it is bound
to some other command (Apple?).
This can be changed temporarily or permanently. The customization allows to set several keys at the same time.
Depending on whether Emacs is run in a graphical environment or a
text-only terminal, either the <insert> or the <insertchar> events are
generated by the INS key. Therefore, by default Uniline defines both
events as the INS key.
Variable uniline-key-insert.
10000.
To avoid an infinite loop in some rare cases.
Variable uniline-contour-max-steps.
There is the option to leave the cursor as it is.
Variable uniline-cursor-type.
Hydra.
It defaults to “full fledged menus”.
Variable uniline-hint-style.
Transient offers a similar setting: transient-show-popup.
Even when turned of, the welcome message can still be displayed by
pressing C-h TAB.
Variable uniline-show-welcome-message.
The line-spacing setting in Emacs can change the display of a
sketch. (This setting is unrelated to Uniline).
The best looking effect is given by:
(setq line-spacing nil)
You may want to change your current setting. Uniline may handle this
variable some day. Right now, line-spacing is left as a matter of
choice for everyone.
╭────┬────────┬────╮ ╺┯━━━━┯┯━━┯┯━┯┯━━━━━━━━┯┯━━━━━━━┯┯━━━━━━┯╸
│▒▒▒▒╰────────╯▒▒▒▒│ │ │╰is╯╰a╯│ ││ │╰around╯
│▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│ ╰this╯ ╰sentence╯╰hanging╯
│▒▒▒╭─╮▒▒▒▒▒▒╭─╮▒▒▒│ △
│▒▒▒╰─╯▒▒▒▒▒▒╰─╯▒▒▒│ │ △
│▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│ ╰─────────┬────────╯
╰──────────────────╯ verbs
(setq line-spacing nil)
Face customization is unrelated to Uniline. However, Uniline can
assist in choosing a good font and customizing the default face. See
the “Which fonts?” chapter.
Type <insert> f to select a font just for the current Uniline
session. Type * to enter the Emacs customization of the default face
and retain your choice for future sessions.
╶───────────┬─────╮
│ │
│ │
│ │
╰───────────╯
unexpected broken lines
╶─────┬───────────╮
│ │
│ │
│ │
╰───────────╯
expected continuous lines
The above example was drawn first with the Chinese-BIG5 language
environment, then with the English environment.
There is nothing specific about Chinese-BIG5. It is just an instance
picked out from more than 100 language environments.
C-x RET l Chinese-BIG5 C-x RET l English
In Chinese-BIG5, some characters are considered twice as wide as
standard characters. Whereas in English, all characters needed by
Uniline are 1 unit wide.
Thanks to rumengling (GitHub) for discovering and diagnosing the issue!
To workaround the issue, when entering uniline-mode, the width of all
characters Uniline uses is checked. If some of them are more than 1,
the char-width-table variable is patched.
What are the consequences of this patch? The char-width-table variable
is an Emacs global. Therefore the patch by Uniline will affect all
buffers. As the characters touched by the patch are graphic, and have
nothing to do with Chinese, it should not have any significance on
text written in Chinese.
It was pondered whether Uniline should put back char-width-table at
its original value upon exiting uniline-mode, or leaving the
patch. For now, it has been decided to leave it. Because anyway,
intertwining several uniline-mode and changes to the language
environment is intractable.
In case of something, re-setting the language environment to its same
value cancels the patch to char-width-table by Uniline.
Picture-mode and uniline-mode are compatible. Their features overlap
somehow:
- Both implement an unlimited buffer in east and south directions.
- Both visually truncate long lines (actual text is not truncated).
- Both set the overwrite mode (
uniline-modeactivatesoverwrite-mode, whilepicture-modere-implements it) - Both are able to draw rectangles (
uniline-modein UNICODE,picture-modein ASCII), copy and yank them.
They also have features unique to each:
Picture-modewrites in 8 possible directionsPicture-modehandles TAB stopsUniline-modedraws lines and arrows
Artist-mode and uniline-mode are mostly incompatible. This is because
artist-mode preempts the arrow keys, which give access to a large part
of uniline-mode features.
However, it is possible to use both one after the other.
Whitespace-mode and uniline-mode are mostly compatible.
Why activate whitespace-mode while in uniline-mode? Because
Uniline creates a lot of white-spaces to implement an infinite
buffer. And it is funny to look at this activity.
To make uniline-mode and whitespace-mode fully compatible, disable
the newline visualization:
M-x customize-variable whitespace-style- uncheck
(Mark) NEWLINEs
This is due to a glitch in move-to-column when a visual property is
attached to newlines. And uniline-mode makes heavy use of move-to-column.
Org Mode. This
is because Org Mode preempts shift-select-mode for other useful
purposes. Just type:
M-x customize-variable org-support-shift-select
and choose “when outside special context”, which sets it to t.
You then get the shift-selection from Org Mode, not from Uniline. The
difference is that the Uniline’s one handles the infinite-ness of the
buffer.
Other than that, Uniline is compatible with Org Mode
Thanks to jdtsmith (GitHub) for sharing a funny fact he discovered. If
a source block is created with the Uniline language (Uniline is
not a language like C++, Python, or Bash), then it can be
edited (M-x org-edit-special) with uniline-mode automatically
activated.
╭───╮ ╭───╮ │ ╷ ╰───╯ ╷ │ │ ╰─ ╶─╯ │ ╰╮ ● ● ╭╯ │ ╷ │ ╰╮ ────╯ ╭╯ ╰───────╯Use the
pmboxdraw LaTex module. This gives limited support for “box
drawing” characters in LaTex documents.
Example:
#+LATEX_HEADER: \usepackage{pmboxdraw}
this works:
┌─────┐ ┌────────────┐
│ ├───────┤ │
└─────┘ │ │
┌─────┐ ┌────┤ │
│ ├──┘ │ │
└─────┘ ┌────┤ │
┌─────┐ │ │ │
│ ├──┘ └────────────┘
└─────┘
this does not quite work:
┏━━━┓ ┏━━┓ ┏━━━━━┓
┃ ┃ ┃ ┣━━━━━┫ ┃
┃ ┗━━┛ ┃ ┏┛ ┃
┗━━━━━━━━━┛ ┗━━━━━━┛
but that is OK:
┏━━━┓
┃ ┃
┗━━━┛
that is OK too:
╺════╦══╗ ╔════╗
║ A║ ║ B ╚══╗
╚══╝ ╚═══════╝
this works:
├── dev
└┬┬ release
│├── new
│└── old
├── graph
└── non-graph
Note that corners of thin lines should be sharp. There is no support for rounded corners.
To export this Org Mode example to PDF through LaTex, type:
C-c C-E l o
\t). Those include
programming code (Python, Perl, C++, D, Rust, JavaScript and so on).
When Uniline draws something in the middle of a TAB, or right onto a
TAB, it first converts it to spaces, then proceeds as usual. This
process is invisible. So be cautious if TABs have a special meaning in
the file.
Also, rectangles are first untabified (if there are TABs) before moving them. This avoids some rare instances of misalignment.
One way to see what is going on, is to activate the whitespace-mode.
Uniline does not work well with ^L (page separation)
character. Nor with similar characters, like ^T. When trying to
draw a line over such a character, the cursor may get stuck. This is
because those characters occupy twice the width of a normal character.
Just try to get away from ^L, ^T and such when drawing with
Uniline.
C-M-F1, C-M-F2, and so on. Such a screen is also
presented when connecting through ssh or tls into a non-graphical server.
By default they use a font named “Fixed” with poor support for Unicode. However, it supports lines of the 3 types, mixing all of them in thin lines though.
Another problem is that by default S-<left> and C-<left> are
indistinguishable from <left>. Same problem with <right>, <up>, <down>
and <insert>. This has nothing to do with Emacs. A solution can be
found here: https://www.emacswiki.org/emacs/MissingKeys
Emacs launched from a terminal typing emacs -nw. In this
environment, <insert> does not exist. It is replaced by
<insertchar>. This has already been taken into account by Uniline
by duplicating the key-bindings for the two flavors of this key.
If you decide to bind globally C-<insert> to the toggling of
Uniline minor mode as suggested, then you will have to do the same
for C-<insertchar>, for example with use-package in your
~/.emacs file:
(use-package uniline
:defer t
:bind ("C-<insert>" . uniline-mode)
:bind ("C-<insertchar>" . uniline-mode))Lucida Console and
Courier New. They are not mono-spaced for the Unicodes used by
Uniline.
Often, the Consolas font is present on Windows. It supports quite well
the required Unicodes to draw lines. A few glyphs produce unaligned
result though. They should be avoided under Consolas: △▶▹◆
Of course, other fonts may be installed. It is quite easy.
CouldUniline be programmed (versus used interactively)?
Yes!
The API is usable programmatically:
Move cursor while drawing lines by calling any of the 4 directions functions:
uniline-write-up↑uniline-write-ri→uniline-write-dw↓uniline-write-lf←
They expect a repeat count (usually 1) and optionally force=t to
overwrite the buffer
Set the current brush by calling any of the following:
uniline--set-brush-nil;; write nothinguniline--set-brush-0;; eraseruniline--set-brush-1;; single thin line╶─╴uniline--set-brush-2;; single thick line╺━╸uniline--set-brush-3;; double line╺═╸uniline--set-brush-block;; blocks ▙▄▟▀
Those functions are equivalent to:
(setq uniline--brush nil)(setq uniline--brush 0)(setq uniline--brush 1)(setq uniline--brush 2)(setq uniline--brush 3)(setq uniline--brush :block)
except the functions also update the mode-line.
For instance, if we want to create a function to draw a “plus” sign, we can code it as follows:(defun uniline-draw-plus ()
(interactive)
(uniline-write-ri→ 1)
(uniline-write-dw↓ 1)
(uniline-write-ri→ 1)
(uniline-write-dw↓ 1)
(uniline-write-lf← 1)
(uniline-write-dw↓ 1)
(uniline-write-lf← 1)
(uniline-write-up↑ 1)
(uniline-write-lf← 1)
(uniline-write-up↑ 1)
(uniline-write-ri→ 1)
(uniline-write-up↑ 1))Calling M-x uniline-draw-plus will result in this nice little
plus-shape:
╭╮ ╭╯╰╮ ╰╮╭╯ ╰╯ generated by M-x uniline-draw-plus
We may modify the function to accept the size of the shape as a parameter:
(defun uniline-draw-plus (size)
(interactive "Nsize? ")
(uniline-write-ri→ size)
(uniline-write-dw↓ size)
(uniline-write-ri→ size)
(uniline-write-dw↓ size)
(uniline-write-lf← size)
(uniline-write-dw↓ size)
(uniline-write-lf← size)
(uniline-write-up↑ size)
(uniline-write-lf← size)
(uniline-write-up↑ size)
(uniline-write-ri→ size)
(uniline-write-up↑ size))The (interactive "Nsize? ") form prompts user for the size of the
shape if not given as a parameter.
This API works in any mode, not only in Uniline minor mode. It takes
care of the infiniteness of the buffer in the right and down
directions.
There are other useful functions operating on many characters at once. Contour tracing and flood-filling are among them:
uniline-contouruniline-fill
The following functions operate on a rectangular region, which must be active prior to calling them:
uniline-draw-inner-rectangleuniline-draw-outer-rectangleuniline-copy-rectangleuniline-kill-rectangleuniline-yank-rectangleuniline-fill-rectangleuniline-move-rect-up↑uniline-move-rect-ri→uniline-move-rect-dw↓uniline-move-rect-lf←
Constants for the 4 directions:
uniline-direction-up↑;; constant 0uniline-direction-ri→;; constant 1uniline-direction-dw↓;; constant 2uniline-direction-lf←;; constant 3
Changing text direction:
uniline-text-direction-up↑uniline-text-direction-ri→uniline-text-direction-dw↓uniline-text-direction-lf←
or (in this case the mode-line is not updated):
(setq uniline-text-direction uniline-direction-up↑)(setq uniline-text-direction uniline-direction-ri→)(setq uniline-text-direction uniline-direction-dw↓)(setq uniline-text-direction uniline-direction-lf←)
Call macro in any direction:
uniline-call-macro-in-direction-up↑uniline-call-macro-in-direction-ri→uniline-call-macro-in-direction-dw↓uniline-call-macro-in-direction-lf←
uniline-insert-fw-arrowuniline-insert-fw-squareuniline-insert-fw-oshapeuniline-insert-fw-crossuniline-insert-bw-arrowuniline-insert-bw-squareuniline-insert-bw-oshapeuniline-insert-bw-cross
Rotate arrow or tweak 4-half-lines or 4-block characters:
uniline-rotate-up↑uniline-rotate-ri→uniline-rotate-dw↓uniline-rotate-lf←
Here are the lowest level functions. Move point, possibly extending the buffer in right and bottom directions:
uniline-move-to-columnuniline-move-to-lineuniline-move-to-lin-coluniline-move-to-delta-columnuniline-move-to-delta-line
A drawing in a rectangular selection may have its style changed:
uniline-change-style-dot-3-2;; 3 dashes vert. ┆, 2 horiz. ╌uniline-change-style-dot-4-4;; 4 dashes vert. ┊ & horiz. ┈uniline-change-style-standard;; back to Uniline base styleuniline-change-style-hard-corners;; rounded corners╭╴become hard┌uniline-change-style-thin;; convert to ╭╴ thin linesuniline-change-style-thick;; convert to ┏╸ thick linesuniline-change-style-double;; convert to ╔═ thick linesuniline-aa2u-rectangle;; call aa2u to convert ASCII to Unicode
The above functions require a region to be marked.
The out-of-the-box mouse support ofEmacs works perfectly. Except when
the mouse clicks on a position outside the buffer. This happens when
clicking past the end of a too short line, or past the end of the buffer.
To handle those cases, a few standard Emacs functions have been
extended to add blank characters or blank lines. Doing so, the
mouse-click now falls on a valid part of the buffer. Of course, those
extensions are only active on uniline-mode activated buffers.
Beware that when the window is at the same time zoomed with C-x C-+
C-- AND horizontally scrolled with C-x <, the cursor positioning is
not accurate. This is due to Emacs limitations and bugs. Just click
twice to fix the inaccuracy.
Add the following lines to your .emacs file,
and reload it, if not already done:
(add-to-list 'package-archives
'("melpa" . "http://melpa.org/packages/")
t)
(package-initialize)Alternately you may customize this variable:
M-x customize-variable package-archives
Then download the package:
(package-install "uniline")Alternately, you can download the Lisp files, and load them.
(load-file "uniline-hydra.el") ;; interpreted form
(load-file "uniline-hydra.elc") ;; byte-compiled form
(load-file "uniline-hydra.eln") ;; native-compiled form
;; this automatically
;; loads "uniline-core.el"
;; or "uniline-core.elc"
;; or "uniline-core.eln"or if you prefer the Transient interface over the Hydra one:
(load-file "uniline-transient.el") ;; interpreted form
(load-file "uniline-transient.elc") ;; byte-compiled form
(load-file "uniline-transient.eln") ;; native-compiled form
;; this automatically
;; loads "uniline-core.el"
;; or "uniline-core.elc"
;; or "uniline-core.eln"You should prefer the byte-compiled or native-compiled forms over the interpreted forms, because there are a lot of optimizations performed at compile time.
You may want to give uniline-mode a key-binding. use-package
in your $HOME/.emacs file is great for that:
(use-package uniline-hydra
:bind ("C-<insert>" . uniline-mode))or:
(use-package uniline-transient
:bind ("C-<insert>" . uniline-mode))or as an alias to uniline-hydra:
(use-package uniline
:bind ("C-<insert>" . uniline-mode))In this example, C-<insert> was chosen. You can use whatever key combinations you want.
<insert> happens to also be the key used inside Uniline.
If you do not have use-package, you can add those lines in your ~/.emacs file:
(require 'uniline-hydra)
(bind-keys :package uniline-hydra ("C-<insert>" . uniline-mode))The downside is that Uniline will be loaded as soon as Emacs is
launched, rather than deferred until invoked.
artist-mode: the ASCII art mode built intoEmacs.ascii-art-to-unicode: as the name suggest, converts ASCII drawings to UNICODE, giving results similar to those ofUniline.picture-mode: as inUniline, the buffer is infinite in east & south directions.ascii-art-to-unicodeASCII art to UNICODE inEmacs. This is a standard ELPA package by Thien-Thi Nguyen (rest in peace).Unilinemay call it to convert ASCII art drawings to equivalent UNICODE.Unilinearranges to not require a dependency onascii-art-to-unicodeby lazy evaluating a call toaa2u.org-pretty-table: Org Mode tables appear to be drawn in UNICODE characters (actually they are still in ASCII).boxes: draws artistic boxes around text, with nice looking unicorns, flowers, parchments, all in ASCII art.org-drawio: a bridge between the Draw.Io editor andEmacs, producing drawing similar to those ofUniline, but in.svg.syntree: draws ASCII trees on-the-fly from description.unicode-enbox: create a UNICODE box around a text; input and output are strings.unicode-fonts: inEmacs, helps alleviate the lack of full UNICODE coverage of most fonts.org-superstar: prettify headings and plain lists in Org Mode, using UNICODE glyphs.charmap: UNICODE table viewer forEmacs.insert-char-preview: insert UNICODEs with character preview in completion prompt.list-unicode-display: list all UNICODE characters, or a selection of them.show-font: show font features in a buffer.ob-svgbob: convert your ascii diagram scribbles into happy little SVGel-easydraw: a full featured SVG editor right inside yourEmacsasciiflow: (notEmacs) draw on the web, then copy-paste your UNICODE textdot-to-ascii.ggerganov.com:(notEmacs) describe your schema in the Graphviz language, and copy-past your UNICODE text.monosketch: (notEmacs) draw on the web, then copy-paste your UNICODE textibm-box-drawing-hydra.el: keyboard interface to insert UNICODE box-drawing characters one at a timeorg-excalidraw: integrate SVG images generated by excalidraw into Org Modercd-box: create tables surrounded by box-drawing characters from Lisp descriptionsob-diagram: generate various diagrams using diagrams backendob-mermaid: generate Mermaid diagrams within org-mode babelquail-boxdrawing.el: input method for box drawing charactersmake-box.el: box around part of a buffervim drawit ascii diagrams: in Vim, in ASCII
- Thierry Banel, author
Feedback:
- Chris Rayner (@riscy), gave recommendations prior to insertion in MELPA
- Adam Porter (@alphapapa), suggested submitting
UnilinetoELPA; should I? - Joost Kremers https://github.com/joostkremers found a bug in the minor-mode key-binding definitions, and incompatibility with
- DogLooksGood https://github.com/DogLooksGood gave feedback on inserting usual characters not moving the cursor
- LuciusChen & lhindir on GitHub, arthurno1 & karthink on Reddit,
pushed toward
Transientas the default interface instead ofHydra - karthink noted that
Transientwas now built intoEmacs, loosening the dependencies conundrum, arthurno1 participated in theHydra-Transientdiscussion - karthink pointed to the new
Aporeticfont family, which was then added to theUnilinesupported fonts - rumengling on GitHub found and diagnosed the misaligned lines issue produced by some “language environments” (see Language environment).
Contributors:
- JD Smith (jdtsmith on GitHub) rewrote the
:lighterfor added flexibility (the information in the mode-line about the state ofUniline) - JD Smith also pointed to
#+begin_src unilineOrg Mode block suprising behavior (editing its content automatically switches touniline-mode)
Utilities:
- Oleh Krehel alias abo-abo for his package
Hydra - The
Magitteam for theTransientlibrary - Thien-Thi Nguyen (RIP) for his package
ascii-art-to-unicode
Uniline is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
Uniline is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.