A tree listing opened folder by folder, then closed again.
A project listed the way tree -F prints it. As upstream draws it, a
cursor walks down the list opening one folder at a time, then closes them
from the bottom up. With walk: false it is a tree to use instead: your
files, the folders you open, and a cursor that keys and clicks move, in a
terminal UI or a LiveView.
Options
Give them to Ascii.new/2 as options:, and new ones while it plays
with Ascii.put_options/2 (or a Phoenix player's options): the tree
is laid out anew from them.
root- the first line, above the listing. Default".".entries- the listing as text: one entry a line, two spaces of indent a level, folders ending in "/". Default: upstream's small web project. Being text, it is cut at 256 characters: for a real tree, givepaths.paths- the entries as a list of paths, asPath.wildcard/1gives them, in place ofentries: each path's folders are made from it, a path ending in "/" is a folder, and every folder's entries come in the order first given (sort them fortree's order). Up to 256 paths. Default[], forentries.entries/1gives the text for paths.walk-true(the default) plays upstream's walk;falsedraws the tree still, asopenandcursorsay, and takes keys and clicks.open- withwalk: false, the paths of the open folders, as["src/", "src/lib/"]. An entry's path is its name after its folders',"src/lib/fetch.ts", a folder's ending in "/". Default[]: only the root's entries show.cursor- withwalk: false, the path of the entry under the cursor, drawn as the walk draws it, the branch turned arrow. One inside a closed folder sits on the nearest folder shown;""(the default), or a path not in the tree, is no cursor. A listing longer than its rows scrolls to keep the cursor in the middle of them.cols,rows- the frame's size, 12 to 200 by 4 to 100; 36 by 23 by default. The listing is centred in the width, between the root and a blank row over the count.
Colours
In one ink, or a gradient, with :ink and :gradient (see
Ascii.Ink); part by part with :parts (see Ascii.Parts),
parts: true taking the colours suggested here:
root- the first line.branch- the tree's lines, grey.cursor- the branch turned arrow, yellow.folder- a folder's name, blue.file, andfile.<extension>- a file's name, and by its extension in lowercase (file.tsforindex.ts; a name without one, or a dotfile, is justfile). Suggested:file.exandfile.exspurple,file.tsblue,file.jsandfile.jsonyellow,file.csspink,file.mdgrey; any other in the ink.%{"file.rs" => "#dea584"}colours a kind of your own.marker- the+on a closed folder, yellow.summary- the count on the last row, grey.
Keys and clicks
With walk: false, Ascii.handle_event/2 takes keys and clicks,
changing cursor and open, from which the app reads the choice:
- ↑ and ↓ move the cursor, as do home, end, page up and page down; with no cursor, any of them puts it on the first entry (end, the last).
- → or enter opens a closed folder, and → on an open one moves into it; ← closes an open folder, or moves to the folder an entry is in; enter and space open and close a folder.
- A click on an entry's row puts the cursor on it, and opens or closes it if it is a folder.
- Enter on a file is ignored, as is a key that would change nothing:
the app has the key, and the file in
cursor.
Walking, it takes none. In Phoenix, give the player interactive (and
notify to be told of each key and click); in ExRatatui,
Ascii.ExRatatui.handle_event/3; in a terminal,
mix ascii.play file-tree --option walk=false --interactive.
Screen readers
Ascii.describe/1 tells the tree and where the cursor is, as "file
tree of my_app: 2 folders, 4 files; at lib/my_app.ex". Walking, it gives
the piece's name and note.
Example
paths = ["lib/my_app.ex", "lib/my_app/repo.ex", "mix.exs", "README.md"]
options = %{walk: false, paths: paths, root: "my_app", open: ["lib/"], cursor: "lib/"}
tree = Ascii.new!("file-tree", options: options, parts: true)
{:ok, tree} = Ascii.handle_event(tree, {:key, "down"})
tree.options.cursor
#=> "lib/my_app.ex"
Ascii.describe(tree)
#=> "file tree of my_app: 2 folders, 4 files; at lib/my_app.ex"<Ascii.Phoenix.live_player id="files" piece="file-tree" options={%{walk: false, paths: @paths}} parts interactive notify />Ported from src/pieces/file-tree.ts in bas3line/ascii (MIT).
Summary
Functions
entries text for a list of paths, as the paths option takes them: each
path's folders are made from it, a path ending in "/" (or holding others)
is a folder, and every folder's entries come in the order first given.
Functions
entries text for a list of paths, as the paths option takes them: each
path's folders are made from it, a path ending in "/" (or holding others)
is a folder, and every folder's entries come in the order first given.
iex> Ascii.Pieces.FileTree.entries(["lib/app.ex", "lib/app/repo.ex", "mix.exs", "priv/"])
"lib/\n app.ex\n app/\n repo.ex\nmix.exs\npriv/"