___                               .-------.
        /   |  __________________          | Tokyo |
       / /| | / ___/ ___/ / / __ \         '-------'   .-----------.
      / ___ |(__  ) /__/ / / /_/ /             ^       | Tuju-Tuju |
     /_/  |_/____/\___/_/_/\____/              |       '-----------'
                                               |             ^
                                           .-------.         |
                                .------.---| Malmö |---------'  .-------.
                                |      |   '-------'            | Korba |
                                v      |       ^                '-------'
                           .--------.  |       |     .-------.      |
                           | Dallas |  |       '-----| Paris |<-----'
                           '--------'  |             '-------'
                                       v
                                  .--------.
                                  | Moscow |
                                  '--------'

Asciio allows you to draw ASCII diagrams in a GUI or TUI. The diagrams can be saved as ASCII text or in a format that allows you to modify them later.

Diagrams consist of boxes and text elements connected by arrows. The elements stay connected when you move them around.

Both GUI and TUI have vim-like bindings, the GUI has a few extra bindings that are usually found in GUI applications; bindings can be modified.

ASCII format is easy and universal, many tools exist to manipulate it and even transform it to other formats.

I've used it a lot to draw trees and graphs when my hand drawn pictures were good enough for presentations. Having the possibility to copy and modify the graphs/diagrams makes it possible to present changes in an attractive way.

History

Asciio was born ... as a dare; someone coined a cool name at a conference in Oslo it's been under development for 20 years. It proved to very useful for embedding graphs in code, documentation, requirements, ...

                          .------.
              .-----------| root |---------.
              |           '------'         |       other process
              |               .------------|-------------.
              v               |            v             |
            .--.              |          .--.            |
        .---'--'              |      .---'--'---.        |
        |     |               |      |          |        |
        v     |               |      v          v        |
      .--.    |      link     |    .--.       .--.       |
   .--'--'    .--------------------'--'       '--'       |
   |          |               |      |                   |
   v          |               |      v                   |
 .--.         v               |    .--.                  |
 '--'       .--.              |    '--'                  |
            '--'              |                          |
                              '--------------------------'

Installation

We're working on having packages pre-build for different distributions

Ubuntu (probably other debian derivates too)

    apt install libdata-compare-perl libdata-compare-perl libdirectory-scratch-structured-perl libeval-context-perl libextutils-pkgconfig-perl libfile-homedir-perl libgtk3-perl libio-prompter-perl libterm-size-any-perl libterm-termkey-perl libtest-block-perl libtermkey-dev libmodule-build-perl libsereal-perl libcompress-bzip2-perl libpango-perl libcarp-clan-perl libtest-deep-perl libtest-most-perl libdevel-stacktrace-perl libexception-class-perl libcapture-tiny-perl libtest-differences-perl libmodule-util-perl libtest-nowarnings-perl 

    cpan install Data::TreeDumper::Renderer::GTK App::Asciio

container

Using the instructions above build an asciio image ; the image will be large (~700 MB) as it contains gtk and co.

You can then run the asciio or tasciio like this:

podman run -it --net=host --env="DISPLAY" --volume="$HOME/.Xauthority:/root/.Xauthority:rw" --volume="$HOME:/home/xxx" asciio [asciio|tasciio]

Windows

In the windows environment, you can use asciio through WSL or cygwin.

WSL

The use of WSL is not much different from the Linux environment.However, there are some things that need attention. This link talks about how to connect to the WSL environment and execute GUI programs through remote connections under Windows.

remote_wsl_use_gui_app

Cygwin

  • First install Cygwin.
  • Make sure the following components are installed correctly
    • x11
    • perl
    • Gnome
    • gun-make
    • gcc-g++
  • Search for "gcrypt" in all the packages to be installed, and install all the packages that appear.
  • Install all dependent modules of asciio

Pay attention when installing perl modules, some may be installed through cpan, but some cannot, and can only be installed manually.

When compiling, the Makefile of several modules has an unrecognized option -lnsl. removed it when install it manually.

Start asciio by the following method:

startxwin >/dev/null 2>&1 &
export DISPLAY=:0.0
asciio

Running asciio

$> asciio [file.asciio] # GUI application using Gtk3

$> tasciio [file.asciio] # TUI application

$> asciio_to_text file.asciio # converts asciio files to ASCII

Platforms

Asciio is developed on both Linux and Windows (cygwin).

Interface

Asciio input is from mouse and keyboard bindings, they are defined in a configuration files that you can change.

Asciio's interface is minimal by design.

keyboard bindings

This is the preferred method, and the fastest. The bindings are vim-like and which make the many bindings much easier to remember. See the Bindings section

mouse binidings

Although work can mostly be done using the keyboard, the mouse is still useful in some ccases (selecting in a TUI is difficult) and it even shines when creating new diagrams. See Working efficiently

My least favorite way of using Asciio, it's slow and cumbersome for most actions. I try to reduce the amount of menu and sub menus.

Unicode support

Asciio supports Unicode is a work under progress; including support for Asian languages, thanks to the co-developer who writes in these languages, but you may need a font that supports them.

https://github.com/be5invis/Sarasa-Gothic/

unicode in Asciio

unicode exported

In the examples above the box is drawn with unicode characters, the box is oversized by design, it shrinks and expands properly.

unicode in Asciioshrunk box

If you want to align Thai, or Arabic, or Hebrew, under normal circumstances, the default monospaced font of the system is fine. If you find that it cannot be aligned, you can download a font that can align them.

unicode_thai_alabo_hebrew

When displayed in exported software, you also need a font that aligns them.

      .-----.      .----------------.
      | abc |----->| สวัสดีเราเคยพบกัน |
      '-----'      '----------------'
                            |
                            |
                            |
                            |   .---------------.
                            '-->| שלום, נפגשנו  |
                                '---------------'
                                        |
                                        |
      .------------------.              |
      | مرحبا هل التقينا |<-------------'
      '------------------'

Accessing documentation

Asciio's documentation is available in multiple formats

  • this HTML documentation, generated by mdbook

  • a manpage, available from within Asciio.

  • info pages

There's also:

  • a bindings list

  • a short help

  • a "user" defined documentation. «h» Add help box

UIs

Asciio offers multiple UIs

  • a GUI
  • a TUI (under construction)
  • a command line interface

There's even a ticket about a web interface, if you're a websocket, rpc, minimal interface geek who like Web technology ... join us!

GUI

Ascii0

          .-------------------------------------------------------------.
          | ........................................................... |
          | ..........-------------..------------..--------------...... |
          | .........| stencils  > || asciio   > || box          |..... |
          | .........| Rulers    > || computer > || text         |..... |
          | .........| File      > || people   > || wirl_arrow   |..... |
     grid----->......'-------------'| divers   > || axis         |..... |
          | ..................^.....'------------'| ...          |..... |
          | ..................|...................'--------------'..... |
          | ..................|........................................ |
          '-------------------|-----------------------------------------'
                              |
               context menu access some commands
               most are accessed through the keyboard

Grid

Grid lines

Grid color

Grid background color

Hint lines

hint lines

Rulers

Night Colors

TUI

TUI

The TUI interface is a work in progress. Drawing graphs in a terminal (without mouse) is more difficult than it seem, I'm actively working on creating better bindings to make as s smooth as when using a mouse.

  • mouse emulation
  • differences
    • dialogs
    • manpage

TUI demo

Asciio TUI and Vim

You can call Asciio from vim and insert your diagram.

    map  <leader><leader>a :call TAsciio()<cr>

    function! TAsciio()
        let line = getline('.')

        let tempn = tempname()
        let tempnt = tempn . '.txt'
        let temp = shellescape(tempn)
        let tempt = shellescape(tempnt)

        exec "normal i Asciio_file:" . tempn . "\<Esc>"

        if ! has("gui_running")
        exec "silent !mkdir -p $(dirname " . temp . ")" 
        exec "silent !cp ~/.config/Asciio/templates/empty.asciio ". temp . "; tasciio " . temp . "; asciio_to_text " . temp . " >" . tempt 
        exec "read " . tempnt
        endif

        redraw!
    endfunction

Stencils

Asciio boxes

Elements

connector resize-handle

You can access some functionality via the popup menu.

popup menu

auto-shrink

If the text is changed, the size of the box will change to fit.

disable connectors

Enable or disable the possibility to connect to the box.

disable optimize

A standard box had four connectors, Asciio optimizes the arrow routes so they don't cross the box. You can disable that optimization.

connect inside element borders

Allow connection to be made anywhere inside the element borders , not just the connectors.

border_connect

rotate box/text

rotated

Types

A box

Binding: «b» Add box

A box with the frame drawn with Unicode characters

Binding: «A-b» Add unicode box

A text

Texts are just boxes without frames.

Binding: «t» Add text

A shrink-box

A box which is already has auto-shrink set

Binding: «B» Add shrink box

Asciio if and process boxes

elementbinding
Add if box«ib»
Add process box«ib»

if-box and process-box

if_and_process.gif

Asciio exec-boxes

An "exec-box" is and object that lets you run an external command and put its output in a box. There are different types of exec-boxes explained below.

Multi command

Binding: «ie» Add exec box

The simplest exec-box accepts multiple commands, one per line. It will redirect stderr for each command.

Editing the box will let you edit the command.

ie

Verbatim

Binding: «iv» Add exec box verbatim

This exec-box doesn't redirect stderr, you can use it for commands that span multiple line or commands that take a multi line input

Editing the box will let you edit the command.

iv

Once

Binding: «io» Add exec box verbatim once

This exec-box will run your commands once, editing the box will let you edit the command's output.

io

Add line numbers

Binding: «i + c-l» Add line numbered box

This is an example of a custom stencil which will add line numbers to your input.

il

Examples

Using previously generated output

If you already have text in a file you can use 'cat your_file' as the command.

Tables

tbd: Command: ...

  +------------+------------+------------+------------+
  | input_size ‖ algorithmA | algorithmB | algorithmC |
  +============+============+============+============+
  |     1      ‖ 206.4 sec. | 206.4 sec. | 0.02 sec.  |
  +------------+------------+------------+------------+
  |    250     ‖     -      |  80 min.   | 2.27 sec.  |
  +------------+------------+------------+------------+

FIGlet

Figlet generates large letters out of ordinary text.

FIGlet_asciio

You can specify a font with the -f option.


