Skip to content
Open
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
93 changes: 91 additions & 2 deletions src/cli/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ enum Commands {
action: Option<ConfigAction>,
},

/// Manage file extensions
Extensions {
#[command(subcommand)]
action: ExtensionsAction,
},

/// Install vgrep integration for coding agents
Install {
#[command(subcommand)]
Expand Down Expand Up @@ -221,6 +227,24 @@ enum ConfigAction {
Path,
}

#[derive(Subcommand)]
enum ExtensionsAction {
/// List configured extensions
List,

/// Add an extension to the list
Add {
/// Extension to add (e.g. "rs", ".txt")
extension: String,
},

/// Remove an extension from the list
Remove {
/// Extension to remove
extension: String,
},
}

#[derive(Clone, ValueEnum)]
enum ConfigKey {
Mode,
Expand Down Expand Up @@ -319,6 +343,7 @@ impl Cli {
Some(Commands::Status) => run_status(&config),
Some(Commands::Models { action }) => run_models(action, &mut config),
Some(Commands::Config { action }) => run_config(action, &mut config),
Some(Commands::Extensions { action }) => run_extensions(action, &mut config),
Some(Commands::Install { agent }) => match agent {
InstallAgent::ClaudeCode => super::install::install_claude_code(),
InstallAgent::Opencode => super::install::install_opencode(),
Expand Down Expand Up @@ -516,7 +541,7 @@ fn run_index(
}

let db = Database::new(&config.db_path()?)?;
let indexer = ServerIndexer::new(db, client, max_size);
let indexer = ServerIndexer::new(db, client, config.clone());
indexer.index_directory(&path, force)?;
}
Mode::Local => {
Expand All @@ -531,7 +556,7 @@ fn run_index(

let db = Database::new(&config.db_path()?)?;
let engine = EmbeddingEngine::new(config)?;
let indexer = Indexer::new(db, engine, max_size);
let indexer = Indexer::new(db, engine, config.clone());
indexer.index_directory(&path, force)?;
}
}
Expand Down Expand Up @@ -1002,6 +1027,70 @@ fn run_models(action: ModelsAction, config: &mut Config) -> Result<()> {
Ok(())
}

fn run_extensions(action: ExtensionsAction, config: &mut Config) -> Result<()> {
match action {
ExtensionsAction::List => {
ui::print_header("Configured Extensions");

if config.extensions.is_empty() {
println!(" {} No extensions configured (using hardcoded defaults?)", ui::WARN);
return Ok(());
}

// Group by first letter for better readability, or just list them sorted
let mut extensions = config.extensions.clone();
extensions.sort();

println!(" {}", style("Extensions allowlist:").bold());
let mut current_line = String::from(" ");

for (i, ext) in extensions.iter().enumerate() {
let item = format!(".{}", ext);
if current_line.len() + item.len() > 80 {
println!("{}", current_line);
current_line = String::from(" ");
}
current_line.push_str(&item);
if i < extensions.len() - 1 {
current_line.push_str(", ");
}
}
if !current_line.trim().is_empty() {
println!("{}", current_line);
}
println!();

println!(
" Add more with: {}",
style("vgrep extensions add .custom").cyan()
);
println!();
}
ExtensionsAction::Add { extension } => {
let ext = extension.trim_start_matches('.').to_lowercase();
if config.extensions.contains(&ext) {
ui::print_warning(&format!("Extension '.{}' is already in the list", ext));
return Ok(());
}

config.extensions.push(ext.clone());
config.save()?;
ui::print_success(&format!("Added extension '.{}'", ext));
}
ExtensionsAction::Remove { extension } => {
let ext = extension.trim_start_matches('.').to_lowercase();
if let Some(pos) = config.extensions.iter().position(|e| e == &ext) {
config.extensions.remove(pos);
config.save()?;
ui::print_success(&format!("Removed extension '.{}'", ext));
} else {
ui::print_warning(&format!("Extension '.{}' was not in the list", ext));
}
}
}
Ok(())
}

fn run_config(action: Option<ConfigAction>, config: &mut Config) -> Result<()> {
match action {
None => {
Expand Down
21 changes: 21 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ pub struct Config {
/// Context size for embeddings
#[serde(default = "default_context_size")]
pub context_size: usize,

/// List of file extensions to index
#[serde(default = "default_extensions")]
pub extensions: Vec<String>,
}

fn default_server_host() -> String {
Expand Down Expand Up @@ -159,6 +163,22 @@ fn default_context_size() -> usize {
512
}

fn default_extensions() -> Vec<String> {
vec![
"rs".into(), "py".into(), "js".into(), "ts".into(), "tsx".into(), "jsx".into(),
"go".into(), "c".into(), "cpp".into(), "h".into(), "hpp".into(), "java".into(),
"kt".into(), "swift".into(), "rb".into(), "php".into(), "cs".into(), "fs".into(),
"scala".into(), "clj".into(), "ex".into(), "exs".into(), "erl".into(), "hs".into(),
"ml".into(), "lua".into(), "r".into(), "jl".into(), "dart".into(), "vue".into(),
"svelte".into(), "astro".into(), "html".into(), "htm".into(), "css".into(),
"scss".into(), "sass".into(), "less".into(), "json".into(), "yaml".into(),
"yml".into(), "toml".into(), "xml".into(), "md".into(), "markdown".into(),
"txt".into(), "rst".into(), "tex".into(), "sh".into(), "bash".into(),
"zsh".into(), "fish".into(), "ps1".into(), "bat".into(), "cmd".into(),
"sql".into(), "graphql".into(), "proto".into(),
]
}

fn default_use_reranker() -> bool {
true
}
Expand All @@ -182,6 +202,7 @@ impl Default for Config {
watch_debounce_ms: default_watch_debounce_ms(),
n_threads: 0,
context_size: default_context_size(),
extensions: default_extensions(),
}
}
}
Expand Down
Loading
Loading