Skip to content
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

Update editor tab on member rename #1907

23 changes: 23 additions & 0 deletions src/api/Tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,12 @@ export namespace Tools {
}
}

/**
* Check whether two given uris point to the same file/member
*/
export function areEquivalentUris(uriA: vscode.Uri, uriB: vscode.Uri) {
return uriStringWithoutFragment(uriA) === uriStringWithoutFragment(uriB);
}

/**
* We do this to find previously opened files with the same path, but different case OR readonly flags.
Expand All @@ -314,6 +320,23 @@ export namespace Tools {
return (isCaseSensitive ? baseUri : baseUri.toLowerCase());
}

/**
* Given the uri of a member or other resource, find all
* (if any) open tabs where that resource is being edited.
*/
export function findUriTabs(uriToFind: vscode.Uri): vscode.Tab[] {
let resourceTabs: vscode.Tab[] = [];
for (const group of vscode.window.tabGroups.all) {
group.tabs.filter(tab =>
(tab.input instanceof vscode.TabInputText)
&& areEquivalentUris(tab.input.uri, uriToFind)
).forEach(tab => {
resourceTabs.push(tab);
});
}
return resourceTabs;
}

/**
* Fixes an SQL statement to make it compatible with db2 CLI program QZDFMDB2.
* - Changes `@clCommand` statements into Call `QSYS2.QCMDEX('clCommand')` procedure calls
Expand Down
3 changes: 3 additions & 0 deletions src/locale/ids/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@
"enddbgsvr.succeeded": "Debug server er stoppet.",
"error": "fejl",
"errors": "fejl",
"file.path.not.parsed": "Filstien kunne ikke fortolkes.",
"file.unsaved.changes": "Filen har ikke-gemte ændringer.",
"generate.certificate": "Generer service certifikat",
"helpView.getStarted": "Dokumentation",
"helpView.officialForum": "Forum",
Expand Down Expand Up @@ -238,6 +240,7 @@
"login.title.create": "Forbind til IBM i",
"login.title.edit": "Login Indstillinger: \"{0}\"",
"MAX_HEAP_SIZE": "Maksimalt tilladt memory",
"member.has.unsaved.changes": "Memberet har ikke-gemte ændringer.",
"members": "Members",
"MEMORY_POOL": "Memory pulje",
"modified": "Ændret",
Expand Down
3 changes: 3 additions & 0 deletions src/locale/ids/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@
"enddbgsvr.succeeded": "Debug server stopped.",
"error": "error",
"errors": "errors",
"file.path.not.parsed": "The file path could not be parsed.",
"file.unsaved.changes": "The file has unsaved changes.",
"generate.certificate": "Generate service certificate",
"helpView.getStarted": "Get started",
"helpView.officialForum": "Open official Forum",
Expand Down Expand Up @@ -238,6 +240,7 @@
"login.title.create": "Connect to IBM i",
"login.title.edit": "Login Settings: \"{0}\"",
"MAX_HEAP_SIZE": "Maximum allowed memory",
"member.has.unsaved.changes": "The member has unsaved changes.",
"members": "Members",
"MEMORY_POOL": "Memory pool",
"modified": "Modified",
Expand Down
3 changes: 3 additions & 0 deletions src/locale/ids/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@
"enddbgsvr.succeeded": "Serveur de débogage arrêté.",
"error": "erreur",
"errors": "erreurs",
"file.path.not.parsed": "Le chemin du fichier n'a pas pu être analysé.",
"file.unsaved.changes": "Le fichier a des changements non sauvegardés.",
"generate.certificate": "Generer le certificat du service",
"helpView.getStarted": "Pour commencer",
"helpView.officialForum": "Forum officiel",
Expand Down Expand Up @@ -238,6 +240,7 @@
"login.title.create": "Connect to IBM i",
"login.title.edit": "paramètres d'authentification: \"{0}\"",
"MAX_HEAP_SIZE": "Mémoire maximum allouée",
"member.has.unsaved.changes": "Le membre a des changements non sauvegardés.",
"members": "Membres",
"MEMORY_POOL": "Pool mémoire",
"modified": "Modifié",
Expand Down
21 changes: 21 additions & 0 deletions src/views/ifsBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,17 @@ export function initializeIFSBrowser(context: vscode.ExtensionContext) {
}),

vscode.commands.registerCommand(`code-for-ibmi.moveIFS`, async (node: IFSItem) => {
// Ensure that the file has a defined uri
if (!node.resourceUri) {
vscode.window.showErrorMessage(t("ifsBrowser.moveIFS.errorMessage", t(String(node.contextValue)), t("file.path.not.parsed")));
return;
}
// Check if the streamfile is currently open in an editor tab
const oldFileTabs = Tools.findUriTabs(node.resourceUri);
if (oldFileTabs.find(tab => tab.isDirty)) {
vscode.window.showErrorMessage(t("ifsBrowser.moveIFS.errorMessage", t(String(node.contextValue)), t("file.unsaved.changes")));
return;
}
const connection = instance.getConnection();
const config = instance.getConfig();
if (config && connection) {
Expand All @@ -637,6 +648,16 @@ export function initializeIFSBrowser(context: vscode.ExtensionContext) {
Tools.escapePath(node.path),
Tools.escapePath(targetPath)
));
// If the file was open in any editor tabs prior to the renaming/movement,
// refresh those tabs to reflect the new file path/name.
// (Directly modifying the label or uri of an open tab is apparently not
// possible with the current VS Code API, so refresh the tab by closing
// it and then opening a new one at the new uri.)
oldFileTabs.forEach((tab) => {
vscode.window.tabGroups.close(tab).then(() => {
vscode.commands.executeCommand(`code-for-ibmi.openEditable`, targetPath);
})
})

} catch (e) {
vscode.window.showErrorMessage(t(`ifsBrowser.moveIFS.errorMessage`, t(String(node.contextValue)), e));
Expand Down
30 changes: 28 additions & 2 deletions src/views/objectBrowser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { SortOptions, SortOrder } from "../api/IBMiContent";
import { Search } from "../api/Search";
import { GlobalStorage } from '../api/Storage';
import { Tools } from "../api/Tools";
import { getMemberUri } from "../filesystems/qsys/QSysFs";
import { getMemberUri, getUriFromPath } from "../filesystems/qsys/QSysFs";
import { instance, setSearchResults } from "../instantiate";
import { t } from "../locale";
import { BrowserItem, BrowserItemParameters, CommandResult, FilteredItem, FocusOptions, IBMiMember, IBMiObject, MemberItem, OBJECT_BROWSER_MIMETYPE, ObjectItem, WithLibrary } from "../typings";
Expand Down Expand Up @@ -734,12 +734,24 @@ export function initializeObjectBrowser(context: vscode.ExtensionContext) {
vscode.commands.registerCommand(`code-for-ibmi.renameMember`, async (node: ObjectBrowserMemberItem) => {
const connection = getConnection();
const oldMember = connection.parserMemberPath(node.path);
const oldUri = node.resourceUri as vscode.Uri;
const library = oldMember.library;
const sourceFile = oldMember.file;
let newBasename: string | undefined = oldMember.basename;
let newMember: MemberParts | undefined;
let newMemberPath: string | undefined;
let newNameOK;

// Check if the member is currently open in an editor tab.
const oldMemberTabs = Tools.findUriTabs(oldUri);

// If the member is currently open in an editor tab, and
// the member has unsaved changes, then prevent the renaming operation.
if(oldMemberTabs.find(tab => tab.isDirty)){
vscode.window.showErrorMessage(t("objectBrowser.renameMember.errorMessage", t("member.has.unsaved.changes")));
return;
}

do {
newBasename = await vscode.window.showInputBox({
value: newBasename,
Expand All @@ -749,8 +761,9 @@ export function initializeObjectBrowser(context: vscode.ExtensionContext) {

if (newBasename) {
newNameOK = true;
newMemberPath = library + `/` + sourceFile + `/` + newBasename;
try {
newMember = connection.parserMemberPath(library + `/` + sourceFile + `/` + newBasename);
newMember = connection.parserMemberPath(newMemberPath);
} catch (e: any) {
newNameOK = false;
vscode.window.showErrorMessage(e);
Expand Down Expand Up @@ -786,6 +799,19 @@ export function initializeObjectBrowser(context: vscode.ExtensionContext) {
}
}
} while (newBasename && !newNameOK)

// If the member was open in an editor tab prior to the renaming,
// refresh those tabs to reflect the new member path/name.
// (Directly modifying the label or uri of an open tab is apparently not
// possible with the current VS Code API, so refresh the tab by closing
// it and then opening a new one at the new uri.)
if (newNameOK && newMemberPath) {
oldMemberTabs.forEach((tab) => {
vscode.window.tabGroups.close(tab).then(() => {
vscode.commands.executeCommand(`code-for-ibmi.openEditable`, newMemberPath);
});
})
}
}),

vscode.commands.registerCommand(`code-for-ibmi.uploadAndReplaceMemberAsFile`, async (node: MemberItem) => {
Expand Down