Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
995b24f
Split MCP transport orchestration from server core
Widthdom Jul 25, 2026
f575f79
Separate MCP message dispatch and batch lifecycle
Widthdom Jul 25, 2026
c2be148
Isolate MCP initialization state management
Widthdom Jul 25, 2026
aa31542
Extract MCP resource listing and reads
Widthdom Jul 25, 2026
48cbfd4
Separate MCP prompts and resource URI helpers
Widthdom Jul 25, 2026
f936652
Extract MCP protocol and rate limit policies
Widthdom Jul 25, 2026
513e202
Separate MCP tool dispatch and telemetry
Widthdom Jul 25, 2026
cac3b38
Isolate MCP database and shutdown lifecycle
Widthdom Jul 25, 2026
8c431e4
Extract MCP response shaping and annotations
Widthdom Jul 25, 2026
c01af77
Extract SQL supplemental symbol analysis
Widthdom Jul 25, 2026
ce1b038
Group PHP and Swift property supplements
Widthdom Jul 25, 2026
1c74e96
Group C++ and C# declaration metadata
Widthdom Jul 25, 2026
7024db7
Extract shell function range scanning
Widthdom Jul 25, 2026
acf82c0
Separate C# and Dart lexical scopes
Widthdom Jul 25, 2026
b761b76
Extract cross-language record components
Widthdom Jul 25, 2026
6ccd088
Isolate symbol container assignment
Widthdom Jul 25, 2026
e1f3a4c
Separate symbol normalization and Rust supplements
Widthdom Jul 25, 2026
7e6e9a7
Split MCP tool catalog construction
Widthdom Jul 25, 2026
1545d27
Unify graph command query validation
Widthdom Jul 25, 2026
1290dad
Extract Python and Java string masking
Widthdom Jul 25, 2026
c03931d
Split symbol extraction dispatch and completion phases
Widthdom Jul 25, 2026
f1239dd
Encapsulate symbol pattern scan inputs
Widthdom Jul 25, 2026
c81afa1
Extract symbol pattern line preparation
Widthdom Jul 25, 2026
0b5d7fb
Split MCP query handlers by tool family
Widthdom Jul 25, 2026
d7115ec
Separate MCP indexing validation and diagnostics
Widthdom Jul 25, 2026
fc9e034
Extract MCP indexing snapshots and result shaping
Widthdom Jul 25, 2026
c807f13
Split concurrent MCP transport frame lifecycle
Widthdom Jul 25, 2026
82f9aa1
Decompose MCP batch dispatch orchestration
Widthdom Jul 25, 2026
48b9678
Separate MCP request validation and notification dispatch
Widthdom Jul 25, 2026
dd6f2c2
Encapsulate MCP request cancellation lifecycle
Widthdom Jul 25, 2026
fcf2e82
Extract pattern signature construction phases
Widthdom Jul 25, 2026
341bbe9
Separate symbol extraction state management
Widthdom Jul 25, 2026
1f2d18e
Separate symbol extraction contracts
Widthdom Jul 25, 2026
42a23b9
Separate symbol extraction pattern catalog
Widthdom Jul 25, 2026
ba00d9e
Unify cross-language pattern symbol emission
Widthdom Jul 25, 2026
810258e
Format specialized extraction switch blocks
Widthdom Jul 25, 2026
ac2f2c2
Restore MCP cancellation method guidance
Widthdom Jul 25, 2026
2251fa5
Split LSP server responsibilities
Widthdom Jul 25, 2026
c766a40
Split reference extraction support concerns
Widthdom Jul 25, 2026
3c934eb
Split reference type analysis phases
Widthdom Jul 25, 2026
b5cd752
Split reference type syntax analysis
Widthdom Jul 25, 2026
80843dc
Split dynamic language reference extractors
Widthdom Jul 25, 2026
8df13a2
Split typed language reference analysis
Widthdom Jul 25, 2026
cce23b5
Split SQL reference extraction phases
Widthdom Jul 25, 2026
314e79e
Split C# reference analysis helpers
Widthdom Jul 25, 2026
e962c46
Split structural line masking strategies
Widthdom Jul 25, 2026
04cbc31
Split cross-language reference support
Widthdom Jul 25, 2026
ae90e75
Split JVM and scripting reference extractors
Widthdom Jul 25, 2026
51b599e
Split specialized language reference extractors
Widthdom Jul 25, 2026
0ce9b94
Split database context responsibilities
Widthdom Jul 25, 2026
3222468
Decompose database schema initialization
Widthdom Jul 25, 2026
26ea898
Split console UI responsibilities
Widthdom Jul 25, 2026
03c32b7
Split index watch responsibilities
Widthdom Jul 25, 2026
b313725
Split export and import responsibilities
Widthdom Jul 25, 2026
630d758
Decompose the database import pipeline
Widthdom Jul 25, 2026
b190212
Split database command responsibilities
Widthdom Jul 25, 2026
4092b90
Decompose query argument parsing
Widthdom Jul 25, 2026
bf6dcad
Split program runner responsibilities
Widthdom Jul 25, 2026
a788a24
Decompose the upgrade workflow
Widthdom Jul 25, 2026
c1bfcd7
Split index command responsibilities
Widthdom Jul 25, 2026
495fee2
Separate index run execution phases
Widthdom Jul 25, 2026
425d69c
Extract C# invocation parsing helpers
Widthdom Jul 25, 2026
0f7ae5a
Extract core reference lookup state
Widthdom Jul 25, 2026
be5152a
Split full scan support concerns
Widthdom Jul 25, 2026
7ed5396
Decompose database argument parsing
Widthdom Jul 25, 2026
5b2bf5c
Split language-specific core reference emission
Widthdom Jul 25, 2026
9f2c9c8
Separate core call reference scanning
Widthdom Jul 25, 2026
5adde21
Split specialized line reference emitters
Widthdom Jul 25, 2026
4c5362d
Separate core type reference dispatch
Widthdom Jul 25, 2026
1a94620
Split core documentation and ambiguous language paths
Widthdom Jul 25, 2026
2dbbd8d
Unify index file byte tracking
Widthdom Jul 25, 2026
f1b84ed
Unify index progress reporting
Widthdom Jul 25, 2026
64288f4
Separate full scan result rendering
Widthdom Jul 25, 2026
0d0b977
Separate update result rendering
Widthdom Jul 25, 2026
6274f8e
Separate index snapshot failure reporting
Widthdom Jul 25, 2026
49caa09
Separate full scan FTS bulk load planning
Widthdom Jul 25, 2026
58d81ad
Separate update C# target coordination
Widthdom Jul 25, 2026
7657850
Separate full scan target preparation
Widthdom Jul 25, 2026
9afd6d5
Separate update C# cleanup planning
Widthdom Jul 25, 2026
bc1aeb2
Separate full scan stale file planning
Widthdom Jul 25, 2026
e16adc2
Split export and import command flows
Widthdom Jul 25, 2026
9302a31
Separate index readiness finalization
Widthdom Jul 25, 2026
fda0edb
Separate update file persistence
Widthdom Jul 25, 2026
72f4f45
Separate full scan extraction pipeline
Widthdom Jul 25, 2026
9dc5577
Unify skipped update file persistence
Widthdom Jul 25, 2026
eaad1b4
Separate update target processing loop
Widthdom Jul 25, 2026
5234152
Separate full scan result consumption
Widthdom Jul 25, 2026
e25b13a
Unify skipped update file handling
Widthdom Jul 25, 2026
ff64855
Split C and C++ type reference groups
Widthdom Jul 25, 2026
666c20b
Separate core call classification
Widthdom Jul 25, 2026
edab4ef
Separate core reference line processing
Widthdom Jul 25, 2026
f87dfc3
Separate scientific native reference emission
Widthdom Jul 25, 2026
715a442
Separate full scan progress session
Widthdom Jul 25, 2026
f2081a5
Separate full scan C# workspace preflight
Widthdom Jul 25, 2026
ba4eb49
Separate update C# workspace preflight
Widthdom Jul 25, 2026
80847d5
Separate update C# mutation guards
Widthdom Jul 25, 2026
73d08d0
Separate full scan target selection
Widthdom Jul 25, 2026
d69af87
Separate final full scan C# revalidation
Widthdom Jul 25, 2026
d3a8153
Separate full scan extraction pipeline
Widthdom Jul 25, 2026
61b5ca3
Preserve reference extraction allocation budgets
Widthdom Jul 25, 2026
b4746a2
Restore MCP method guidance contract
Widthdom Jul 25, 2026
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
228 changes: 228 additions & 0 deletions src/CodeIndex/Cli/ConsoleUi.Branding.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
using CodeIndex.Database;
using CodeIndex.Diagnostics;
using CodeIndex.Indexer;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;

