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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.2.4 (Unreleased)

- Added new `gitdoc.alwaysShowStatusBarIcon` setting to optionally keep the status bar icon visible when GitDoc is disabled (#89), and improved icon display to properly indicate when viewing files that don't match the file pattern
- Added new `GitDoc: Toggle Status Bar Icon Visibility` command to quickly toggle the status bar icon visibility
- Fixed issue where GitDoc was inactive on codespace start despite being enabled in settings (#90)

## v0.2.3 (12/26/2024)

- Introduced a new `GitDoc > AI: Use Emojis` setting, to alloq prepending AI-generated commit messages with an emoji.
Expand Down
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Auto-committing is useful for tracking unique versions, however, depending on ho

<img width="700px" src="https://user-images.githubusercontent.com/116461/79668805-3c84ab00-816c-11ea-9ec9-845650b999b8.gif" />

> Demystification: Behind the scenes, this command performs a `git reset --soft`, starting at the commit _before_ the selected one. It then runs `git commit -m <message>`, where `message` is the string you specified. This preserves your working directory/index, while "rewritting" the commit history.
> Demystification: Behind the scenes, this command performs a `git reset --soft`, starting at the commit _before_ the selected one. It then runs `git commit -m <message>`, where `message` is the string you specified. This preserves your working directory/index, while "rewritten" the commit history.

## Undoing versions

Expand All @@ -77,7 +77,13 @@ If you've made a bunch of changes to a file, and want to restore an older versio

## Status Bar

Whenever `GitDoc` is enabled, it will contribute a status bar item to your status bar. This simply indicates that it's enabled, and makes it easier for you to know which "versioning mode" you're in (auto-commit vs. manual commit). Additionally, if you enable [auto-pushing](#auto-pushing), then the status bar will indicate when it's syncing your commits with your repo. If you click the `GitDoc` status bar item, this will disable `GitDoc`. This allows you to easily enable GitDoc for a period of time, and then quickly turn it off.
Whenever `GitDoc` is installed, it will contribute a status bar item to your status bar. The status bar icon changes based on the current state:

- When disabled: Shows a "sync-ignored" icon ($(sync-ignored))
- When enabled and viewing a matching file: Shows a "mirror" icon ($(mirror))
- When enabled but viewing a non-matching file: Shows a "mirror" icon with a circle-slash next to it ($(mirror) $(circle-slash))

Additionally, if you enable [auto-pushing](#auto-pushing), then the status bar will indicate when it's syncing your commits with your repo. If you click the `GitDoc` status bar item, this will toggle between enabled and disabled states. This allows you to easily enable GitDoc for a period of time, and then quickly turn it off.

## Contributed Commands

Expand All @@ -87,6 +93,8 @@ When you install the `GitDoc` extension, the following commands are contributed

- `GitDoc: Disable` - Disables auto-commits. This command is only visible when GitDoc is enabled.

- `GitDoc: Toggle Status Bar Icon Visibility` - Toggles whether the GitDoc status bar icon is always visible or only visible when GitDoc is enabled. This provides a quick way to toggle the `gitdoc.alwaysShowStatusBarIcon` setting.

- `GitDoc: Commit` - Manually commits changes. This command allows you to trigger a commit without waiting for the auto-commit interval.

## Contributed Settings
Expand Down Expand Up @@ -129,4 +137,15 @@ The following settings enable you to customize the default behavior of `GitDoc`:

- `GitDoc > AI: Custom Instructions` - Specifies custom instructions to use when generating commit messages (e.g. use conventional commit syntax, use emojis). This setting only applies when `GitDoc > AI: Enabled` is set to `true`."

- `GitDoc > AI: Use Emojis` - Specifies whether to prepend AI-generated commit messages with an emoji. This setting only applies when `GitDoc > AI: Enabled` is set to `true`. Defaults to `false`.
- `GitDoc > AI: Use Emojis` - Specifies whether to prepend AI-generated commit messages with an emoji. This setting only applies when `GitDoc > AI: Enabled` is set to `true`. Defaults to `false`.

## Configuration Settings

You can customize `GitDoc`'s behavior using the following settings:

| Setting | Description |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `gitdoc.enabled` | Specifies whether to automatically create a commit each time you save a file. |
| `gitdoc.alwaysShowStatusBarIcon` | When true, the status bar icon is always visible (even when GitDoc is disabled), with its appearance changing to indicate the current state. When false (default), the status bar icon is only visible when GitDoc is enabled. |
| `gitdoc.autoCommitDelay` | Specifies the number of milliseconds to wait before automatically committing changes. |
| `gitdoc.filePattern` | Specifies a glob pattern that indicates the specific files that should be automatically committed. |
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 20 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"displayName": "GitDoc",
"publisher": "vsls-contrib",
"icon": "images/icon.png",
"description": "Automatically commit/push/pull changes on save, so you can edit a Git repo like a multi-file, versioned document.",
"version": "0.2.3",
"description": "A continuous, frictionless, background-saving experience that intelligently commits your changes.",
"version": "0.2.4",
"extensionKind": [
"workspace"
],
Expand Down Expand Up @@ -40,6 +40,11 @@
"title": "Enable",
"category": "GitDoc"
},
{
"command": "gitdoc.toggleStatusBarIcon",
"title": "Toggle Status Bar Icon Visibility",
"category": "GitDoc"
},
{
"command": "gitdoc.restoreVersion",
"title": "Restore Version"
Expand Down Expand Up @@ -95,12 +100,17 @@
"gitdoc.autoPushDelay": {
"type": "number",
"default": 30000,
"markdownDescription": "Controls the delay in ms after which any commits are automatically pushed. Only applies when `GitDoc: Auto Push` is set to `afterDelay`."
"description": "Specifies the number of milliseconds to wait before automatically pushing changes to a remote branch. This setting only applies when 'GitDoc > Auto Push' is set to 'After Delay'."
},
"gitdoc.alwaysShowStatusBarIcon": {
"type": "boolean",
"default": false,
"description": "Specifies whether to always show the status bar icon, even when GitDoc is disabled. When true, the icon appearance will change to indicate whether GitDoc is enabled or disabled."
},
"gitdoc.commitMessageFormat": {
"type": "string",
"default": "ff",
"markdownDescription": "Specifies the date/time format string (using Luxon) to use when generating auto-commit messages. Views [the docs](https://moment.github.io/luxon/#/formatting?id=table-of-tokens) for more details."
"default": "lll",
"markdownDescription": "Specifies the format to use for auto-generated commit messages. This setting only applies when `GitDoc > AI: Enabled` is set to `false`. By default, it uses the [Luxon date format](https://moment.github.io/luxon/#/formatting)."
},
"gitdoc.commitValidationLevel": {
"type": "string",
Expand Down Expand Up @@ -196,6 +206,10 @@
"command": "gitdoc.enable",
"when": "gitOpenRepositoryCount != 0 && !gitdoc:enabled"
},
{
"command": "gitdoc.toggleStatusBarIcon",
"when": "gitOpenRepositoryCount != 0"
},
{
"command": "gitdoc.restoreVersion",
"when": "false"
Expand Down Expand Up @@ -253,4 +267,4 @@
"minimatch": "^3.0.4",
"mobx": "^5.14.2"
}
}
}
22 changes: 21 additions & 1 deletion src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as vscode from "vscode";
import { EXTENSION_NAME } from "./constants";
import { getGitApi } from "./git";
import { updateContext } from "./utils";
import { commit } from "./watcher";
import { commit, updateStatusBarItem } from "./watcher";

interface GitTimelineItem {
message: string;
Expand All @@ -20,6 +20,26 @@ export function registerCommands(context: vscode.ExtensionContext) {
registerCommand("enable", updateContext.bind(null, true));
registerCommand("disable", updateContext.bind(null, false));

registerCommand("toggleStatusBarIcon", async () => {
// Get the current setting value
const currentValue = vscode.workspace.getConfiguration("gitdoc").get("alwaysShowStatusBarIcon", false);

// Toggle the setting
await vscode.workspace.getConfiguration("gitdoc").update(
"alwaysShowStatusBarIcon",
!currentValue,
vscode.ConfigurationTarget.Global
);

// Show notification to the user
vscode.window.showInformationMessage(
`GitDoc: Status bar icon will ${!currentValue ? "always" : "only"} be visible ${!currentValue ? "even when disabled" : "when enabled"}`
);

// Update the status bar immediately
updateStatusBarItem(vscode.window.activeTextEditor);
});

registerCommand("restoreVersion", async (item: GitTimelineItem) => {
if (!vscode.window.activeTextEditor) {
return;
Expand Down
3 changes: 3 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export default {
get autoPushDelay(): number {
return config().get("autoPushDelay", DEFAULT_DELAY_MS);
},
get alwaysShowStatusBarIcon(): boolean {
return config().get("alwaysShowStatusBarIcon", false);
},
get commitMessageFormat(): string {
return config().get("commitMessageFormat", "lll");
},
Expand Down
43 changes: 37 additions & 6 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,34 @@ import { registerCommands } from "./commands";
import config from "./config";
import { getGitApi, GitAPI, RefType } from "./git";
import { store } from "./store";
import { commit, watchForChanges } from "./watcher";
import { commit, watchForChanges, ensureStatusBarItem, updateStatusBarItem } from "./watcher";
import { updateContext } from "./utils";

export async function activate(context: vscode.ExtensionContext) {
// Wait for Git extension to be ready
const git = await getGitApi();
if (!git) {
return;
}

// Initialize the store based on the
// user/workspace configuration.
// Wait for initial repository to be available
// This is needed to fix issue #90 where GitDoc is inactive on codespace start
if (git.repositories.length === 0) {
await new Promise<void>((resolve) => {
const disposable = git.onDidOpenRepository(() => {
disposable.dispose();
resolve();
});
});
}

// Initialize the store based on the configuration
store.enabled = config.enabled;

// Create status bar item and ensure it's properly initialized
const statusBar = ensureStatusBarItem();
context.subscriptions.push(statusBar);

registerCommands(context);

// Enable/disable the auto-commit watcher as the user
Expand All @@ -25,18 +40,33 @@ export async function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(git.onDidOpenRepository(() => checkEnabled(git)));
context.subscriptions.push(git.onDidCloseRepository(() => checkEnabled(git)));

// Watch for active editor changes to update icon state
context.subscriptions.push(
vscode.window.onDidChangeActiveTextEditor((editor) => {
updateStatusBarItem(editor);
})
);

// Initial check of enabled state
await checkEnabled(git);

// Watch for store changes
reaction(
() => [store.enabled],
() => checkEnabled(git)
() => store.enabled,
(enabled) => {
checkEnabled(git);
}
);

context.subscriptions.push(
vscode.workspace.onDidChangeConfiguration((e) => {
if (e.affectsConfiguration("gitdoc.enabled") ||
e.affectsConfiguration("gitdoc.excludeBranches") ||
e.affectsConfiguration("gitdoc.autoCommitDelay") ||
e.affectsConfiguration("gitdoc.filePattern")) {
e.affectsConfiguration("gitdoc.filePattern") ||
e.affectsConfiguration("gitdoc.alwaysShowStatusBarIcon")) {
checkEnabled(git);
updateStatusBarItem(vscode.window.activeTextEditor);
}
})
);
Expand All @@ -61,6 +91,7 @@ async function checkEnabled(git: GitAPI) {
store.enabled && !!branchName && !config.excludeBranches.includes(branchName);

updateContext(enabled, false);
updateStatusBarItem(vscode.window.activeTextEditor);

if (enabled) {
watcher = watchForChanges(git);
Expand Down
100 changes: 50 additions & 50 deletions src/watcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ async function hasRemotes(repository: Repository): Promise<boolean> {
return refs.some((ref) => ref.type === RefType.RemoteHead);
}

function matches(uri: vscode.Uri) {
export function matches(uri: vscode.Uri) {
return minimatch(uri.path, config.filePattern, { dot: true });
}

Expand Down Expand Up @@ -232,49 +232,65 @@ export function ensureStatusBarItem() {
statusBarItem = vscode.window.createStatusBarItem(
vscode.StatusBarAlignment.Left
);

statusBarItem.text = "$(mirror)";
statusBarItem.tooltip = "GitDoc: Auto-commiting files on save";
statusBarItem.command = "gitdoc.disable";
updateStatusBarItem(vscode.window.activeTextEditor);
statusBarItem.show();
}

return statusBarItem;
}

export function updateStatusBarItem(editor: vscode.TextEditor | undefined) {
if (!statusBarItem) return;

const enabled = store.enabled;
const isMatchingFile = editor && matches(editor.document.uri);

// When always show status bar is false and GitDoc is disabled, hide the status bar
if (!enabled && !config.alwaysShowStatusBarIcon) {
statusBarItem.hide();
return;
}

// Ensure the status bar is visible
statusBarItem.show();

// Set the base state first (before any async operations might trigger)
if (!enabled) {
statusBarItem.text = "$(sync-ignored)";
statusBarItem.tooltip = "GitDoc: Click to enable auto-commit";
statusBarItem.command = "gitdoc.enable";
return;
}

// Handle enabled state
const suffix = store.isPushing
? " (Pushing...)"
: store.isPulling
? " (Pulling...)"
: "";

// Icon states:
// - Enabled + Matching file: Show mirror
// - Enabled + Non-matching file: Show mirror with circle-slash overlay using ~
const icon = isMatchingFile ? "$(mirror)" : "$(mirror) $(circle-slash)";

statusBarItem.text = `${icon}${suffix}`;
statusBarItem.tooltip = `GitDoc: ${isMatchingFile ? "Auto-committing this file on save" : "This file is not auto-committed"}`;
statusBarItem.command = "gitdoc.disable";
}

// Add reaction to store changes
reaction(
() => [store.enabled, store.isPushing, store.isPulling],
() => {
updateStatusBarItem(vscode.window.activeTextEditor);
}
);

let disposables: vscode.Disposable[] = [];
export function watchForChanges(git: GitAPI): vscode.Disposable {
const commitAfterDelay = debouncedCommit(git.repositories[0]);
disposables.push(git.repositories[0].state.onDidChange(commitAfterDelay));

ensureStatusBarItem();

disposables.push(
vscode.window.onDidChangeActiveTextEditor((editor) => {
if (editor && matches(editor.document.uri)) {
statusBarItem?.show();
} else {
statusBarItem?.hide();
}
})
);

if (
vscode.window.activeTextEditor &&
matches(vscode.window.activeTextEditor.document.uri)
) {
statusBarItem?.show();
} else {
statusBarItem?.hide();
}

disposables.push({
dispose: () => {
statusBarItem?.dispose();
statusBarItem = null;
},
});

if (config.autoPush === "afterDelay") {
const interval = setInterval(async () => {
pushRepository(git.repositories[0]);
Expand All @@ -298,22 +314,6 @@ export function watchForChanges(git: GitAPI): vscode.Disposable {
});
}

const reactionDisposable = reaction(
() => [store.isPushing, store.isPulling],
() => {
const suffix = store.isPushing
? " (Pushing...)"
: store.isPulling
? " (Pulling...)"
: "";
statusBarItem!.text = `$(mirror)${suffix}`;
}
);

disposables.push({
dispose: reactionDisposable,
});

if (config.pullOnOpen) {
pullRepository(git.repositories[0]);
}
Expand Down