Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Auto-indent dot syntax on Enter for `objectscript`/`objectscript-int` (replicates leading dots). (#6)
- Added `resolveContextExpression` command: posts current line/routine to API, inserts returned code on success, shows error otherwise. (#7)
- Refactor API: extracted request util and updated endpoints (#8)
- Add Ctrl+Q shortcut to fetch “global documentation” for the current selection/line and print the response to the Output. (#14)

## [3.0.6] 09-Sep-2025

Expand Down
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@
"command": "vscode-objectscript.viewOthers",
"when": "vscode-objectscript.connectActive"
},
{
"command": "vscode-objectscript.getGlobalDocumentation",
"when": "editorLangId =~ /^objectscript/ && vscode-objectscript.connectActive"
},
{
"command": "vscode-objectscript.subclass",
"when": "editorLangId =~ /^objectscript/ && vscode-objectscript.connectActive"
Expand Down Expand Up @@ -840,6 +844,12 @@
"command": "vscode-objectscript.resolveContextExpression",
"title": "Resolve Context Expression"
},
{
"category": "ObjectScript",
"command": "vscode-objectscript.getGlobalDocumentation",
"title": "Show Global Documentation",
"enablement": "vscode-objectscript.connectActive"
},
{
"category": "ObjectScript",
"command": "vscode-objectscript.compile",
Expand Down Expand Up @@ -939,6 +949,12 @@
"enablement": "vscode-objectscript.connectActive",
"title": "View Other"
},
{
"category": "ObjectScript",
"command": "vscode-objectscript.getGlobalDocumentation",
"enablement": "vscode-objectscript.connectActive",
"title": "Show Global Documentation"
},
{
"category": "ObjectScript",
"command": "vscode-objectscript.subclass",
Expand Down Expand Up @@ -1220,6 +1236,12 @@
"mac": "Cmd+Alt+Space",
"when": "editorTextFocus && editorLangId =~ /^objectscript/"
},
{
"command": "vscode-objectscript.getGlobalDocumentation",
"key": "Ctrl+Q",
"mac": "Cmd+Q",
"when": "editorTextFocus && editorLangId =~ /^objectscript/"
},
{
"command": "vscode-objectscript.viewOthers",
"key": "Ctrl+Shift+V",
Expand Down
4 changes: 4 additions & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,10 @@ export class AtelierAPI {
});
}

public getGlobalDocumentation(body: { selectedText: string }): Promise<Atelier.Response> {
return this.request(1, "POST", `${this.ns}/action/getglobaldocumentation`, body);
}

// v1+
public actionCompile(docs: string[], flags?: string, source = false): Promise<Atelier.Response> {
docs = docs.map((doc) => this.transformNameIfCsp(doc));
Expand Down
48 changes: 48 additions & 0 deletions src/ccs/commands/globalDocumentation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as vscode from "vscode";

import { GlobalDocumentationClient } from "../sourcecontrol/clients/globalDocumentationClient";
import { handleError, outputChannel } from "../../utils";

const sharedClient = new GlobalDocumentationClient();

function getSelectedOrCurrentLineText(editor: vscode.TextEditor): string {
const { selection, document } = editor;

if (!selection || selection.isEmpty) {
return document.lineAt(selection.active.line).text.trim();
}

return document.getText(selection).trim();
}

export async function showGlobalDocumentation(): Promise<void> {
const editor = vscode.window.activeTextEditor;

if (!editor) {
return;
}

const selectedText = getSelectedOrCurrentLineText(editor);

if (!selectedText) {
void vscode.window.showErrorMessage("Selection is empty. Select text or place the cursor on a line with content.");
return;
}

try {
const content = await sharedClient.fetch(editor.document, { selectedText });

if (!content || !content.trim()) {
void vscode.window.showInformationMessage("Global documentation did not return any content.");
return;
}

outputChannel.appendLine("==================== Global Documentation ====================");
for (const line of content.split(/\r?\n/)) {
outputChannel.appendLine(line);
}
outputChannel.show(true);
} catch (error) {
handleError(error, "Failed to retrieve global documentation.");
}
}
4 changes: 4 additions & 0 deletions src/ccs/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ export interface SourceControlError {
message: string;
cause?: unknown;
}
export interface GlobalDocumentationResponse {
content?: string | string[] | Record<string, unknown> | null;
message?: string;
}
2 changes: 2 additions & 0 deletions src/ccs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ export { getCcsSettings, isFlagEnabled, type CcsSettings } from "./config/settin
export { logDebug, logError, logInfo, logWarn } from "./core/logging";
export { SourceControlApi } from "./sourcecontrol/client";
export { resolveContextExpression } from "./commands/contextHelp";
export { showGlobalDocumentation } from "./commands/globalDocumentation";
export { ContextExpressionClient } from "./sourcecontrol/clients/contextExpressionClient";
export { GlobalDocumentationClient } from "./sourcecontrol/clients/globalDocumentationClient";
47 changes: 47 additions & 0 deletions src/ccs/sourcecontrol/clients/globalDocumentationClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as vscode from "vscode";

import { AtelierAPI } from "../../../api";
import { getCcsSettings } from "../../config/settings";
import { logDebug } from "../../core/logging";
import { SourceControlApi } from "../client";
import { ROUTES } from "../routes";

interface GlobalDocumentationPayload {
selectedText: string;
}

export class GlobalDocumentationClient {
private readonly apiFactory: (api: AtelierAPI) => SourceControlApi;

public constructor(apiFactory: (api: AtelierAPI) => SourceControlApi = SourceControlApi.fromAtelierApi) {
this.apiFactory = apiFactory;
}

public async fetch(document: vscode.TextDocument, payload: GlobalDocumentationPayload): Promise<string> {
const api = new AtelierAPI(document.uri);

let sourceControlApi: SourceControlApi;
try {
sourceControlApi = this.apiFactory(api);
} catch (error) {
logDebug("Failed to create SourceControl API client for global documentation", error);
throw error;
}

const { requestTimeout } = getCcsSettings();

try {
const response = await sourceControlApi.post<string>(ROUTES.getGlobalDocumentation(), payload, {
timeout: requestTimeout,
responseType: "text",
transformResponse: [(data) => data],
validateStatus: (status) => status >= 200 && status < 300,
});

return typeof response.data === "string" ? response.data : "";
} catch (error) {
logDebug("Global documentation request failed", error);
throw error;
}
}
}
1 change: 1 addition & 0 deletions src/ccs/sourcecontrol/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const BASE_PATH = "/api/sourcecontrol/vscode" as const;

export const ROUTES = {
resolveContextExpression: () => `/resolveContextExpression`,
getGlobalDocumentation: () => `/getGlobalDocumentation`,
} as const;

export type RouteKey = keyof typeof ROUTES;
60 changes: 60 additions & 0 deletions src/commands/globalDocumentation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import * as vscode from "vscode";

import { AtelierAPI } from "../api";
import { currentFile, handleError, outputChannel } from "../utils";

function getSelectedOrCurrentLineText(editor: vscode.TextEditor): string {
const { selection, document } = editor;
if (!selection || selection.isEmpty) {
return document.lineAt(selection.active.line).text.trim();
}
return document.getText(selection).trim();
}

export async function showGlobalDocumentation(): Promise<void> {
const file = currentFile();
const editor = vscode.window.activeTextEditor;

if (!file || !editor) {
return;
}

const selectedText = getSelectedOrCurrentLineText(editor);

if (!selectedText) {
void vscode.window.showErrorMessage("Selection is empty. Select text or place the cursor on a line with content.");
return;
}

const api = new AtelierAPI(file.uri);

if (!api.active) {
void vscode.window.showErrorMessage("No active connection to retrieve global documentation.");
return;
}

try {
const response = await api.getGlobalDocumentation({ selectedText });
const content = response?.result?.content;
let output = "";

if (Array.isArray(content)) {
output = content.join("\n");
} else if (typeof content === "string") {
output = content;
} else if (content && typeof content === "object") {
output = JSON.stringify(content, null, 2);
}

if (!output) {
void vscode.window.showInformationMessage("Global documentation did not return any content.");
return;
}

outputChannel.appendLine("==================== Global Documentation ====================");
outputChannel.appendLine(output);
outputChannel.show(true);
} catch (error) {
handleError(error, "Failed to retrieve global documentation.");
}
}
7 changes: 5 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@ import {
import { WorkspaceNode, NodeBase } from "./explorer/nodes";
import { showPlanWebview } from "./commands/showPlanPanel";
import { isfsConfig } from "./utils/FileProviderUtil";
import { resolveContextExpression } from "./ccs";

import { resolveContextExpression, showGlobalDocumentation } from "./ccs";
const packageJson = vscode.extensions.getExtension(extensionId).packageJSON;
const extensionVersion = packageJson.version;
const aiKey = packageJson.aiKey;
Expand Down Expand Up @@ -1372,6 +1371,10 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
sendCommandTelemetryEvent("viewOthers");
viewOthers(false);
}),
vscode.commands.registerCommand("vscode-objectscript.getGlobalDocumentation", () => {
sendCommandTelemetryEvent("getGlobalDocumentation");
void showGlobalDocumentation();
}),
vscode.commands.registerCommand("vscode-objectscript.serverCommands.sourceControl", (uri?: vscode.Uri) => {
sendCommandTelemetryEvent("serverCommands.sourceControl");
mainSourceControlMenu(uri);
Expand Down