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

Feature/edit vs browse #1757

Merged
merged 11 commits into from
Jan 6, 2024
52 changes: 48 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,15 @@
"default": true,
"description": "If enabled, will clear the IBM i Output before an Action is run."
},
"code-for-ibmi.defaultOpenMode": {
"type": "string",
"default": "edit",
"enum": [
"browse",
"edit"
],
"description": "The action to take when clicking on a source member or stream file to open it."
},
"code-for-ibmi.autoOpenFile": {
"type": "boolean",
"default": true,
Expand Down Expand Up @@ -1564,6 +1573,12 @@
"title": "Browse",
"enablement": "code-for-ibmi:connected",
"category": "IBM i"
},
{
"command": "code-for-ibmi.edit",
"title": "Edit",
"enablement": "code-for-ibmi:connected",
"category": "IBM i"
}
],
"keybindings": [
Expand Down Expand Up @@ -1685,6 +1700,14 @@
{
"id": "code-for-ibmi.sortMembers",
"label": "Sort by"
},
{
"id": "code-for-ibmi.openIFSFile",
"label": "Open"
},
{
"id": "code-for-ibmi.openMember",
"label": "Open"
}
],
"menus": {
Expand All @@ -1704,6 +1727,23 @@
"command": "code-for-ibmi.sortMembersByDate"
}
],
"code-for-ibmi.openIFSFile": [
{
"command": "code-for-ibmi.browse"
},
{
"command": "code-for-ibmi.edit"
}
],
"code-for-ibmi.openMember": [
{
"command": "code-for-ibmi.browse"
},
{
"command": "code-for-ibmi.edit",
"when": "viewItem == member"
}
],
"commandPalette": [
{
"command": "code-for-ibmi.userLibraryList.enable",
Expand Down Expand Up @@ -1793,6 +1833,10 @@
"command": "code-for-ibmi.browse",
"when": "never"
},
{
"command": "code-for-ibmi.edit",
"when": "never"
},
{
"command": "code-for-ibmi.copyFilter",
"when": "never"
Expand Down Expand Up @@ -2218,9 +2262,9 @@
"group": "5_sourceFileStuff@1"
},
{
"command": "code-for-ibmi.browse",
"submenu": "code-for-ibmi.openMember",
"when": "view == objectBrowser && viewItem =~ /^member.*$/",
"group": "0_browse@1"
"group": "0_open@1"
},
{
"command": "code-for-ibmi.runAction",
Expand Down Expand Up @@ -2278,9 +2322,9 @@
"group": "inline"
},
{
"command": "code-for-ibmi.browse",
"submenu": "code-for-ibmi.openIFSFile",
"when": "view == ifsBrowser && !listMultiSelection && viewItem == streamfile",
"group": "0_browse@1"
"group": "0_open@1"
},
{
"command": "code-for-ibmi.runAction",
Expand Down
5 changes: 4 additions & 1 deletion src/api/Configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as vscode from 'vscode';
import { DeploymentMethod } from '../typings';

export type SourceDateMode = "edit" | "diff";
export type DefaultOpenMode = "browse" | "edit";

const getConfiguration = (): vscode.WorkspaceConfiguration => {
return vscode.workspace.getConfiguration(`code-for-ibmi`);
Expand Down Expand Up @@ -58,6 +59,7 @@ export namespace ConnectionConfiguration {
readOnlyMode: boolean;
quickConnect: boolean;
defaultDeploymentMethod: DeploymentMethod | '';
protectedPaths: string[];
[name: string]: any;
}

Expand Down Expand Up @@ -135,7 +137,8 @@ export namespace ConnectionConfiguration {
debugEnableDebugTracing: (parameters.debugEnableDebugTracing === true),
readOnlyMode: (parameters.readOnlyMode === true),
quickConnect: (parameters.quickConnect === true || parameters.quickConnect === undefined),
defaultDeploymentMethod: parameters.defaultDeploymentMethod || ``
defaultDeploymentMethod: parameters.defaultDeploymentMethod || ``,
protectedPaths: (parameters.protectedPaths || [])
}
}

Expand Down
22 changes: 18 additions & 4 deletions src/api/IBMiContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,10 +438,10 @@ export default class IBMiContent {
*/
async getObjectList(filters: { library: string; object?: string; types?: string[]; }, sortOrder?: SortOrder): Promise<IBMiFile[]> {
const library = filters.library.toUpperCase();
if(!await this.checkObject({ library: "QSYS", name: library, type: "*LIB"})){
if (!await this.checkObject({ library: "QSYS", name: library, type: "*LIB" })) {
throw new Error(`Library ${library} does not exist.`);
}

const object = (filters.object && filters.object !== `*` ? filters.object.toUpperCase() : `*ALL`);
const sourceFilesOnly = (filters.types && filters.types.includes(`*SRCPF`));

Expand Down Expand Up @@ -561,7 +561,7 @@ export default class IBMiContent {
results = await this.getTable(tempLib, TempName, TempName, true);
if (results.length === 1 && String(results[0].MBNAME).trim() === ``) {
return [];
}
}

if (member || memberExt) {
let pattern: RegExp | undefined, patternExt: RegExp | undefined;
Expand Down Expand Up @@ -845,6 +845,20 @@ export default class IBMiContent {
return (await this.ibmi.runCommand({
command: `CHKOBJ OBJ(${object.library.toLocaleUpperCase()}/${object.name.toLocaleUpperCase()}) OBJTYPE(${object.type.toLocaleUpperCase()}) AUT(${authorities.join(" ")})`,
noLibList: true
}))?.code === 0;
})).code === 0;
}

async testStreamFile(path: string, right: "r" | "w" | "x") {
return (await this.ibmi.sendCommand({ command: `test -${right} ${path}` })).code === 0;
}

isProtectedPath(path: string) {
if (path.startsWith('/')) { //IFS path
return this.config.protectedPaths.some(p => path.startsWith(p));
}
else { //QSYS path
const [library] = path.split('/');
return this.config.protectedPaths.includes(library.toLocaleUpperCase());
}
}
}
84 changes: 39 additions & 45 deletions src/instantiate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import { Tools } from './api/Tools';
import path, { dirname } from 'path';
import * as vscode from "vscode";
import { CompileTools } from './api/CompileTools';
import { ConnectionConfiguration, GlobalConfiguration, onCodeForIBMiConfigurationChange } from "./api/Configuration";
import { ConnectionConfiguration, DefaultOpenMode, GlobalConfiguration, onCodeForIBMiConfigurationChange } from "./api/Configuration";
import Instance from "./api/Instance";
import { Search } from "./api/Search";
import { Terminal } from './api/Terminal';
import { refreshDiagnosticsFromServer } from './api/errors/diagnostics';
import { QSysFS, getMemberUri, getUriFromPath } from "./filesystems/qsys/QSysFs";
import { QSysFS, getUriFromPath } from "./filesystems/qsys/QSysFs";
import { init as clApiInit } from "./languages/clle/clApi";
import * as clRunner from "./languages/clle/clRunner";
import { initGetNewLibl } from "./languages/clle/getnewlibl";
import { SEUColorProvider } from "./languages/general/SEUColorProvider";
import { Action, BrowserItem, DeploymentMethod, QsysFsOptions } from "./typings";
import { Action, BrowserItem, DeploymentMethod, MemberItem, OpenEditableOptions, WithPath } from "./typings";
import { SearchView } from "./views/searchView";
import { ActionsUI } from './webviews/actions';
import { VariablesUI } from "./webviews/variables";
Expand Down Expand Up @@ -101,36 +101,29 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) {
`searchView`,
searchViewContext
),
vscode.commands.registerCommand(`code-for-ibmi.openEditable`, async (path: string, line?: number, options?: QsysFsOptions) => {
vscode.commands.registerCommand(`code-for-ibmi.openEditable`, async (path: string, options?: OpenEditableOptions) => {
console.log(path);
if (!options?.readonly && !path.startsWith('/')) {
const [library, name] = path.split('/');
const writable = await instance.getContent()?.checkObject({ library, name, type: '*FILE' }, "*UPD");
if (!writable) {
options = options || {};
options.readonly = true;
options = options || {};
options.readonly = options.readonly || instance.getContent()?.isProtectedPath(path);
if (!options.readonly) {
if (path.startsWith('/')) {
options.readonly = !await instance.getContent()?.testStreamFile(path, "w");
}
else {
const [library, name] = path.split('/');
const writable = await instance.getContent()?.checkObject({ library, name, type: '*FILE' }, "*UPD");
if (!writable) {
options.readonly = true;
}
}
}

const uri = getUriFromPath(path, options);
try {
if (line) {
// If a line is provided, we have to do a specific open
let doc = await vscode.workspace.openTextDocument(uri); // calls back into the provider
const editor = await vscode.window.showTextDocument(doc, { preview: false });

if (editor) {
const selectedLine = editor.document.lineAt(line);
editor.selection = new vscode.Selection(line, selectedLine.firstNonWhitespaceCharacterIndex, line, 100);
editor.revealRange(selectedLine.range, vscode.TextEditorRevealType.InCenter);
}

} else {
// Otherwise, do a generic open
await vscode.commands.executeCommand(`vscode.open`, uri);
}
await vscode.commands.executeCommand(`vscode.openWith`, uri, 'default', { selection: options.position } as vscode.TextDocumentShowOptions);

// Add file to front of recently opened files list.
const recentLimit = GlobalConfiguration.get(`recentlyOpenedFilesLimit`) as number;
const recentLimit = GlobalConfiguration.get<number>(`recentlyOpenedFilesLimit`);
const storage = instance.getStorage();
if (recentLimit) {
const recent = storage!.getRecentlyOpenedFiles();
Expand All @@ -142,7 +135,6 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) {
return true;
} catch (e) {
console.log(e);

return false;
}
}),
Expand Down Expand Up @@ -435,11 +427,14 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) {
from QSYS2.SYSPARTITIONSTAT
where ( SYSTEM_TABLE_SCHEMA, SYSTEM_TABLE_NAME, SYSTEM_TABLE_MEMBER ) = ( '${lib}', '${file}', '${member.name}' )
limit 1
`).then((resultSet) => { return resultSet.length !== 1 ? {} :
{ base: `${resultSet[0].MEMBER}.${resultSet[0].TYPE}`,
name: `${resultSet[0].MEMBER}`,
ext: `${resultSet[0].TYPE}`,
}});
`).then((resultSet) => {
return resultSet.length !== 1 ? {} :
{
base: `${resultSet[0].MEMBER}.${resultSet[0].TYPE}`,
name: `${resultSet[0].MEMBER}`,
ext: `${resultSet[0].TYPE}`,
}
});
if (!fullMember) {
vscode.window.showWarningMessage(`Member ${lib}/${file}/${member.base} does not exist.`);
return;
Expand All @@ -457,8 +452,8 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) {
}
selection = selection.toUpperCase() === quickPick.value.toUpperCase() ? quickPick.value : selection;
}
vscode.commands.executeCommand(`code-for-ibmi.openEditable`, selection, 0, { readonly });
quickPick.hide()
vscode.commands.executeCommand(`code-for-ibmi.openEditable`, selection, { readonly });
quickPick.hide();
} else {
quickPick.value = selection.toUpperCase() + '/'
}
Expand Down Expand Up @@ -623,18 +618,17 @@ export async function loadAllofExtension(context: vscode.ExtensionContext) {
return value;
}),

vscode.commands.registerCommand("code-for-ibmi.browse", (node: any) => { //any for now, typed later after TS conversion of browsers
let uri;
if (node?.member) {
uri = getMemberUri(node?.member, { readonly: true });
}
else if (node?.path) {
uri = getUriFromPath(node?.path, { readonly: true });
}
vscode.commands.registerCommand("code-for-ibmi.browse", (item: WithPath | MemberItem) => {
return vscode.commands.executeCommand("code-for-ibmi.openWithDefaultMode", item, "browse" as DefaultOpenMode);
}),

if (uri) {
return vscode.commands.executeCommand(`vscode.open`, uri);
}
vscode.commands.registerCommand("code-for-ibmi.edit", (item: WithPath | MemberItem) => {
return vscode.commands.executeCommand("code-for-ibmi.openWithDefaultMode", item, "edit" as DefaultOpenMode);
}),

vscode.commands.registerCommand("code-for-ibmi.openWithDefaultMode", (item: WithPath, overrideMode?: DefaultOpenMode) => {
const readonly = (overrideMode || GlobalConfiguration.get<DefaultOpenMode>("defaultOpenMode")) === "browse";
vscode.commands.executeCommand(`code-for-ibmi.openEditable`, item.path, { readonly });
})
);

Expand Down
8 changes: 5 additions & 3 deletions src/typings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Ignore } from 'ignore';
import { ProviderResult, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode";
import { ProviderResult, Range, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode";
import { ConnectionConfiguration } from './api/Configuration';
import { CustomUI } from "./api/CustomUI";
import Instance from "./api/Instance";
Expand Down Expand Up @@ -195,11 +195,13 @@ export interface MemberItem extends FilteredItem, WithPath {

export type IBMiMessage = {
id: string
text: string
text: string
}

export type IBMiMessages = {
messages: IBMiMessage[]
findId(id:string) : IBMiMessage | undefined
findId(id: string): IBMiMessage | undefined
}
export const IFS_BROWSER_MIMETYPE = "application/vnd.code.tree.ifsbrowser";

export type OpenEditableOptions = QsysFsOptions & { position?: Range };
Loading