Packages
fnord
0.7.16
0.9.40
0.9.39
0.9.38
0.9.37
0.9.36
0.9.35
0.9.34
0.9.33
0.9.32
0.9.31
0.9.30
0.9.29
0.9.28
0.9.27
0.9.26
0.9.25
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.14
0.9.13
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.99
0.8.98
0.8.97
0.8.96
0.8.95
0.8.94
0.8.93
0.8.92
0.8.91
0.8.90
0.8.89
0.8.88
0.8.87
0.8.86
0.8.85
0.8.84
0.8.83
0.8.82
0.8.81
0.8.80
0.8.79
0.8.78
0.8.77
0.8.76
0.8.75
0.8.74
0.8.73
0.8.72
0.8.71
0.8.70
0.8.69
0.8.68
0.8.67
0.8.66
0.8.65
0.8.64
0.8.63
0.8.62
0.8.61
0.8.60
0.8.59
0.8.58
0.8.57
0.8.56
0.8.55
0.8.54
0.8.53
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.47
0.8.46
0.8.45
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.1
0.8.0
0.7.24
0.7.23
0.7.22
0.7.21
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.44
0.4.43
0.4.42
0.4.41
0.4.40
0.4.39
0.4.38
0.4.37
0.4.36
0.4.35
0.4.34
0.4.33
0.4.32
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
AI code archaeology
Current section
Files
Jump to
Current section
Files
lib/fnord.ex
defmodule Fnord do
@moduledoc """
Fnord is a code search tool that uses OpenAI's embeddings API to index and
search code files.
"""
@desc "fnord - an AI powered, conversational interface for your project that learns"
@doc """
Main entry point for the application. Parses command line arguments and
dispatches to the appropriate subcommand.
"""
def main(args) do
{:ok, _} = Application.ensure_all_started(:briefly)
Once.start_link([])
configure_logger()
with {:ok, [command | subcommands], opts, unknown} <- parse_options(args) do
opts = set_globals(opts)
version_check_task =
if command == :upgrade do
nil
else
Task.async(fn -> Util.get_latest_version() end)
end
command
|> to_module_name()
|> apply(:run, [opts, subcommands, unknown])
if !is_nil(version_check_task) do
with {:ok, {:ok, latest}} <- Task.yield(version_check_task, 1000) do
current = Util.get_running_version()
if Version.compare(current, latest) == :lt do
IO.puts(:stderr, """
A new version of fnord is available! To upgrade to v#{latest}:
fnord upgrade
""")
end
end
end
end
end
def spec() do
[
name: "fnord",
description: @desc,
allow_unknown_args: false,
version: Util.get_running_version(),
options: [
prompt: [
value_name: "PROMPT",
long: "--prompt",
short: "-p",
help: "Shortcut to the default command",
required: false
]
],
subcommands:
[
Cmd.Ask,
Cmd.Config,
Cmd.Conversations,
Cmd.Default,
Cmd.Files,
Cmd.Frobs,
Cmd.Index,
Cmd.Notes,
Cmd.Projects,
Cmd.Replay,
Cmd.Search,
Cmd.Summary,
Cmd.Tool,
Cmd.Torch,
Cmd.Upgrade
]
|> Enum.flat_map(& &1.spec())
]
end
defp parse_options(args) do
spec()
|> Optimus.new!()
|> Optimus.parse!(args)
|> case do
{subcommand, %Optimus.ParseResult{} = result} ->
{:ok, subcommand, merge_options(result), result.unknown}
%Optimus.ParseResult{} = result ->
{:ok, [:default], merge_options(result), result.unknown}
end
end
defp merge_options(optimus_result) do
optimus_result.args
|> Map.merge(optimus_result.options)
|> Map.merge(optimus_result.flags)
end
def configure_logger do
{:ok, handler_config} = :logger.get_handler_config(:default)
updated_config = Map.update!(handler_config, :config, &Map.put(&1, :type, :standard_error))
:ok = :logger.remove_handler(:default)
:ok = :logger.add_handler(:default, :logger_std_h, updated_config)
:ok =
:logger.update_formatter_config(
:default,
:template,
["[", :level, "] ", :message, "\n"]
)
logger_level =
System.get_env("LOGGER_LEVEL", "info")
|> String.to_existing_atom()
:ok = :logger.set_primary_config(:level, logger_level)
end
defp set_globals(args) do
args
|> Enum.each(fn
{:workers, workers} -> Application.put_env(:fnord, :workers, workers)
{:project, project} -> Application.put_env(:fnord, :project, project)
{:quiet, quiet} -> Application.put_env(:fnord, :quiet, quiet)
_ -> :ok
end)
# --------------------------------------------------------------------------
# When not connected to a TTY, the --quiet flag is automatically enabled,
# unless the user explicitly specifies it.
# --------------------------------------------------------------------------
cond do
args[:quiet] -> args
IO.ANSI.enabled?() -> args
true -> Map.put(args, :quiet, true)
end
end
defp to_module_name(subcommand) do
submodule =
subcommand
|> Atom.to_string()
|> Macro.camelize()
Module.concat("Cmd", submodule)
end
end