This commit is contained in:
thePR0M3TH3AN
2025-05-15 23:33:27 -04:00
parent e82c5cb53e
commit b606f6ed29
3 changed files with 80 additions and 68 deletions

View File

@@ -1,99 +1,75 @@
# Quick start & Demo
## Quick start
```bash
# initialize the demo database
marlin init
# index only your demo folder
marlin scan ~/marlin_demo_complex
# tag all markdown in your demo Projects as “project/md”
marlin tag "~/marlin_demo_complex/Projects/**/*.md" project/md
# mark your demo reports as reviewed
marlin attr set "~/marlin_demo_complex/Reports/*.pdf" reviewed yes
# search for any reviewed files
marlin search "attr:reviewed=yes"
# snapshot the demo database
marlin backup
# test linking within your demo
touch ~/marlin_demo_complex/foo.txt ~/marlin_demo_complex/bar.txt
marlin scan ~/marlin_demo_complex
foo=~/marlin_demo_complex/foo.txt
bar=~/marlin_demo_complex/bar.txt
marlin link add "$foo" "$bar"
marlin link list "$foo"
marlin link backlinks "$bar"
````
---
# Marlin Demo # Marlin Demo
Heres a little “complexdemo you can spin up to exercise tags, attributes, FTS queries, `--exec` hooks, backups & restores. Just copypaste each block into your terminal: Heres a little demo you can spin up to exercise tags, attributes, FTS queries, `--exec` hooks, backups & restores, and linking. Just copypaste each block into your terminal:
---
### 0Create the demo folder and some files ### 0Create the demo folder and some files
```bash ```bash
rm -rf ~/marlin_demo_complex cargo build --release
mkdir -p ~/marlin_demo_complex/{Projects/{Alpha,Beta,Gamma},Logs,Reports,Scripts,Media/Photos} ```
```bash
sudo install -Dm755 target/release/marlin /usr/local/bin/marlin
```
```bash
rm -rf ~/marlin_demo
mkdir -p ~/marlin_demo/{Projects/{Alpha,Beta,Gamma},Logs,Reports,Scripts,Media/Photos}
# Projects # Projects
cat <<EOF > ~/marlin_demo_complex/Projects/Alpha/draft1.md cat <<EOF > ~/marlin_demo/Projects/Alpha/draft1.md
# Alpha draft 1 # Alpha draft 1
- [ ] TODO: outline architecture - [ ] TODO: outline architecture
- [ ] TODO: write tests - [ ] TODO: write tests
EOF EOF
cat <<EOF > ~/marlin_demo_complex/Projects/Alpha/draft2.md cat <<EOF > ~/marlin_demo/Projects/Alpha/draft2.md
# Alpha draft 2 # Alpha draft 2
- [x] TODO: outline architecture - [x] TODO: outline architecture
- [ ] TODO: implement feature X - [ ] TODO: implement feature X
EOF EOF
cat <<EOF > ~/marlin_demo_complex/Projects/Beta/notes.md cat <<EOF > ~/marlin_demo/Projects/Beta/notes.md
Beta meeting notes: Beta meeting notes:
- decided on roadmap - decided on roadmap
- ACTION: follow up with design team - ACTION: follow up with design team
EOF EOF
cat <<EOF > ~/marlin_demo_complex/Projects/Beta/final.md cat <<EOF > ~/marlin_demo/Projects/Beta/final.md
# Beta Final # Beta Final
All tasks complete. Ready to ship! All tasks complete. Ready to ship!
EOF EOF
cat <<EOF > ~/marlin_demo_complex/Projects/Gamma/TODO.txt cat <<EOF > ~/marlin_demo/Projects/Gamma/TODO.txt
Gamma tasks: Gamma tasks:
TODO: refactor module Y TODO: refactor module Y
EOF EOF
# Logs # Logs
echo "2025-05-15 12:00:00 INFO Starting app" > ~/marlin_demo_complex/Logs/app.log echo "2025-05-15 12:00:00 INFO Starting app" > ~/marlin_demo/Logs/app.log
echo "2025-05-15 12:01:00 ERROR Oops, crash" >> ~/marlin_demo_complex/Logs/app.log echo "2025-05-15 12:01:00 ERROR Oops, crash" >> ~/marlin_demo/Logs/app.log
echo "2025-05-15 00:00:00 INFO System check OK" > ~/marlin_demo_complex/Logs/system.log echo "2025-05-15 00:00:00 INFO System check OK" > ~/marlin_demo/Logs/system.log
# Reports # Reports
printf "Q1 financials\n" > ~/marlin_demo_complex/Reports/Q1_report.pdf printf "Q1 financials
" > ~/marlin_demo/Reports/Q1_report.pdf
# Scripts # Scripts
cat <<'EOF' > ~/marlin_demo_complex/Scripts/deploy.sh cat <<'EOF' > ~/marlin_demo/Scripts/deploy.sh
#!/usr/bin/env bash #!/usr/bin/env bash
echo "Deploying version $1..." echo "Deploying version $1..."
EOF EOF
chmod +x ~/marlin_demo_complex/Scripts/deploy.sh chmod +x ~/marlin_demo/Scripts/deploy.sh
# Media # Media
echo "JPEGDATA" > ~/marlin_demo_complex/Media/Photos/event.jpg echo "JPEGDATA" > ~/marlin_demo/Media/Photos/event.jpg
``` ```
--- ---
@@ -102,7 +78,7 @@ echo "JPEGDATA" > ~/marlin_demo_complex/Media/Photos/event.jpg
```bash ```bash
marlin init marlin init
marlin scan ~/marlin_demo_complex marlin scan ~/marlin_demo
``` ```
--- ---
@@ -111,13 +87,13 @@ marlin scan ~/marlin_demo_complex
```bash ```bash
# Tag all project markdown as “project/md” # Tag all project markdown as “project/md”
marlin tag "~/marlin_demo_complex/Projects/**/*.md" project/md marlin tag "~/marlin_demo/Projects/**/*.md" project/md
# Tag your logs # Tag your logs
marlin tag "~/marlin_demo_complex/Logs/**/*.log" logs/app marlin tag "~/marlin_demo/Logs/**/*.log" logs/app
# Tag everything under Projects/Beta as “project/beta” # Tag everything under Projects/Beta as “project/beta”
marlin tag "~/marlin_demo_complex/Projects/Beta/**/*" project/beta marlin tag "~/marlin_demo/Projects/Beta/**/*" project/beta
``` ```
--- ---
@@ -126,10 +102,10 @@ marlin tag "~/marlin_demo_complex/Projects/Beta/**/*" project/beta
```bash ```bash
# Mark only the “final.md” as complete # Mark only the “final.md” as complete
marlin attr set "~/marlin_demo_complex/Projects/Beta/final.md" status complete marlin attr set "~/marlin_demo/Projects/Beta/final.md" status complete
# Mark PDF as reviewed # Mark PDF as reviewed
marlin attr set "~/marlin_demo_complex/Reports/*.pdf" reviewed yes marlin attr set "~/marlin_demo/Reports/*.pdf" reviewed yes
``` ```
--- ---
@@ -161,8 +137,8 @@ marlin search "attr:reviewed=yes" --exec 'xdg-open {}'
### 5Try JSON output & verbose mode ### 5Try JSON output & verbose mode
```bash ```bash
marlin --format=json attr ls ~/marlin_demo_complex/Projects/Beta/final.md marlin --format=json attr ls ~/marlin_demo/Projects/Beta/final.md
marlin --verbose scan ~/marlin_demo_complex marlin --verbose scan ~/marlin_demo
``` ```
--- ---
@@ -181,4 +157,42 @@ marlin restore "$snap"
# Confirm you still see “TODO” # Confirm you still see “TODO”
marlin search TODO marlin search TODO
``` ```
---
### 7Test linking functionality
```bash
# Create two demo files
touch ~/marlin_demo/foo.txt ~/marlin_demo/bar.txt
# Re-scan to index new files
marlin scan ~/marlin_demo
# Link foo.txt → bar.txt
foo=~/marlin_demo/foo.txt
bar=~/marlin_demo/bar.txt
marlin link add "$foo" "$bar"
# List outgoing links for foo.txt
marlin link list "$foo"
# List incoming links (backlinks) to bar.txt
marlin link backlinks "$bar"
```
---
That gives you:
* **wide folder structures** (Projects, Logs, Reports, Scripts, Media)
* **hierarchical tags** you can mix and match
* **key-value attributes** to flag state & review
* **FTS5 queries** with AND/OR/NOT
* **`--exec` hooks** to trigger external commands
* **JSON output** for programmatic gluing
* **backups & restores** to guard your data
* **file-to-file links** for graph relationships
Have fun playing around!

View File

@@ -217,8 +217,8 @@ fn attr_ls(conn: &rusqlite::Connection, path: &std::path::Path) -> Result<()> {
} }
/// Build and run an FTS5 search query, with optional exec. /// Build and run an FTS5 search query, with optional exec.
/// Now splits “tag:foo/bar” into `tags_text:foo AND tags_text:bar` /// “tag:foo/bar” tags_text:foo AND tags_text:bar
/// and “attr:key=value” into `attrs_text:key AND attrs_text:value`. /// “attr:key=value” attrs_text:"key=value"
fn run_search(conn: &rusqlite::Connection, raw_query: &str, exec: Option<String>) -> Result<()> { fn run_search(conn: &rusqlite::Connection, raw_query: &str, exec: Option<String>) -> Result<()> {
let mut fts_query_parts = Vec::new(); let mut fts_query_parts = Vec::new();
let parts = shlex::split(raw_query).unwrap_or_else(|| vec![raw_query.to_string()]); let parts = shlex::split(raw_query).unwrap_or_else(|| vec![raw_query.to_string()]);
@@ -234,13 +234,11 @@ fn run_search(conn: &rusqlite::Connection, raw_query: &str, exec: Option<String>
fts_query_parts.push(format!("tags_text:{}", escape_fts_query_term(seg))); fts_query_parts.push(format!("tags_text:{}", escape_fts_query_term(seg)));
} }
} else if let Some(attr) = part.strip_prefix("attr:") { } else if let Some(attr) = part.strip_prefix("attr:") {
if let Some((k, v)) = attr.split_once('=') { // treat the entire key=value as one term
fts_query_parts.push(format!("attrs_text:{}", escape_fts_query_term(k))); fts_query_parts.push(format!(
fts_query_parts.push("AND".into()); "attrs_text:{}",
fts_query_parts.push(format!("attrs_text:{}", escape_fts_query_term(v))); escape_fts_query_term(attr)
} else { ));
fts_query_parts.push(format!("attrs_text:{}", escape_fts_query_term(attr)));
}
} else { } else {
fts_query_parts.push(escape_fts_query_term(&part)); fts_query_parts.push(escape_fts_query_term(&part));
} }

Binary file not shown.