Skip to content

Commit

Permalink
WIP Cache encoding for nodes
Browse files Browse the repository at this point in the history
Signed-off-by: Timothy Johnson <[email protected]>
  • Loading branch information
t1m0thyj committed Dec 1, 2023
1 parent 81996ca commit 07ef9d2
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 112 deletions.
23 changes: 18 additions & 5 deletions packages/zowe-explorer-api/src/tree/IZoweTreeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ export interface IZoweDatasetTreeNode extends IZoweTreeNode {
*/
filter?: DatasetFilter;
/**
* List of child nodes downloaded in binary format
* List of child nodes and user-selected encodings
*/
binaryFiles?: Record<string, unknown>;
encodingMap?: Record<string, string>;
/**
* Binary indicator. Default false (text)
*/
Expand Down Expand Up @@ -185,10 +185,11 @@ export interface IZoweDatasetTreeNode extends IZoweTreeNode {
*/
setEtag?(etag: string);
/**
* Specifies the field as binary
* @param binary true is a binary file otherwise false
* Sets the codepage value for the file
*
* @param {string}
*/
setBinary?(binary: boolean);
setEncoding?(encoding: string);
}

/**
Expand All @@ -204,8 +205,13 @@ export interface IZoweUSSTreeNode extends IZoweTreeNode {
shortLabel?: string;
/**
* List of child nodes downloaded in binary format
* @deprecated Use `encodingMap` instead
*/
binaryFiles?: Record<string, unknown>;
/**
* List of child nodes and user-selected encodings
*/
encodingMap?: Record<string, string>;
/**
* Binary indicator. Default false (text)
*/
Expand Down Expand Up @@ -257,9 +263,16 @@ export interface IZoweUSSTreeNode extends IZoweTreeNode {
rename?(newNamePath: string);
/**
* Specifies the field as binary
* @deprecated Use `setEncoding` instead
* @param binary true is a binary file otherwise false
*/
setBinary?(binary: boolean);
/**
* Sets the codepage value for the file
*
* @param {string}
*/
setEncoding?(encoding: string);
// /**
// * Opens the text document
// * @return vscode.TextDocument
Expand Down
2 changes: 1 addition & 1 deletion packages/zowe-explorer-api/src/tree/ZoweTreeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class ZoweTreeNode extends vscode.TreeItem {
public fullPath = "";
public dirty = false;
public children: IZoweTreeNode[] = [];
public binaryFiles = {};
public encodingMap = {};
public binary = false;
public shortLabel = "";

Expand Down
9 changes: 4 additions & 5 deletions packages/zowe-explorer/i18n/sample/src/shared/utils.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@
"zowe.shared.utils.promptForEncoding.binary.description": "Raw data representation",
"zowe.shared.utils.promptForEncoding.other.label": "Other",
"zowe.shared.utils.promptForEncoding.other.description": "Specify another codepage",
"zowe.shared.utils.promptForEncoding.current.description": "Current (local)",
"zowe.shared.utils.promptForEncoding.tagged.description": "Tagged (remote)",
"zowe.shared.utils.promptForEncoding.untagged.description": "Untagged",
"zowe.shared.utils.promptForEncoding.profile.description": "Inherit from profile",
"zowe.shared.utils.promptForEncoding.qp.placeHolder": "Choose an encoding",
"zowe.shared.utils.promptForEncoding.profile.description": "From profile {0}",
"zowe.shared.utils.promptForEncoding.tagged.description": "USS file tag",
"zowe.shared.utils.promptForEncoding.qp.title": "Choose encoding for {0}",
"zowe.shared.utils.promptForEncoding.qp.placeHolder": "Current encoding is {0}",
"zowe.shared.utils.promptForEncoding.input.placeHolder": "Enter a codepage in the format 1047 or IBM-1047"
}
25 changes: 15 additions & 10 deletions packages/zowe-explorer/src/dataset/DatasetTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ export class DatasetTree extends ZoweTreeProvider implements IZoweTree<IZoweData
profileNodeInFavorites,
node.getSession(),
node.contextValue,
undefined,
node.getEtag(),
node.getProfile()
);
Expand All @@ -538,6 +539,7 @@ export class DatasetTree extends ZoweTreeProvider implements IZoweTree<IZoweData
profileNodeInFavorites,
node.getSession(),
node.contextValue,
undefined,
node.getEtag(),
node.getProfile()
);
Expand Down Expand Up @@ -1311,7 +1313,16 @@ export class DatasetTree extends ZoweTreeProvider implements IZoweTree<IZoweData
}
}
// Creates ZoweDatasetNode to track new session and pushes it to mSessionNodes
const node = new ZoweDatasetNode(profile.name, vscode.TreeItemCollapsibleState.Collapsed, null, session, undefined, undefined, profile);
const node = new ZoweDatasetNode(
profile.name,
vscode.TreeItemCollapsibleState.Collapsed,
null,
session,
undefined,
undefined,
undefined,
profile
);
node.contextValue = globals.DS_SESSION_CONTEXT + (profile.type !== "zosmf" ? `.profile=${profile.type}.` : "");
await this.refreshHomeProfileContext(node);
const icon = getIconByNode(node);
Expand Down Expand Up @@ -1542,15 +1553,9 @@ export class DatasetTree extends ZoweTreeProvider implements IZoweTree<IZoweData