$ ls /usr/share/figlet/
646-ca.flc   646-hu.flc   646-se2.flc  big.flf       lean.flf      smslant.flf
646-ca2.flc  646-irv.flc  646-yu.flc   block.flf     mini.flf      standard.flf
646-cn.flc   646-it.flc   8859-2.flc   bubble.flf    mnemonic.flf  term.flf
646-cu.flc   646-jp.flc   8859-3.flc   digital.flf   moscow.flc    upper.flc
646-de.flc   646-kr.flc   8859-4.flc   frango.flc    script.flf    ushebrew.flc
646-dk.flc   646-no.flc   8859-5.flc   hz.flc        shadow.flf    uskata.flc
646-es.flc   646-no2.flc  8859-7.flc   ilhebrew.flc  slant.flf     utf8.flc
646-es2.flc  646-pt.flc   8859-8.flc   ivrit.flf     small.flf
646-fr.flc   646-pt2.flc  8859-9.flc   jis0201.flc   smscript.flf
646-gb.flc   646-se.flc   banner.flf   koi8r.flc     smshadow.flf

For example, we want to specify this font: slant

FLGlet_asciio_slant_font

This is the exported effect:

            .-----------------------------------.
            |     _                _  _         |
            |    / \    ___   ___ (_)(_)  ___   |
            |   / _ \  / __| / __|| || | / _ \  |
            |  / ___ \ \__ \| (__ | || || (_) | |
            | /_/   \_\|___/ \___||_||_| \___/  |
            |                                   |
            '-----------------------------------'

            .------------------------------------.
            |     ___                 _  _       |
            |    /   |   _____ _____ (_)(_)____  |
            |   / /| |  / ___// ___// // // __ \ |
            |  / ___ | (__  )/ /__ / // // /_/ / |
            | /_/  |_|/____/ \___//_//_/ \____/  |
            |                                    |
            '------------------------------------'

Diagon

Diagon transforms markdown expressions into an ascii-art representation.

diagon_help.gif

Mathematical Expressions

diagon_math

File Tree

Use exec verbatim box to input multiple lines.

diagon_ascii_tree

diagon_unicode_tree

plantuml

PlantUML

Asciio arrows

elementbinding
Add arrow«ia»
Add Unicode arrow«i+Alt-a»
Add angled arrow«iA»

insert arrows

wirl-arrow

Rotating the end clockwise or counter-clockwise changes its direction.

wirl arrows

multi section wirl-arrow

A set of whirl arrows connected to each other.

insert arrows sections

angled-arrow and axis

angled arrow and axis

Note that an axis doesn't connect.

Connecting lines

A specialized wirl-arrow with no head nor tail.

elementbinding
Add ASCII line«il»
Add Unicode line«iL»
Add Unicode bold line«i+Alt-l»
Add Unicode double line«i+Shift+Alt-l»

connecting lines

Non connecting lines

A specialized wirl-arrow with no head nor tail and auto-connection turned off, it's often used to draw the table in the crossing mode.

elementbinding
Add ASCII non-connecting line«ik»
Add Unicode non-connecting line«iK»
Add Unicode non-connecting bold line«i+Alt-k»
Add Unicode non-connecting double line«i+Shift+Alt-K»

ascii line

                    ----------------------.
                                          |
                                          |
                                          |
                                          |
                                          |

unicode line

                      ─────────────────────────╮
                                               │
                                               │
                                               │
                                               │
                                               │

unicode bold line

                        ━━━━━━━━━━━━━━━━━━━━━━━┓
                                               ┃
                                               ┃
                                               ┃
                                               ┃

unicode double line

                  ═══════════════════════════╗
                                             ║
                                             ║
                                             ║
                                             ║
                                             ║

Example of non-connecting lines in crossing mode

                     ╔═════╦═════╦══════╦═════╦════╦═════╗
                     ║     ║     ║      ║     ║    ║     ║
                     ╠═════╬═════╬══════╬═════╬════╬═════╣
                     ║     ║  A  ║      ║  B  ║    ║     ║
                     ╠═════╬═════╬══════╬═════╬════╬═════╣
                     ║     ║  C  ║      ║     ║    ║     ║
                     ╠═════╬═════╬══════╬═════╬════╬═════╣
                     ║     ║     ║      ║     ║  D ║     ║
                     ╠═════╬═════╬══════╬═════╬════╬═════╣
                     ╚═════╩═════╩══════╩═════╩════╩═════╝

Pseudo-connectors

Pseudo-connectors are a one-glyph-text boxes, used by git mode for example, which can also be used to add connectors to user-created groups.

  • create a pseudo-connector
  • change its glyph if necessary
  • place it
  • group all your elements

pseudo-connector with 4 "optimized" connectors

BindingConnector
o«ic»
*«iC»

pseudo-connector with one connector

Use a "center connect box"

Center_Box

Example

Add Connector

Box connectors

It is possible to add custom connectors when creating a box stencil, see setup/Asciio for the default stencils.

create_box
	(
	NAME               => 'rabbit paw',
	TEXT_ONLY          => <<'TEXT'
(\_/)
(O.o)
/>
TEXT
,
	RESIZABLE          => 0,
	WITH_FRAME         => 0,
	DEFAULT_CONNECTORS => 0,
	CONNECTORS         => [[2, -1, -1, 2, -1, -1, 'paw']]
	),

CONNECTORS

[ # An array of connector
	[
	2,      # X coordinate
	-1,     # percentage of width, -1 to disabe
	-1,     # offset added to position if perventage is used
	2,      # Y coordinate
	-1,     # same as above for Y
	-1,     # same as above for Y
	'paw'   # connector name
	],
	[
	# next connector
	...
	],
]

The box element class also has these functions:

  • add_connector, dynamically add connector
  • remove_connector, by name

Example

box_connector

Asciio shapes

You can add triangles, rombus, and elipses via the popup menu or use the bindings below:

elementbinding
Add rhombus«ir»
Add ellipse«ie»

asciio shapes

verbatim objects

Text elements with ASCII art or normal text. Asciio has as set of verbatim elements in its stencils which can be accessed via the popup menu, or you can add a binding if you use them often. The element's text can be edited. You can also use any Ascii-art/Text you have in a file via an exec-box.

verbatim_objects

                   ___________  
1                 //////|\\\\\\ 
2                '.-----------.'
3                 |    ___    | 
4      (\_/) Zzz  | [] | | [] |  (\_/)
5      (-.-)      |____|_|____|  (o.o)
6      (> <)                     (> <)
7
8
9
0

scales

Simple text elements representing scales/rulers that you can use to scale or align, see hints, your elements.

1    1234567890
2
3    1___5____0____5____0____5____0____5____0____5____0
4
5
6
7
8
9
0

User stencils

You can create stencils that you are going to reuse, details of how to do it in the best way can be found in the Configuration section.

Here are three examples:

asciio-ditaa

asciio_contrib

integrating Asciio and ditaa (third party example)


There was a page (Corn Empire) where a user detailed how to make an integration.

That page is not online anymore, I modified a copy for this documentation.

If you are the original author please contact me so I can give you credit.

Introduction

You found this page because you are looking for more information on installing asciio and ditaa, and then modifying asciio to better interact with ditaa. Well you came to the right place. This guide will take you step-by-step through installing both tools, and modifying asciio to output diagrams to ditaa.

Modifying asciio

Make yourself familiar with ditaa and asciio, you may see the benefit of outputting asciio text files that are compatible with ditaa without modification. Or better yet, generate your diagrams for you when you save :) . This section will explain how to do all of that and more!

Adding in a Ditaa Stencil

You will need to create a new stencils file to create boxes and arrows that are compatible with ditaa (you could optionally modify the standard files if you will only use asciio for ditaa purposes). I got the idea for the modifications from here: http://strawp.net/archive/geeking-out-with-diagrams-in-ascii/

A Standard Box

Go to the App/Asciio/setup/stencils (in the /usr/share/perl5/ or /usr/share/perl/5.10.0/) directory, and find the asciio file. Using for favourite editor, copy and paste the standard box code into a new file called ditaa. Then make the following changes to the standard box code in this new file:

To change the corners, modify line 14/33 and change . to + and modify line 17/36 and change ' to +.

Then modify lines 5 and 7 in the same way. Replace the . with + and the ' with +.

Or you could optionally just copy and paste the completed code below (the $VAR1 = [ is only needed once, and just starts off the file, the ]; at the end of the block, ends the file. All bless calls should be between these lines) :

$VAR1 = [
 
          bless( {
                   'HEIGHT' => 3,
                   'TEXT' => '+---+
|   |
+---+',
                   'NAME' => 'ditaabox',
                   'WIDTH' => 5,
		   'TEXT_ONLY' => '',
		   'TITLE' => '',
		   'BOX_TYPE' => 
				[
				[TRUE, 'top', '+', '-', '+', TRUE, ],
				[FALSE, 'title separator', '|', '-', '|', TRUE, ],
				[TRUE, 'body separator', '| ', '|', ' |', TRUE, ], 
				[TRUE, 'bottom', '+', '-', '+', TRUE, ],
				] ,
		   'EDITABLE' => 1,
		   RESIZABLE => 1,
		   X_OFFSET => 0, Y_OFFSET => 0,
                 }, 'App::Asciio::stripes::editable_box2' ),
 
                ];

Add Rounded Box

But why stop there? How about we add in a nice ditaa rounded box. Add this code to the ditaa stencil file just below our modified box code:

          bless( {
                   'HEIGHT' => 3,
                   'TEXT' => '/---\\
|   |
\\---/',
                   'NAME' => 'roundedbox',
                   'WIDTH' => 5,
                   'TEXT_ONLY' => '',
                   'TITLE' => '',
                   'BOX_TYPE' =>
                                [
                                [TRUE, 'top', '/', '-', '\\', TRUE, ],
                                [FALSE, 'title separator', '|', '-', '|', TRUE, ],
                                [TRUE, 'body separator', '| ', '|', ' |', TRUE, ],
                                [TRUE, 'bottom', '\\', '-', '/', TRUE, ],
                                ] ,
                   'EDITABLE' => 1,
                   RESIZABLE => 1,
                   X_OFFSET => 0, Y_OFFSET => 0,
                 }, 'App::Asciio::stripes::editable_box2' ),

Add ditaa Arrows

The asciio arrows don't jive well with ditaa. You can add this in the ditaa stencil file, it is based on the whirl arrow:

