Skip to content

feat(workspace): copy as command #3544

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 8 commits into from
Sep 23, 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
14 changes: 14 additions & 0 deletions packages/plugin-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,10 @@
"command": "dendron.copyCodespaceURL",
"title": "Dendron: Copy Codespace URL"
},
{
"command": "dendron.copyAs",
"title": "Dendron: Copy As"
},
{
"command": "dendron.delete",
"title": "Dendron: Delete"
Expand Down Expand Up @@ -660,6 +664,10 @@
"command": "dendron.copyCodespaceURL",
"when": "dendron:pluginActive && shellExecutionSupported"
},
{
"command": "dendron.copyAs",
"when": "dendron:pluginActive && shellExecutionSupported"
},
{
"command": "dendron.delete",
"when": "dendron:pluginActive && shellExecutionSupported"
Expand Down Expand Up @@ -1324,6 +1332,12 @@
"mac": "cmd+shift+r",
"when": "editorFocus && dendron:pluginActive"
},
{
"command": "dendron.copyAs",
"key": "ctrl+k ctrl+c",
"mac": "cmd+k cmd+c",
"when": "dendron:pluginActive"
},
{
"command": "dendron.delete",
"key": "ctrl+shift+d",
Expand Down
9 changes: 9 additions & 0 deletions packages/plugin-core/src/ExtensionProvider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { DendronError } from "@dendronhq/common-all";
import { PodUtils } from "@dendronhq/pods-core";
import { ensureDirSync } from "fs-extra";
import _ from "lodash";
import { IDendronExtension } from "./dendronExtensionInterface";
import { IWSUtilsV2 } from "./WSUtilsV2Interface";
Expand Down Expand Up @@ -51,4 +53,11 @@ export class ExtensionProvider {
static register(extension: IDendronExtension) {
ExtensionProvider.extension = extension;
}

static getPodsDir() {
const { wsRoot } = ExtensionProvider.getDWorkspace();
const podsDir = PodUtils.getPodDir({ wsRoot });
ensureDirSync(podsDir);
return podsDir;
}
}
38 changes: 35 additions & 3 deletions packages/plugin-core/src/KeybindingUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,12 +344,44 @@ export class KeybindingUtils {
return result[0].key;
} else if (result.length > 1) {
throw new DendronError({
message: KeybindingUtils.MULTIPLE_KEYBINDINGS_MSG_FMT,
message: this.getMultipleKeybindingsMsgFormat("pod"),
});
}
return undefined;
}

static MULTIPLE_KEYBINDINGS_MSG_FMT =
"Multiple keybindings found for pod command shortcut.";
static getKeybindingsForCopyAsIfExists(format: string): string | undefined {
const { keybindingConfigPath } = this.getKeybindingConfigPath();

if (!fs.existsSync(keybindingConfigPath)) {
return undefined;
}

const keybindings = readJSONWithCommentsSync(keybindingConfigPath);

if (!KeybindingUtils.checkKeybindingsExist(keybindings)) {
return undefined;
}

const result = keybindings.filter((item) => {
return (
item.command &&
item.command === DENDRON_COMMANDS.COPY_AS.key &&
item.args === format
);
});

if (result.length === 1 && result[0].key) {
return result[0].key;
} else if (result.length > 1) {
throw new DendronError({
message: this.getMultipleKeybindingsMsgFormat("copy as"),
});
}
return undefined;
}

static getMultipleKeybindingsMsgFormat(cmd: string) {
return `Multiple keybindings found for ${cmd} command shortcut.`;
}
}
80 changes: 80 additions & 0 deletions packages/plugin-core/src/commands/CopyAsCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { DendronError } from "@dendronhq/common-all";
import {
CopyAsFormat,
getAllCopyAsFormat,
JSONV2PodConfig,
MarkdownV2PodConfig,
PodExportScope,
PodV2Types,
} from "@dendronhq/pods-core";
import _ from "lodash";
import { PodCommandFactory } from "../components/pods/PodCommandFactory";
import { PodUIControls } from "../components/pods/PodControls";
import { DENDRON_COMMANDS } from "../constants";
import { VSCodeUtils } from "../vsCodeUtils";
import { BasicCommand, CodeCommandInstance } from "./base";

