gv(3perl)

🌸 NAME 🌸

gv_perl β€” graph manipulation in perl πŸ’…

okay bestie, welcome to the manual page for gv(3perl), aka the perl extension that lets you do graph stuff. yes, that graph stuff. graphviz. in perl. iconic behavior honestly πŸ¦‹


✨ SYNOPSIS ✨

the vibe check, in code:

#!/usr/bin/perl
use gv;

that's it. that's the whole ritual. no cap πŸŽ€


πŸ’– USAGE πŸ’–

this section is out here living its best minimalist life β€” it has no body text of its own. all the actual tea is served in INTRODUCTION and COMMANDS right below, so keep scrolling, bestie, don't stop here 🫢


🌈 INTRODUCTION 🌈

gv_perl</purl> is a dynamically loaded extension for perl that provides access to the graph facilities of graphviz. literally that's the whole pitch. dynamic loading? we love a flexible queen. πŸ’œ


πŸ‘‘ COMMANDS πŸ‘‘

🌟 New graphs 🌟

New empty graph

graph_handle gv::graph (name);
graph_handle gv::digraph (name);
graph_handle gv::strictgraph (name);
graph_handle gv::strictdigraph (name);

four flavors, pick your fighter. graph, digraph, strictgraph, strictdigraph β€” all of them hand you back a graph_handle and all of them want a name. πŸŽ€

New graph from a dot-syntax string or file

graph_handle gv::readstring (string);
graph_handle gv::read (string filename);
graph_handle gv::read (channel);

readstring takes a string, read takes either a string filename or a channel. two totally different inputs, one function name, and honestly? we respect the range. πŸ¦‹

Add new subgraph to existing graph

graph_handle gv::graph (graph_handle, name);

pass in an existing graph_handle plus a name and boom, subgraph. nesting era. πŸ’…

πŸ“ New nodes πŸ“

Add new node to existing graph

node_handle gv::node (graph_handle, name);

give it a graph_handle and a name, get a node_handle back. the circle of life, but for nodes. ✨

πŸ”₯ New edges πŸ”₯

Add new edge between existing nodes

edge_handle gv::edge (tail_node_handle, head_node_handle);

two real, already-existing node handles walk in, one edge_handle walks out. πŸ’–

Add a new edge between an existing tail node, and a named head node which will be induced in the graph if it doesn't already exist

edge_handle gv::edge (tail_node_handle, head_name);

real tail node handle + a head_name. and the tea here is that the named head node gets induced in the graph if it doesn't already exist β€” it just shows up, uninvited but welcome. πŸ™ˆ

Add a new edge between an existing head node, and a named tail node which will be induced in the graph if it doesn't already exist

edge_handle gv::edge (tail_name, head_node_handle);

mirror image, same energy: real head node handle + a tail_name, and that named tail node will be induced in the graph if it doesn't already exist. 🧚

Add a new edge between named tail and head nodes which will be induced in the graph if they don't already exist

edge_handle gv::edge (graph_handle, tail_name, head_name);

now we're doing it with a graph_handle, a tail_name and a head_name, and both named nodes get induced if they don't already exist. manifesting nodes fr fr ⭐

πŸ’œ Setting attribute values πŸ’œ

Set value of named attribute of graph/node/edge β€” creating attribute if necessary

string gv::setv (graph_handle, attr_name, attr_value);
string gv::setv (node_handle, attr_name, attr_value);
string gv::setv (edge_handle, attr_name, attr_value);

works on a graph_handle, a node_handle or an edge_handle, returns a string, and takes attr_name + attr_value. key detail bestie: it creates the attribute if necessary. it does not ask permission. it simply ships. πŸ‘‘

Set value of existing attribute of graph/node/edge (using attribute handle)

string gv::setv (graph_handle, attr_handle, attr_value);
string gv::setv (node_handle, attr_handle, attr_value);
string gv::setv (edge_handle, attr_handle, attr_value);

same three targets, same string return, but this time you're passing an attr_handle instead of a name. note the description says existing attribute β€” this one isn't out here creating anything new. πŸ’…

πŸŽ€ Getting attribute values πŸŽ€

Get value of named attribute of graph/node/edge

string gv::getv (graph_handle, attr_name);
string gv::getv (node_handle, attr_name);
string gv::getv (edge_handle, attr_name);

three targets, one attr_name, and a string coming back at you. retrieval girlies rise. 🫢

Get value of attribute of graph/node/edge (using attribute handle)

string gv::getv (graph_handle, attr_handle);
string gv::getv (node_handle, attr_handle);
string gv::getv (edge_handle, attr_handle);

same deal but with an attr_handle. still returning a string. still eating. ✨

πŸ¦‹ Obtain names from handles πŸ¦‹

string gv::nameof (graph_handle);
string gv::nameof (node_handle);
string gv::nameof (attr_handle);