bless({
        'NAME' => 'ditaa_arrow',
        'HEIGHT' => 6,
        'WIDTH' => 17,
        'POINTS' => [[16,5]],
        'SELECTED' => 0,
        'EDITABLE' => 1,
        'ALLOW_DIAGONAL_LINES' => 0,
        'POINTS_OFFSETS' => [[0,0]],
        'DIRECTION' => 'down-right' ,
        'ARROW_TYPE' =>
                [
                ['origin', '', '*', '', '', '', TRUE],
                ['up', '|', '|', '', '', '^', TRUE],
                ['down', '|', '|', '', '', 'v', TRUE],
                ['left', '-', '-', '', '', '<', TRUE],
                ['upleft', '|', '|', '\\', '-', '<', TRUE],
                ['leftup', '-', '-', '\\', '|', '^', TRUE],
                ['downleft', '|', '|', '/', '-', '<', TRUE],
                ['leftdown', '-', '-', '/', '|', 'v', TRUE],
                ['right', '-', '-','', '', '>', TRUE],
                ['upright', '|', '|', '/', '-', '>', TRUE],
                ['rightup', '-', '-', '/', '|', '^', TRUE],
                ['downright', '|', '|', '\\', '-', '>', TRUE],
                ['rightdown', '-', '-', '\\', '|', 'v', TRUE],
                ['45', '/', '/', '', '', '^', TRUE, ],
                ['135', '\\', '\\', '', '', 'v', TRUE, ],
                ['225', '/', '/', '', '', 'v', TRUE, ],
                ['315', '\\', '\\', '', '', '^', TRUE, ],
                ],
 
        'ARROWS' =>
                [
                bless(
                        {
                        'HEIGHT' => 6,
                        'STRIPES' =>
                                [
                                {'TEXT' => '|
|
|
|
|
\'',
 
                                'HEIGHT' => 6,
                                'Y_OFFSET' => 0,
                                'WIDTH' => 1,
                                'X_OFFSET' => 0}
                                ,
                                {
                                'TEXT' => '--------------->',
                                'HEIGHT' => 1,
                                'Y_OFFSET' => 5,
                                'WIDTH' => 16,
                                'X_OFFSET' => 1
                                }
                                ],
                        'WIDTH' => 17,
                        'END_X' => 16,
                        'ARROW_TYPE' =>
                                [
                                #name: $start, $body, $connection, $body_2, $end
 
                                ['origin', '', '*', '', '', '', TRUE],
                                ['up', '|', '|', '', '', '^', TRUE],
                                ['down', '|', '|', '', '', 'v', TRUE],
                                ['left', '-', '-', '', '', '<', TRUE],
                                ['upleft', '|', '|', '\\', '-', '<', TRUE],
                                ['leftup', '-', '-', '\\', '|', '^', TRUE],
                                ['downleft', '|', '|', '/', '-', '<', TRUE],
                                ['leftdown', '-', '-', '/', '|', 'v', TRUE],
                                ['right', '-', '-','', '', '>', TRUE],
                                ['upright', '|', '|', '/', '-', '>', TRUE],
                                ['rightup', '-', '-', '/', '|', '^', TRUE],
                                ['downright', '|', '|', '\\', '-', '>', TRUE],
                                ['rightdown', '-', '-', '\\', '|', 'v', TRUE],
                                ['45', '/', '/', '', '', '^', TRUE, ],
                                ['135', '\\', '\\', '', '', 'v', TRUE, ],
                                ['225', '/', '/', '', '', 'v', TRUE, ],
                                ['315', '\\', '\\', '', '', '^', TRUE, ],
                                ],
                        'END_Y' => 5,
                        'DIRECTION' => 'down-right'
                        }, 'App::Asciio::stripes::wirl_arrow' ),
 
                ],
        }, 'App::Asciio::stripes::section_wirl_arrow' ) ,

Add Colours and Special Shape Codes

All of the above will give you the core functionality of ditaa into asciio. But what about some basic colour tags, and shape codes. I've created a special stencil file for those. You can copy this below, and place it in a file called ditaatags next to the asciio stencil file.

my @ascii =
        (
        'shapes/document' => <<'EOA',
{d}
EOA
        'shapes/storage' => <<'EOA',
{s}
EOA
	'shapes/input_output' => <<'EOA',
{io}
EOA
        'shapes/tr' => <<'EOA',
{tr}
EOA
        'shapes/o' => <<'EOA',
{o}
EOA
        'shapes/mo' => <<'EOA',
{mo}
EOA
        'shapes/c' => <<'EOA',
{c}
EOA
        'colours/Red' => <<'EOA',
cRED
EOA
        'colours/Blue' => <<'EOA',
cBLU
EOA
        'colours/Pink' => <<'EOA',
cPNK
EOA
        'colours/Black' => <<'EOA',
cBLK
EOA
        'colours/Green' => <<'EOA',
cGRE
EOA
        'colours/Yellow' => <<'EOA',
cYEL
EOA
 
        ) ;
 
my @boxes ;
 
use App::Asciio::stripes::editable_box2 ;
 