type CommandOutput = void;
type CommandOpts = CodeCommandInstance;

/**
* Command that will find the appropriate export command to run, and then run
* it. This is the UI entry point for all export pod functionality.
*/
export class CopyAsCommand extends BasicCommand<
CommandOpts,
CommandOutput,
CopyAsFormat
> {
public format: CopyAsFormat[];
key = DENDRON_COMMANDS.COPY_AS.key;

constructor(_name?: string) {
super(_name);
this.format = getAllCopyAsFormat();
}

async sanityCheck() {
if (_.isUndefined(VSCodeUtils.getActiveTextEditor())) {
return "you must have a note open to execute this command";
}
return;
}

async gatherInputs(copyAsFormat?: CopyAsFormat) {
const format =
copyAsFormat || (await PodUIControls.promptToSelectCopyAsFormat());

if (!format) {
return;
}
switch (format) {
case CopyAsFormat.JSON: {
const config: JSONV2PodConfig = {
destination: "clipboard",
exportScope: PodExportScope.Note,
podType: PodV2Types.JSONExportV2,
podId: "copyAs.json", // dummy value, required property
};
return PodCommandFactory.createPodCommandForStoredConfig({ config });
}
case CopyAsFormat.MARKDOWN: {
const config: MarkdownV2PodConfig = {
destination: "clipboard",
exportScope: PodExportScope.Note,
podType: PodV2Types.MarkdownExportV2,
podId: "copyAs.markdown", // dummy value, required property
};
return PodCommandFactory.createPodCommandForStoredConfig({ config });
}
default:
throw new DendronError({
message: `${format} is not a valid copy as format. If you are using a keybinding, make sure the argument is one of the following values: ${getAllCopyAsFormat()}`,
});
}
}

async execute(opts: CommandOpts) {
opts.run();
}
}
2 changes: 2 additions & 0 deletions packages/plugin-core/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ import { CreateNoteCommand } from "./CreateNoteCommand";
import { MergeNoteCommand } from "./MergeNoteCommand";
import { CopyCodespaceURL } from "./CopyCodespaceURL";
import { MoveSelectionToCommand } from "./MoveSelectionToCommand";
import { CopyAsCommand } from "./CopyAsCommand";

