-
-
Notifications
You must be signed in to change notification settings - Fork 3
feat: add 13 new builtin extensions (sources, previewers, renderers) #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
75b036b
Add CLAUDE.md to provide guidance for Claude Code
lambdalisue 6bdfbe0
feat(source): add window source for listing Vim windows
lambdalisue ad2d410
feat(source): add tabpage source for listing Vim tab pages
lambdalisue 9004a59
feat(source): add loclist source for listing location list items
lambdalisue d337686
feat(source): add colorscheme source for listing available colorschemes
lambdalisue d8a627c
feat(source): add highlight source for listing highlight groups
lambdalisue 33e58cd
feat(source): add jumplist source for listing jump locations
lambdalisue fd1a7c8
feat(source): add register source for listing Vim registers
lambdalisue 5006534
feat(source): add mark source for listing Vim marks
lambdalisue 1c0e825
feat(source): add command source for listing user-defined commands
lambdalisue 9c39f46
feat(source): add mapping source for listing key mappings
lambdalisue e8f21f1
feat(source): add git status source for listing modified files
lambdalisue 881a059
feat(source): add grep source for vim's :grep command results
lambdalisue c3bf51b
feat(source): add vimgrep source for vim's :vimgrep command results
lambdalisue 89e0265
feat(source): add autocmd source for vim autocmds
lambdalisue c74961d
feat(previewer): add shell command previewer
lambdalisue bfba569
feat(renderer): add file info renderer for displaying file metadata
lambdalisue 8090011
feat(renderer): add buffer info renderer for displaying buffer metadata
lambdalisue 0f0a8f2
feat(renderer): add smart grep renderer for formatting grep-like results
lambdalisue e9a3319
feat(refiner): add file info refiner for filtering by file properties
lambdalisue c166b92
feat(refiner): add buffer info refiner for filtering by buffer proper…
lambdalisue File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,213 @@ | ||
| import * as fn from "@denops/std/function"; | ||
| import { join } from "@std/path/join"; | ||
|
|
||
| import { defineSource, type Source } from "../../source.ts"; | ||
|
|
||
| type Detail = { | ||
| /** | ||
| * File path relative to git root | ||
| */ | ||
| path: string; | ||
|
|
||
| /** | ||
| * Absolute file path | ||
| */ | ||
| absolutePath: string; | ||
|
|
||
| /** | ||
| * Git status code (e.g., "M", "A", "D", "??") | ||
| */ | ||
| status: string; | ||
|
|
||
| /** | ||
| * Human-readable status description | ||
| */ | ||
| statusDescription: string; | ||
|
|
||
| /** | ||
| * Whether the file is staged | ||
| */ | ||
| staged: boolean; | ||
|
|
||
| /** | ||
| * Whether the file is unstaged | ||
| */ | ||
| unstaged: boolean; | ||
| }; | ||
|
|
||
| export type GitStatusOptions = { | ||
| /** | ||
| * Whether to include untracked files. | ||
| * @default true | ||
| */ | ||
| includeUntracked?: boolean; | ||
|
|
||
| /** | ||
| * Whether to include ignored files. | ||
| * @default false | ||
| */ | ||
| includeIgnored?: boolean; | ||
|
|
||
| /** | ||
| * Whether to show status in submodules. | ||
| * @default false | ||
| */ | ||
| includeSubmodules?: boolean; | ||
| }; | ||
|
|
||
| // Git status format codes | ||
| const STATUS_CODES = { | ||
| STAGED: { | ||
| M: "modified", | ||
| A: "added", | ||
| D: "deleted", | ||
| R: "renamed", | ||
| C: "copied", | ||
| }, | ||
| UNSTAGED: { | ||
| M: "modified", | ||
| D: "deleted", | ||
| }, | ||
| UNTRACKED: "??", | ||
| IGNORED: "!!", | ||
| } as const; | ||
|
|
||
| /** | ||
| * Creates a Source that generates items from git status. | ||
| * | ||
| * This Source runs `git status` and generates items for each modified, | ||
| * staged, or untracked file in the repository. | ||
| * | ||
| * @param options - Options to customize git status listing. | ||
| * @returns A Source that generates items representing git status files. | ||
| */ | ||
| export function gitStatus( | ||
| options: Readonly<GitStatusOptions> = {}, | ||
| ): Source<Detail> { | ||
| const includeUntracked = options.includeUntracked ?? true; | ||
| const includeIgnored = options.includeIgnored ?? false; | ||
| const includeSubmodules = options.includeSubmodules ?? false; | ||
|
|
||
| return defineSource(async function* (denops, _params, { signal }) { | ||
| // Get current working directory | ||
| const cwd = await fn.getcwd(denops); | ||
| signal?.throwIfAborted(); | ||
|
|
||
| // Build git status command | ||
| const args = ["status", "--porcelain=v1"]; | ||
| if (includeUntracked) { | ||
| args.push("-u"); | ||
| } else { | ||
| args.push("-uno"); | ||
| } | ||
| if (includeIgnored) { | ||
| args.push("--ignored"); | ||
| } | ||
| if (!includeSubmodules) { | ||
| args.push("--ignore-submodules"); | ||
| } | ||
|
|
||
| try { | ||
| // Run git status | ||
| const cmd = new Deno.Command("git", { | ||
| args, | ||
| cwd, | ||
| stdout: "piped", | ||
| stderr: "piped", | ||
| signal, | ||
| }); | ||
|
|
||
| const { stdout, stderr, success } = await cmd.output(); | ||
|
|
||
| if (!success) { | ||
| // Not a git repository or git command failed | ||
| const errorText = new TextDecoder().decode(stderr); | ||
| if (errorText.includes("not a git repository")) { | ||
| // Silently return empty - not an error condition | ||
| return; | ||
| } | ||
| throw new Error(`git status failed: ${errorText}`); | ||
| } | ||
|
|
||
| // Parse git status output | ||
| const output = new TextDecoder().decode(stdout); | ||
| const lines = output.trim().split("\n").filter((line) => line); | ||
|
|
||
| const items = lines.map((line, index) => { | ||
| // Git status format: XY filename | ||
| // X = staged status, Y = unstaged status | ||
| const staged = line[0]; | ||
| const unstaged = line[1]; | ||
| const filename = line.substring(3); | ||
|
|
||
| // Determine status code and description | ||
| const status = `${staged}${unstaged}`; | ||
| let statusDescription = ""; | ||
| let isStaged = false; | ||
| let isUnstaged = false; | ||
|
|
||
| // Parse status codes | ||
| if (status === STATUS_CODES.UNTRACKED) { | ||
| statusDescription = "untracked"; | ||
| isUnstaged = true; | ||
| } else if (status === STATUS_CODES.IGNORED) { | ||
| statusDescription = "ignored"; | ||
| } else { | ||
| // Handle staged status | ||
| const stagedDesc = | ||
| STATUS_CODES.STAGED[staged as keyof typeof STATUS_CODES.STAGED]; | ||
| if (stagedDesc) { | ||
| statusDescription = stagedDesc; | ||
| isStaged = true; | ||
| } | ||
|
|
||
| // Handle unstaged status | ||
| const unstagedDesc = STATUS_CODES | ||
| .UNSTAGED[unstaged as keyof typeof STATUS_CODES.UNSTAGED]; | ||
| if (unstagedDesc) { | ||
| statusDescription += isStaged ? `, ${unstagedDesc}` : unstagedDesc; | ||
| isUnstaged = true; | ||
| } | ||
| } | ||
|
|
||
| // Create status indicator | ||
| const indicator = status === STATUS_CODES.UNTRACKED | ||
| ? "[?]" | ||
| : status === STATUS_CODES.IGNORED | ||
| ? "[!]" | ||
| : `[${status}]`; | ||
|
|
||
| // Format display value | ||
| const absolutePath = join(cwd, filename); | ||
| const displayPath = filename; | ||
| const value = `${indicator.padEnd(5)} ${displayPath}`; | ||
|
|
||
| return { | ||
| id: index, | ||
| value, | ||
| detail: { | ||
| path: filename, | ||
| absolutePath, | ||
| status, | ||
| statusDescription, | ||
| staged: isStaged, | ||
| unstaged: isUnstaged, | ||
| }, | ||
| }; | ||
| }); | ||
|
|
||
| yield* items; | ||
| } catch (err) { | ||
| // Handle errors gracefully | ||
| if (err instanceof Error) { | ||
| if (err.name === "NotFound") { | ||
| // Git not installed - silently return empty | ||
| return; | ||
| } | ||
| // Re-throw other errors with context | ||
| throw new Error(`Failed to get git status: ${err.message}`); | ||
| } | ||
| throw err; | ||
| } | ||
| }); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a parser as a pure function so that we can easily test.