File size: 4,361 Bytes
5bdd26d 230b1a5 560aacd 6ee54ae 5bdd26d 230b1a5 5bdd26d 230b1a5 5bdd26d 230b1a5 5bdd26d 230b1a5 5bdd26d 230b1a5 5bdd26d 560aacd 5bdd26d 560aacd 5bdd26d 560aacd 5bdd26d 3fcefb9 6ee54ae 5bdd26d 3fcefb9 5bdd26d 6ee54ae 5bdd26d 6ee54ae |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# app.py
import streamlit as st
from pathlib import Path
from core.file_scanner import FileScanner, FileInfo
# セッション状態を初期化
if 'scanned_files' not in st.session_state:
st.session_state.scanned_files = [] # List[FileInfo]
if 'selected_files' not in st.session_state:
st.session_state.selected_files = set() # {Path} 相対パス or 絶対パス
st.title("指定拡張子のみディレクトリスキャン & 選択ダウンロード")
# --- 1) ユーザー入力: スキャンしたいローカルディレクトリパス ---
dir_path_str = st.text_input("ローカルディレクトリパス", value=".")
# --- 2) ユーザー入力: スキャン対象拡張子選択 ---
st.subheader("スキャン対象拡張子")
available_exts = [".py", ".js", ".ts", ".md", ".txt", ".java", ".cpp"]
chosen_exts = []
for ext in available_exts:
if st.checkbox(ext, key=f"ext_{ext}", value=(ext in [".py", ".md"])):
chosen_exts.append(ext)
# --- 3) 「スキャン実行」ボタン ---
if st.button("スキャン開始"):
base_path = Path(dir_path_str).resolve()
if not base_path.is_dir():
st.error("有効なディレクトリを指定してください")
else:
scanner = FileScanner(base_path, set(chosen_exts))
found_files = scanner.scan_files()
st.session_state.scanned_files = found_files
st.session_state.selected_files = set() # スキャン毎に選択リセット
st.success(f"スキャン完了: {len(found_files)}個のファイル")
# --- 4) ファイルを表示するUI(ディレクトリ構造 or リスト) + 全選択 / 全解除 ---
if st.session_state.scanned_files:
# 全選択 / 全解除ボタン
col1, col2 = st.columns(2)
with col1:
if st.button("すべて選択"):
# すべてのファイルを選択
base_path = Path(dir_path_str).resolve()
# relative_to で相対パスを使うか、絶対パスを使うかは好みでOK
st.session_state.selected_files = {
f.path.relative_to(base_path) for f in st.session_state.scanned_files
}
with col2:
if st.button("すべて解除"):
st.session_state.selected_files = set()
st.write("### ファイル一覧 (指定拡張子のみ)")
base_path = Path(dir_path_str).resolve()
for file_info in st.session_state.scanned_files:
# 相対パスで扱う例
rel_path = file_info.path.relative_to(base_path)
checked = (rel_path in st.session_state.selected_files)
# チェックボックス + ファイル名表示
new_checked = st.checkbox(
f"{rel_path} ({file_info.formatted_size})",
value=checked,
key=str(rel_path) # keyは重複しないように文字列にしておく
)
# 選択状態を更新
if new_checked:
st.session_state.selected_files.add(rel_path)
else:
st.session_state.selected_files.discard(rel_path)
# --- 5) 選択ファイルをまとめてMarkdown化 & ダウンロード ---
def create_markdown_for_selected(files, selected_paths, base_dir: Path) -> str:
"""
選択されたファイルだけをMarkdownテキストとして返す
"""
output = []
for f in files:
rel_path = f.path.relative_to(base_dir)
if rel_path in selected_paths:
output.append(f"## {rel_path}")
output.append("------------")
if f.content is not None:
output.append(f.content)
else:
output.append("# Failed to read content")
output.append("") # 空行
return "\n".join(output)
if st.session_state.scanned_files:
st.write("### 選択ファイルをMarkdownダウンロード")
if st.button("選択ファイルをまとめてダウンロード"):
base_path = Path(dir_path_str).resolve()
markdown_text = create_markdown_for_selected(
st.session_state.scanned_files,
st.session_state.selected_files,
base_path
)
st.download_button(
label="ダウンロード",
data=markdown_text,
file_name="selected_files.md",
mime="text/markdown"
)
|