for(my $ascii_index = 0 ; $ascii_index < $#ascii ; $ascii_index+= 2)
        {
        my $box = new App::Asciio::stripes::editable_box2
                                ({
                                TEXT_ONLY => $ascii[$ascii_index + 1],
                                EDITABLE => 1,
                                RESIZABLE => 1,
                                }) ;
 
        $box->set_box_type([map{$_->[0] = 0; $_} @{$box->get_box_type()}]) ;
        $box->shrink() ;
        $box->{'NAME'} = $ascii[$ascii_index] ;
        push @boxes, $box ;
        }
 
[@boxes] ;

Once these have been added, you need to modify the setup.ini file to point to the new stencils. To do that, run the following commands:

cd .. sudo vim setup.ini Where it says 'stencils/divers', add on the next line, 'stencils/ditaa', and then 'stencils/ditaatags',. Your new file should look like this:

{
STENCILS =>
        [
        'stencils/asciio',
        'stencils/computer',
        'stencils/people',
        'stencils/divers',
        'stencils/ditaa',
        'stencils/ditaatags',
        ],

ACTION_FILES =>
        [
        'actions/align.pl',
        'actions/clipboard.pl',
        'actions/debug.pl',
        'actions/new_elements.pl',
        'actions/elements_manipulation.pl',
        'actions/file.pl',
        'actions/mouse.pl',
        'actions/colors.pl',
        'actions/unsorted.pl',
        'actions/presentation.pl',

        'actions/context_menu_multi_wirl.pl',
        'actions/context_menu_box.pl',
        'actions/context_menu_rulers.pl',
        ],

HOOK_FILES =>
        [
        'hooks/canonize_connections.pl',
        ],

ASCIIO_OBJECT_SETUP =>
        [
        'asciio_object/basic.pl',
        ],

IMPORT_EXPORT =>
        [
        'import_export/ascii.pl',
        'import_export/perl.pl',
        'import_export/asciioe.pl',
        'import_export/png.pl',
        ],
}

Modifying Saving

It is nice to generate a text file of the data in case you need to make further tweaks before running it through ditaa. It is also required if you want to generate .pngs on the fly of your diagrams.

Go to App/Asciio/setup/actions and load up the file.pl file.

On line 65, replace the original saving code with the following:

		#$new_title = $self->save_with_type($elements_to_save, $type, $file_name) ;
		## Regardless of previous stuff, save one asciio file and one asciio.<ext>.txt ascii file
		## Courtesy of Strawp of http://strawp.net/archive/geeking-out-with-diagrams-in-ascii/
		$new_title = $self->save_with_type($elements_to_save, "asciio", $file_name) ;
		$new_title = $self->save_with_type($elements_to_save, "txt", $file_name.".txt") ;
 
		## Run ditaa to convert text version into nice copy
		## Use this if you have Proc::Background available.  Otherwise, use the system call below.
		#use Proc::Background;
		#my $proc1 = Proc::Background->new("c:\\bin\\ditaa.bat \"".$file_name.".txt\" \"".$file_name.".png\"");
		#my $proc1 = Proc::Background->new("java -jar /home/thomas/programs/ditaa/ditaa0_9.jar \"".$file_name.".txt\" \"".$file_name.".png\"");
		## This call converts while saving.  Slows down save time.  Replace the path below with your path to ditaa.jar
                ## You can add any special parameters here that you commonly use as well.
                ## Use this command if you unzipped the .jar file
		system("java -jar /home/thomas/programs/asciio-ditaa/ditaa0_9.jar \"".$file_name.".txt\" \"".$file_name.".png\"");
		## Use this command if you installed the .deb.
		#system("ditaa \"".$file_name.".txt\" \"".$file_name.".png\"");

Using the New Setup

Now that you have made all of your tweaks, you are ready to start using your asciio/ditaa combo! Start by making a simple diagram. Here is one below:

Notice when you save this file for the first time:

Several files are created at first. As well as our rendered image.

Now, lets spice it up with some colour and some shapes. Use the right click menu to add the document tag to each of the items labelled document. To do this you will need to:

Right click and select stencils → ditaatags → shapes → document Drag the {d} over the first document. I suggest you group any shapes, and shape modifiers by using CTRL+G once you set them up. If you do this, all of your pieces will move around if you have to tweak your image. Grouping involves selecting each item (hold shift while clicking each item), then press CTRL+G on your keyboard. This will cause this group of items to change background colour, and if you move one item, they will all move together. (You can ungroup by pressing CTRL+U) Add another {d} to the other document. If your item is falling behind the item you want, you can press CTRL+F to bring it to the foreground. Or CTRL+B to push the item on top into the background. Now lets add some colour. Right click, and add some colour tags to the documents. As you save, you will notice the .png updates automatically.

Here is your final work of art:

Troubleshooting

asciio Won't Load File I've noticed that if you modify the stock asciio shapes (either through the gui itself, or in the stencils file) often times if you launch asciio, and then try to load a file with altered shapes, it will fail to load. It generates this output in the terminal:

thomas@thomas-desktop:~/programs/asciio-ditaa$ asciio Using setup directory:'/usr/share/perl5/App/Asciio/setup/' running action 'Open'. load_file: can't load file '/home/thomas/programs/asciio-ditaa/saves/test': Unrecognized character \x8E in column 23827 at (eval 105) line 372. You can still get asciio to open, you just need to launch it with the file you want to load. So either launch it by typing something like:

thomas@thomas-desktop:~/programs/asciio-ditaa$ asciio /home/thomas/programs/asciio-ditaa/saves/test Using setup directory:'/usr/share/perl5/App/Asciio/setup/' running action 'Open'. Or launch from your file manager. In my case, Nautilus:

asciio Forgets Where I Saved

When loading asciio for the first time, and saving, I find that asciio forgets where I saved the document. It always returns to the original launching location.

To avoid this, I'd recommend that after your first save, you reopen asciio by using one of the two procedures mentioned above. This will allow it to remember where you are working, and the Save function will work correctly.

Editing elements text and attributes

Asciio has two editing mode, Dialog and Inline, the default mode is Dialog.

Dialog editing

Binding: Return, double-click

Asciio opens a dialog which lets you set:

  • boxing options
  • title
  • text

edit in dialog

Inline editing

Binding: Return, double-click

In this mode you can only edit the text.

edit inline

Alternate editing

You can edit in the other mode with these bindings:

  • ctl + Return
  • ctl + double-click

Changing mode

To change the mode during the session use:

Binding: «zi»

Setting the editing mode in the user configuration

EDIT_TEXT_INLINE => 0,
  • EDIT_TEXT_INLINE => 0 Indicates that the default editing mode is Dialog editing
  • EDIT_TEXT_INLINE => 1 Indicates that the default editing mode is Inline editing

Markup mode

We can use color in asciio, But if exported, the color information will be lost. The markup mode adds marks in the chart, and these marks can be retained when exporting, so that special effects can be displayed in some specific software.

1 Use markup mode

To use marks in the chart, turn on this option in the configuration.The markup enable variable is the basic attribute of the chart and cannot be changed at runtime.

USE_MARKUP_MODE => 'zimwiki',

If you do not need to use any markup mode, please keep this variable empty.

USE_MARKUP_MODE => '',

Currently, only zimwiki format markup is supported, then markdown format or pure html format may be supported in the future.

2 zimwiki format description

2.1 Edit marks

zimwiki markup mode currently supports text editing of box type elements.Just place the text in the middle of the marks.

Currently supports 5 types of markers:

  • bold
    • <b>something</b>
  • underline
    • <u>something</u>
  • double underline
    • <span link="https://github.com/nkh/P5-App-Asciio">link name</span>
  • strikethrough
    • <s>something</s>
  • italics
    • <i>something</i>

This is what it looks like in Asciio:

markup_effect

This is the effect in inline editing mode:

markup_mode_modify

Marks can only be valid for a single line, not multi lines.

Marks support nesting:

markup_nesting

Although this function is supported, it is not recommended to use it in this way, and it does not make much sense

2.2 Export

Normally, when exporting to ascii, you will get the following text

Binding: «ctl-e» «shift-Y» «Y»

                          .----------.  .---------------.  .-----------. .---------------.
                          | italics  |  | strikethrough |  | underline | | asciio github |
                          '----------'  '---------------'  '-----------' '---------------'

Currently, an export format is also supported, and the mark up character is added, which can be recognized by zim.

Binding: «ctl-shift-E»

                          .----------.  .---------------.  .-----------.
                          | //italics//  |  | ~~strikethrough~~ |  | __underline__ |
                          '----------'  '---------------'  '-----------'

In the zim environment, they will be rendered like this:

markup_mode_zim

Working efficiently

You can do a lot of thing with just the mouse and the popup menus but that would be a mistake, keyboard bindings are much faster and more efficient, including moving elements around.

The mouse shines when quick-linking elements, they allow you to create a base diagram fast but editing and fine tuning goes faster with the keyboard or keyboard + mouse.

Learn the keyboard bindings, they are a very good way to use Asciio.

Keyboard

Asciio has many bindings which let you work effectively, a list of all the bindings can be found in the Bindings section.

Example
actionbinding
insert a boxib
resize it2, 4
move ithjkl/Arrows
insert a new boxib
insert an arrowia
connect other boxAlt+A, hjkl/Arrows
escape arrow end modeEscape
select both boxesV
align themA, t

only keyboard

Mouse

Binding: «alt-left-mouse-click»

  • create a box is nothing is selected
  • if only a box is selected, create a new box and connect to it
  • if a box is selected and mouse over a box, connect them
  • if multiple boxes are selected, create a box and connect to all boxes

quick link

Quick copy

Binding: «alt-shift-left-mouse-click»

Copy the current selection and move it to another position, see cloning

quick copy

Quick arrow

Binding: «ctl-alt-mouse-motion»

If an arrow is selected, move its end point with the mouse.

quick arrow

Quick section

Binding: «ctl-alt-left-mouse-click»

  • If a wirl arrow is selected, add section.
  • if another element is selected, add new arror

You can then move the its end point with the mouse. releasing «ctl» lets you move the mouse to another position for a new section.

quick section

Quick box and section

You can quickly create boxes and section by combining quick link and quick section.

  • «alt-left-mouse-click», create a box
  • «ctl-alt-left-mouse-click», link the box to a new arrow
  • move mouse
  • «ctl-alt-left-mouse-click», add a section
  • move mouse
  • «ctl-alt-left-mouse-click», add a section
  • move mouse
  • «alt-left-mouse-click», connect last section to new box

quick box and section

Cloning

You can activate the cloning feature to quickly add elements.

Binding: c

Cloning Base Elements

When you initiate cloning without any elements selected, Asciio allows you to clone one of the base elements.

ElementBinding
Boxb
Textt
Wirl Arrowa
Angled ArrowA

Clone Base Elements

Cloning the Selection

You can also clone a set of elements that have been selected. The bindings for the base elements are still applicable.

Clone Selection

Hint Lines

If hint lines are enabled, additional lines are displayed to indicate the limits of the elements being cloned. You can toggle the hint lines on and off.

Binding: h

Clone Hint Lines

Stencils and "Drag And Drop"

Stencils

You can access Stencils via "Drag and Drop".

Asciio has bindings to open stencils in a separate instance

Start Binding: is

Then uses one of the following keys:

bindingsaction
sselect from user stencils in $HOME/.config/Asciio/stencils/
dopen stencil 'default_stencil.asciio' from current directory
aselect stencil from your computer
0open 'elements.asciio' from $HOME/.config/Asciio/stencils/
1open 'computer.asciio' from $HOME/.config/Asciio/stencils/
2open 'people.asciio' from $HOME/.config/Asciio/stencils/
3open 'buildings.asciio' from $HOME/.config/Asciio/stencils/

user stencils

User stencils are plain Asciio files.

The distribution contains a few asciio stencils in "setup/Stencils/*.asciio", copy the ones you want to your $HOME/.config/Asciio/stencils.

You can create a new stencil directly from the file picker, just type the name of the new stencil and open it.

Drag and Drop

Binding: control + left click + drag

TypeFromTo
Asciio elementsAsciioAsciio
Asciio elementsAsciiotext applications
Texttext applicationsAsciio
URLsURL aplicationsAsciio

Drag And Drop

Strip groups

Export/Save

Asciio format

Exporting to ASCII

You can export to a file in ASCII by using a '.txt' file extension.

You can also export the selection, in ASCII, to the Primary clipboard.

SVG

Asciio doesn't export directly to SVG but uses a text to SVG application like Goat or SvgBob.

Goat svgbob

Create a diagram in Asciio

SVG source

Export it to SVG

SVG

Further process the SVG

I used fskpf web site to generate a pseudo hand-drawn graph out of it

hand drawn

The svg2roughj sproject is here

svg2roughjs

Clipboard

Modes

git


                     .*-----*------------------------------*
                    /                                       \
                   /                                         \
           *------*---------*-----BETA---.                    \
                   \                      \                    \
                    \    .-----.           '                    \
 .-------------.     *---| fix |---*-----RELEASE 1.3------>*-----*---------*
 | Release 2.0 |         '-----'    \                     /               /
 |-------------|                     \                   /               /
 | changes     |------------------->  '---*-------*--------------*------*
 | tag: ...    |                           \           /
 | eta: ...    |                            \         /
 '-------------'                             *-------'

The git mode allows you to draw git graph quickly.

The git mode redefines some bindings to allow you to work faster. Only the bindings listed below are available when editing.

actionbinding
Exit git mode«Escape»
Undo«u»
Insert and link node«g» «right-click»
Change arrow direction«d»
Add box«b»
Add text«t»
Add arrow«a»
Select objects«left-click»
Edit Selected element«Return» «double-click»
Delete elements«Delete» «x»
Flip hint lines«h»
Display popup menu«alt+right-click»

When you insert and link a node:

  • if nothing is under the pointer or selected, it will insert a commit node
  • if a node is selected and nothing under the pointer, it will insert a new node and connect with the previously selected node
  • if a node is selected and the pointer is over a node, it will link the nodes

Let's create a git graph.

git graph

You can export the text and use it in our documentation

                 .----------------------------------.
                 |          feature branch          |
                 |                                  |
                 |       *-------------------*      |
                 |      /                     \     |
                 |     /                       \    |
                 '----/-------------------------\---'
                     /                           \
          *---------*---------*---------*---------*---------*
                    ^                             ^
                    |                             |
                    |                             |
                    |                             |
             we need a new              we want to merge here
             feature branch

or you can generate some fancy SVGs for a presentation.

git graph

git graph

The connector and arrow type of the git mode can be changed.

In the user configuration for the connector,

GIT_MODE_CONNECTOR_CHAR_LIST => ['*', 'o', '+', 'x', 'X', '┼', '╋', '╬'],

or in the popup menu for both.

git_popup menu

Cross Mode

1 Introduction

In normal mode, elements boundaries are independent of each.

normal_elements

In cross mode intersections are merged:

cross_elements

2 Complex graphics

The cross-mode lets you create graphics like this table


        ╔═══════╤══════════════════════════════════════════════════════════════╗
        ║       │   test scores                                                ║
        ║       ├──────┬───────┬───────┬────────┬───────┬──────┬────────┬──────╢
        ║  Name │  Math│Physics│       │        │       │      │        │      ║
        ╟───────┼──────┼───────┼───────┼────────┼───────┼──────┼────────┼──────╢
        ║ Jim   │  A+  │  B    │       │        │       │      │        │      ║
        ╟───────┼──────┼───────┼───────┼────────┼───────┼──────┼────────┼──────╢
        ║Stephen│  B   │  A    │       │        │       │      │        │      ║
        ╟───────┼──────┼───────┼───────┼────────┼───────┼──────┼────────┼──────╢
        ║ Kate  │  A   │  C    │       │        │       │      │        │      ║
        ╚═══════╧══════╧═══════╧═══════╧════════╧═══════╧══════╧════════╧══════╝

3 Enabling cross-mode

3.1 Globally

Add this line in your user configuration.

USE_CROSS_MODE => 1,

3.2 Dynamically

Binding: «z-x» 'Switch cross mode'

4 Line and Box

cross_lines

cross_boxs

5 Lines and boxes

cross_box_line

6 Exported to text

        .--------.      ╭────────╮    ┏━━━━━━━━┓    ╔════════╗
        |        |      │        │    ┃        ┃    ║        ║
        |        |      │        │    ┃  ┏━━━━━┻━━┓ ║        ║
        |        |      │        │    ┃  ┃        ┃ ║        ║
        '--------'      ╰────────╯    ┗━━┫        ┃ ╚════════╝
                                         ┃        ┃
                                         ┗━━━━━━━━┛

                |               │            ┃           ║
                |               │            ┃           ║
                |               │            ┃           ║
                |               │       ━━━━━╋━━━━━━     ║
                |               │            ┃           ║
                |               │            ┃           ║
                |               │            ┃           ║
                |               │            ┃           ║
                |               │            ┃           ║





                .--------.
                |        |          ╭─┬────────┬─────╮
                |  .-----'--.       │ │        │     │
                |  |        |       │ │        │     │
                '--.        |       │ │        │     │    ╔══════════════╗
                   |        |       │ ╰────────╯     │    ║              ║
                   '--------'       │                │    ║              ║
                                    │                │    ║              ║
                                    │        ╔═══════╧╗   ║              ║
                                    │        ║        ║   ║              ║
                                    ╰────────╢        ║   ║              ║
                                             ║        ║   ║              ║
                                             ╚════════╝   ╚══════════════╝

slides

You can create a slide show with Asciio ... but it's a work in progress. We write some documentation here but you're better off asking the developers directly.

Bindings

bindingaction
Senter slides mode
Escapeescape slides mode
LLoad slides
nnext slide
Nprevious slide
gfirst slide
srun script
n/ashow previous message
n/ashow next message

Slides Format

Slides are a very simplified script.

use strict ;
use warnings ;

use App::Asciio::Utils::Presentation ;

# the slides definition
[
	# first slide
	[ 
		# text is added to a box at 0, 0
		"0 intro", 
	
		# you can add scritpt with shortcuts per slide
		{
		a => sub
			{
			my ($self) = @_ ;
			App::Asciio::Actions::Elements::add_element($self, ['Asciio/box', 0, 20, 20]) ;
			},
		},
	],
	
	# second slide
	[ 
		# if you have multiple elements in squre bracket, Asciio uses them as steps in your slide
		[ "1.0", ],
		[ "1.1", ],
		
		# a step within a step, thereäs no limit but navigation becomes more intricate
		[ 
			["1.2.0", ]
		],
	],
	
	# third slide
	[
	clear_and_box_at(0, 0, "2"), ], 
	],
	
	# fourth slide
	[ 
		# you can load an asciio file
		load(0, 0, 'path/file.asciio'),
		
		# and add elements to the slide
		box(10, 20, 'title', '3', 0),
	],
	
	# final slide
	[
	clear_all(),
	
	# multiline box
	box(19, 11, '', <<'EOT', 0), 
6.0
(\_/)
(O.o) ASCII world domination is near!
(> <) 
EOT
	],
]