namespace CodeIndex.Cli;

public static partial class ConsoleUi
{
public static void PrintBanner()
{
const string banner = """

██████╗ ██████╗ ██████╗ ███████╗██╗███╗ ██╗██████╗ ███████╗██╗ ██╗
██╔════╝██╔═══██╗██╔══██╗██╔════╝██║████╗ ██║██╔══██╗██╔════╝╚██╗██╔╝
██║ ██║ ██║██║ ██║█████╗ ██║██╔██╗ ██║██║ ██║█████╗ ╚███╔╝
██║ ██║ ██║██║ ██║██╔══╝ ██║██║╚██╗██║██║ ██║██╔══╝ ██╔██╗
╚██████╗╚██████╔╝██████╔╝███████╗██║██║ ╚████║██████╔╝███████╗██╔╝ ██╗
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝╚═╝ ╚═══╝╚═════╝ ╚══════╝╚═╝ ╚═╝
""";
Console.WriteLine(banner);
}

public static void PrintIndexCompleteSummary(
string projectRoot,
string resolvedDbPath,
bool incremental,
int filesScanned,
IReadOnlyDictionary<string, int> languageCounts)
{
Console.WriteLine(incremental ? "Next steps (incremental):" : "Next steps:");
Console.WriteLine(" - Search code: cdidx search \"authenticate\" --path src/");
Console.WriteLine(" - Find a definition: cdidx definition SymbolName");
Console.WriteLine($" - Start MCP: cdidx mcp --db {QuoteForDisplay(resolvedDbPath)}");
Console.WriteLine($" - Database: {resolvedDbPath}");
Console.WriteLine(" - Exclude paths with .gitignore or .cdidxignore, then rerun cdidx index .");
Console.WriteLine($" - Scanned {Counted(filesScanned, "file", format: "N0")} under {projectRoot}");
if (languageCounts.Count > 0)
{
var summary = string.Join(
", ",
languageCounts
.OrderByDescending(static pair => pair.Value)
.ThenBy(static pair => pair.Key, StringComparer.Ordinal)
.Take(6)
.Select(static pair => $"{pair.Key} {pair.Value.ToString("N0", CultureInfo.InvariantCulture)}"));
Console.WriteLine($" - Languages: {summary}");
}
Console.WriteLine();
}

public static void EmitCompletionNotification(CompletionNotificationMode mode, string message)
{
var resolved = mode == CompletionNotificationMode.Auto
? ShouldUseInteractiveConsole() ? CompletionNotificationMode.Bell : CompletionNotificationMode.None
: mode;
if (resolved == CompletionNotificationMode.None)
return;

var safeMessage = message.Replace('\r', ' ').Replace('\n', ' ');
if (resolved == CompletionNotificationMode.Osc9)
Console.Error.Write($"\u001b]9;{safeMessage}\a");
else
Console.Error.Write('\a');
Console.Error.Flush();
}

private static string QuoteForDisplay(string value)
=> value.IndexOfAny([' ', '\t', '"']) < 0
? value
: $"\"{value.Replace("\"", "\\\"", StringComparison.Ordinal)}\"";