public async openWithEncoding(node: IZoweDatasetTreeNode): Promise<void> {
const encoding = await promptForEncoding(node);
if (encoding === undefined) {
return;
} else if (encoding === "binary") {
node.setBinary(true);
node.encoding = null;
} else {
node.setBinary(false);
node.encoding = encoding;
if (encoding !== undefined) {
node.setEncoding(encoding);
await dsActions.openPS(node, true, false, this);
}
await dsActions.openPS(node, true, false, this);
}
}
35 changes: 26 additions & 9 deletions packages/zowe-explorer/src/dataset/ZoweDatasetNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod
public memberPattern = "";
public dirty = true;
public children: ZoweDatasetNode[] = [];
public binaryFiles = {};
public encodingMap = {};
public binary = false;
public errorDetails: zowe.imperative.ImperativeError;
public ongoingActions: Record<NodeAction | string, Promise<any>> = {};
Expand All @@ -78,11 +78,13 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod
mParent: IZoweDatasetTreeNode,
session: zowe.imperative.Session,
contextOverride?: string,
encoding?: "text" | "binary" | string,
private etag?: string,
profile?: zowe.imperative.IProfileLoaded
) {
super(label, collapsibleState, mParent, session, profile);

this.binary = encoding === "binary";
this.encoding = this.binary ? undefined : encoding === "text" ? null : encoding;
if (contextOverride) {
this.contextValue = contextOverride;
} else if (collapsibleState !== vscode.TreeItemCollapsibleState.None) {
Expand Down Expand Up @@ -201,6 +203,7 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod
null,
undefined,
undefined,
undefined,
this.getProfile()
);
elementChildren[temp.label.toString()] = temp;
Expand All @@ -213,6 +216,7 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod
null,
globals.DS_FILE_ERROR_CONTEXT,
undefined,
undefined,
this.getProfile()
);
temp.errorDetails = item.error; // Save imperative error to avoid extra z/OS requests
Expand All @@ -226,6 +230,7 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod
null,
globals.DS_MIGRATED_FILE_CONTEXT,
undefined,
undefined,
this.getProfile()
);
elementChildren[temp.label.toString()] = temp;
Expand All @@ -247,17 +252,20 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod
null,
globals.VSAM_CONTEXT,
undefined,
undefined,
this.getProfile()
);
}
} else if (contextually.isSessionNotFav(this)) {
// Creates a ZoweDatasetNode for a PS
const cachedEncoding = this.getSessionNode().encodingMap[item.dsname];
const temp = new ZoweDatasetNode(
item.dsname,
vscode.TreeItemCollapsibleState.None,
this,
null,
undefined,
cachedEncoding,
undefined,
this.getProfile()
);
Expand All @@ -266,12 +274,14 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod
} else {
// Creates a ZoweDatasetNode for a PDS member
const memberInvalid = item.member?.includes("\ufffd");
const cachedEncoding = this.getSessionNode().encodingMap[`${item.dsname as string}(${item.member as string})`];
const temp = new ZoweDatasetNode(
item.member,
vscode.TreeItemCollapsibleState.None,
this,
null,
memberInvalid ? globals.DS_FILE_ERROR_CONTEXT : undefined,
cachedEncoding,
undefined,
this.getProfile()
);
Expand Down Expand Up @@ -489,19 +499,26 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod
return responses;
}