Utilities are defined in lib/App/Asciio/Utils/Presentation.pm

Examples

Unix structure

              .---.  .---. .---.  .---.    .---.  .---.
     OS API   '---'  '---' '---'  '---'    '---'  '---'
                |      |     |      |        |      |
                v      v     |      v        |      v
              .------------. | .-----------. |  .-----.
              | Filesystem | | | Scheduler | |  | MMU |
              '------------' | '-----------' |  '-----'
                     |       |      |        |
                     v       |      |        v
                  .----.     |      |    .---------.
                  | IO |<----'      |    | Network |
                  '----'            |    '---------'
                     |              |         |
                     v              v         v
              .---------------------------------------.
              |                  HAL                  |
              '---------------------------------------'


Documenting hardware instrumentation

      _____ 
     | ___ |
     ||___|| load
     | ooo |--.------------------.------------------------.
     '_____'  |                  |                        |
              v                  v                        v
      .----------.  .--------------------------.  .----------------.
      | module C |  |         module A         |  |    module B    |
      '----------'  |--------------------------|  | (instrumented) |
           |        |        .-----.           |  '----------------'
           '---------------->| A.o |           |          |
                    |        '-----'           |          |
                    |   .------------------.   |          |
                    |   | A.instrumented.o |<-------------'
                    |   '------------------'   |
                    '--------------------------'

Decorating Forth code

       index? dup dup dup dup dup average @ + average ! ." data = " .
    .--------------.
    |  Data Stack  |
    |--------------|
    | next element |-----> average @ + average !
    | dup          |-----> ." data = " .
    | dup          |-----> minv @ < if--.
    | dup          |                    '------> minv ! ." (new minv) " or DROP after ELSE
    | dup          |-----> maxv @ > if---.
    | dup          |                     '---->  maxv ! ." (new maxv) " or DROP after ELSE
    '--------------'
       minv @ < if
       minv ! ." (new minv) "
       else    drop                                                                        \ data > minv so it's ignored
           maxv @ > if
           maxv ! ." (new maxv) "
           else drop                                                                       \ data < maxv so it's ignored
           then
       then
       counter @ 1 - counter !                                                             \ Decrement counter

example 1

describing a class hierarchy


                                 .-Base::Class::Derived_B
                                /
     Something::Else           /
             \                .----Base::Class::Derived_C 
              \              /
               '----Base::Class
                     '       \
                    /         '----Latest::Greatest
      Some::Thing--'                                           

German railroad

Graph-Easy is an application that generates graphs in ASCII, a bit like GraphViz.

Graph-Easy

               ..................................
               :                                v
+------+     +--------+     .............     +---------+     +---------+
| Bonn | --> | Berlin | --> :           : --> | Potsdam | ==> | Cottbus |
+------+     +--------+     :           :     +---------+     +---------+
               ^            :           :                       ^
               |            : Frankfurt :                       |
               |            :           :                       |
             +--------+     :           :     +---------+       |
             |   x    | --> :           : <-- |    y    | ------+
             +--------+     :...........:     +---------+
                              |
                              |
                              v
                            +-----------+
                            |  Dresden  |
                            +-----------+

I re-drew the example above in Asciio.


                 .------------------------------.
                 |                              |
                 |                              v
.------.    .--------.    .-----------.    .---------.  .---------.
| Bonn |-.->| Berlin |-.->| Frankfurt |-.->| Potsdam |->| Cottbus |
'------' |  '--------' |  '-----------' |  '---------'  '---------'
         |             |                |                    ^
       .---.           |                |  .---------.       |
       | x |-----------'                '->| Dresden |       |
       '---'           |                   '---------'       |
       .---.           |                                     |
       | y |-----------'-------------------------------------'
       '---'

There are few interesting things to notice:

  • Graph-Easy smartly changes the size of the boxes to accommodate more connections
  • Asciio doesn't have a routing functionality for graph, it would be a nice addition
  • Asciio has 4 connectors per box (but you can get around it)

Unicode Example

Asciio does't generate SVG but, in the spirit of unix tools, rely on another tool to convert text files to SVG.

