Skip to content

Commit

Permalink
Merge branch '#76-os-specific-commands' into 0.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Taitava committed Oct 30, 2021
2 parents 1abc7fb + 11276d7 commit a394a62
Show file tree
Hide file tree
Showing 18 changed files with 759 additions and 280 deletions.
19 changes: 19 additions & 0 deletions src/Common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import {App, Editor, FileSystemAdapter, MarkdownView, normalizePath} from "obsidian";
import {PlatformId} from "./settings/ShellCommandsPluginSettings";
import {platform} from "os";
import * as path from "path";

export function getVaultAbsolutePath(app: App) {
// Original code was copied 2021-08-22 from https://github.com/phibr0/obsidian-open-with/blob/84f0e25ba8e8355ff83b22f4050adde4cc6763ea/main.ts#L66-L67
Expand All @@ -17,6 +20,18 @@ export function isWindows() {
return process.platform === "win32";
}

/**
* This is just a wrapper around platform() in order to cast the type to PlatformId.
* TODO: Consider renaming this to getPlatformId().
*/
export function getOperatingSystem(): PlatformId {
// @ts-ignore In theory, platform() can return an OS name not included in OperatingSystemName. But as Obsidian
// currently does not support anything else than Windows, Mac and Linux (except mobile platforms, but they are
// ruled out by the manifest of this plugin), it should be safe to assume that the current OS is one of those
// three.
return platform();
}

export function getView(app: App) {
let view = app.workspace.getActiveViewOfType(MarkdownView);
if (!view) {
Expand Down Expand Up @@ -86,6 +101,10 @@ export function normalizePath2(path: string) {
return path;
}

export function extractFileName(file_path: string) {
return path.parse(file_path).base;
}

export function joinObjectProperties(object: {}, glue: string) {
let result = "";
for (let property_name in object) {
Expand Down
14 changes: 7 additions & 7 deletions src/ConfirmExecutionModal.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import {Modal, Setting} from "obsidian";
import ShellCommandsPlugin from "./main";
import {ShellCommandConfiguration} from "./settings/ShellCommandConfiguration";
import {TShellCommand} from "./TShellCommand";

export class ConfirmExecutionModal extends Modal {
private plugin: ShellCommandsPlugin;
private readonly shell_command: string;
private shell_command_configuration: ShellCommandConfiguration;
private readonly t_shell_command: TShellCommand;

constructor(plugin: ShellCommandsPlugin, shell_command: string, shell_command_configuration: ShellCommandConfiguration) {
constructor(plugin: ShellCommandsPlugin, shell_command: string, t_shell_command: TShellCommand) {
super(plugin.app);
this.plugin = plugin;
this.shell_command = shell_command;
this.shell_command_configuration = shell_command_configuration;
this.t_shell_command = t_shell_command;
}

open() {
super.open();

// Information about the shell command
this.modalEl.createEl("h2", {text: this.shell_command, attr: {style: "margin-bottom: 0;"}});
if (this.shell_command_configuration.alias) {
let paragraph = this.modalEl.createEl("p", {text: "Alias: " + this.shell_command_configuration.alias, attr: {style: "margin-top: 0;"}});
if (this.t_shell_command.getAlias()) {
let paragraph = this.modalEl.createEl("p", {text: "Alias: " + this.t_shell_command.getAlias(), attr: {style: "margin-top: 0;"}});
}
this.modalEl.createEl("p", {text: "Execute this shell command?"});

Expand All @@ -30,7 +30,7 @@ export class ConfirmExecutionModal extends Modal {
.setButtonText("Yes, execute!")
.onClick(() => {
console.log("User confirmed execution of shell command: " + this.shell_command);
this.plugin.executeShellCommand(this.shell_command, this.shell_command_configuration);
this.plugin.executeShellCommand(this.shell_command, this.t_shell_command);
this.close();
})
)
Expand Down
47 changes: 45 additions & 2 deletions src/Migrations.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import ShellCommandsPlugin from "./main";
import {newShellCommandConfiguration} from "./settings/ShellCommandConfiguration";
import {newShellCommandConfiguration, ShellCommandConfiguration} from "./settings/ShellCommandConfiguration";

export async function RunMigrations(plugin: ShellCommandsPlugin) {
let save = MigrateCommandsToShellCommands(plugin);
save ||= MigrateShellCommandToPlatforms(plugin);
save ||= EnsureShellCommandsHaveAllFields(plugin);
save ||= DeleteEmptyCommandsField(plugin);
if (save) {
// Only save if there were changes to configuration.
console.log("Saving migrations...")
Expand All @@ -13,6 +15,9 @@ export async function RunMigrations(plugin: ShellCommandsPlugin) {
}

function MigrateCommandsToShellCommands(plugin: ShellCommandsPlugin) {
if (undefined === plugin.settings.commands) {
return false;
}
let count_shell_commands = plugin.settings.commands.length;
let save = false;
if (0 < count_shell_commands) {
Expand Down Expand Up @@ -59,7 +64,7 @@ function EnsureShellCommandsHaveAllFields(plugin: ShellCommandsPlugin) {
let save = false;
let shell_command_default_configuration = newShellCommandConfiguration();
let shell_command_id: string;
let shell_command_configurations = plugin.getShellCommands();
let shell_command_configurations = plugin.settings.shell_commands;
for (shell_command_id in shell_command_configurations) {
let shell_command_configuration = shell_command_configurations[shell_command_id];
for (let property_name in shell_command_default_configuration) {
Expand All @@ -77,4 +82,42 @@ function EnsureShellCommandsHaveAllFields(plugin: ShellCommandsPlugin) {
}
}
return save;
}

function MigrateShellCommandToPlatforms(plugin: ShellCommandsPlugin) {
let save = false;
for (let shell_command_id in plugin.settings.shell_commands) {
let shell_command_configuration: ShellCommandConfiguration = plugin.settings.shell_commands[shell_command_id];
if (undefined !== shell_command_configuration.shell_command) {
// The shell command should be migrated.
if (undefined === shell_command_configuration.platform_specific_commands || shell_command_configuration.platform_specific_commands.default === "") {
console.log("Migrating shell command #" + shell_command_id + ": shell_command string will be moved to platforms.default: " + shell_command_configuration.shell_command);
shell_command_configuration.platform_specific_commands = {
default: shell_command_configuration.shell_command,
};
delete shell_command_configuration.shell_command;
save = true;
} else {
console.log("Migration failure for shell command #" + shell_command_id + ": platforms exists already.");
}
}
}
return save;
}

/**
* Can be removed in 1.0.0.
*
* @param plugin
* @constructor
*/
function DeleteEmptyCommandsField(plugin: ShellCommandsPlugin) {
let save = false;
if (undefined !== plugin.settings.commands) {
if (plugin.settings.commands.length === 0) {
delete plugin.settings.commands;
save = true;
}
}
return save;
}
22 changes: 22 additions & 0 deletions src/Shell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {extractFileName, getOperatingSystem, isWindows} from "./Common";
import {PlatformShells} from "./settings/ShellCommandsPluginSettings";

export function getUsersDefaultShell(): string {
if (isWindows()) {
return process.env.ComSpec;
} else {
return process.env.SHELL;
}
}

export function isShellSupported(shell: string) {
const shell_file_name = extractFileName(shell);
const supported_shells = PlatformShells[getOperatingSystem()];
for (let supported_shell_path in supported_shells) {
if (supported_shell_path.substr(-shell_file_name.length, shell_file_name.length).toLowerCase() === shell_file_name.toLowerCase()) {
// If supported_shell_path (e.g. /bin/bash or CMD.EXE) ends with shell_file_name (e.g. bash, derived from /bin/bash or CMD.EXE, derived from C:\System32\CMD.EXE), then the shell can be considered to be supported.
return true;
}
}
return false;
}
104 changes: 104 additions & 0 deletions src/TShellCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {ShellCommandConfiguration} from "./settings/ShellCommandConfiguration";
import ShellCommandsPlugin from "./main";
import {getOperatingSystem} from "./Common";

export interface TShellCommandContainer {
[key: string]: TShellCommand,
}

export class TShellCommand {

private readonly id: string;
private plugin: ShellCommandsPlugin;
private configuration: ShellCommandConfiguration;

constructor (plugin: ShellCommandsPlugin, shell_command_id: string, configuration: ShellCommandConfiguration) {
this.plugin = plugin;
this.id = shell_command_id;
this.configuration = configuration;
}

public getPlugin() {
return this.plugin;
}
/**
* Use this when you need to alter the configuration values. if you only need to read configuration values, use get*()
* methods instead.
*/
public getConfiguration() {
return this.configuration;
}

public getId() {
return this.id;
}

public getShell(): string {
let operating_system = getOperatingSystem();

// Check if the shell command has defined a specific shell.
if (undefined === this.configuration.shells[operating_system]) {
// The shell command does not define an explicit shell.
// Use a default shell from the plugin's settings.
return this.plugin.getDefaultShell();
} else {
// The shell command has an explicit shell defined.
return this.configuration.shells[operating_system];
}
}

public getShells() {
return this.configuration.shells;
}

/**
* Returns a shell command string specific for the current operating system, or a generic shell command if this shell
* command does not have an explicit version for the current OS.
*/
public getShellCommand(): string {
let operating_system = getOperatingSystem();

// Check if the shell command has defined a specific command for this operating system.
if (undefined === this.configuration.platform_specific_commands[operating_system]) {
// No command is defined specifically for this operating system.
// Return an "OS agnostic" command.
return this.configuration.platform_specific_commands.default;
} else {
// The shell command has defined a specific command for this operating system.
return this.configuration.platform_specific_commands[operating_system];
}
}

/**
* Returns a version of the shell command that should be used if no platform specific command is defined for the
* current platform. If you plan to use this for execution, consider using getShellCommand() instead, as it takes the
* current platform into account.
*/
public getDefaultShellCommand() {
return this.configuration.platform_specific_commands.default;
}

public getPlatformSpecificShellCommands() {
return this.configuration.platform_specific_commands;
}

public getAlias() {
return this.configuration.alias;
}

public getConfirmExecution() {
return this.configuration.confirm_execution;
}

public getIgnoreErrorCodes() {
return this.configuration.ignore_error_codes;
}

public getOutputChannelOrder() {
return this.configuration.output_channel_order;
}

public getOutputChannels() {
return this.configuration.output_channels;
}
}
32 changes: 32 additions & 0 deletions src/TShellCommandTemporary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {TShellCommand} from "./TShellCommand";
import ShellCommandsPlugin from "./main";
import {ShellCommandConfiguration} from "./settings/ShellCommandConfiguration";
import {cloneObject} from "./Common";

export class TShellCommandTemporary extends TShellCommand {

/**
* @private Do not create new objects directly, use fromTShellCommand() instead.
* @param plugin
* @param shell_command_configuration
*/
constructor(plugin: ShellCommandsPlugin, shell_command_configuration: ShellCommandConfiguration) {
super(plugin, null, shell_command_configuration);
}

public getId(): string {
throw Error("TShellCommandTemporary does not have an ID, because it is a clone of a real TShellCommand that should not be saved.");
}

/**
* Returns a TShellCommandTemporary instance, which contains configuration that is copied from the given TShellCommand.
* The clone can be used for altering the configuration temporarily. The clone cannot be saved, and it's ID cannot be
* accessed.
*/
public static fromTShellCommand(t_shell_command: TShellCommand) {
return new TShellCommandTemporary(
t_shell_command.getPlugin(),
cloneObject(t_shell_command.getConfiguration()),
);
}
}
Loading

0 comments on commit a394a62

Please sign in to comment.