The library provides basic functions to work with Graphviz dot lang from rust code.

Overview

Description

The library provides the basic access to the graphs in graphviz format with ability to import into or export from it.

Base examples:

Parse dot source

b2} aaa[color=red] aaa -> bbb } aa -> be -> subgraph v { d -> aaa} aa -> aaa -> v } "#).unwrap(); assert_eq!( g, graph!(strict di id!("t"); node!("aa";attr!("color","green")), subgraph!("v"; node!("aa"; attr!("shape","square")), subgraph!("vv"; edge!(node_id!("a2") => node_id!("b2"))), node!("aaa";attr!("color","red")), edge!(node_id!("aaa") => node_id!("bbb")) ), edge!(node_id!("aa") => node_id!("be") => subgraph!("v"; edge!(node_id!("d") => node_id!("aaa")))), edge!(node_id!("aa") => node_id!("aaa") => node_id!("v")) ) ) } ">
use dot_structures::*;
use dot_generator::*;

fn parse_test() {
    let g: Graph = parse(r#"
        strict digraph t {
            aa[color=green]
            subgraph v {
                aa[shape=square]
                subgraph vv{a2 -> b2}
                aaa[color=red]
                aaa -> bbb
            }
            aa -> be -> subgraph v { d -> aaa}
            aa -> aaa -> v
        }
        "#).unwrap();

    assert_eq!(
        g,
        graph!(strict di id!("t");
              node!("aa";attr!("color","green")),
              subgraph!("v";
                node!("aa"; attr!("shape","square")),
                subgraph!("vv"; edge!(node_id!("a2") => node_id!("b2"))),
                node!("aaa";attr!("color","red")),
                edge!(node_id!("aaa") => node_id!("bbb"))
                ),
              edge!(node_id!("aa") => node_id!("be") => subgraph!("v"; edge!(node_id!("d") => node_id!("aaa")))),
              edge!(node_id!("aa") => node_id!("aaa") => node_id!("v"))
            )
    )
}

Print graph into dot source

 use dot_structures::*;
use dot_generator::*;
use graphviz_rust::printer::{PrinterContext, DotPrinter};

fn print_test() {
    let mut g = graph!(strict di id!("id"));
    assert_eq!("strict digraph id {}".to_string(), g.print(&mut PrinterContext::default()));
}

Transform graph into external formats with cmd engine

subgraph!(; node!("n"; NodeAttributes::color(color_name::black), NodeAttributes::shape(shape::egg)) )) ), edge!(node_id!("a1") => node_id!(esc "a2")) ); let graph_svg = exec(g, PrinterContext::default(), vec![ CommandArg::Format(Format::Svg), ]).unwrap(); } ">
 use dot_structures::*;
use dot_generator::*;
use graphviz_rust::{exec, parse};
use graphviz_rust::cmd::{CommandArg, Format};
use graphviz_rust::printer::{PrinterContext, DotPrinter};
use graphviz_rust::attributes::*;

fn output_test() {
    let mut g = graph!(id!("id");
             node!("nod"),
             subgraph!("sb";
                 edge!(node_id!("a") => subgraph!(;
                    node!("n";
                    NodeAttributes::color(color_name::black), NodeAttributes::shape(shape::egg))
                ))
            ),
            edge!(node_id!("a1") => node_id!(esc "a2"))
        );
    let graph_svg = exec(g, PrinterContext::default(), vec![
        CommandArg::Format(Format::Svg),
    ]).unwrap();
}

Structure:

The structure pursues to follow the dot notation closely, therefore it has straight accordance. The structures can be found in dot_structures::* and has the following denotion:

 strict digraph t {                     : graph with t as id
         aa[color=green]                : node aa and attributes in []
         subgraph v {                   : subgraph v
 	        aa[shape=square]            : node aa in subgraph 
 	        subgraph vv{a2 -> b2}       : another subgraph carrying edge inside( a type of the edge is Pair)
 	        aaa[color=red]
 	        aaa -> subgraph { d -> aaa} : subgraph id is anonymous id
         }
        aa -> be -> d -> aaa            : other edge with a type Chain
    }

Generate a dot structure:

The library provides a set of macros alleviating the process of graph construction.

Most of them, which have the sequence pattern(nodes with attributes, graphs or subgraphs with statements etc.) have the following syntax:

  • name or id or any other markers
  • list of structure with a comma or seq of elems with a semicolon
assert_eq!(
    node!("node_id"; attr!("atr1","val1"),attr!("atr2","val2")),
    node!("node_id", vec![attr!("atr1","val1"),attr!("atr2","val2")])
);

The macros can be found in dot_generator::* and has the following denotion:

