Skip to content

Commit 2a2b721

Browse files
77nnit77nn
andauthored
ascii-tree-factory: Fixed same depth branches visualization. Added style and separator user options. (#244)
* Added Ascii Tree Factory * Update readme.md the `l` got lost in the `.qml` extension... * Added ToDo section to readme file * Update readme.md * Update info.json Build was failing for inconsistent identifier * Update info.json * Update and rename ASCII-Tree-Factory.qml to ascii-tree-factory.qml * Update info.json Removed Linux and MacOs as not tested * Update ascii-tree-factory.qml regression bug due to changing identifier * Update info.json * fix: missing else * Fix: same levels now connect better Enhancement: style selector Enhancement: separator selector modified: ascii-tree-factory/ASCII-Tree-Factory.qml modified: ascii-tree-factory/info.json modified: ascii-tree-factory/readme.md * Fix: filename and indetifier casing renamed: ascii-tree-factory/ASCII-Tree-Factory.qml -> ascii-tree-factory/ascii-tree-factory.qml modified: ascii-tree-factory/readme.md * info.json: Added extended description * Fix: description adjustment, it was too long * Update info.jsonversion update --------- Co-authored-by: 77nn <mbpub4com+cdbrg@posteo.it>
1 parent 8480b42 commit 2a2b721

File tree

3 files changed

+138
-75
lines changed

3 files changed

+138
-75
lines changed

ascii-tree-factory/ascii-tree-factory.qml

Lines changed: 116 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,69 +2,125 @@ import QtQml 2.0
22
import QOwnNotesTypes 1.0
33

44
Script {
5-
/**
6-
* Sarà eseguito quando il motore di scripting parte
7-
*/
8-
function init() {
9-
script.registerCustomAction("ascii-tree-factory", "Generate ASCII tree from path");
10-
}
5+
property string pathSeparator;
6+
property string style;
117

12-
function customActionInvoked(identifier) {
13-
switch (identifier) {
14-
case "ascii-tree-factory": {
15-
var selection = script.noteTextEditSelectedText();
16-
// break selection strings at line ends
17-
var lines = selection.split("\n");
18-
// initialize tree object
19-
var tree = {};
20-
//for each line in selection
21-
lines.forEach(function(line){
22-
// break line at slashes
23-
var path = line.split("/");
24-
var current = tree;
25-
// for each segment
26-
path.forEach(function(subpath){
27-
// if the key doesn't have descendants, attach an empty object.
28-
if (!current[subpath]){
29-
current[subpath] = {};
30-
}
31-
// else move to the next level
32-
current = current[subpath];
33-
});
8+
property variant settingsVariables: [
9+
{
10+
"identifier": "pathSeparator",
11+
"name": "Path separator",
12+
"description": "Please select a separator character:",
13+
"type": "selection",
14+
"default": "/",
15+
"items": {"/": "/ (forward-slash)", "\\": "\\ (back-slash)", "-": "- (hyphen)", ">":"> (right-angle)"},
16+
},
17+
{
18+
"identifier": "style",
19+
"name": "Tree style",
20+
"description": "Select the preferred tree style",
21+
"type": "selection",
22+
"default": "normalExt",
23+
"items": {"compact": "Compact ASCII", "compactExt": "Compact Extended ASCII", "normal":"Normal ASCII","normalExt":"Normal Extended ASCII"},
24+
},
25+
];
26+
27+
function init() {
28+
script.registerCustomAction("ascii-tree-factory", "Selection to ASCII tree","",true,true,false);
29+
}
30+
31+
function customActionInvoked(identifier) {
32+
switch (identifier) {
33+
case "ascii-tree-factory": {
34+
// applying a style based on selection
35+
switch(style){
36+
case "compactExt":{
37+
var root="──";
38+
var prevLast = " ";
39+
var prevNotLast="";
40+
var currLast="└─";
41+
var currNotLast="├─";
42+
break;
43+
}
44+
case "compact":{
45+
var root="--";
46+
var prevLast = " ";
47+
var prevNotLast="| ";
48+
var currLast="--";
49+
var currNotLast="|-";
50+
break;
51+
}
52+
case "normalExt":{
53+
var root="─── ";
54+
var prevLast = " ";
55+
var prevNotLast="";
56+
var currLast="└── ";
57+
var currNotLast="├── ";
58+
break;
59+
}
60+
case "normal":{
61+
var root="--- ";
62+
var prevLast = " ";
63+
var prevNotLast="| ";
64+
var currLast="--- ";
65+
var currNotLast="|-- ";
66+
break;
67+
}
68+
}
69+
var selection = script.noteTextEditSelectedText();
70+
// break selection strings at line ends
71+
var lines = selection.split("\n");
72+
// initialize tree object
73+
var tree = {};
74+
//for each line in selection
75+
lines.forEach(function(line){
76+
// break line at slashes
77+
var path = line.split(pathSeparator);
78+
var current = tree;
79+
// for each segment
80+
path.forEach(function(subpath){
81+
// if the key doesn't have descendants, attach an empty object.
82+
if (!current[subpath]){
83+
current[subpath] = {};
84+
}
85+
// else move to the next level
86+
current = current[subpath];
3487
});
35-
// uncomment for troubleshooting
36-
// script.log(JSON.stringify(tree));
37-
38-
// Start rendering the codeblock with the "graphical" tree
39-
var codeBlockTree = `\`\`\`\n`;
40-
// init an array to keep track if each level is the last one at that depth
41-
var lastLevel = [];
42-
// recursive function to print the tree
43-
function printTree(tree, level){
44-
lastLevel.push(false);
45-
let keys = Object.keys(tree);
46-
for (var k=0; k < keys.length; k++){
47-
if (k == keys.length - 1){
48-
lastLevel[level]=true;
49-
}
50-
// preparing the string that will be printed before the current key
51-
let previousLevelsRendering = "";
52-
for (var l=0; l<level; l++){
53-
// for each previous level print a "│ " if it's not the last key at that level
54-
previousLevelsRendering += lastLevel[l] ? " " : "";
55-
}
56-
// put together the string to be printed accounting for first level and last key at that level
57-
codeBlockTree += `${(level==0) ? keys[k] : previousLevelsRendering +(lastLevel[level]?"└─" :"├─" )+keys[k]}\n`;
58-
printTree(tree[keys[k]], level + 1);
88+
});
89+
// uncomment for troubleshooting
90+
// script.log(JSON.stringify(tree));
91+
92+
// Start rendering the codeblock with the "graphical" tree
93+
var codeBlockTree = `\`\`\`\n`;
94+
// init an array to keep track if each level is the last one at that depth
95+
var lastLevel = [];
96+
// recursive function to print the tree
97+
function printTree(tree, level){
98+
lastLevel.push(false);
99+
let keys = Object.keys(tree);
100+
for (var k = 0; k < keys.length; k++){
101+
if (k == (keys.length - 1)){
102+
lastLevel[level]=true;
103+
} else {
104+
lastLevel[level]=false;
59105
}
106+
// preparing the string that will be printed before the current key
107+
let previousLevelsRendering = "";
108+
for (var l = 0; l < level; l++){
109+
// for each previous level print a "│ " if it's not the last key at that level
110+
previousLevelsRendering += lastLevel[l] ? prevLast : prevNotLast;
111+
}
112+
// put together the string to be printed accounting for first level and last key at that level
113+
codeBlockTree += `${(level==0) ? root + keys[k] : previousLevelsRendering + (lastLevel[level]? currLast : currNotLast ) + keys[k]}\n`;
114+
printTree(tree[keys[k]], level + 1);
60115
}
61-
// calling the recursive function
62-
printTree(tree, 0);
63-
// closing the codeblock
64-
codeBlockTree += `\`\`\``;
65-
script.noteTextEditWrite(codeBlockTree);
66-
break;
67116
}
68-
}
69-
}
117+
// calling the recursive function
118+
printTree(tree, 0);
119+
// closing the codeblock
120+
codeBlockTree += `\`\`\``;
121+
script.noteTextEditWrite(codeBlockTree);
122+
break;
123+
}
124+
}
125+
}
70126
}

ascii-tree-factory/info.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
"identifier": "ascii-tree-factory",
44
"script": "ascii-tree-factory.qml",
55
"authors": ["@77nnit"],
6-
"platforms": ["windows"],
7-
"version": "0.1.0",
6+
"platforms": ["linux", "windows"],
7+
"version": "0.2.0",
88
"minAppVersion": "24.10.5",
9-
"description" : "This script converts forward-slashes-separated lines to an ASCII tree representation, replacing the selected text."
9+
"description" : "The ASCII Tree Factory plugin for QOwnNotes allows users to <b>generate an ASCII tree representation from a given path structure</b>. This can be particularly useful for visualizing directory structures or any hierarchical data within your notes.</br>Usage:<ol><li><b>Select Text</b>: highlight the text in your note that represents the path structure you want to convert into an ASCII tree. Text can be multi-line</li><li><b>Run the Plugin</b>: Right-click on the selected text, choose Custom Actions > Generate ASCII tree from path.</li><li>The plugin will replace the selected text (single or multi-line) with an ASCII tree representation.</li></ol></br>If you have suggestions or improvements, feel free to reach me using GitHub or Codeberg."
1010
}

ascii-tree-factory/readme.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,22 @@ The ASCII Tree Factory plugin for QOwnNotes allows users to generate an ASCII tr
55

66
## Manual Installation
77

8-
1. **Download the Plugin**: Save the `ASCII-Tree-Factory.qml` file to your local machine.
8+
1. **Download the Plugin**: Save the `ascii-tree-factory.qml` file to your local machine.
99
2. **Add to QOwnNotes**:
1010
- Open QOwnNotes.
1111
- Navigate to `Settings` > `Scripting`.
1212
- Click on `Add script... > Add local script`.
13-
- Select the `ASCII-Tree-Factory.qml` file in the script folder.
13+
- Select the `ascii-tree-factory.qml` file in the script folder.
1414
3. **Activate the Plugin**:
1515
- Go back to QOwnNotes.
16-
- In the `Scripting` settings, ensure that `ASCII-Tree-Factory.qml` is listed and checked.
16+
- In the `Scripting` settings, ensure that `ascii-tree-factory.qml` is listed and checked.
17+
18+
## Settings
19+
20+
Two settings are available in the Script configuration:
21+
22+
- **Path separator**: lets the user select one of the available separators;
23+
- **Tree style**: lets the user choose from 4 ASCII tree styles;
1724

1825
## Usage
1926

@@ -37,13 +44,13 @@ root/folder2/subfolder1/file3.txt
3744
### Output
3845

3946
```
40-
root
41-
├─folder1
42-
│ └─file1.txt
43-
└─folder2
44-
└─file2.txt
45-
└─subfolder1
46-
└─file3.txt
47+
─── root
48+
├── folder1
49+
│ └── file1.txt
50+
└── folder2
51+
├── file2.txt
52+
└── subfolder1
53+
└── file3.txt
4754
```
4855

4956
## Contributing
@@ -52,8 +59,8 @@ If you have suggestions or improvements, feel free to fork the repository and su
5259

5360
## ToDo
5461

55-
- [ ] Generalize settings such as item separator (default is `/`)
56-
- [ ] Provide aesthetic options to the tree generation
62+
- [x] Generalize settings such as item separator (default is `/`)
63+
- [x] Provide aesthetic options to the tree generation
5764
- [ ] Look for libraries that can render good looking and customizable tree structures (any idea???)
5865

5966
## License

0 commit comments

Comments
 (0)