dotfiles

Repositório dotfiles
git clone git://git.sivaldodavi.com/dotfiles.git
Log | Files | Refs | README

commit e7c870cf962cc5a5d81e0aa82dda60d1ff84c367
parent 20f2333605be1a355087ffd9b39c9e4f14d0e6cf
Author: Sivaldo <gxixtx@xsxixvxaxlxdxoxdxaxvxix.xcxoxm>
Date:   Mon, 10 Aug 2026 15:20:45 -0300

feat(culto): adicionar categorias de músicas e ajustar cabeçalhos

Diffstat:
M.local/bin/culto | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 70 insertions(+), 22 deletions(-)

diff --git a/.local/bin/culto b/.local/bin/culto @@ -127,14 +127,15 @@ def slides_read(rows, ref_label, no_cover, resp): if resp: for i, row in enumerate(rows): label = "DIRIGENTE" if i % 2 == 0 else "IGREJA" - out += [f"{label}\n{row['verse']}. {row['text']}", ""] + header = f"{row['book']} {row['chapter']} ({label})" + out += [f"{header}\n{row['verse']}. {row['text']}", ""] else: full_text = " ".join(f"{r['verse']}. {r['text']}" for r in rows) chunks = _chunks(full_text, SLIDE_WIDTH) for i, chunk in enumerate(chunks): pre = "... " if i > 0 else "" pos = " ..." if i < len(chunks) - 1 else "" - out += [f"{pre}{chunk}{pos}", ""] + out += [f"{ref_label}\n{pre}{chunk}{pos}", ""] return "\n".join(out) def terminal_read(rows, ref_label): @@ -215,14 +216,15 @@ clear_sent() { _ensure_musicas() { if [ ! -f "$MUSICAS_FILE" ]; then - echo "{}" > "$MUSICAS_FILE" # Cria vazio se não existir + # Cria vazio, já com as categorias, se não existir + printf '{\n "Hinos": {},\n "Salmos": {},\n "Cânticos Espirituais": {}\n}\n' > "$MUSICAS_FILE" fi } _render_json_song() { local title="$1" MUSICAS_FILE="$MUSICAS_FILE" python3 - "$title" <<'PYEOF' -import sys, json, os, signal +import sys, json, os, re, signal signal.signal(signal.SIGPIPE, signal.SIG_DFL) @@ -230,12 +232,25 @@ musicas_file = os.environ["MUSICAS_FILE"] target_title = sys.argv[1] with open(musicas_file, encoding='utf-8') as f: - songs = json.load(f) - -if target_title in songs: - print(target_title) - print("\n\n") - for stanza in songs[target_title]: + categorias = json.load(f) + +# Procura o título em qualquer categoria (Hinos / Salmos / Cânticos Espirituais) +stanzas = None +for cat_songs in categorias.values(): + if target_title in cat_songs: + stanzas = cat_songs[target_title] + break + +if stanzas is not None: + m = re.match(r'^(\d+(?:-[A-Za-z])?)\s*-\s*.+$', target_title) + if m: + print(f"HINO {m.group(1)}") + print("\n\n") + elif re.search(r'salmo', target_title, re.IGNORECASE): + print(target_title) + print("\n\n") + + for stanza in stanzas: print(stanza) print("\n") else: @@ -248,9 +263,13 @@ pick_song() { _ensure_musicas || return 1 local chosen - # Adicionado o signal import e handler aqui também no one-liner - chosen=$(python3 -c "import json, signal; signal.signal(signal.SIGPIPE, signal.SIG_DFL); data=json.load(open('$MUSICAS_FILE')); print('\n'.join(sorted(data.keys())))" \ - | fzf --reverse --prompt="Música: ") + chosen=$(python3 -c " +import json, signal +signal.signal(signal.SIGPIPE, signal.SIG_DFL) +data = json.load(open('$MUSICAS_FILE')) +titulos = sorted(t for cat_songs in data.values() for t in cat_songs) +print('\n'.join(titulos)) +" | fzf --reverse --prompt="Música: ") [ -z "$chosen" ] && return 0 @@ -274,6 +293,8 @@ action = sys.argv[1] title = sys.argv[2] tmp_md = sys.argv[3] +CATEGORIAS = ["Hinos", "Salmos", "Cânticos Espirituais"] + if os.path.exists(musicas_file): with open(musicas_file, 'r', encoding='utf-8') as f: try: @@ -283,26 +304,48 @@ if os.path.exists(musicas_file): else: songs = {} +# Garante que as categorias existam +for c in CATEGORIAS: + songs.setdefault(c, {}) + +def find_category(title): + """Procura em qual categoria o título já existe. None se for novo.""" + for cat in CATEGORIAS: + if title in songs.get(cat, {}): + return cat + return None + +def infer_category(title): + """Para músicas novas: decide a categoria pelo padrão do título.""" + if re.match(r'^\d+(?:-[A-Za-z])?\s*-\s*.+$', title): + return "Hinos" + if re.search(r'salmo', title, re.IGNORECASE): + return "Salmos" + return "Cânticos Espirituais" + if action == "extract": - text = "\n\n".join(songs.get(title, [])) + cat = find_category(title) + text = "\n\n".join(songs.get(cat, {}).get(title, [])) if cat else "" with open(tmp_md, 'w', encoding='utf-8') as f: f.write(f"# {title}\n\n{text}\n") - + elif action == "save": with open(tmp_md, 'r', encoding='utf-8') as f: content = f.read() - + # Remove o título em markdown (ex: # Nome da música) content = re.sub(r'^#.*\n?', '', content, flags=re.MULTILINE) - + # Separa os blocos (estrofes) por linhas em branco stanzas = [b.strip() for b in re.split(r'\n{2,}', content) if b.strip()] - + if stanzas: - songs[title] = stanzas + # Se já existe em alguma categoria, atualiza lá; senão, infere a categoria + cat = find_category(title) or infer_category(title) + songs[cat][title] = stanzas with open(musicas_file, 'w', encoding='utf-8') as f: json.dump(songs, f, ensure_ascii=False, indent=2) - print(f"✅ Música salva com sucesso no JSON!") + print(f"✅ Música salva com sucesso em '{cat}'!") else: print("⚠️ Nenhuma estrofe encontrada. Alteração descartada.") PYEOF @@ -329,8 +372,13 @@ edit_song() { _ensure_musicas || return 1 local chosen - chosen=$(python3 -c "import json, signal; signal.signal(signal.SIGPIPE, signal.SIG_DFL); data=json.load(open('$MUSICAS_FILE')); print('\n'.join(sorted(data.keys())))" \ - | fzf --reverse --prompt="Editar Música: ") + chosen=$(python3 -c " +import json, signal +signal.signal(signal.SIGPIPE, signal.SIG_DFL) +data = json.load(open('$MUSICAS_FILE')) +titulos = sorted(t for cat_songs in data.values() for t in cat_songs) +print('\n'.join(titulos)) +" | fzf --reverse --prompt="Editar Música: ") [ -z "$chosen" ] && return 0