// --- Easter eggs / イースターエッグ ---

/// <summary>
/// Print easter egg message (standalone mode). Renders the catalog entry for
/// <paramref name="flag"/> in the language chosen by <see cref="UiLanguageResolver"/>
/// (<c>CDIDX_LANG</c> env > <see cref="System.Globalization.CultureInfo.CurrentUICulture"/>
/// > English fallback). Unknown flags print two blank lines for legacy compatibility.
/// Pass <paramref name="languageOverride"/> to bypass env/culture resolution (used by
/// tests so they do not mutate the live process environment).
/// イースターエッグメッセージを表示(単体実行時)。<see cref="UiLanguageResolver"/>
/// が選んだ言語(<c>CDIDX_LANG</c> 環境変数 &gt; カルチャ &gt; 英語)でカタログ
/// エントリを描画する。未知フラグは従来互換で空行を2つ出力。
/// <paramref name="languageOverride"/> を指定すると環境変数/カルチャ判定をスキップする
/// (テストがプロセス環境を書き換えずに済むようにするためのフック)。
/// </summary>
public static void PrintEasterEggMessage(string flag, UiLanguage? languageOverride = null)
{
var pair = flag switch
{
"--sushi" => UiMessages.EasterEggSushi,
"--coffee" => UiMessages.EasterEggCoffee,
"--ramen" => UiMessages.EasterEggRamen,
"--wine" => UiMessages.EasterEggWine,
"--beer" => UiMessages.EasterEggBeer,
"--matcha" => UiMessages.EasterEggMatcha,
"--whisky" => UiMessages.EasterEggWhisky,
_ => null,
};
if (pair is null)
{
Console.WriteLine();
Console.WriteLine();
return;
}

var lang = languageOverride ?? UiLanguageResolver.Resolve();
foreach (var line in UiMessages.Render(pair, lang))
Console.WriteLine(line);
}