hand it a graph_handle, node_handle or attr_handle, and it tells you the string name. "who are you?" "here's who i am." πŸ’–

πŸ’… Find handles from names πŸ’…

graph_handle gv::findsubg (graph_handle, name);
node_handle gv::findnode (graph_handle, name);
edge_handle gv::findedge (tail_node_handle, head_node_handle);
attribute_handle gv::findattr (graph_handle, name);
attribute_handle gv::findattr (node_handle, name);
attribute_handle gv::findattr (edge_handle, name);

the reverse maneuver: findsubg gives a graph_handle, findnode gives a node_handle, findedge gives an edge_handle (from a tail_node_handle and a head_node_handle β€” no name needed, the nodes themselves are the address), and findattr gives an attribute_handle whether you feed it a graph_handle, a node_handle or an edge_handle. equal opportunity attribute hunting. πŸ”

🌟 Misc graph navigators returning handles 🌟

node_handle gv::headof (edge_handle);
node_handle gv::tailof (edge_handle);
graph_handle gv::graphof (graph_handle);
graph_handle gv::graphof (edge_handle);
graph_handle gv::graphof (node_handle);
graph_handle gv::rootof (graph_handle);

headof and tailof each take an edge_handle and give you a node_handle. graphof takes a graph_handle, an edge_handle or a node_handle and gives you a graph_handle. rootof takes a graph_handle and gives you a graph_handle. navigators stay navigating. 🧭

πŸ“ Obtain handles of proto node/edge for setting default attribute values πŸ“

node_handle gv::protonode (graph_handle);
edge_handle gv::protoedge (graph_handle);

want defaults? get the proto. protonode returns a node_handle, protoedge returns an edge_handle, both from a graph_handle. set your default attribute values on these bad boys. πŸ”₯

🌈 Iterators 🌈

Iteration termination tests

bool gv::ok (graph_handle);
bool gv::ok (node_handle);
bool gv::ok (edge_handle);
bool gv::ok (attr_handle);

gv::ok takes any of the four handle types and returns a bool. are we still going? yes or no. that's the whole job. πŸ’€

Iterate over subgraphs of a graph

graph_handle gv::firstsubg (graph_handle);
graph_handle gv::nextsubg (graph_handle, subgraph_handle);

firstsubg kicks it off, nextsubg keeps it going with a graph_handle and a subgraph_handle. both return a graph_handle. πŸ’–

Iterate over supergraphs of a graph (obscure and rarely useful)

graph_handle gv::firstsupg (graph_handle);
graph_handle gv::nextsupg (graph_handle, subgraph_handle);

and the original page straight up says these are obscure and rarely useful. not me being honest! but they exist, they take what they take, they return a graph_handle, and you deserve to know. πŸ™ˆ

Iterate over edges of a graph

edge_handle gv::firstedge (graph_handle);
edge_handle gv::nextedge (graph_handle, edge_handle);

firstedge starts you off from a graph_handle, nextedge moves you along with a graph_handle + edge_handle. both hand back an edge_handle. ✨

Iterate over outedges of a graph

edge_handle gv::firstout (graph_handle);
edge_handle gv::nextout (graph_handle, edge_handle);

out-edges only. firstout from a graph_handle, nextout with graph_handle + edge_handle, both returning an edge_handle. outgoing girlies only. πŸ’…

Iterate over edges of a node

edge_handle gv::firstedge (node_handle);
edge_handle gv::nextedge (node_handle, edge_handle);

same function names, now node-flavored: firstedge from a node_handle, nextedge with node_handle + edge_handle, returning an edge_handle. πŸŽ€

Iterate over out-edges of a node

edge_handle gv::firstout (node_handle);
edge_handle gv::nextout (node_handle, edge_handle);

firstout from a node_handle, nextout with node_handle + edge_handle, edge_handle out the other side. πŸ”₯

Iterate over head nodes reachable from out-edges of a node

node_handle gv::firsthead (node_handle);
node_handle gv::nexthead (node_handle, head_node_handle);

you start at a node_handle, you follow the out-edges, and you land on head nodes. firsthead and nexthead (which wants a node_handle and a head_node_handle) both return a node_handle. πŸ¦‹

Iterate over in-edges of a graph

edge_handle gv::firstin (graph_handle);
edge_handle gv::nextin (node_handle, edge_handle);

okay so this is exactly what the page says, and i am copying it character for character because that is the rule: firstin takes a graph_handle, and nextin takes a node_handle plus an edge_handle. both return an edge_handle. no edits, no "fixes", that's canon. πŸ‘‘ (same situation right below, bestie, i'm not the one who wrote it, i'm the one who's faithful to it πŸ’–)

Iterate over in-edges of a node

edge_handle gv::firstin (node_handle);
edge_handle gv::nextin (graph_handle, edge_handle);

as promised: firstin with a node_handle, nextin with a graph_handle plus an edge_handle, both returning an edge_handle. verbatim, bestie, always. 🫢

