Skip to content
This repository has been archived by the owner on Apr 1, 2020. It is now read-only.

Commit

Permalink
Sort out CLI for Oni (#2372)
Browse files Browse the repository at this point in the history
* Very first version of new CLI.

* Hook up calling on Windows.

* Try for Mac and Linux.

Need to test on Mac.

* Fix mac path.

* Small changes to CLI script.

* Fix bin pointing to CLI.

* Clarify changes in cli_args.

* Update Registry key check.

* Update Windows installer to get around path issues.

* Update Mac add to PATH command.

* Fix logic error.
  • Loading branch information
CrossR authored Jul 1, 2018
1 parent 4615f90 commit 8919a86
Show file tree
Hide file tree
Showing 13 changed files with 285 additions and 76 deletions.
15 changes: 11 additions & 4 deletions browser/src/Platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ export const isLinux = () => os.platform() === "linux"

export const getUserHome = () => (isWindows() ? process.env["APPDATA"] : process.env["HOME"]) // tslint:disable-line no-string-literal

export const getLinkPath = () => (isMac() ? "/usr/local/bin/oni" : "") // TODO: windows + linux
export const getLinkPath = () => (isMac() ? "/usr/local/bin/oni" : "") // TODO: Linux
export const isAddedToPath = () => {
if (isMac()) {
try {
fs.lstatSync(getLinkPath())

const currentLinkPath = fs.readlinkSync(getLinkPath())

// Temporary guard to check if the old script has been linked to.
if (currentLinkPath.indexOf("cli/mac/oni.sh") === -1) {
return false
}
} catch (_) {
return false
}
Expand All @@ -21,14 +28,14 @@ export const isAddedToPath = () => {

return false
}
export const removeFromPath = () => (isMac() ? fs.unlinkSync(getLinkPath()) : false) // TODO: windows + other
export const removeFromPath = () => (isMac() ? fs.unlinkSync(getLinkPath()) : false) // TODO: Linux

export const addToPath = async () => {
if (isMac()) {
const appDirectory = path.join(path.dirname(process.mainModule.filename), "..", "..")
const options = { name: "Oni", icns: path.join(appDirectory, "Resources", "Oni.icns") }
const linkPath = path.join(appDirectory, "Resources", "app", "oni.sh")
await _runSudoCommand(`ln -s ${linkPath} ${getLinkPath()}`, options)
const linkPath = path.join(appDirectory, "Resources", "app", "cli", "mac", "oni.sh")
await _runSudoCommand(`ln -fs ${linkPath} ${getLinkPath()}`, options)
}
}

Expand Down
4 changes: 3 additions & 1 deletion build/BuildSetupTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const packageJsonContents = fs.readFileSync(path.join(__dirname, "..", "package.
const packageMeta = JSON.parse(packageJsonContents)
const { version, name } = packageMeta
const prodName = packageMeta.build.productName
const pathVariable = "{app}\\resources\\app\\cli\\windows\\"

let buildFolderPrefix = os.arch() === "x32" ? "ia32-" : ""

Expand All @@ -37,10 +38,11 @@ const valuesToReplace = {
SourcePath: path.join(__dirname, "..", "dist", `win-${buildFolderPrefix}unpacked`, "*"),
WizardImageFilePath: path.join(__dirname, "setup", "Oni_128.bmp"),
WizardSmallImageFilePath: path.join(__dirname, "setup", "Oni_54.bmp"),
cliPath: pathVariable,
}

const addToEnv = `
Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}"; Tasks: addtopath; Check: NeedsAddPath(ExpandConstant('{app}'))
Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};${pathVariable}"; Tasks: addtopath; Check: NeedsAddPath(ExpandConstant('${pathVariable}'))
Root: HKCU; Subkey: "SOFTWARE\\Classes\\*\\shell\\${prodName}"; ValueType: expandsz; ValueName: ""; ValueData: "Open with ${prodName}"; Tasks: addToRightClickMenu; Flags: uninsdeletekey
Root: HKCU; Subkey: "SOFTWARE\\Classes\\*\\shell\\${prodName}"; ValueType: expandsz; ValueName: "Icon"; ValueData: "{app}\\resources\\app\\images\\oni.ico"; Tasks: addToRightClickMenu
Expand Down
83 changes: 83 additions & 0 deletions build/setup.template.iss
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,88 @@ begin
Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0;
end;
// http://stackoverflow.com/a/23838239/261019
procedure Explode(var Dest: TArrayOfString; Text: String; Separator: String);
var
i, p: Integer;
begin
i := 0;
repeat
SetArrayLength(Dest, i+1);
p := Pos(Separator,Text);
if p > 0 then begin
Dest[i] := Copy(Text, 1, p-1);
Text := Copy(Text, p + Length(Separator), Length(Text));
i := i + 1;
end else begin
Dest[i] := Text;
Text := '';
end;
until Length(Text)=0;
end;
// This update step checks for the old path variable ({app}) and removes it when installing if needed.
// This is a modified version of the UninstallStepChanged, taken from VSCode.
procedure CurStepChanged(CurUninstallStep: TSetupStep);
var
Path: string;
OldOniPath: string;
Parts: TArrayOfString;
NewPath: string;
i: Integer;
begin
if not CurUninstallStep = ssInstall then begin
exit;
end;
if not RegQueryStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', Path)
then begin
exit;
end;
NewPath := '';
OldOniPath := ExpandConstant('{app}')
Explode(Parts, Path, ';');
for i:=0 to GetArrayLength(Parts)-1 do begin
if CompareText(Parts[i], OldOniPath) <> 0 then begin
NewPath := NewPath + Parts[i];
if i < GetArrayLength(Parts) - 1 then begin
NewPath := NewPath + ';';
end;
end;
end;
RegWriteExpandStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', NewPath);
end;
// This is taken from the VSCode installer file.
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
Path: string;
OniPath: string;
Parts: TArrayOfString;
NewPath: string;
i: Integer;
begin
if not CurUninstallStep = usUninstall then begin
exit;
end;
if not RegQueryStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', Path)
then begin
exit;
end;
NewPath := '';
OniPath := ExpandConstant('{{cliPath}}')
Explode(Parts, Path, ';');
for i:=0 to GetArrayLength(Parts)-1 do begin
if CompareText(Parts[i], OniPath) <> 0 then begin
NewPath := NewPath + Parts[i];
if i < GetArrayLength(Parts) - 1 then begin
NewPath := NewPath + ';';
end;
end;
end;
RegWriteExpandStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', NewPath);
end;
[Registry]
{{RegistryKey}}
19 changes: 19 additions & 0 deletions cli/linux/oni.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

# Get the path to the currently running script:
self=$0

# Test if $self is a symlink
if [ -L "$self" ] ; then
# readlink returns the path to the file the link points to:
target=$(readlink "$self")
else
target=$self
fi

ONI_PATH=$(dirname "$target")
ONI_EXECUTABLE="${ONI_PATH}/../../../../oni"
CLI_SCRIPT="${ONI_PATH}/../../lib/cli/src/cli.js"

ELECTRON_RUN_AS_NODE=1 "${ONI_EXECUTABLE}" "$CLI_SCRIPT" "$*"
exit $?
19 changes: 19 additions & 0 deletions cli/mac/oni.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

# Get the path to the currently running script:
self=$0

# Test if $self is a symlink
if [ -L "$self" ] ; then
# readlink returns the path to the file the link points to:
target=$(readlink "$self")
else
target=$self
fi

ONI_PATH=$(dirname "$target")
ONI_EXECUTABLE="${ONI_PATH}/../../../../MacOS/Oni"
CLI_SCRIPT="${ONI_PATH}/../../lib/cli/src/cli.js"

ELECTRON_RUN_AS_NODE=1 "${ONI_EXECUTABLE}" "$CLI_SCRIPT" "$*"
exit $?
29 changes: 0 additions & 29 deletions cli/oni

This file was deleted.

82 changes: 82 additions & 0 deletions cli/src/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import * as path from "path"

import { CLIArgs, parseCLIProcessArgv } from "./cli_args"

import { spawn } from "child_process"

export async function main(cli_arguments: string[]): Promise<any> {
// First, try to parse the CLI args and deal with them.
let args: CLIArgs

try {
args = parseCLIProcessArgv(cli_arguments)
} catch (err) {
process.stdout.write(err.message)
throw err
}

if (args.help || args.version) {
const version = require(path.join(__dirname, "..", "..", "..", "package.json")).version // tslint:disable-line no-var-requires
process.stdout.write("Oni: Modern Modal Editing - powered by Neovim\n")
process.stdout.write(` version: ${version}\n`)
process.stdout.write("\nUsage:\n oni [FILE]\t\tEdit file\n")
process.stdout.write("\nhttps://github.com/onivim/oni\n")

return Promise.resolve(true)
}

// Otherwise, was loaded normally, so launch Oni.

const env = assign({}, process.env, {
ONI_CLI: "1", // Let Oni know it was started from the CLI
ELECTRON_NO_ATTACH_CONSOLE: "1",
})

delete env["ELECTRON_RUN_AS_NODE"]

const options = {
detached: true,
env,
}

const child = await spawn(process.execPath, cli_arguments.slice(2), options)
child.unref()

child.on("close", code => {
if (code !== 0) {
throw Error(`Exit code was ${code}, not 0.`)
} else {
return Promise.resolve(true)
}
})

child.on("error", err => {
throw err
})

child.on("exit", code => {
if (code && code !== 0) {
throw Error(`Exit code was ${code}, not 0.`)
} else {
return Promise.resolve(true)
}
})
}

function assign(destination: any, ...sources: any[]): any {
sources.forEach(source => Object.keys(source).forEach(key => (destination[key] = source[key])))
return destination
}

function eventuallyExit(code: number): void {
setTimeout(() => process.exit(code), 0)
}

main(process.argv)
.then(() => {
eventuallyExit(0)
})
.then(null, err => {
console.error(err.message || err.stack || err)
eventuallyExit(1)
})
27 changes: 27 additions & 0 deletions cli/src/cli_args.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as minimist from "minimist"

export interface CLIArgs {
help?: boolean
version?: boolean
[arg: string]: any
}

const options: minimist.Opts = {
boolean: ["help", "version"],
alias: {
help: "h",
version: "v",
},
}

export function parseArgs(args: string[]): CLIArgs {
return minimist(args, options) as CLIArgs
}

// Skip the first 2 arguments as that is the location of the Electron binary,
// and the location of the cli.ts script.
export function parseCLIProcessArgv(processArgv: string[]): CLIArgs {
let [, , ...args] = processArgv

return parseArgs(args)
}
29 changes: 29 additions & 0 deletions cli/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"compilerOptions": {
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react",
"lib": ["dom", "es2017"],
"module": "commonjs",
"moduleResolution": "node",
"newLine": "LF",
"noEmitOnError": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"outDir": "../lib/cli",
"pretty": true,
"removeComments": true,
"rootDir": ".",
"skipLibCheck": true,
"strictNullChecks": false,
"suppressImplicitAnyIndexErrors": true,
"target": "es2015",
"sourceMap": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
5 changes: 5 additions & 0 deletions cli/windows/oni.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@echo off
setlocal
set ELECTRON_RUN_AS_NODE=1
call "%~dp0..\..\..\..\Oni.exe" "%~dp0..\..\lib\cli\src\cli.js" %*
endlocal
12 changes: 1 addition & 11 deletions main/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as minimist from "minimist"
import * as path from "path"

import { app, BrowserWindow, ipcMain, Menu } from "electron"
Expand All @@ -23,16 +22,7 @@ if (isAutomation) {
Log.info("Verbose flag set since running automation")
}

// We want to check for the 'help' flag before initializing electron
const argv = minimist(process.argv.slice(1))
const version = require(path.join(__dirname, "..", "..", "..", "package.json")).version // tslint:disable-line no-var-requires
if (argv.help || argv.h) {
process.stdout.write("ONI: Modern Modal Editing - powered by Neovim\n")
process.stdout.write(` version: ${version}\n`)
process.stdout.write("\nUsage:\n oni [FILE]\t\tEdit file\n")
process.stdout.write("\nhttps://github.com/onivim/oni\n")
process.exit(0)
}
// const argv = minimist(process.argv.slice(1))

interface IWindowState {
bounds?: {
Expand Down
Loading

0 comments on commit 8919a86

Please sign in to comment.