The "goat" project (https://github.com/blampe/goat) has been chosen to make the conversion, it must be installed, but you can use any converter you want; I recommend having a look athe ecexelent SVGBob too.

See the "Exporter" section to learn how to write your own.

Unicode

videos

  • presentation

  • efficient session

  • grouping

  • working with external commands

    • input to asciio

    • using Asciio's output

  • doing a presentation with Asciio

  • writing requirements with Asciio and markdown

Some older videos (15 years!) that show some basic usage:

old video

asciio 1.0

Bindings

Both GUI and TUI have vim-like bindings, the GUI has a few extra bindings that are usually found in GUI applications; bindings can be modified.

It's faster and easier to work with keyboard shortcuts than the mouse and the number of combination of mouse buttons * control-keys is very limited.

Asciio bindings are vim-like, they initially take more time to get used to, and often take multiple key presses but they are much more logical as families of commands are accessed with shortcuts that start with the same letter.

The bindings can be changed in your user configuration, See configuration/user_bindings

Bindings help

Binding: zb

bindings_help

You can get a pop up showing the bindings (? in the top level) Or you can configure it:

USE_BINDINGS_COMPLETION => 1,

Bindings map

bindings change truth is in the config not this snapshot

bindings

Mouse

actionbinding
Edit selected element000-2button-press-1
Edit selected element inlineC00-2button-press-1
Mouse right-click000-button-press-3,
Mouse left-click000-button-press-1,
Mouse expand selection00S-button-press-1,
Mouse selection flipC00-button-press-1,
Mouse quick link0A0-button-press-1
Mouse duplicate elements0AS-button-press-1
Mouse quick boxC0S-button-press-1
Arrow to mouseCA0-motion_notify,
Arrow mouse change directionCA0-2button-press-1
Arrow change directionCA0-d,
Wirl arrow add sectionCA0-button-press-1,
Wirl arrow insert flex pointCA0-button-press-2,
Mouse motion000-motion_notify,
Mouse motion 20AS-motion_notify,
Mouse drag canvasC00-motion_notify,
Zoom inC00-scroll-up,
Zoom outC00-scroll-down,

Mouse emulation

actionbinding
Toggle mouse«'»
Mouse shift-left-click«Ö»
Mouse left-click«ö»
Mouse right-click«ä»
Mouse drag left 3«H»
Mouse drag down 3«J»
Mouse drag up 3«K»
Mouse drag right 3«L»
Mouse drag down«Down»
Mouse drag left«Left»
Mouse drag right«Right»
Mouse drag up«Up»
Mouse drag down«A-Down»
Mouse drag left«A-Left»
Mouse drag right«A-Right»
Mouse drag up«A-Up»
Mouse alt-left-click«ö»
Mouse ctl-left-click«ö»

Why vim-like bindings

Combinations

To simplify, let's start with having 26 letters accessible on the keyboard, no uppercase.

  • using ctl + alt + key gives us around 100 combinations
  • letter + leter gives use around 650 combinations
  • letter + letter + letter gives use around 18 000 combinations

If we had uppercase, ie, 52 letters

  • using ctl + alt + key gives us around 200 combinations
  • letter + letter + letter gives use around 140 000 combinations

Speed

typing ctl + alt + key is not faster than key + key + key, and even less key + key

Structure and mnemonics

Of course we don't need tens of thousands of combinations

But do you know what CA0-a does? C0S-A? 0AS-a? CAS-A? C00-A? 0A0-a? 00S-a? ... without looking at the docs?

The whole point vim-like binding is to remember them, it's not a perfect system but it's expandable and easier to remember

Let me give you and example, we have multiple types of boxes, let's say

  • normal
  • unicode
  • shrink
  • with hash tag as a border

Let' start with a generic binder «i» for insert and «b» for box

  • «ibb» normal, we cound have used «ibn» too but the most used keys are usually double for speed
  • «ibu» unicode
  • «ibs» shrink
  • «ibh» with hash tag as a border

The good thing here is that we can use the same thing for arrows but with «ia» as a prefix.

But let's imagine that you come up with 4 new types of unicode borders (well you have), I don't want to imagine how to do that with the mouse, and with ctl + .... we've run out of shortcuts that are easy to remember. on the other hand ...

  • «ibb» normal, we cound have used «ibn» too but the most used keys are usually double for speed
  • «ibuu» unicode
  • «ibu1» unicode
  • «ibu2» unicode
  • «ibu3» unicode
  • «ibs» shrink
  • «ibh» with hash tag as a border

I used 1, 2, and 3 because I was lacking imagination but

  • double
  • thick
  • whatnot

would have given us keys to remember.

Quizz

Do you remember (although you've just seen it) ...

  • insert a box
  • insert a box using unicode type 2
  • insert a box that shrinks
  • inserta box with the default unicode

single key bindings

 «Enter»            Edit selected element

 «d»                Delete selected element(s)

 «u»                Undo

 «C»-r              Redo

 «.»                Quick link

 «,»                Quick copy

 «R»                Remove rulers

GUI bindings

keyboard

 «C00-a»            Select all elements

 «C00-c»            Copy to clipboard

 «C00-e»            Export to clipboard & primary as ascii

 «C00-v»            Insert from clipboard

 «C0S-V»            Import from primary to box

 «C00-z»            Undo

 «C00-y»            Redo

 «+»                Zoom in

 «-»                Zoom out

mouse

 «double-click»     Edit selected element

 «C00-button-1»     Add to selection

 «0A0-button-1»     Quick link

 «0AS-button-1»     Duplicate elements

 «CA0-button-1»     Insert flex point (in arrow)

Moving elements

     «h»                Move selected elements left

     «j»                Move selected elements down

     «k»                Move selected elements up

     «l»                Move selected elements right


     «Left»             Move selected elements left

     «Down»             Move selected elements down

     «Up»               Move selected elements up

     «Right»            Move selected elements right

Selecting elements

     «n»                Select next element

     «N»                Select previous element

     «Tab»              Select next element move mouse

     «V»                Select all elements

     «v»                Select connected elements

     «Escape»           Deselect all elements

Resizing elements

Bindings:

  • «1» Make element narrower

  • «2» Make element taller

  • «3» Make element shorter

  • «4» Make element wider

resize

  • «s» Shrink box

shrink

There an auto-shrink attribute so you don't have to shrink boxes manually each time you change their size.

auto shrink

There's also a box you can add which already has auto-shrink set; you can insert it with a shortcut or via the popup menu.

Binding: «iB» Add auto-shrink box:

auto shrink_box

Clipboard

     «y»                Copy to clipboard

     «p»                Insert from clipboard

     «Y»                Export to clipboard & primary as ascii

     «P»                Import from primary to box

     «A-P»              Import from primary to text

multiple key bindings

«:» command group:

 «:» command group:

     «q»                Quit

     «Q»                Quit no save

     «w»                Save

     «W»                SaveAs

     «e»                Open

     «r»                Insert

     «m»                Display manpage

     «h»                Help

     «c»                Display commands

     «f»                Display action files

     «k»                Display keyboard mapping

«i» Insert group

 «i» Insert group:

     «A»                Add angled arrow

     «a»                Add arrow

     «A-a»              Add unicode arrow

     «B»                Add shrink box

     «b»                Add box

     «A-b»              Add unicode box

     «c»                Add connector

     «E»                Add exec-box no border

     «e»                Add exec-box

     «f»                Insert from file

     «g»                Add group object type 1

     «h»                Add help box

     «i»                Add if-box

     «R»                Add horizontal ruler

     «x»                External command output in a box

     «X»                External command output in a box no frame

     «p»                Add process

     «r»                Add vertical ruler

     «t»                Add text

«a» arrow group

 «a» arrow group:

     «S»                Insert multi-wirl section

     «f»                Flip arrow start and end

     «d»                Change arrow direction

     «s»                Append multi-wirl sectioni

     «A-s»              Remove last section from multi-wirl

«A» align group

 «A» align group:


 «t»                Align top

     «l»                Align left

 «b»                Align bottom

     «r»                Align right

 «h»                Align horizontally

 «v»                Align vertically

«g» grouping group

 «g» grouping group:

     «g»                Group selected elements

     «u»                Ungroup selected elements

     «F»                Temporary move selected element to the front

     «f»                Move selected elements to the front

     «b»                Move selected elements to the back

«A-g» stripes-group group

 «A-g» stripes-group group:

     «1»                Create one stripe group

     «g»                Create stripes group

     «u»                Ungroup stripes group

«z» display group

 «z» display group:

     «C»                Change grid color

     «c»                Change Asciio background color

     «g»                Flip grid display

     «s»                Flip color scheme

     «t»                Flip transparent element background

«S» slides group

 «S» slides group:

     «N»                Previous slide

     «g»                First slide

     «l»                Load slides

     «n»                Next slide

«D» Debug group

 «D» debug group:

     «E»                Dump selected elements

     «e»                Dump all elements

     «S»                Display undo stack statistics

     «o»                Test

     «s»                Dump self

     «t»                Display numbered objects

Configuration

Your user configuration is '$HOME/.config/Asciio/Asciio.ini'

Your configuration file has this format:

{
STENCILS =>
	[
	#'stencils/asciio',
	],
	
ACTION_FILES =>
	[
	#'actions/xxx.pl',
	],
	
HOOK_FILES =>
	[
	],

ASCIIO_OBJECT_SETUP =>
	[
	#$ASCIIO_UI eq 'TUI' ? 'asciio_object/tui.pl' : 'asciio_object/gui.pl' ,
	],
	
IMPORT_EXPORT =>
	[
	#'import_export/ascii.pl',
	],
}

user bindings

The bindings can be changed in your user configuration. File '$HOME/.config/Asciio/Asciio.ini' points at the

Here's and example of binding:

'Change elements foreground color' => ['000-c',  \&App::Asciio::Actions::Colors::change_elements_colors, 0 ],

Bindings are composed of:

  • a command name
  • a set of keyboard shortcuts

To change a binding:

  • Find the command name for the binding you want to change
  • decide a new keyboard shortcuts
  • add your binding to your configuration file

Your configuration file has this format:

{
...
ACTION_FILES =>
	[
	'actions/colors.pl', # new configuration file where you want to put your color bindings
	],
...
}

Create '$HOME/.config/Asciio/actions/colors.pl' and add:

register_action_handlers
	(
	'Change elements foreground color' => ['000-Z'],
	) ;

Binding format

A binding contains:

  • unique name for your binding
  • shortcut, multiple shortcuts are passed as ['shortcut_1', 'shortcut_2', ...]
  • action sub reference
  • arguments to the action sub reference, optional
  • popup-menu sub reference, optional

Example:


'Edit selected element inline'  => 
    [
    ['C00-2button-press-1','C00-Return'],
    \&App::Asciio::Actions::ElementsManipulation::edit_selected_element,
    1
    ],

Group bindings

Bindings can be grouped so you can use multiple key presses (vim-like) to reach an action.


'group name' =>
	{
	SHORTCUTS => 'C00-x',
	
	'sub group name' => 
		{
		SHORTCUTS => 'C00-x',
		
		'binding in sub group' => ['C00-x', sub { print "you're in x/x/x\n" ; } ],  
		} ,
	
	'binding 1' => ['000-1', sub { print "you're in x/1\n" ; } ],  
	'binding 2' => ['000-2', sub { print "you're in x/2\n" ; } ],  
	},

Capturing groups

If a group has an ESCAPE_KEY, the group is a capturing group. The group's bindings will be used repeatedly till the ESCAPE_KEY is pressed.


'capture group' =>
	{
	SHORTCUTS => '0A0-c',
	ESCAPE_KEY => '000-Escape',
	
	'capture x'     => [ '000-x', sub { print "captured x\n"; } ],
	'capture y'     => [ '000-y', sub { print "captured y\n"; } ],
	},

Binding override

You can re-bind an existing shortcut to another command, Asciio will generate a warning in the console.

Overriding shortcut 'C00-y'
        new is 'Redo 2' defined in file '.../actions/override_bindings.pl'
        old was 'Redo' defined in file 'actions/default_bindings.pl'

warning Don't use the same shortcut multiple times in the same file, the order of registration in the same file not guaranteed.

Capturing groups with overlay

capture with overlay

Define overlays

my $click_choice_element = ['Asciio/box', 0] ;
my $box_overlay =
	[
	[0, 0, '.'],
	[1, 0, '-'],
	[2, 0, '-'],
	[3, 0, '-'],
	[4, 0, '.'],
	
	[0, 1, '|'],
	[4, 1, '|'],
	
	[0, 2, "'"],
	[1, 2, '-'],
	[2, 2, '-'],
	[3, 2, '-'],
	[4, 2, "'"],
	] ;

my $text_overlay =
	[
	[0, 0, 'T.'],
	[1, 0, 'e'],
	[2, 0, 'x'],
	[3, 0, 't'],
	] ;

my $arrow_overlay =
	[
	[2, -2, '.'],
	[3, -2, '-'],
	[1, -1, '/'],
	[0, 0,  "'"],
	] ;

Declare callbacks

my $click_element_overlay = $box_overlay ;

sub click_choice_add_element { App::Asciio::Actions::Elements::add_element($_[0], $click_choice_element) ; }

sub click_element_choice
{
my ($asciio, $args) = @_ ;
($click_element_overlay, $click_choice_element) = $args->@* ;
$asciio->update_display ;
}

sub click_element_enter { print "enter!!\n" ; my ($asciio) = @_ ; $asciio->set_overlays_sub(\&click_element_overlay) ; $asciio->update_display ; }
sub click_element_escape { my ($asciio) = @_ ; $asciio->set_overlays_sub(undef) ; $asciio->update_display ; }

sub click_element_mouse_motion 
{
my ($asciio, $event) = @_ ;

App::Asciio::Actions::Mouse::mouse_motion($asciio, $event) ;
$asciio->update_display() ; 
}

sub click_element_overlay
{
my ($asciio) = @_ ;
my @overlays = map { [ $asciio->{MOUSE_X} + $_->[0], $asciio->{MOUSE_Y} + $_->[1], $_->[2] ] } @$click_element_overlay ;

@overlays
}

Declare bindings


register_action_handlers
(
'insert on click' =>
	{
	SHORTCUTS => '0A0-i',
	ENTER_GROUP => \&click_element_enter,
	ESCAPE_KEY => '000-Escape',
	
	'click element escape'  => [ '000-Escape',          \&click_element_escape                                               ],
	'click element motion'  => [ '000-motion_notify',   \&click_element_mouse_motion                                         ], 
	
	'click element insert'  => [ '000-button-press-1',  \&click_choice_add_element                                           ],
	'click element arrow'   => [ '000-a',               \&click_element_choice, [$arrow_overlay, ['Asciio/angled_arrow', 0]] ],
	'click element box'     => [ '000-b',               \&click_element_choice, [$box_overlay,   ['Asciio/box', 0]]          ],
	'click element text'    => [ '000-t',               \&click_element_choice, [$text_overlay,  ['Asciio/text', 0]]         ],
	
	},
) ;

For Developers

Scripting

# Generated by documentation/scripting/multi_wirl.pl

.------.
| box1 |<-----------------------------------.
'------'                                    |
    |                                   .------.
    |                                   | box3 |
    |                                   '------'
    |                                       ^
    |                                       |
    |               .------.                |
    '-------------->| box2 |----------------'
                    '------'


     __________
     \         \
      \  line 1 \
       ) line 2  )
      /  line 3 /
     /_________/