/**
* Note: this does not contain commands that have parametered constructors, as
Expand Down Expand Up @@ -181,6 +182,7 @@ const ALL_COMMANDS = [
MergeNoteCommand,
CreateNoteCommand,
CopyCodespaceURL,
CopyAsCommand,
] as CodeCommandConstructor[];

export { ALL_COMMANDS };
12 changes: 7 additions & 5 deletions packages/plugin-core/src/commands/pods/ExportPodV2Command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ export class ExportPodV2Command extends BaseCommand<

// If a podId is passed in, use this instead of prompting the user
if (args?.podId) {
return PodCommandFactory.createPodCommandForStoredConfig(
{ podId: args.podId },
args.exportScope
);
return PodCommandFactory.createPodCommandForStoredConfig({
configId: { podId: args.podId },
exportScope: args.exportScope,
});
}

const exportChoice = await PodUIControls.promptForExportConfigOrNewExport();
Expand All @@ -66,7 +66,9 @@ export class ExportPodV2Command extends BaseCommand<
}
return PodCommandFactory.createPodCommandForPodType(podType);
} else {
return PodCommandFactory.createPodCommandForStoredConfig(exportChoice);
return PodCommandFactory.createPodCommandForStoredConfig({
configId: exportChoice,
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,19 @@ export class JSONExportPodCommand extends BaseExportPodCommand<
exportReturnValue: JSONExportReturnType;
config: RunnableJSONV2PodConfig;
}) {
let successMessage = "Finished running JSON export pod.";
const data = exportReturnValue.data?.exportedNotes;
if (_.isString(data) && config.destination === "clipboard") {
vscode.env.clipboard.writeText(data);
successMessage += " Content is copied to the clipboard";
}
if (ResponseUtil.hasError(exportReturnValue)) {
const errorMsg = `Finished JSON Export. Error encountered: ${ErrorFactory.safeStringify(
exportReturnValue.error
)}`;
this.L.error(errorMsg);
} else {
vscode.window.showInformationMessage("Finished running JSON export pod.");
vscode.window.showInformationMessage(successMessage);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,10 @@ export class MarkdownExportPodCommand extends BaseExportPodCommand<
config: RunnableMarkdownV2PodConfig;
}) {
const data = exportReturnValue.data?.exportedNotes;
let successMessage = "Finished running Markdown export pod.";
if (_.isString(data) && config.destination === "clipboard") {
vscode.env.clipboard.writeText(data);
successMessage += " Content is copied to the clipboard";
}
const count = data?.length ?? 0;
if (ResponseUtil.hasError(exportReturnValue)) {
Expand All @@ -133,9 +135,7 @@ export class MarkdownExportPodCommand extends BaseExportPodCommand<
)}`;
this.L.error(errorMsg);
} else {
vscode.window.showInformationMessage(
"Finished running Markdown export pod."
);
vscode.window.showInformationMessage(successMessage);
}
}

Expand Down
56 changes: 40 additions & 16 deletions packages/plugin-core/src/components/pods/PodCommandFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { JSONExportPodCommand } from "../../commands/pods/JSONExportPodCommand";
import { MarkdownExportPodCommand } from "../../commands/pods/MarkdownExportPodCommand";
import { NotionExportPodCommand } from "../../commands/pods/NotionExportPodCommand";
import { ExtensionProvider } from "../../ExtensionProvider";
import { getExtension } from "../../workspace";

export class PodCommandFactory {
/**
Expand All @@ -22,27 +21,52 @@ export class PodCommandFactory {
* @param configId
* @returns A pod command configured with the found configuration
*/
public static createPodCommandForStoredConfig(
configId: Pick<ExportPodConfigurationV2, "podId">,
exportScope?: PodExportScope
): CodeCommandInstance {
const storedConfig = PodV2ConfigManager.getPodConfigById({
podsDir: path.join(getExtension().podsDir, "custom"),
opts: configId,
});

if (!storedConfig) {
public static createPodCommandForStoredConfig({
configId,
exportScope,
config,
}: {
configId?: Pick<ExportPodConfigurationV2, "podId">;
exportScope?: PodExportScope;
config?: ExportPodConfigurationV2 & { destination?: string };
}): CodeCommandInstance {
// configId is a required param for all cases except when called from CopyAsCommand. It sends a predefined config
if (!configId && !config) {
throw new DendronError({
message: `No pod config with id ${configId.podId} found.`,
message: `Please provide a config id to continue.`,
});
}
// overrides the exportScope of stored config with the exportScope passed in args
if (exportScope) {
storedConfig.exportScope = exportScope;
let podType: PodV2Types;
let storedConfig: ExportPodConfigurationV2 | undefined;
if (config) {
podType = config.podType;
storedConfig = config;
} else {
if (!configId) {
throw new DendronError({
message: `Please provide a config id`,
});
}

storedConfig = PodV2ConfigManager.getPodConfigById({
podsDir: path.join(ExtensionProvider.getPodsDir(), "custom"),
opts: configId,
});

if (!storedConfig) {
throw new DendronError({
message: `No pod config with id ${configId.podId} found.`,
});
}
// overrides the exportScope of stored config with the exportScope passed in args
if (exportScope) {
storedConfig.exportScope = exportScope;
}
podType = storedConfig.podType;
}
let cmdWithArgs: CodeCommandInstance;
const extension = ExtensionProvider.getExtension();
switch (storedConfig.podType) {
switch (podType) {
case PodV2Types.AirtableExportV2: {
const airtableCmd = new AirtableExportPodCommand(extension);
cmdWithArgs = {
Expand Down
Loading