// --- Version loading / バージョン読み込み ---

/// <summary>
/// Load version from version.json.
/// version.jsonからバージョンを読み込み。
/// </summary>
public static string LoadVersion()
{
var exeDir = AppContext.BaseDirectory;
var path = Path.Combine(exeDir, "version.json");
if (!File.Exists(LongPath.EnsureWindowsPrefix(path)))
{
// Fallback: look relative to current directory / カレントディレクトリからの相対パスでフォールバック
path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "version.json");
}
var ioPath = LongPath.EnsureWindowsPrefix(path);
if (File.Exists(ioPath))
return LoadVersionFromFile(ioPath);

return FallbackVersion;
}

internal static string LoadVersionFromFile(string ioPath)
{
try
{
var json = DataDirectorySecurity.ReadTextWithinLimit(ioPath, MaxVersionJsonBytes);
if (json is null)
return FallbackVersion;

using var doc = BoundedJson.ParseDocument(json, MaxVersionJsonBytes, MaxVersionJsonDepth);
if (doc.RootElement.TryGetProperty("version", out var ver))
return ver.GetString() ?? FallbackVersion;
}
catch (Exception ex) when (ex is IOException
or UnauthorizedAccessException
or JsonException
or InvalidDataException
or InvalidOperationException)
{
return FallbackVersion;
}

return FallbackVersion;
}

/// <summary>
/// Format byte counts for human-facing CLI output using binary units.
/// 人間向けCLI出力用にバイト数を2進単位で整形する。
/// </summary>
public static string FormatBytes(long bytes)
{
if (bytes < 0)
return string.Create(CultureInfo.InvariantCulture, $"{bytes:N0} bytes");
if (bytes < 1024)
return string.Create(CultureInfo.InvariantCulture, $"{bytes:N0} bytes");

var value = (double)bytes;
var unitIndex = 0;
while (value >= 1024 && unitIndex < ByteUnits.Length - 1)
{
value /= 1024;
unitIndex++;
}

return string.Create(CultureInfo.InvariantCulture, $"{value:N1} {ByteUnits[unitIndex]}");
}

/// <summary>
/// Build metadata stamped into the assembly at compile time, used by
/// `--version` so dev builds and tagged releases are distinguishable in
/// bug reports (#1550). Any field can be "unknown" when the build host
/// lacks git (e.g. a tarball-only checkout).
/// `--version` がバグ報告で dev ビルドとタグ済みリリースを区別できる
/// よう、ビルド時にアセンブリへ刻んだメタデータ (#1550)。git の無い
/// ビルドホストでは各フィールドが "unknown" になりうる。
/// </summary>
public sealed record BuildMetadata(string Version, string Commit, string BuildDate, string Dirty);

/// <summary>
/// Load the full build metadata: semver from version.json plus commit/build
/// date/dirty flag stamped into the assembly via <c>AssemblyMetadataAttribute</c>.
/// version.json の semver と、AssemblyMetadataAttribute で刻まれた
/// commit / build date / dirty フラグを合わせて読み込む。
/// </summary>
public static BuildMetadata LoadBuildMetadata()
{
var assembly = typeof(ConsoleUi).Assembly;
return new BuildMetadata(
Version: LoadVersion(),
Commit: ReadAssemblyMetadata(assembly, "CdidxCommit"),
BuildDate: ReadAssemblyMetadata(assembly, "CdidxBuildDate"),
Dirty: ReadAssemblyMetadata(assembly, "CdidxBuildDirty"));
}

private static string ReadAssemblyMetadata(Assembly assembly, string key)
{
foreach (var attr in assembly.GetCustomAttributes<AssemblyMetadataAttribute>())
{
if (string.Equals(attr.Key, key, StringComparison.Ordinal))
return string.IsNullOrWhiteSpace(attr.Value) ? "unknown" : attr.Value!;
}
return "unknown";
}

// --- Usage / 使い方 ---

/// <summary>
/// Print usage information.
/// 使い方を表示する。
/// </summary>
}
Loading
Loading