Skip to content
This repository has been archived by the owner on May 21, 2019. It is now read-only.

Standalone windows patch #129

Merged
merged 9 commits into from
Sep 14, 2015
Merged
Show file tree
Hide file tree
Changes from 8 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
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

/// <reference path="../node/node.d.ts" />

declare module 'pty.js' {
declare module 'ptyw.js' {
/** Options that can be used when creating a new pseudo-terminal. */
interface TerminalOptions {
name?: string;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"lodash": "3.10.1",
"node-ansiparser": "2.0.2",
"octicons": "2.4.1",
"pty.js": "0.3.0",
"ptyw.js": "^0.3.2",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please just change the version to point to your master on Github instead of changing the name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ShockOne If I point to http://github.com/iiegor/pty.js (specifically I'm pointing to the win-fix branch), the git submodule of the repo doesn't initialize, so node-gyp rebuild fails 😕

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood, let's leave it as is.

"react": "0.13.3",
"react-json-inspector": "5.2.1",
"rx": "3.1.2"
Expand Down
6 changes: 4 additions & 2 deletions src/Aliases.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as pty from 'pty.js';
import * as _ from 'lodash'
import * as pty from 'ptyw.js';
import * as _ from 'lodash';

export default class Aliases {
static aliases: _.Dictionary<string>;
Expand All @@ -14,6 +14,8 @@ export default class Aliases {
}

private static importAliases(shellName: string = process.env.SHELL): void {
if (process.platform === 'win32') return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about creating an enum with platforms in Enums.ts and a helper function Utils.isWindows? You could also search for 'darvin' comparison and replace in in a similar manner, if you feel like so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you noticed my comment about an enum? #129 (comment)


var shell = pty.spawn(shellName, ['-i', '-c', 'alias'], {env: process.env});

var aliases = '';
Expand Down
5 changes: 4 additions & 1 deletion src/Buffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ export default class Buffer extends events.EventEmitter {
var current = {attributes: <i.Attributes>null, text: ''};
var cursorPosition = cursor.getPosition();

if (index === cursorPosition.row && this.cursor.getShow()) {
/* Quick fix for the strange character at the end (https://github.com/black-screen/black-screen/pull/56#issuecomment-139653723) */
if (process.platform === 'win32' && row.length < 1) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Triple equal is useless in TypeScript. In JS it compares with types, but, you know, TypeScript compares types out of the box. :)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a mistake to use strict equality (triple equals) in TypeScript. When you read a piece of code that contains strict equality it's obvious to the reader that no type coercion will happen there. TypeScript transpiles equality operators as is to the JavaScript code, so the meaning is still clear in js.
Also if you take a look at the official TypeScript samples, you will see they almost always use strict equality in their ts files (e.g. raytracer.ts).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, my bad.


if (index == cursorPosition.row && this.cursor.getShow()) {
var rowWithCursor: Char[] = [];

for (var i = 0; i !== row.length; ++i) {
Expand Down
7 changes: 4 additions & 3 deletions src/Command.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import * as fs from 'fs';
import * as Path from 'path';
import Utils from './Utils';

// A class representing built in commands
export default class Command {
static cd(currentDirectory: string, args: Array<string>): string {
if (!args.length) {
return process.env.HOME;
return Utils.getHomeDirectory();
}
var path = args[0].replace(/^~/, process.env.HOME);
var path = args[0].replace(/^~/, Utils.getHomeDirectory());
var newDirectory = Path.resolve(currentDirectory, path);

if (!fs.existsSync(newDirectory)) {
Expand All @@ -21,7 +22,7 @@ export default class Command {
return newDirectory;
}

static isBuiltIn(command: String): any {
static isBuiltIn(command: string): any {
return command === 'cd';
}
}
53 changes: 49 additions & 4 deletions src/CommandExecutor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import Invocation from "./Invocation";
import Command from "./Command";
import Utils from './Utils';
import * as pty from 'pty.js';
import * as Path from 'path';
import * as pty from 'ptyw.js';
import * as _ from 'lodash';

abstract class CommandExecutionStrategy {
Expand Down Expand Up @@ -63,6 +64,47 @@ class SystemFileExecutionStrategy extends CommandExecutionStrategy {
}
}

class WindowsSystemFileExecutionStrategy extends CommandExecutionStrategy {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create the hierarchy

CommandExecutionStrategy
    SystemFileExecutionStrategy
        WindowsSystemFileExecutionStrategy
        UnixSystemFileExecutionStrategy

and extract the common logic to SystemFileExecutionStrategy.

static canExecute(command: string): Promise<boolean> {
return new Promise(resolve => Utils.getExecutablesInPaths().then(executables => resolve(_.include(executables, command))));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this should be

return new Promise(resolve => resolve(Utils.isWindows()));

}

startExecution() {
return new Promise((resolve, reject) => {
this.args.unshift(this.command);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can call Prompt.getWholeCommand() instead of building it from parts.

this.args = ['/s', '/c', this.args.join(' ')];
this.command = this.cmdPath;

this.invocation.command = pty.spawn(this.command, this.args, {
cols: this.invocation.dimensions.columns,
rows: this.invocation.dimensions.rows,
cwd: this.invocation.directory,
env: process.env
});

this.invocation.command.stdout.on('data', (data: string) => this.invocation.parser.parse(data.toString()));
this.invocation.command.on('exit', (code: number) => {
/* In windows there is no code returned (null) so instead of comparing to 0 we check if its 0 or null with ! */
if (Number(code) === 0) {
resolve();
} else {
reject();
}
})
})
}

private get cmdPath(): string {
if (process.env.comspec) {
return process.env.comspec;
}
else if (process.env.SystemRoot) {
return require('path').join(process.env.SystemRoot, 'System32', 'cmd.exe');
}
else return 'cmd.exe';
}
}

class NullExecutionStrategy extends CommandExecutionStrategy {
static canExecute(command: string): Promise<boolean> {
return new Promise(resolve => resolve(true));
Expand All @@ -76,14 +118,17 @@ class NullExecutionStrategy extends CommandExecutionStrategy {
export default class CommandExecutor {
private static executors = [
BuiltInCommandExecutionStrategy,
SystemFileExecutionStrategy,
process.platform === 'win32' ? WindowsSystemFileExecutionStrategy : SystemFileExecutionStrategy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just add two of them unconditionally, maybe we need to rename the old one to UnixSystem.... They should figure out if they're applicable.

];

static execute(invocation: Invocation): Promise<CommandExecutionStrategy> {
var command = invocation.getPrompt().getCommandName();

return Utils.filterWithPromising(this.executors.concat(NullExecutionStrategy), executor => executor.canExecute(command))
.then(applicableExecutors => new applicableExecutors[0](invocation, command).startExecution());
return Utils.filterWithPromising(
this.executors.concat(NullExecutionStrategy),
executor => executor.canExecute(command))
.then(applicableExecutors => new applicableExecutors[0](invocation, command).startExecution()
);
}
}

2 changes: 1 addition & 1 deletion src/Invocation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// <reference path="references.ts" />

import * as pty from 'pty.js';
import * as pty from 'ptyw.js';
import * as child_process from 'child_process';
import * as _ from 'lodash';
import * as React from 'react';
Expand Down
23 changes: 13 additions & 10 deletions src/Terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ export default class Terminal extends events.EventEmitter {
history: History;
gitBranchWatcher: fs.FSWatcher;

private stateFileName = `${process.env.HOME}/.black-screen-state`;
private stateFileName = `${Utils.getHomeDirectory()}/.black-screen-state`;

// The value of the dictionary is the default value used if there is no serialized data.
private serializableProperties: _.Dictionary<any> = {
currentDirectory: `String:${process.env.HOME}`,
currentDirectory: `String:${Utils.getHomeDirectory()}`,
history: `History:[]`
};

Expand All @@ -37,14 +37,17 @@ export default class Terminal extends events.EventEmitter {

createInvocation(): void {
var invocation = new Invocation(this.currentDirectory, this.dimensions, this.history);
invocation.once('end', () => {
if (app.dock) {
app.dock.bounce('informational');
}
this.createInvocation();
}).once('working-directory-changed', (newWorkingDirectory: string) =>
this.setCurrentDirectory(newWorkingDirectory)
);

invocation
.once('clear', _ => this.clearInvocations())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll remove events in the future, so try to avoid them. Although, I'll accept this PR even with the new event, because it might be hard to implement it in a different way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't noticed the previous time: what is 'clear'? You must have accidentally added it to this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It clears the invocations, like pressing CTRL + L but typing the command clear.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, but there is no command typing part of the story in this PR, right? And shouldn't be for that matter, because it's not about Windows support.

.once('end', _ => {
if (app.dock) {
app.dock.bounce('informational');
}
this.createInvocation();
})
.once('working-directory-changed', (newWorkingDirectory: string) => this.setCurrentDirectory(newWorkingDirectory));

this.invocations = this.invocations.concat(invocation);
this.emit('invocation');
}
Expand Down
4 changes: 4 additions & 0 deletions src/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ export default class Utils {
});
}

static getHomeDirectory(): string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see you use the get syntax in the other place. Maybe we should do it here as well?

return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember about === here and everywhere else.

}

private static delegate(name: string, args: Array<any>): void {
if ((typeof window !== 'undefined') && (<any>window)['DEBUG']) {
(<any>console)[name](...args);
Expand Down
2 changes: 1 addition & 1 deletion src/references.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
/// <reference path="../dts/typings/jquery/jquery.d.ts" />
/// <reference path="../dts/typings/lodash/lodash.d.ts" />
/// <reference path="../dts/typings/react/react.d.ts" />
/// <reference path="../dts/typings/pty.js/pty.js.d.ts" />
/// <reference path="../dts/typings/ptyw.js/ptyw.js.d.ts" />