refactor: Simplify prompt content and file map generation

- Extract recursive file tree logic into new helper function
- Remove explicit file content generation from prompt
- Simplify `build_file_map` to only generate file trees
- Eliminate file metadata calculation from `build_file_map`
- Comment out extensive example workspace operations
This commit is contained in:
Mahmoud-Emad
2025-09-09 11:50:12 +03:00
parent 1870f2a7ce
commit 154c08411c
3 changed files with 64 additions and 181 deletions

View File

@@ -9,20 +9,22 @@ import os
// )!
mut workspace := heroprompt.get(
name: 'example_ws'
name: 'example_wsx'
path: '${os.home_dir()}/code/github/freeflowuniverse/herolib'
create: true
)!
println('workspace (initial): ${workspace}')
println('selected (initial): ${workspace.selected_children()}')
// println('workspace (initial): ${workspace}')
// println('selected (initial): ${workspace.selected_children()}')
// Add a directory and a file
workspace.add_dir(path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker')!
workspace.add_file(
path: '${os.home_dir()}/code/github/freeflowuniverse/herolib/docker/docker_ubuntu_install.sh'
)!
println('selected (after add): ${workspace.selected_children()}')
// workspace.add_dir(
// path: '${os.home_dir()}/code/github/freeflowuniverse/docusaurus_template/example/docs/howitworks'
// )!
// workspace.add_file(
// path: '${os.home_dir()}/code/github/freeflowuniverse/docusaurus_template/example/docs/howitworks/participants.md'
// )!
// println('selected (after add): ${workspace.selected_children()}')
// Build a prompt from current selection (should be empty now)
mut prompt := workspace.prompt(
@@ -33,18 +35,18 @@ println('--- PROMPT START ---')
println(prompt)
println('--- PROMPT END ---')
// Remove the file by name, then the directory by name
workspace.remove_file(name: 'docker_ubuntu_install.sh') or { println('remove_file: ${err}') }
workspace.remove_dir(name: 'docker') or { println('remove_dir: ${err}') }
println('selected (after remove): ${workspace.selected_children()}')
// // Remove the file by name, then the directory by name
// workspace.remove_file(name: 'docker_ubuntu_install.sh') or { println('remove_file: ${err}') }
// workspace.remove_dir(name: 'docker') or { println('remove_dir: ${err}') }
// println('selected (after remove): ${workspace.selected_children()}')
// List workspaces (names only)
mut all := heroprompt.list_workspaces() or { []&heroprompt.Workspace{} }
mut names := []string{}
for w in all {
names << w.name
}
println('workspaces: ${names}')
// // List workspaces (names only)
// mut all := heroprompt.list_workspaces() or { []&heroprompt.Workspace{} }
// mut names := []string{}
// for w in all {
// names << w.name
// }
// println('workspaces: ${names}')
// Optionally delete the example workspace
workspace.delete_workspace() or { println('delete_workspace: ${err}') }
// // Optionally delete the example workspace
// workspace.delete_workspace() or { println('delete_workspace: ${err}') }

View File

@@ -185,41 +185,48 @@ pub fn build_file_tree_fs(roots []string, prefix string) string {
connector := if i == roots.len - 1 { ' ' } else { ' ' }
out += '${prefix}${connector}${os.base(root)}\n'
child_prefix := if i == roots.len - 1 { prefix + ' ' } else { prefix + ' ' }
// list children under root
entries := os.ls(root) or { []string{} }
// sort: dirs first then files
mut dirs := []string{}
mut files := []string{}
for e in entries {
fp := os.join_path(root, e)
if os.is_dir(fp) {
dirs << fp
} else if os.is_file(fp) {
files << fp
}
out += build_file_tree_fs_recursive(root, child_prefix)
}
return out
}
// build_file_tree_fs_recursive builds the contents of a directory without adding the directory name itself
fn build_file_tree_fs_recursive(root string, prefix string) string {
mut out := ''
// list children under root
entries := os.ls(root) or { []string{} }
// sort: dirs first then files
mut dirs := []string{}
mut files := []string{}
for e in entries {
fp := os.join_path(root, e)
if os.is_dir(fp) {
dirs << fp
} else if os.is_file(fp) {
files << fp
}
dirs.sort()
files.sort()
// files
for j, f in files {
file_connector := if j == files.len - 1 && dirs.len == 0 {
' '
} else {
' '
}
out += '${child_prefix}${file_connector}${os.base(f)} *\n'
}
dirs.sort()
files.sort()
// files
for j, f in files {
file_connector := if j == files.len - 1 && dirs.len == 0 {
' '
} else {
' '
}
// subdirectories
for j, d in dirs {
sub_connector := if j == dirs.len - 1 { ' ' } else { ' ' }
out += '${child_prefix}${sub_connector}${os.base(d)}\n'
sub_prefix := if j == dirs.len - 1 {
child_prefix + ' '
} else {
child_prefix + ' '
}
out += build_file_tree_fs([d], sub_prefix)
out += '${prefix}${file_connector}${os.base(f)} *\n'
}
// subdirectories
for j, d in dirs {
sub_connector := if j == dirs.len - 1 { ' ' } else { ' ' }
out += '${prefix}${sub_connector}${os.base(d)}\n'
sub_prefix := if j == dirs.len - 1 {
prefix + ' '
} else {
prefix + ' '
}
out += build_file_tree_fs_recursive(d, sub_prefix)
}
return out
}

130
lib/develop/heroprompt/heroprompt_workspace.v Normal file → Executable file
View File

@@ -263,26 +263,6 @@ fn (wsp Workspace) build_file_content() !string {
}
}
}
// files under selected directories, using CodeWalker for filtered traversal
for ch in wsp.children {
if ch.path.cat == .dir && ch.include_tree {
mut cw := codewalker.new(codewalker.CodeWalkerArgs{})!
mut fm := cw.filemap_get(path: ch.path.path)!
for rel, fc in fm.content {
if content.len > 0 {
content += '\n\n'
}
abs := os.join_path(ch.path.path, rel)
content += abs + '\n'
ext := get_file_extension(os.base(abs))
if fc.len == 0 {
content += '(Empty file)\n'
} else {
content += '```' + ext + '\n' + fc + '\n```'
}
}
}
}
return content
}
@@ -300,115 +280,9 @@ fn (wsp Workspace) build_user_instructions(text string) string {
// build_file_map creates a complete file map with base path and metadata
fn (wsp Workspace) build_file_map() string {
mut file_map := ''
// roots are selected directories
mut roots := []HeropromptChild{}
mut files_only := []HeropromptChild{}
for ch in wsp.children {
if ch.path.cat == .dir && ch.include_tree {
roots << ch // only include directories explicitly marked to include subtree
} else if ch.path.cat == .file {
files_only << ch
}
}
if roots.len > 0 || files_only.len > 0 {
// derive a parent path for display
mut parent_path := ''
if roots.len > 0 {
if roots.len == 1 {
// Single root - show parent directory
base_path := roots[0].path.path
parent_path = if base_path.contains('/') {
base_path.split('/')[..base_path.split('/').len - 1].join('/')
} else {
base_path
}
} else {
// Multiple roots - show all root paths, comma-separated
mut root_paths := []string{}
for r in roots {
root_paths << r.path.path
}
parent_path = root_paths.join(', ')
// Truncate if too long for UI display
if parent_path.len > 100 {
parent_path = parent_path[..97] + '...'
}
}
} else {
// no roots; show the parent of first file if available
parent_path = if files_only.len > 0 {
os.dir(files_only[0].path.path)
} else {
''
}
}
// metadata
mut total_files := 0
mut total_content_length := 0
mut file_extensions := map[string]int{}
// files under dirs (only when roots present)
if roots.len > 0 {
for r in roots {
for f in codewalker.list_files_recursive(r.path.path) {
total_files++
ext := get_file_extension(os.base(f))
if ext.len > 0 {
file_extensions[ext] = file_extensions[ext] + 1
}
total_content_length += (os.read_file(f) or { '' }).len
}
}
}
// standalone files
for fo in files_only {
total_files++
ext := get_file_extension(fo.name)
if ext.len > 0 {
file_extensions[ext] = file_extensions[ext] + 1
}
// if content not loaded, read length on demand
file_len := if fo.content.len == 0 {
(os.read_file(fo.path.path) or { '' }).len
} else {
fo.content.len
}
total_content_length += file_len
}
mut extensions_summary := ''
for ext, count in file_extensions {
if extensions_summary.len > 0 {
extensions_summary += ', '
}
extensions_summary += '${ext}(${count})'
}
file_map = '${parent_path}\n'
file_map += '# Selected Files: ${total_files} | Total Content: ${total_content_length} chars'
if extensions_summary.len > 0 {
file_map += ' | Extensions: ${extensions_summary}'
}
file_map += '\n\n'
// Build a comprehensive tree that includes all files from selected directories
mut all_file_paths := []string{}
// For each selected directory, get all files within it
for r in roots {
mut cw := codewalker.new(codewalker.CodeWalkerArgs{}) or { continue }
fm := cw.filemap_get(path: r.path.path) or { continue }
for rel_path, _ in fm.content {
abs_file_path := os.join_path(r.path.path, rel_path)
all_file_paths << abs_file_path
}
}
// Add all standalone file paths
for fo in files_only {
all_file_paths << fo.path.path
}
if all_file_paths.len > 0 {
// Build a tree that shows all files in their proper directory structure
file_map += codewalker.build_file_tree_fs(all_file_paths, '')
}
file_map += codewalker.build_file_tree_fs([ch.path.path], '')
file_map += '\n'
}
return file_map
}