b2} aaa[color=red] aaa -> bbb } aa -> be -> subgraph v { d -> aaa} aa -> aaa -> v } "#; graph!(strict di id!("t"); node!("aa";attr!("color","green")), subgraph!("v"; node!("aa"; attr!("shape","square")), subgraph!("vv"; edge!(node_id!("a2") => node_id!("b2"))), node!("aaa";attr!("color","red")), edge!(node_id!("aaa") => node_id!("bbb")) ), edge!(node_id!("aa") => node_id!("be") => subgraph!("v"; edge!(node_id!("d") => node_id!("aaa")))), edge!(node_id!("aa") => node_id!("aaa") => node_id!("v")) ); } ">
       fn graph_test() {
    use dot_generator::*;
    use dot_structures::*;

    let g = r#"
            strict digraph t {
                aa[color=green]
                subgraph v {
                    aa[shape=square]
                    subgraph vv{a2 -> b2}
                    aaa[color=red]
                    aaa -> bbb
                }
                aa -> be -> subgraph v { d -> aaa}
                aa -> aaa -> v
            }
            "#;

    graph!(strict di id!("t");
                  node!("aa";attr!("color","green")),
                  subgraph!("v";
                    node!("aa"; attr!("shape","square")),
                    subgraph!("vv"; edge!(node_id!("a2") => node_id!("b2"))),
                    node!("aaa";attr!("color","red")),
                    edge!(node_id!("aaa") => node_id!("bbb"))
                    ),
                  edge!(node_id!("aa") => node_id!("be") => subgraph!("v"; edge!(node_id!("d") => node_id!("aaa")))),
                  edge!(node_id!("aa") => node_id!("aaa") => node_id!("v"))
                );
}

Attributes

The graphviz provides an enormous amount of possible attributes and to support it, the library provides a set of structures alleviating the navigation among them namely:

  • custom attribute can be easily compound with the macros attr!(id,id) nevertheless another possible formats:
  • using named attributes like graphviz_rust::attributes::color for the color attribute
  • using the particular structures graphviz_rust::attributes::{EdgeAttributes,SubgraphAttributes GraphAttributes, NodeAttributes} grouping and displaying which attribute belongs to the struct.
   use graphviz_rust::attributes::{color, color_name, GraphAttributes, NodeAttributes};
use into_attr::IntoAttribute;
use dot_structures::*;
use dot_generator::*;

fn test() {
   assert_eq!(GraphAttributes::center(true), attr!("center",true));
   assert_eq!(
       NodeAttributes::color(color_name::antiquewhite1),
       attr!("color","antiquewhite1"));
   assert_eq!(color::default().into_attr(), attr!("color","black"));
}

Transform into string following a dot format

The trait DotPrinter is summoned to transform a graph structure into string.

node_id!("b"))); assert_eq!(s.print(&mut ctx), "subgraph id {\n abc\n a -- b \n}".to_string()); } ">
     use dot_generator::*;
use dot_structures::*;
use graphviz_rust::printer::{PrinterContext, DotPrinter};

fn subgraph_test() {
    let mut ctx = PrinterContext::default();
    let s = subgraph!("id"; node!("abc"), edge!(node_id!("a") => node_id!("b")));

    assert_eq!(s.print(&mut ctx), "subgraph id {\n    abc\n    a -- b \n}".to_string());
}

The module allows adjusting some of the parameters such as indent step or line separator using PrinterContext:

     fn ctx() {
    use self::graphviz_rust::printer::PrinterContext;
    let mut ctx = PrinterContext::default();

    ctx.always_inline(); // everything in one line
    ctx.with_semi(); // semicolon at the end of every element
    ctx.with_indent_step(4); // indent 4 (default 2)
    ctx.with_inline_size(60); // size indicating the line needs to break into multilines
}

External formats anf others using cmd engine

The library provides an ability to use command commands from the rust code. The details are denoted in graphviz_rust::{exec}.

  fn output_test() {
    let mut g = graph!(id!("id"));
    exec(g, PrinterContext::default(), vec![
        CommandArg::Format(Format::Svg),
        CommandArg::Output("path_to_file".to_string())
    ]);
}

Note: to have it successfully up and running the command client should be installed