Executing your scripts

Executing your scripts

transform JSON, via Data::TreeDumper, to Asciio script

The *json_dtd_to_asciio_script' script is installed with Asciio. It will read a JSON stream from stdin.

It takes the following arguments:

  • title
  • x position
  • y position
  • 'box', if you want the data to be boxed
  • start_level, 0/1: 0 meanss no start tree grlyph
<coordinates_json ./script/json_dtd_to_asciio_script '' 10 10 box 0 | stdin_to_asciio 

Simplified scripting interface

The simplified scripting interface is an API which hides some of the scripting details for you.

Examples of scripts, using both the simplified API and full API, can be found in the documentation/scripting directory of the distribution.

Simplified scripting API

Create a new Perl script

Crate a file and add these lines

use strict; use warnings;

use App::Asciio::Scripting ;

This will set some sanity checks on your code and load the simplified scripting interface.

Adding boxes


add 'box1', new_box(TEXT_ONLY =>'box1'),  0,  2 ;
add 'box2', new_box(TEXT_ONLY =>'box2'), 20, 10 ;
add 'box3', new_box(TEXT_ONLY =>'box3'), 40,  5 ;

The simplified scripting interface lets you name your object so you can later connect them together.

Adding connections

connect_elements 'box1', 'box2', 'down' ;
connect_elements 'box2', 'box3' ;
connect_elements 'box3', 'box1', 'up' ;

You can hint Asciio about the direction of your arrows.

Canonizing connections

Asciio tries to route the arrows properly, this is done automatically in the UIs but you need to do it manually in scripts.


optimize ;

Printing and saving the result

save_to "from_script.asciio" ;

ascii_out ;

You can save your work to an asciio file or print it out

Adding multi-wirl arrows

You can write more advanced script where you route multi sections arrows around your elements.

     |
     |
     |
     |
     |
     '----.
          |
          '----.
               |
               |
               |
               |
               |
               |
            <--'

You'll also need to use the right module; in fact you have access to everything that's in Asciio from your scrips, it's just a little bit more work than using the simplified interface.

# documentation/scripting/multi_wirl.pl

use strict; use warnings;

use App::Asciio::Scripting ;

#-----------------------------------------------------------------------------

add 'multi_wirl', new_wirl_arrow([5, 5, 'downright'], [10, 7, 'downright'], [7, 14, 'downleft']), 5, 5 ;

ascii_out ;

Full example

You can find more examples in the documentation/scripting/ library of the project.

#  documentation/scripting/multi_wirl.pl

use strict; use warnings;

use App::Asciio::Scripting ;

#-----------------------------------------------------------------------------

add 'text1', new_text(TEXT_ONLY =>'text'),  22,  20 ;

add 'box1', new_box(TEXT_ONLY =>'box1'),  0,  2 ;
add 'box2', new_box(TEXT_ONLY =>'box2'), 20, 10 ;
add 'box3', new_box(TEXT_ONLY =>'box3'), 40,  5 ;

connect_elements 'box1', 'box2', 'down' ;
connect_elements 'box2', 'box3' ;
connect_elements 'box3', 'box1', 'up' ;
connect_elements 'box2', 'text1' ;

my $process = add_type 'process', 'Asciio/Boxes/process', 5, 15 ;
$process->set_text("line 1\nline 2\nline 3") ;

optimize ;

save_to "from_script.asciio" ;

ascii_out ;

Executing your script

From the command line

The script is a normal perl script.

perl my_asciio_script.pl

From within Asciio

Binding: «:!»

Pick the file you want to execute.

Or pass it on the command line

asciio -s full_path_to_script

Via Asciio's Web server

You can POST scripts via HTTP.

Asciio runs a web server at port 4444; you can change the port with --port other_port.

script commands

POST http://localhost:4444/script script="add '1', new_box, 0, 0 ;"

You can have multiple commands in your script.

script file

POST http://localhost:4444/script_file script="path_to_script"