public setBinary(binary: boolean): void {
ZoweLogger.trace("ZoweDatasetNode.setBinary called.");
public setEncoding(encoding: "text" | "binary" | string): void {
ZoweLogger.trace("ZoweDatasetNode.setEncoding called.");
if (!(this.contextValue.startsWith(globals.DS_DS_CONTEXT) || this.contextValue.startsWith(globals.DS_MEMBER_CONTEXT))) {
throw new Error(`Cannot set node with context ${this.contextValue} as binary`);
throw new Error(`Cannot set encoding for node with context ${this.contextValue}`);
}
this.binary = binary;
const isMemberNode = this.contextValue.startsWith(globals.DS_MEMBER_CONTEXT);
if (this.binary) {
if (encoding === "binary") {
this.contextValue = isMemberNode ? globals.DS_MEMBER_BINARY_CONTEXT : globals.DS_DS_BINARY_CONTEXT;
this.getSessionNode().binaryFiles[this.fullPath] = true;
this.binary = true;
this.encoding = undefined;
} else {
this.contextValue = isMemberNode ? globals.DS_MEMBER_CONTEXT : globals.DS_DS_CONTEXT;
delete this.getSessionNode().binaryFiles[this.fullPath];
this.binary = false;
this.encoding = encoding === "text" ? null : encoding;
}
const fullPath = isMemberNode ? `${this.getParent().label as string}(${this.label as string})` : (this.label as string);
if (this.binary || this.encoding != null) {
this.getSessionNode().encodingMap[fullPath] = encoding;
} else {
delete this.getSessionNode().encodingMap[fullPath];
}
if (this.getParent() && this.getParent().contextValue === globals.FAV_PROFILE_CONTEXT) {
this.contextValue += globals.FAV_SUFFIX;
Expand Down
2 changes: 1 addition & 1 deletion packages/zowe-explorer/src/dataset/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ export async function createMember(parent: api.IZoweDatasetTreeNode, datasetProv
datasetProvider.refreshElement(parent);

await openPS(
new ZoweDatasetNode(name, vscode.TreeItemCollapsibleState.None, parent, null, undefined, undefined, parent.getProfile()),
new ZoweDatasetNode(name, vscode.TreeItemCollapsibleState.None, parent, null, undefined, undefined, undefined, parent.getProfile()),
false,
true,
datasetProvider
Expand Down
83 changes: 41 additions & 42 deletions packages/zowe-explorer/src/shared/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,20 @@ export async function compareFileContent(
}
}

export async function promptForEncoding(node: IZoweDatasetTreeNode | IZoweUSSTreeNode, taggedEncoding?: string): Promise<string | undefined> {
export function getCachedEncoding<T extends IZoweTreeNode>(node: T): string {
if (isZoweUSSTreeNode(node)) {
return (node.getSessionNode() as IZoweUSSTreeNode).encodingMap[node.fullPath] as string;

Check failure on line 417 in packages/zowe-explorer/src/shared/utils.ts

View workflow job for this annotation

GitHub Actions / lint

This assertion is unnecessary since it does not change the type of the expression
} else {
const isMemberNode = node.contextValue.startsWith(globals.DS_MEMBER_CONTEXT);
const fullPath = isMemberNode ? `${node.getParent().label as string}(${node.label as string})` : (node.label as string);
return (node.getSessionNode() as IZoweDatasetTreeNode).encodingMap[fullPath] as string;

Check failure on line 421 in packages/zowe-explorer/src/shared/utils.ts

View workflow job for this annotation

GitHub Actions / lint

This assertion is unnecessary since it does not change the type of the expression
}
}

export async function promptForEncoding(
node: IZoweDatasetTreeNode | IZoweUSSTreeNode,
taggedEncoding?: string
): Promise<"text" | "binary" | string | undefined> {
const ebcdicItem: vscode.QuickPickItem = {
label: localize("zowe.shared.utils.promptForEncoding.ebcdic.label", "EBCDIC"),
description: localize("zowe.shared.utils.promptForEncoding.ebcdic.description", "z/OS default codepage"),
Expand All @@ -425,74 +438,60 @@ export async function promptForEncoding(node: IZoweDatasetTreeNode | IZoweUSSTre
label: localize("zowe.shared.utils.promptForEncoding.other.label", "Other"),
description: localize("zowe.shared.utils.promptForEncoding.other.description", "Specify another codepage"),
};

const fileItems: vscode.QuickPickItem[] = [];
let currentEncoding = node.encoding;
if (node.binary) {
currentEncoding = binaryItem.label;
} else if (node.encoding === null) {
currentEncoding = ebcdicItem.label;
}
if (currentEncoding != null) {
fileItems.push({
label: currentEncoding,
description: localize("zowe.shared.utils.promptForEncoding.current.description", "Current (local)"),
const items: vscode.QuickPickItem[] = [ebcdicItem, binaryItem, otherItem, globals.SEPARATORS.RECENT];
const profile = node.getProfile();
if (profile.profile?.encoding != null) {
items.splice(0, 0, {
label: profile.profile?.encoding,
description: localize("zowe.shared.utils.promptForEncoding.profile.description", "From profile {0}", profile.name),
});
}
if (taggedEncoding != null) {
if (taggedEncoding === currentEncoding.toLowerCase()) {
fileItems[0].description += ", " + localize("zowe.shared.utils.promptForEncoding.tagged.description", "Tagged (remote)");
} else {
fileItems.push({
label: taggedEncoding,
description: localize("zowe.shared.utils.promptForEncoding.tagged.description", "Tagged (remote)"),
});
}
} else if (currentEncoding != null) {
fileItems[0].description += ", " + localize("zowe.shared.utils.promptForEncoding.untagged.description", "Untagged");
}
if (fileItems.length > 0) {
fileItems.push(globals.SEPARATORS.BLANK);
}

const globalItems: vscode.QuickPickItem[] = [ebcdicItem, binaryItem, otherItem, globals.SEPARATORS.RECENT];
const profileEncoding = node.getProfile().profile?.encoding;
if (profileEncoding != null) {
globalItems.splice(0, 0, {
label: profileEncoding,
description: localize("zowe.shared.utils.promptForEncoding.profile.description", "Inherit from profile"),
items.splice(0, 0, {
label: taggedEncoding,
description: localize("zowe.shared.utils.promptForEncoding.tagged.description", "USS file tag"),
});
}

const recentItems: vscode.QuickPickItem[] = [];
let currentEncoding = node.encoding ?? getCachedEncoding(node);
if (node.binary || currentEncoding === "binary") {
currentEncoding = binaryItem.label;
} else if (node.encoding === null || currentEncoding === "text") {
currentEncoding = ebcdicItem.label;
}
const encodingHistory = ZoweLocalStorage.getValue<string[]>("encodingHistory") ?? [];
if (encodingHistory.length > 0) {
for (const encoding of encodingHistory) {
recentItems.push({ label: encoding });
items.push({ label: encoding });
}
} else {
// Pre-populate recent list with some common encodings
recentItems.push({ label: "IBM-1047" }, { label: "ISO8859-1" });
items.push({ label: "IBM-1047" }, { label: "ISO8859-1" });
}

let encoding = (
await Gui.showQuickPick([...fileItems, ...globalItems, ...recentItems], {
placeHolder: localize("zowe.shared.utils.promptForEncoding.qp.placeHolder", "Choose an encoding"),
await Gui.showQuickPick(items, {
title: localize("zowe.shared.utils.promptForEncoding.qp.title", "Choose encoding for {0}", node.label as string),
placeHolder:
currentEncoding && localize("zowe.shared.utils.promptForEncoding.qp.placeHolder", "Current encoding is {0}", currentEncoding),
})
)?.label;
switch (encoding) {
case ebcdicItem.label:
encoding = null;
encoding = "text";
break;
case binaryItem.label:
encoding = "binary";
break;
case otherItem.label:
encoding = await Gui.showInputBox({
title: localize("zowe.shared.utils.promptForEncoding.qp.title", "Choose encoding for {0}", node.label as string),
placeHolder: localize("zowe.shared.utils.promptForEncoding.input.placeHolder", "Enter a codepage in the format 1047 or IBM-1047"),
});
encodingHistory.push(encoding);
ZoweLocalStorage.setValue("encodingHistory", encodingHistory.slice(0, globals.MAX_FILE_HISTORY));
if (encoding != null) {
encodingHistory.push(encoding);
ZoweLocalStorage.setValue("encodingHistory", encodingHistory.slice(0, globals.MAX_FILE_HISTORY));
}
break;
}
return encoding;
Expand Down
Loading

0 comments on commit 07ef9d2

Please sign in to comment.