Comments
  • Graph should be visible

    Graph should be visible

    The Graph enum and its fields should be visible. For reasons where the printer interface does not satisfy more complex use-cases, e.g. interact with a graph database or such stuff

    opened by anon767 7
  • Tests failing on macOS

    Tests failing on macOS

    Hi! Thanks for the wonderful package, but I have a problem on macOS. I tried to perform export to svg example and faced the error No such file or directory.

    Then I ran your tests and faced the same error

    running 24 tests
    test attributes::tests::test ... ok
    test parser::test::edge_test ... ok
    test parser::test::attr_test ... ok
    test parser::test::comments_test ... ok
    test parser::test::attr_stmts_test ... ok
    test parser::test::edge_stmt_test ... ok
    test parser::test::attr_list_test ... ok
    test parser::test::node_test ... ok
    test parser::test::node_id_test ... ok
    test printer::tests::attr_test ... ok
    test parser::test::vertex_test ... ok
    test printer::tests::edge_test ... ok
    test parser::test::stmt_test ... ok
    test printer::tests::graph_attr_test ... ok
    test parser::test::id_test ... ok
    test printer::tests::graph_test ... ok
    test printer::tests::node_id_test ... ok
    test printer::tests::node_test ... ok
    test parser::test::graph_test ... ok
    test printer::tests::subgraph_test ... ok
    test parser::test::graph_html_test ... ok
    test tests::parse_test ... ok
    test tests::exec_test ... FAILED
    test tests::print_test ... ok
    
    failures:
    
    ---- tests::exec_test stdout ----
    thread 'tests::exec_test' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/lib.rs:194:12
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    
    
    failures:
        tests::exec_test
    
    test result: FAILED. 23 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
    

    I tried running it with sudo and it didn't help.

    opened by qzarx1 6
  • chore: use dprint to format the code

    chore: use dprint to format the code

    This fixes the inconsistent formatting in the code and the documentation via dprint

    Before this, the documentation and code had inconsistent indentation that made the code hard to read. As an example: https://lib.rs/crates/dot-generator

    The commits are separated. The first commit adds the dprint config, and the second commit is fully automated and runs dprint fmt. No functional code changes have been made.

    opened by aminya 3
  • Add Clone/Copy impls for enum cmd::Format, export a version of exec that takes a rendered graph, add more descriptive error messages

    Add Clone/Copy impls for enum cmd::Format, export a version of exec that takes a rendered graph, add more descriptive error messages

    Hi, I'm currently using graphviz-rust to build some dependency graph visualizations and I've run into some small issues with the API that mildly affect UX.

    1. No way to clone a cmd::Format. cmd::Format doesn't implement Clone, so there's no way to set constants for default layouts, or take a desired layout as a command-line argument. It seems that it should be possible to derive Clone on this type given that it's a simple enum.

    2. No way to cache the result of printing a Graph before passing it to exec. I'm currently building a Graph then rendering it to svg, but I'd like to export the rendered .dot file as well. The exec function exported from the crate root only takes a Graph as an argument, but runs print on it immediately. There's no way to reuse the result of print and pass it directly to exec afterward - this results in the graph needing to be printed twice in order to both save the raw .dot markup and call graphviz on it. It would be nice to have a similar function, e.g. exec_from_dot_file, that takes a string as input.

    3. Nondescriptive error message when graphviz is missing from PATH If the user doesn't have dot in their PATH, exec fails with an error No file or directory found. It isn't immediately obvious what the source of this error is, or how to remedy it. exec should ideally return a message telling the user to install graphviz; this caveat is mentioned in the docs but buried inside the cmd module.

    Thank you for releasing this crate, it's super useful!

    opened by dreamsmasher 3
  • Special characters in IDs result in invalid output

    Special characters in IDs result in invalid output

    Example:

    let graph = {
        use graphviz_rust::dot_generator::*;
        graph!(strict di id!("h[t]"))
    };
    
    let mut ctx = PrinterContext::default();
    ctx.with_indent_step(2);
    let out = graph.print(&mut ctx);
    

    Output (invalid DOT):

    strict digraph h[t] {
    
    }
    

    Expected output:

    strict digraph "h[t]" {
    
    }
    
    opened by MingweiSamuel 3
  • dot pest update

    dot pest update

    Hey! First of all, thanks for the awesome library! I am trying to create a uml diagram for my db and have issues with the parse function specifically on the code <tr><td>address_id: int</td></tr> I suspect its the dot.pest file the needs to be updated to handle special characters like : or _ thanks

    opened by yashmasani 1
  • Change the way of parsing GraphAttributes

    Change the way of parsing GraphAttributes

    The structure of parsing GraphAttributes follows the notation but the fact that the seq of extra elements following after the node is concealed:

    graph {
    node[style=filled]; a b c d;
    }
    

    Therefore now it is being parsed as a set of independent statements but apparently, they have to be merged.

    opened by besok 0
  • Inability to use Attribute builder with escaped strings

    Inability to use Attribute builder with escaped strings

    It is no way to use GraphAttributes or any other builders like that:

    GraphAttributes::attribute("val") == attr!("attribute", esc "\"val\"")
    
    opened by besok 0
