Skip to content

Improve exporting #818

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

Merged
merged 2 commits into from
Jan 10, 2022
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
2 changes: 1 addition & 1 deletion docs/SettingsReference.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ The extensions in the InterSystems ObjectScript Extension Pack provide many sett
| `"objectscript.export.atelier"` | Export source code as Atelier did it, with packages as subfolders. | `boolean` | `true` | |
| `"objectscript.export.category"` | Category of source code to export: `CLS` = classes; `RTN` = routines; `CSP` = csp files; `OTH` = other. Default is `*` = all. | `string` or `object` | `"*"` | |
| `"objectscript.export.dontExportIfNoChanges"` | Do not rewrite the local file if the content is identical to what came from the server. | `boolean` | `false` | |
| `"objectscript.export.filter"` | SQL filter to limit what to export. | `string` | `""` | |
| `"objectscript.export.filter"` | SQL filter to limit what to export. | `string` | `""` | The filter is applied to document names using the [LIKE predicate](https://irisdocs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=RSQL_like) (i.e. `Name LIKE '%filter%'`). |
| `"objectscript.export.folder"` | Folder for exported source code within workspace. | `string` | `"src"` | |
| `"objectscript.export.generated"` | Export generated source code files, such as INTs generated from classes. | `boolean` | `false` | |
| `"objectscript.export.map"` | Map file names before export, with regexp pattern as a key and replacement as a value. | `object` | `{}` | For example, `{ \"%(.*)\": \"_$1\" }` to make % classes or routines use underscore prefix instead. |
Expand Down
19 changes: 17 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@
{
"command": "vscode-objectscript.showClassDocumentationPreview",
"when": "editorLangId == objectscript-class"
},
{
"command": "vscode-objectscript.exportCurrentFile",
"when": "resourceScheme == objectscript && vscode-objectscript.connectActive"
}
],
"view/title": [
Expand Down Expand Up @@ -333,6 +337,11 @@
"command": "vscode-objectscript.compileOnly",
"when": "editorLangId =~ /^objectscript/ && vscode-objectscript.connectActive",
"group": "objectscript@7"
},
{
"command": "vscode-objectscript.exportCurrentFile",
"when": "resourceScheme == objectscript && vscode-objectscript.connectActive",
"group": "objectscript@8"
}
],
"editor/title": [
Expand Down Expand Up @@ -497,7 +506,7 @@
{
"category": "ObjectScript",
"command": "vscode-objectscript.export",
"title": "Export Sources",
"title": "Export Code from Server",
"enablement": "!isWeb"
},
{
Expand Down Expand Up @@ -695,6 +704,12 @@
"title": "Show Class Documentation Preview",
"enablement": "!isWeb",
"icon": "$(open-preview)"
},
{
"category": "ObjectScript",
"command": "vscode-objectscript.exportCurrentFile",
"title": "Export Current File from Server",
"enablement": "!isWeb"
}
],
"keybindings": [
Expand Down Expand Up @@ -895,7 +910,7 @@
"type": "boolean"
},
"filter": {
"description": "SQL filter to limit what to export.",
"markdownDescription": "SQL filter to limit what to export. The filter is applied to document names using the [LIKE predicate](https://irisdocs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=RSQL_like) (i.e. `Name LIKE '%filter%'`).",
"type": "string"
},
"category": {
Expand Down
113 changes: 90 additions & 23 deletions src/commands/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,10 @@ import fs = require("fs");
import path = require("path");
import * as vscode from "vscode";
import { AtelierAPI } from "../api";
import { config, explorerProvider } from "../extension";
import { mkdirSyncRecursive, notNull, outputChannel, uriOfWorkspaceFolder } from "../utils";
import { config, explorerProvider, OBJECTSCRIPT_FILE_SCHEMA, schemas } from "../extension";
import { currentFile, mkdirSyncRecursive, notNull, outputChannel, uriOfWorkspaceFolder } from "../utils";
import { NodeBase } from "../explorer/models/nodeBase";

const filesFilter = (file: any) => {
if (file.cat === "CSP" || file.name.startsWith("%") || file.name.startsWith("INFORMATION.")) {
return false;
}
return true;
};

export const getCategory = (fileName: string, addCategory: any | boolean): string => {
const fileExt = fileName.split(".").pop().toLowerCase();
if (typeof addCategory === "object") {
Expand Down Expand Up @@ -216,27 +209,86 @@ export async function exportList(files: string[], workspaceFolder: string, names
);
}

export async function exportAll(workspaceFolder?: string): Promise<any> {
if (!workspaceFolder) {
const list = vscode.workspace.workspaceFolders
.filter((folder) => config("conn", folder.name).active)
.map((el) => el.name);
if (list.length > 1) {
return vscode.window.showQuickPick(list).then((folder) => (folder ? exportAll : null));
} else {
workspaceFolder = list.pop();
export async function exportAll(): Promise<any> {
let workspaceFolder: string;
const workspaceList = vscode.workspace.workspaceFolders
.filter((folder) => !schemas.includes(folder.uri.scheme) && config("conn", folder.name).active)
.map((el) => el.name);
if (workspaceList.length > 1) {
const selection = await vscode.window.showQuickPick(workspaceList, {
placeHolder: "Select the workspace folder to export files to.",
});
if (selection === undefined) {
return;
}
workspaceFolder = selection;
} else if (workspaceList.length === 1) {
workspaceFolder = workspaceList.pop();
} else {
vscode.window.showInformationMessage(
"There are no folders in the current workspace that code can be exported to.",
"Dismiss"
);
return;
}
if (!config("conn", workspaceFolder).active) {
return;
}
const api = new AtelierAPI(workspaceFolder);
outputChannel.show(true);
const { category, generated, filter, ns } = config("export", workspaceFolder);
const files = (data) => data.result.content.filter(filesFilter).map((file) => file.name);
return api.getDocNames({ category, generated, filter }).then((data) => {
return exportList(files(data), workspaceFolder, ns);
});
const { category, generated, filter } = config("export", workspaceFolder);
// Replicate the behavior of getDocNames() but use StudioOpenDialog for better performance
let filterStr = "";
switch (category) {
case "CLS":
filterStr = "Type = 4";
break;
case "CSP":
filterStr = "Type %INLIST $LISTFROMSTRING('5,6')";
break;
case "OTH":
filterStr = "Type NOT %INLIST $LISTFROMSTRING('0,1,2,3,4,5,6,11,12')";
break;
case "RTN":
filterStr = "Type %INLIST $LISTFROMSTRING('0,1,2,3,11,12')";
break;
}
if (filter !== "") {
if (filterStr !== "") {
filterStr += " AND ";
}
filterStr += `Name LIKE '%${filter}%'`;
}
return api
.actionQuery("SELECT Name FROM %Library.RoutineMgr_StudioOpenDialog(?,?,?,?,?,?,?,?)", [
"*",
"1",
"1",
api.config.ns.toLowerCase() === "%sys" ? "1" : "0",
"1",
"0",
generated ? "1" : "0",
filterStr,
])
.then(async (data) => {
let files: vscode.QuickPickItem[] = data.result.content.map((file) => {
return { label: file.Name, picked: true };
});
files = await vscode.window.showQuickPick(files, {
canPickMany: true,
ignoreFocusOut: true,
placeHolder: "Uncheck a file to exclude it. Press 'Escape' to cancel export.",
title: "Files to Export",
});
if (files === undefined) {
return;
}
return exportList(
files.map((file) => file.label),
workspaceFolder,
api.config.ns
);
});
}

export async function exportExplorerItems(nodes: NodeBase[]): Promise<any> {
Expand Down Expand Up @@ -264,3 +316,18 @@ Would you like to continue?`,
return exportList(items.flat(), workspaceFolder, namespace).then(() => explorerProvider.refresh());
});
}

export async function exportCurrentFile(): Promise<any> {
const openEditor = vscode.window.activeTextEditor;
if (openEditor === undefined) {
// Need an open document to export
return;
}
const openDoc = openEditor.document;
if (openDoc.uri.scheme !== OBJECTSCRIPT_FILE_SCHEMA) {
// Only export files opened from the explorer
return;
}
const api = new AtelierAPI(openDoc.uri);
return exportList([currentFile(openDoc).name], api.configName, api.config.ns);
}
15 changes: 9 additions & 6 deletions src/explorer/models/rootNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { RoutineNode } from "./routineNode";
import { AtelierAPI } from "../../api";
import { ClassNode } from "./classNode";
import { CSPFileNode } from "./cspFileNode";
import { StudioOpenDialog } from "../../queries";

type IconPath =
| string
Expand Down Expand Up @@ -58,9 +57,12 @@ export class RootNode extends NodeBase {
return this.getItems(path, this._category);
}

public getList(path: string, category: string, flat: boolean): Promise<(StudioOpenDialog & { fullName: string })[]> {
const sql = "CALL %Library.RoutineMgr_StudioOpenDialog(?,?,?,?,?,?,?)";
// const sql = "CALL %Library.RoutineMgr_StudioOpenDialog(?,,,,,,?)";
public getList(
path: string,
category: string,
flat: boolean
): Promise<{ Name: string; Type: string; fullName: string }[]> {
const sql = "SELECT Name, Type FROM %Library.RoutineMgr_StudioOpenDialog(?,?,?,?,?,?,?)";
let spec = "";
switch (category) {
case "CLS":
Expand Down Expand Up @@ -102,15 +104,16 @@ export class RootNode extends NodeBase {
return content;
})
.then((data) =>
data.map((el: StudioOpenDialog) => {
data.map((el: { Name: string; Type: number }) => {
let fullName = el.Name;
if (this instanceof PackageNode) {
fullName = this.fullName + "." + el.Name;
} else if (this.isCsp) {
fullName = this.fullName + "/" + el.Name;
}
return {
...el,
Name: el.Name,
Type: String(el.Type),
fullName,
};
})
Expand Down
3 changes: 2 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
compileOnly,
} from "./commands/compile";
import { deleteExplorerItems } from "./commands/delete";
import { exportAll, exportExplorerItems } from "./commands/export";
import { exportAll, exportCurrentFile, exportExplorerItems } from "./commands/export";
import { serverActions } from "./commands/serverActions";
import { subclass } from "./commands/subclass";
import { superclass } from "./commands/superclass";
Expand Down Expand Up @@ -929,6 +929,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
vscode.commands.registerCommand("vscode-objectscript.showClassDocumentationPreview", () =>
DocumaticPreviewPanel.create(context.extensionUri)
),
vscode.commands.registerCommand("vscode-objectscript.exportCurrentFile", exportCurrentFile),

/* Anything we use from the VS Code proposed API */
...proposed
Expand Down