connecting to Asciio Web server

  • directly from your application
  • via a command line application like xh (https://github.com/ducaale/xh) or httpie.
  • piping to stdin_to_asciio script which is installed with asciio (uses xh).

Example:


# bash script that adds an element to an asciio instance, offsets it, and deletes it

# create a script to add one element, the script can contain many scripting commands
# httpie has a large startup time, use xh instead

script= ; for i in $(seq 1) ; do script="$script add '1', new_box(TEXT_ONLY =>'$i'),  $((($i - 1) * 6)),  $((($i - 1) * 4)) ;" ; done

# execute the script
xh -f POST http://localhost:4444/script script="$script"

# offset the element
for i in $(seq 25) ; do sleep .05 ; xh  -f POST http://localhost:4444/script script="offset '1', 1, 1 ;" ; done

# delete the element
xh  -f POST http://localhost:4444/script script="delete_by_name '1' ;"

Simplified Scripting API

stop_updating_display

Stops updating the display until start_updating_display is called; this can be used to reduce flickering.

stop_updating_display

start_updating_display

Start updating the display; display will automatically be updated from when this is called. An update is also made.

start_updating_display

create_undo_snapshot

Creates an undo snapshot.

create_undo_snapshot ;

add

Adds a named element:

  • element_name
  • element, see new_box new_text, ... below
  • x coordinate
  • y coordinate
add 'text1', new_text(TEXT_ONLY =>'text'),  22,  20 ;

delete_by_name

Deletes an element by name

delete_by_name 'text1' ;

delete_selected_elements

Deletes selected elements

delete_selected_elements ;

add_type

Adds a named element:

  • element_name
  • element_type
  • x coordinate
  • y coordinate

Returns the element.

my $process = add_type 'process', 'Asciio/Boxes/process', 5, 15 ;

new_box

Creates a new box element. Use it with add.

new_box() ; # default box text
new_box(TEXT_ONLY =>'text') ;

new_text

Creates a new text element. Use it with add.

new_text(TEXT_ONLY =>'text') ;

new_wirl_arrow

Creates a new wirl-arrow element. Use it with add.

Pass wirl arrow section coordinates and directions as arguments.

new_wirl_arrow([5, 5, 'downright'], [10, 7, 'downright'], [7, 14, 'downleft']) ;

move

Moves a namex element to a new coordinate:

  • element name
  • x position
  • y position
move 'text1', 22,  20 ;

offset

Offsets a named element:

  • element name
  • x offset
  • y offset
offset 'text1', 22,  20 ;

change_selected_elements_color

Changes selected elements background or foreground color.

change_selected_elements_color 1, [1, 0, 0] ; # foreground color to red

select_by_name

Selects an elements by name.

select_by_name 'A' ;

select_all_elements

Selects all the elements in Asciio.

select_all_elements ;

deselect_all_elements

Deselects all the elements in Asciio.

deselect_all_elements ;

select_all_script_elements

Selects all the elements added by the script.

select_all_script_elements ;

deselect_all_script_elements

Deselects all the elements added by the script.

deselect_all_script_elements ;

connect_elements

Connects named elements with a wirl-arrow.

connect_elements 'box2', 'text1' ;

optimize

Optimizes the connections.

optimize

delete_all_ruler_lines

Deletes all ruler lines.

delete_all_ruler_lines ;

add_ruler_line

Adds a ruler line.

  • axis: 'vertical' or 'horizontal'
  • position
add_ruler_line 'vertical, 10 ;

save_to

Saves the diagram to a file in Asciio's native format.

save_to 'diagram.asciio' ;

to_ascii

Returns the diagram as ASCII.

to_ascii ;

ascii_out

Prints the diagram, as ASCII, to stdout.

ascii_out ;

Modifying Asciio

Bindings

Bindings consists of

  • a descriptive but short name

  • one or more key to assign the binding

  • a reference to a handler

  • possible arguments for the handler

'Mouse quick link git' => [['0A0-button-press-3', '00S-semicolon'],  \&App::Asciio::Actions::Git::quick_link]

Goals when adding bindings:

  • keep code separate from other bindings code if the new bindings are not very general, ie: code them in their own module

  • align the structures

  • avoid long or generic or numbered name

  • if possible the bindings should be the same as the vim-bindings

    • some GUI standards may require different bindings, IE: C00-A to select everything
  • create an equivalent binding set in the vim bindings file

  • documents the bindings

    • name, keep them logical, start with an uppercase
    • key
    • what they do, preferably with some screenshot
  • don't use control, shift and alt if possible (logical)

  • split groups if they become too large

  • sort by name or key if possible

Binding Groups

'<< selection leader >>' =>
	{
	SHORTCUTS   => '000-r',                                               # also accepts multiple entries in an array ref
	ENTER_GROUP => \&App::Asciio::Actions::Selection::selection_enter,
	ESCAPE_KEYS => [ '000-r', '000-Escape' ],                             # also accepts single entry

	# ESCAPE_KEYS need to be define of group will catch input untill an action is selected 
	
	# same keys as the ESCAPE_KEYS, will be called on exit
	'Selection escape'               => [ '000-r',             \&App::Asciio::Actions::Selection::selection_escape                      ],
	'Selection escape2'              => [ '000-Escape',        \&App::Asciio::Actions::Selection::selection_escape                      ],

	# simple action 
	'select flip mode'               => [ '000-f',             \&App::Asciio::Actions::Selection::selection_mode_flip                   ],

	# handle mouse movement
	'select motion'                  => [ '000-motion_notify', \&App::Asciio::Actions::Selection::select_elements                       ],
	},

Debugging

See the Debugging bindings.

Asiio can output to the console, any call to print will be displayed in it.

You can use Data::TreeDumper to display structured debug output.

You can of course run Asciio in the perl debugger.

Basic introduction

When the borders of two text elements intersect, we generate some compensating characters to cover the borders, resulting in nicer graphics

          |            ││    │  │
          |            ││    │  │
     -----|--->      ──││────│──│─
          |            ││    │  │
          |            ││    │  │
          v

Look at the text above, their borders are overlapping each other. The text we need to generate is as follows:

          |            ││    │  │
          |            ││    │  │
     -----+--->      ──┼┼────┼──┼─
          |            ││    │  │
          |            ││    │  │
          v

We need to generate padding characters at their boundaries, then the steps are as follows:

  1. find the cross point.
  2. Determine the characters to be filled at the current cross point according to the characters around the cross point.
  3. Determine whether the current cross point has the expected fill character, if so, keep it, if not, add it, and delete the old fill character.
  4. remove all filling characters that are not at cross points.
  5. update drawing.

Detailed steps

1 Find the cross point

The cross point must be the coverage of characters, and the characters that cover each other are the characters we care about. >The characters we care about refer to commonly used tab characters, or ascii plus dots, etc.

Commonly used symbols include these, of course not only these

'-', '|', '.', '\'', '\\', '/', '+', 
'─', '│', '┼', '┤', '├', '┬', '┴', '╭', '╮', '╯', '╰',
'━', '┃', '╋', '┫', '┣', '┳', '┻', '┏', '┓', '┛', '┗', 
'═', '║', '╬', '╣', '╠', '╦', '╩', '╔', '╗', '╝', '╚',
'╫', '╪', '╨', '╧', '╥', '╤', '╢', '╡', '╟', '╞', '╜', 
'╛', '╙', '╘', '╖', '╕', '╓', '╒'

condition of cross points:

  1. text elements crossed
  2. The two characters that intersect each other are the characters we care about

When the condition is found to be met, both characters need to be logged. At the same time, we need to record the characters around the cross point, because they absolutely determine what kind of cross point is generated. >Record the upper, lower, left, and right characters. If you want to achieve diagonal crossing, you also need to record characters at 45 degrees, 135 degrees, 225 degrees, and 315 degrees.

2 Judgment scene

2.1 General situation

First of all, all cross characters are directional, we need to group them by direction and type.

Let me give you an example, if the center has generated a character, Then we can use the method of proof by contradiction, its left side must be these characters, otherwise it is unreasonable.

'─',    '┼',    '├',    '┬',    '┴',    '╭',    '╰'

These characters all can appear to the left of it(Because their right sides can be extended to become a line), But if these characters do not appear on the left side of , then we think it is unreasonable to use this , and the disproof condition is false.

'-', '|', '.', '\'', '\\', '/', '+', 
'─', '│', '┼', '┤', '├', '┬', '┴', '╭', '╮', '╯', '╰',
'━', '┃', '╋', '┫', '┣', '┳', '┻', '┏', '┓', '┛', '┗', 
'═', '║', '╬', '╣', '╠', '╦', '╩', '╔', '╗', '╝', '╚',
'╫', '╪', '╨', '╧', '╥', '╤', '╢', '╡', '╟', '╞', '╜', 
'╛', '╙', '╘', '╖', '╕', '╓', '╒'

Make assumptions about the occurrence of each possible padding crossing character above, untilSupposed to be true.

                             │
                           ──│──
                             │

For the plus sign, the condition for its appearance is that:

  1. A character in the upper character set appears in the upper direction
  2. A character in the down direction character set appears in the down direction
  3. A character in the left-direction character set appears in the left direction
  4. A character in the right-direction character set appears in the right direction

If these conditions are met, the intermediate characters can be corrected as :

                             │
                           ──┼──
                             │

Let's look at a more complex situation, The intersection below, we know, needs one to fill.

  ═══│════
     │
     │

For the sign, the condition for its appearance is that:

  1. Left is one of the left characters of the double-line character set
  2. Right is one of the right characters of the double-line character set
  3. Down is one of the down characters in the single-line character set
  4. Up cannot be one of the up characters in the single-line character set

Pay attention to the bold part above, because if this condition is true, then the filling character should be , not .

2.2 Improve efficiency

There is no need to perform calculations every time to determine the characters filled in the middle. Whenever a new scene calculation occurs, we can save the calculation result in a cache and read it directly next time without performing logical calculations again.

A hash table is most suitable for this, and the hash key can use a combination of upper, lower, left, and right characters(The oblique lines are the four diagonal directions.).

2.3 An additional case needs to be considered separately

   ││
 ──││─────
   ││
   ││

please see this text, It is expected that we are going to get the following text:

   ││
 ──┼┼─────
   ││
   ││

As you noticed, there are two plus signs filled.

Let's take the point that needs to be filled on the left as an example: cross_condition

We can see that characters in three directions meet the requirements, but characters in one direction do not meet the requirements. But the point on the right is actually also an cross point, it has two characters, one in the foreground and one in the background. The character in the background is ok, so we think it ok!

In summary: If the character next to it is also an cross point, then either the foreground character or the background character of the intersection can meet the requirements.So I said earlier that the foreground and background characters of the cross point all need to be recorded.In fact, there may be more than one character that meets the condition in the background, so all of these characters need to be considered, not just limited to 2 characters.

2.4 The case of character coverage

There is another situation that needs to be explained separately,Similar to above but slightly different

 ╭─────╮
 │ ╭─────╮
 │ │     │
 │ │     │
 ╰─│     │
   ╰─────╯

The text we need to get is this:

 ╭─────╮
 │ ╭───┴─╮
 │ │     │
 │ │     │
 ╰─┤     │
   ╰─────╯

This looks like two boxes stacked,According to the above statement, the overlapping parts, both foreground characters and background characters must be considered.**But not like this!**The overlapping foreground characters are spaces, and spaces are not characters in the character set, so they are not considered.

To put it simply: as long as it is not an cross point, only foreground characters are considered.

The definition of the cross point has already been mentioned in the previous chapter

2.5 A method to simplify logical judgment

When we determine what characters should be filled in a point, we first consider the characters in the four directions. Then after these characters are considered, characters in three directions are considered, and finally characters in two directions are considered. The advantage of this is that if the characters in the four directions do not meet the conditions, then when judging the characters in the three directions, there is no need to repeatedly consider that a certain character may be a character in the four directions, because it has been ruled out before. Similar logic is used for two-way characters. This can greatly reduce the complexity of logical judgment.

Unicode character classification

  • characters of length 1
  • characters of length 2
  • characters of length 0

The length mentioned here refers to the printed length of the characters, that is, the length seen by the eyes

Characters of length 1

Most unicode characters are characters with a length of 1, such as the commonly used tab character, ascii characters.

a b c d , . ┼ ┬ │

Characters of length 2

Characters with a typographical width of 2 refer primarily to East Asian pictographs and related special punctuation, as well as full-width characters.

你好啊!《》
안녕하세요
こんにちは

They need to occupy two grids in the UI interface. Then aligning them requires special fonts that align 2:1 with width 1 characters.Here is a commonly used font.

https://github.com/be5invis/Sarasa-Gothic/

These characters have a special property called East Asian Width. They are included in the unicode standard, so they can be used as a programming basis.

Links to the unicode standard: https://www.unicode.org/reports/tr11/tr11-40.html

In perl's unicode documentation, corresponding properties are also provided to use.

This represents a wide character, occupying two spaces:

\p{EA=W}

This represents a full-width character, which also occupies two spaces:

\p{EA=F}

The above information can be found here:

https://perldoc.perl.org/perlunicook

https://perldoc.perl.org/perlunicode

Characters of length 0

In some languages, there are special characters whose string length is 1, but they do not occupy physical space on the interface, they will be attached to the previous characters.they are called nonspacing characters.Occurs in Thai and Arabic, as well as Hebrew

◌ั ◌ึ ◌ุ

Please look at the above characters, they cannot appear alone, they must be used in combination with the previous entity characters, and then they will appear above or below the previous characters.

These characters are called Nonspacing characters in the unicode standard, and then they have the following properties that can be used for programming

\p{gc:Mn}

To support Thai, or Arabic, or Hebrew, like East Asian languages, we also need a special font that can be aligned.In general, the system's default monospaced font can align them

Overlay

After Asciio draws the elements, a user defined call back is called.

User defined callback

The callback receives an instance of Asciio as the first argument, you can use that instance to get elements, ...

The callback return a list of 1character overlay in array references:

  • x coordinate
  • y coordinate
  • character
  • optional background color
  • optional foreground color

Example list:

[ 0, 0, 'T'],
[ 1, 0, 'e'],
[ 2, 0, 's'],
[ 3, 0, 't'],

Setting and resetting the callback

The callback is set by calling $asciio->set_overlays_sub. The simplest is to do it via a key binding.

'set overlays' =>
	[
	'0A0-o',
	sub 
		{
		my ($asciio) = @_ ;
		
		$asciio->set_overlays_sub
			(
			sub { [0, 0, 'O'], [1, 0, 'K'] }
			) ;
		
		$asciio->update_display ;
		}
	],

Reset the callback

'reset overlays' => [ '000-o', sub { $_[0]->set_overlays_sub(undef) ; $_[0]->update_display ; } ],

Callback access to canvas

The callback can also have access to the canvas, but don't

Arguments:

  • $asciio
  • $UI_type, set to GUI/TUI
  • $gc
  • $widget_width
  • $widget_height
  • $character_width
  • $character_height

Example: draw and overlay and a filled rectangle above the mouse pointer

sub click_element_overlay
{
my ($asciio, $UI_type, $gc, $widget_width, $widget_height, $character_width, $character_height) = @_ ;

# draw directly
if($UI_type eq 'GUI')
	{
	my $surface = Cairo::ImageSurface->create('argb32', 50, 50) ;
	my $gco = Cairo::Context->create($surface) ;
	
	my $background_color = $asciio->get_color('cross_filler_background') ;
	$gco->set_source_rgb(@$background_color) ;
	
	$gco->rectangle(0, 0, $character_width, $character_height) ;
	$gco->fill() ;
	
	$gc->set_source_surface($surface, ($asciio->{MOUSE_X} - 1 ) * $character_width, ($asciio->{MOUSE_Y} - 1) * $character_height);
	$gc->paint() ; 
	}

# send a list of characters to draw
my @overlays = map { [ $asciio->{MOUSE_X} + $_->[0], $asciio->{MOUSE_Y} + $_->[1], $_->[2] ] } @$click_element_overlay ;

@overlays
}

Callback hide/show mouse

Hide and show the mouse pointer, useful if you draw objects that are moved around.


sub callback_enter { my ($asciio) = @_ ; $asciio->hide_cursor ; ... }

sub callback_escape { my ($asciio) = @_ ; $asciio->show_cursor ; ... }

Contributors

    Khemir Nadim ibn Hamouda
    https://github.com/nkh
    CPAN ID: NKH
    Qin Qing
    northisland2017@gmail.com
    Unicode support, scroll bar, and rhombus object

License and copyright

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself or GPL3.

See Also

SVG conversion: goat

Tree generation: ascii_tree

ASCII Math and other: Diagon

Fun! AACircuit

schemascii

asciidiagram

Impressive shaape

ditaa

Stencils Asciio ditaa

Figlet

Source for some of the network stencil Ascii art

Ascii art

     *\o_               _o/*
      /  *             *  \
     <\       *\o/*       />
                )
         o/*   / >    *\o
         <\            />
 __o     */\          /\*     o__
 * />                        <\ *
  /\*    __o_       _o__     */\
        * /  *     *  \ *
         <\           />
              *\o/*
 ejm97        __)__