Owner
Boris
Boris
CLI for image processing with histograms, binary treshold and other functions

Image-Processing-CLI-in-Rust CLI for processing images in Rust. Some implementation is custom and for some functionality it uses 3rd party libraries.

Miki Graf 25 Jul 24, 2022
Generate QR code easily for free - QR Code Generation as a Service.

QRcode.show Generate QR code easily for free - QR Code Generation as a Service. INPUT: curl qrcode.show/INPUT curl qrcode.show -d INPUT curl qrcode.sh

Arijit Basu 572 Dec 24, 2022
Baryon is a compact 3D engine focused on fast prototyping in code.

baryon Baryon is a compact 3D engine focused on fast prototyping in code. No big dependencies, no fancy run-times, GUI editors, or other magic. Depend

Dzmitry Malyshau 63 Jan 1, 2023
Construct graphs from parsed source code

tree-sitter-graph The tree-sitter-graph library defines a DSL for constructing arbitrary graph structures from source code that has been parsed using

null 102 Nov 23, 2022
Graph data structure library for Rust.

petgraph Graph data structure library. Supports Rust 1.41 and later. Please read the API documentation here Crate feature flags: graphmap (default) en

null 2k Jan 9, 2023
A graph library for Rust.

Gamma A graph library for Rust. Gamma provides primitives and traversals for working with graphs. It is based on ideas presented in A Minimal Graph AP

Metamolecular, LLC 122 Dec 29, 2022
Simple but powerful graph library for Rust

Graphlib Graphlib is a simple and powerful Rust graph library. This library attempts to provide a generic api for building, mutating and iterating ove

Purple Protocol 177 Nov 22, 2022
Rust library for of graph ensembles

Rust library for random graph ensembles Minimal Rust version: 1.55.0 Implements simple sampling and monte carlo (or rather markov-) steps, that can be

Yannick Feld 2 Dec 14, 2022
Generic framebuffer implementation in Rust for use with embedded-graphics library

Fraramebuffer implementation for Rust's Embedded-graphics Framebuffer approach helps to deal with display flickering when you update multiple parts of

Bernard Kobos 9 Nov 29, 2022
A 2D vector graphics library optimized for GUIs, written in Rust and wgpu

RootVG A 2D vector graphics library optimized for GUIs, written in Rust and wgpu How it Works Unlike other 2D vector graphics libraries which have a s

Meadowlark 14 Jul 10, 2024
An SVG rendering library.

resvg resvg is an SVG rendering library. Purpose resvg can be used as a Rust library, a C library and as a CLI application to render SVG files based o

Evgeniy Reizner 1.8k Jan 7, 2023
Library for Rubik's cube applications.

Rubik Master cube-demo3.mov Do you like to solve Rubik's cube? I do. As a cuber and programmer, I want to build a toolset to build applications like S

Akira Hayakawa 12 Nov 3, 2022
Sub-pixel precision light spot rendering library for astronomy and video tracking applications.

Planetarium Sub-pixel precision light spot rendering library for astronomy and video tracking applications. Example usage use planetarium::{Canvas, Sp

Sergey Kvachonok 5 Mar 27, 2022
Small, lightweight and fast library for rendering text with wgpu.

wgpu-text wgpu-text is a wrapper over glyph-brush for fast and easy text rendering in wgpu. This project was inspired by and is similar to wgpu_glyph,

Leon 20 Nov 30, 2022
Python library for embedding large graphs in 2D space, using force-directed layouts.

Graph Force A python/rust library for embedding graphs in 2D space, using force-directed layouts. Installation pip install graph_force Usage The first

Niko Abeler 159 Dec 29, 2022
Pathfinding library for calculating all node pairs' shortest paths in an unweighted undirected graph.

bit_gossip bit_gossip, named after its implementation technique, is a simple pathfinding library for calculating all node pairs' shortest paths in an

Jack Lee 49 Sep 4, 2024
A toy ray tracer in Rust

tray_rust - A Toy Ray Tracer in Rust tray_rust is a toy physically based ray tracer built off of the techniques discussed in Physically Based Renderin

Will Usher 492 Dec 19, 2022
A low-overhead Vulkan-like GPU API for Rust.

Getting Started | Documentation | Blog gfx-rs gfx-rs is a low-level, cross-platform graphics and compute abstraction library in Rust. It consists of t

Rust Graphics Mages 5.2k Jan 8, 2023
A complete harfbuzz's shaping algorithm port to Rust

rustybuzz rustybuzz is a complete harfbuzz's shaping algorithm port to Rust. Matches harfbuzz v2.7.0 Why? Because you can add rustybuzz = "*" to your

Evgeniy Reizner 310 Dec 22, 2022