Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 116 additions & 60 deletions ascii-tree-factory/ascii-tree-factory.qml
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,125 @@ import QtQml 2.0
import QOwnNotesTypes 1.0

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

function customActionInvoked(identifier) {
switch (identifier) {
case "ascii-tree-factory": {
var selection = script.noteTextEditSelectedText();
// break selection strings at line ends
var lines = selection.split("\n");
// initialize tree object
var tree = {};
//for each line in selection
lines.forEach(function(line){
// break line at slashes
var path = line.split("/");
var current = tree;
// for each segment
path.forEach(function(subpath){
// if the key doesn't have descendants, attach an empty object.
if (!current[subpath]){
current[subpath] = {};
}
// else move to the next level
current = current[subpath];
});
property variant settingsVariables: [
{
"identifier": "pathSeparator",
"name": "Path separator",
"description": "Please select a separator character:",
"type": "selection",
"default": "/",
"items": {"/": "/ (forward-slash)", "\\": "\\ (back-slash)", "-": "- (hyphen)", ">":"> (right-angle)"},
},
{
"identifier": "style",
"name": "Tree style",
"description": "Select the preferred tree style",
"type": "selection",
"default": "normalExt",
"items": {"compact": "Compact ASCII", "compactExt": "Compact Extended ASCII", "normal":"Normal ASCII","normalExt":"Normal Extended ASCII"},
},
];

function init() {
script.registerCustomAction("ascii-tree-factory", "Selection to ASCII tree","",true,true,false);
}

function customActionInvoked(identifier) {
switch (identifier) {
case "ascii-tree-factory": {
// applying a style based on selection
switch(style){
case "compactExt":{
var root="──";
var prevLast = " ";
var prevNotLast="│ ";
var currLast="└─";
var currNotLast="├─";
break;
}
case "compact":{
var root="--";
var prevLast = " ";
var prevNotLast="| ";
var currLast="--";
var currNotLast="|-";
break;
}
case "normalExt":{
var root="─── ";
var prevLast = " ";
var prevNotLast="│ ";
var currLast="└── ";
var currNotLast="├── ";
break;
}
case "normal":{
var root="--- ";
var prevLast = " ";
var prevNotLast="| ";
var currLast="--- ";
var currNotLast="|-- ";
break;
}
}
var selection = script.noteTextEditSelectedText();
// break selection strings at line ends
var lines = selection.split("\n");
// initialize tree object
var tree = {};
//for each line in selection
lines.forEach(function(line){
// break line at slashes
var path = line.split(pathSeparator);
var current = tree;
// for each segment
path.forEach(function(subpath){
// if the key doesn't have descendants, attach an empty object.
if (!current[subpath]){
current[subpath] = {};
}
// else move to the next level
current = current[subpath];
});
// uncomment for troubleshooting
// script.log(JSON.stringify(tree));

// Start rendering the codeblock with the "graphical" tree
var codeBlockTree = `\`\`\`\n`;
// init an array to keep track if each level is the last one at that depth
var lastLevel = [];
// recursive function to print the tree
function printTree(tree, level){
lastLevel.push(false);
let keys = Object.keys(tree);
for (var k=0; k < keys.length; k++){
if (k == keys.length - 1){
lastLevel[level]=true;
}
// preparing the string that will be printed before the current key
let previousLevelsRendering = "";
for (var l=0; l<level; l++){
// for each previous level print a "│ " if it's not the last key at that level
previousLevelsRendering += lastLevel[l] ? " " : "│ ";
}
// put together the string to be printed accounting for first level and last key at that level
codeBlockTree += `${(level==0) ? keys[k] : previousLevelsRendering +(lastLevel[level]?"└─" :"├─" )+keys[k]}\n`;
printTree(tree[keys[k]], level + 1);
});
// uncomment for troubleshooting
// script.log(JSON.stringify(tree));

// Start rendering the codeblock with the "graphical" tree
var codeBlockTree = `\`\`\`\n`;
// init an array to keep track if each level is the last one at that depth
var lastLevel = [];
// recursive function to print the tree
function printTree(tree, level){
lastLevel.push(false);
let keys = Object.keys(tree);
for (var k = 0; k < keys.length; k++){
if (k == (keys.length - 1)){
lastLevel[level]=true;
} else {
lastLevel[level]=false;
}
// preparing the string that will be printed before the current key
let previousLevelsRendering = "";
for (var l = 0; l < level; l++){
// for each previous level print a "│ " if it's not the last key at that level
previousLevelsRendering += lastLevel[l] ? prevLast : prevNotLast;
}
// put together the string to be printed accounting for first level and last key at that level
codeBlockTree += `${(level==0) ? root + keys[k] : previousLevelsRendering + (lastLevel[level]? currLast : currNotLast ) + keys[k]}\n`;
printTree(tree[keys[k]], level + 1);
}
// calling the recursive function
printTree(tree, 0);
// closing the codeblock
codeBlockTree += `\`\`\``;
script.noteTextEditWrite(codeBlockTree);
break;
}
}
}
// calling the recursive function
printTree(tree, 0);
// closing the codeblock
codeBlockTree += `\`\`\``;
script.noteTextEditWrite(codeBlockTree);
break;
}
}
}
}
6 changes: 3 additions & 3 deletions ascii-tree-factory/info.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"identifier": "ascii-tree-factory",
"script": "ascii-tree-factory.qml",
"authors": ["@77nnit"],
"platforms": ["windows"],
"version": "0.1.0",
"platforms": ["linux", "windows"],
"version": "0.2.0",
"minAppVersion": "24.10.5",
"description" : "This script converts forward-slashes-separated lines to an ASCII tree representation, replacing the selected text."
"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."
}
31 changes: 19 additions & 12 deletions ascii-tree-factory/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,22 @@ The ASCII Tree Factory plugin for QOwnNotes allows users to generate an ASCII tr

## Manual Installation

1. **Download the Plugin**: Save the `ASCII-Tree-Factory.qml` file to your local machine.
1. **Download the Plugin**: Save the `ascii-tree-factory.qml` file to your local machine.
2. **Add to QOwnNotes**:
- Open QOwnNotes.
- Navigate to `Settings` > `Scripting`.
- Click on `Add script... > Add local script`.
- Select the `ASCII-Tree-Factory.qml` file in the script folder.
- Select the `ascii-tree-factory.qml` file in the script folder.
3. **Activate the Plugin**:
- Go back to QOwnNotes.
- In the `Scripting` settings, ensure that `ASCII-Tree-Factory.qml` is listed and checked.
- In the `Scripting` settings, ensure that `ascii-tree-factory.qml` is listed and checked.

## Settings

Two settings are available in the Script configuration:

- **Path separator**: lets the user select one of the available separators;
- **Tree style**: lets the user choose from 4 ASCII tree styles;

## Usage

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

```
root
├─folder1
│ └─file1.txt
└─folder2
└─file2.txt
└─subfolder1
└─file3.txt
─── root
├── folder1
│ └── file1.txt
└── folder2
├── file2.txt
└── subfolder1
└── file3.txt
```

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

## ToDo

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

## License
Expand Down
Loading