Iterate over tail nodes reachable from in-edges of a node

node_handle gv::firsttail (node_handle);
node_handle gv::nexttail (node_handle, tail_node_handle);

firsttail starts from a node_handle, nexttail takes a node_handle and a tail_node_handle, both give you a node_handle. the mirror of the head situation. ⭐

Iterate over nodes of a graph

node_handle gv::firstnode (graph_handle);
node_handle gv::nextnode (graph_handle, node_handle);

firstnode from a graph_handle, nextnode with graph_handle + node_handle, node_handle returned. 🌟

Iterate over nodes of an edge

node_handle gv::firstnode (edge_handle);
node_handle gv::nextnode (edge_handle, node_handle);

now edge-flavored: firstnode from an edge_handle, nextnode with edge_handle + node_handle, node_handle back. πŸ’œ

Iterate over attributes of a graph

attribute_handle gv::firstattr (graph_handle);
attribute_handle gv::nextattr (graph_handle, attr_handle);

firstattr from a graph_handle, nextattr with graph_handle + attr_handle, attribute_handle returned. πŸŽ€

Iterate over attributes of an edge

attribute_handle gv::firstattr (edge_handle);
attribute_handle gv::nextattr (edge_handle, attr_handle);

firstattr from an edge_handle, nextattr with edge_handle + attr_handle, attribute_handle returned. πŸ”₯

Iterate over attributes of a node

attribute_handle gv::firstattr (node_handle);
attribute_handle gv::nextattr (node_handle, attr_handle);

firstattr from a node_handle, nextattr with node_handle + attr_handle, attribute_handle returned. three flavors, one gorgeous pattern. ✨

Remove graph objects

bool gv::rm (graph_handle);
bool gv::rm (node_handle);
bool gv::rm (edge_handle);

gv::rm takes a graph_handle, a node_handle or an edge_handle and returns a bool. bye bestie, love you, blocked. πŸ’€

⭐ Layout ⭐

Annotate a graph with layout attributes and values using a specific layout engine

bool gv::layout (graph_handle, string engine);

give it a graph_handle and a string engine, get a bool back. this is where your graph gets its whole look. main character makeover arc. πŸ’…

🧚 Render 🧚

Render a layout into attributes of the graph

bool gv::render (graph_handle);

just the graph_handle, bool returned. the layout goes into the attributes of the graph itself. ✨

Render a layout to stdout

bool gv::render (graph_handle, string format);

add a string format and it goes straight to stdout. yes, straight to your terminal, out loud. 🫢

Render to an open file

bool gv::render (graph_handle, string format, channel fout);

graph_handle, string format, and a channel fout that's already open. you opened it, you own it. πŸ’–

Render a layout to an unopened file by name

bool gv::render (graph_handle, string format, string filename);

this time the third argument is a string filename β€” the file is unopened, and it's found by name. πŸŽ€

Render to a string result

string gv::renderresult (graph_handle ing, string format);
gv::renderresult (graph_handle, string format, string outdata);

okay bestie, graph_handle ing β€” with the space and the ing β€” is verbatim from the page. i do not touch the sacred texts, i only decorate them. πŸ’… the two-argument form returns a string; the three-argument form takes a graph_handle, a string format and a string outdata, and the page gives it no return type at all. take it up with the page, not with me. πŸ™ˆ

Render to an open channel

bool gv::renderchannel (graph_handle, string format, string channelname);

graph_handle, string format, string channelname, bool returned. open channel energy. 🌈

Render a layout to a malloc'ed string, to be free'd by the caller

deprecated β€” too easy to leak memory 😭
string gv::renderdata (graph_handle, string format);

the page also notes it's still needed for "eval [gv::renderdata $G tk]", so like. it's deprecated but it's still doing shifts. we don't make the rules. ⭐

Writing graph back to file

bool gv::write (graph_handle, string filename);
bool gv::write (graph_handle, channel);

gv::write takes a graph_handle plus either a string filename or a channel, and returns a bool. save your work bestie, i am begging. 🫢

Graph transformation tools

bool gv::tred (graph_handle);

one graph_handle in, one bool out. transformation era. πŸ¦‹


πŸŽ€ KEYWORDS πŸŽ€

graph, dot, neato, fdp, circo, twopi, perl.


that's the whole page, bestie, and you ate it πŸ’… go make some graphs. this was gv(3perl), dated 21 March 2026 β€” mwah, love you, bye! πŸ’–βœ¨πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from
  • fedora 44: graphviz-perl 14.1.4-2.fc44 Β· epl-1.0 AND cpl-1.0 AND bsd-3-clause AND mit AND gpl-3.0-or-later WITH bison-exception-2.2 AND apache-1.1 AND lgpl-2.0-or-later WITH libtool-exception AND smlnj AND hpnd-uc
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms