Packages
portfolio_coder
0.1.0
Code Intelligence Platform built on the Portfolio RAG ecosystem. Repository analysis, semantic code search, dependency graphs, and AI-powered code understanding with multi-language support.
Current section
Files
Jump to
Current section
Files
lib/mix/tasks/code.search.ex
defmodule Mix.Tasks.Code.Search do
@moduledoc """
Search indexed code repositories.
## Usage
mix code.search QUERY [OPTIONS]
## Options
* `--index` - Name of the index to search (default: "default")
* `--language` - Filter by programming language
* `--limit` - Maximum number of results (default: 10)
* `--file` - Filter by file pattern
## Examples
mix code.search "authentication logic"
mix code.search "database connection" --language elixir
mix code.search "error handling" --limit 5
mix code.search "API endpoint" --file "controllers/"
"""
use Mix.Task
@shortdoc "Search indexed code"
@impl Mix.Task
def run(args) do
{:ok, _} = Application.ensure_all_started(:portfolio_coder)
{opts, query_parts, _} =
OptionParser.parse(args,
strict: [
index: :string,
language: :string,
limit: :integer,
file: :string,
help: :boolean
],
aliases: [i: :index, l: :language, n: :limit, f: :file, h: :help]
)
if opts[:help] do
shell_info(@moduledoc)
else
query = Enum.join(query_parts, " ")
if query == "" do
shell_error("Error: Please provide a search query")
exit({:shutdown, 1})
end
search_code(query, opts)
end
end
defp search_code(query, opts) do
shell_info("Searching for: #{query}\n")
search_opts =
[]
|> maybe_add(:index_id, opts[:index])
|> maybe_add(:language, parse_language(opts[:language]))
|> maybe_add(:limit, opts[:limit])
|> maybe_add(:file_pattern, opts[:file])
case PortfolioCoder.search_code(query, search_opts) do
{:ok, results} ->
if results == [] do
shell_info("No results found.")
else
Enum.each(results, &print_result/1)
shell_info("\nFound #{length(results)} results.")
end
{:error, reason} ->
shell_error("Error: #{inspect(reason)}")
exit({:shutdown, 1})
end
end
defp print_result(result) do
shell_info("""
-----------------------------------------
File: #{result.path}
Language: #{result.language} | Score: #{Float.round(result.score, 3)}
#{truncate(result.content, 300)}
""")
end
defp truncate(text, max) when byte_size(text) > max do
String.slice(text, 0, max) <> "..."
end
defp truncate(text, _max), do: text
defp shell_info(message), do: IO.puts(message)
defp shell_error(message), do: IO.puts(:stderr, message)
defp maybe_add(opts, _key, nil), do: opts
defp maybe_add(opts, key, value), do: Keyword.put(opts, key, value)
defp parse_language(nil), do: nil
defp parse_language(lang), do: String.to_existing_atom(lang)
end