Simplify bitwisecmm (#16)

This commit is contained in:
Borys Levytskyi
2021-01-14 20:07:59 +02:00
committed by GitHub
parent 49e5265985
commit f671b32b63
16 changed files with 85 additions and 193 deletions

View File

@@ -1,12 +1,11 @@
import React from 'react';
import InputBox from './components/InputBox';
import DisplayResultView from './components/DisplayResultView';
import AppState from './core/AppState';
import AppState, { CommandResultView } from './core/AppState';
import cmd from './core/cmd';
import CommandResult from './models/CommandResult';
import log from 'loglevel';
import Indicators from './components/Indicators';
import CommandLink from './components/CommandLink';
import hash from './core/hash';
type AppRootProps = {
appState: AppState,
@@ -15,7 +14,7 @@ type AppRootProps = {
type AppRootState = {
uiTheme: string,
emphasizeBytes: boolean,
commandResults: CommandResult[]
commandResults: CommandResultView[]
}
export default class AppRoot extends React.Component<AppRootProps, AppRootState> {
@@ -35,7 +34,10 @@ export default class AppRoot extends React.Component<AppRootProps, AppRootState>
getResultViews() : JSX.Element[] {
log.debug('getting result views')
var results = this.state.commandResults.map((r, i) => <DisplayResultView key={i} content={r} input={r.input} inputHash={r.inputHash} appState={this.props.appState} />);
var results = this.state.commandResults.map((r, i) =>
<DisplayResultView key={r.key} input={r.input} inputHash={hash.encodeHash(r.input)} appState={this.props.appState}>
{r.view}
</DisplayResultView>);
return results;
}
@@ -66,7 +68,7 @@ export default class AppRoot extends React.Component<AppRootProps, AppRootState>
<InputBox onCommandEntered={(input) => cmd.execute(input)} />
<span className="configPnl">
<span id="emphasizeBytes" data-cmd="em" className={"indicator " + this.getIndicator(this.state.emphasizeBytes)} title="Toggle Emphasize Bytes" onClick={e => this.toggleEmphasizeBytes()}>[em]</span>
<span id="emphasizeBytes" data-cmd="em" className={"indicator " + this.getIndicator(this.state.emphasizeBytes)} title="Toggle Emphasize Bytes" onClick={() => this.toggleEmphasizeBytes()}>[em]</span>
</span>
</div>

View File

@@ -1,18 +1,17 @@
import HelpResult from './models/HelpResult';
import AboutResult from './models/AboutResult';
import UnknownCommandResult from './models/UnknownCommandResult';
import ExpressionResult from './models/ExpressionResult';
import {UnhandledErrorResult, ErrorResult} from './models/ErrorResults';
import WahtsnewResult from './models/WhatsnewResult';
import StringResult from './models/StringResult';
import * as expression from './expression/expression';
import React from 'react';
import uuid from 'uuid/v4';
import { CommandInput, CmdShell } from './core/cmd';
import { ExpressionInput } from './expression/expression-interfaces';
import AppState from './core/AppState';
import {ParsingError, IpAddress, ipAddressParser, IpAddressWithSubnetMask, ParsedIpObject} from './ipaddress/ip'
import IpAddressResult from './models/IpAddressResult';
import { isGetAccessor, isPrefixUnaryExpression } from 'typescript';
import ErrorResultView from './components/results/ErrorResultView';
import HelpResultView from './components/results/HelpResultView';
import AboutResultView from './components/results/AboutResultView';
import WhatsnewResultView from './components/results/WhatsNewResultView';
import TextResultView from './components/results/TextResultView';
import IpAddressView from './components/results/IpAddressView';
import UnknownInputResultView from './components/results/UnknownInputResultView';
import BitwiseOperationExpressionView from './components/results/expressions/BitwiseOperationExpressionView';
export default {
initialize (cmd: CmdShell, appState: AppState) {
@@ -20,19 +19,19 @@ export default {
cmd.debugMode = appState.debugMode;
appState.onChange(() => cmd.debugMode = appState.debugMode);
cmd.command("help", (c: CommandInput) => appState.addCommandResult(new HelpResult(c.input)));
cmd.command("clear", (c: CommandInput) => appState.clearCommandResults());
cmd.command("em", (c: CommandInput) => appState.toggleEmphasizeBytes());
cmd.command("dark", (c: CommandInput) => appState.setUiTheme('dark'));
cmd.command("light", (c: CommandInput) => appState.setUiTheme('light'));
cmd.command("midnight", (c: CommandInput) => appState.setUiTheme('midnight'));
cmd.command("about", (c: CommandInput) => appState.addCommandResult(new AboutResult(c.input)));
cmd.command("whatsnew", (c: CommandInput) => appState.addCommandResult(new WahtsnewResult(c.input)));
cmd.command("guid", (c: CommandInput) => appState.addCommandResult(new StringResult(c.input, uuid())));
cmd.command("-notrack", (c: CommandInput) => {});
cmd.command("help", (c: CommandInput) => appState.addCommandResult(c.input, <HelpResultView />));
cmd.command("clear", () => appState.clearCommandResults());
cmd.command("em", () => appState.toggleEmphasizeBytes());
cmd.command("dark", () => appState.setUiTheme('dark'));
cmd.command("light", () => appState.setUiTheme('light'));
cmd.command("midnight", () => appState.setUiTheme('midnight'));
cmd.command("about", (c: CommandInput) => appState.addCommandResult(c.input, <AboutResultView />));
cmd.command("whatsnew", (c: CommandInput) => appState.addCommandResult(c.input, <WhatsnewResultView />));
cmd.command("guid", (c: CommandInput) => appState.addCommandResult(c.input, <TextResultView text={uuid()} />));
cmd.command("-notrack", () => {});
cmd.command("-debug", (c: CommandInput) => {
appState.toggleDebugMode();
appState.addCommandResult(new StringResult(c.input, `Debug Mode: ${appState.debugMode}`))
appState.addCommandResult(c.input, <TextResultView text={`Debug Mode: ${appState.debugMode}`}/>);
});
@@ -46,7 +45,7 @@ export default {
return;
if(result instanceof ParsingError) {
appState.addCommandResult(new ErrorResult(c.input, result.errorMessage));
appState.addCommandResult(c.input, <ErrorResultView errorMessage={result.errorMessage} />);
return;
}
@@ -63,7 +62,7 @@ export default {
}
});
appState.addCommandResult(new IpAddressResult(c.input, ipAddresses));
appState.addCommandResult(c.input, <IpAddressView ipAddresses={ipAddresses} />);
}
})
@@ -72,16 +71,16 @@ export default {
canHandle: (input:string) => expression.parser.canParse(input),
handle: function(c: CommandInput) {
var expr = expression.parser.parse(c.input);
appState.addCommandResult(new ExpressionResult(c.input, expr as ExpressionInput));
appState.addCommandResult(c.input, <BitwiseOperationExpressionView expression={expr!} emphasizeBytes={appState.emphasizeBytes} />);
}
})
// Last command handler reports that input is unknown
cmd.command({
canHandle: () => true,
handle: (c: CommandInput) => appState.addCommandResult(new UnknownCommandResult(c.input))
handle: (c: CommandInput) => appState.addCommandResult(c.input, <UnknownInputResultView input={c.input}/>)
});
cmd.onError((input: string, err: Error) => appState.addCommandResult(new UnhandledErrorResult(input, err)));
cmd.onError((input: string, err: Error) => appState.addCommandResult(input, <ErrorResultView errorMessage={err.toString()} />));
}
}

View File

@@ -1,81 +1,23 @@
import React from 'react';
import HelpResult from '../models/HelpResult';
import AboutResult from '../models/AboutResult';
import HelpResultView from './results/HelpResultView';
import AboutResultView from './results/AboutResultView';
import ExpressionResult from '../models/ExpressionResult';
import BitwiseOperationExpressionView from './results/expressions/BitwiseOperationExpressionView';
import WhatsnewResult from '../models/WhatsnewResult';
import WhatsnewResultView from './results/WhatsNewResultView';
import {UnhandledErrorResult, ErrorResult} from '../models/ErrorResults';
import StringResult from '../models/StringResult';
import IpAddressView from './results/IpAddressView';
import CommandResult from '../models/CommandResult';
import AppState from '../core/AppState';
import IpAddressResult from '../models/IpAddressResult';
type DisplayResultProps = {
content : CommandResult,
appState: AppState,
inputHash: string,
input: string,
key: number
}
export default class DisplayResult extends React.Component<DisplayResultProps> {
export default class DisplayResultView extends React.Component<DisplayResultProps> {
render() {
return <div className="result">
<div className="input mono"><span className="cur">&gt;</span>{this.props.content.input}<a className="hashLink" title="Link for this expression" href={window.location.pathname + '#' + this.props.inputHash}>#</a></div>
<div className="input mono"><span className="cur">&gt;</span>{this.props.input}<a className="hashLink" title="Link for this expression" href={window.location.pathname + '#' + this.props.inputHash}>#</a></div>
<div className="content">
{this.findResultComponent(this.props.content)}
{this.props.children}
</div>
</div>;
}
}
findResultComponent(result: CommandResult) : JSX.Element {
if(result instanceof HelpResult) {
return <HelpResultView />
}
if(result instanceof AboutResult) {
return <AboutResultView />
}
if(result instanceof ExpressionResult) {
return <BitwiseOperationExpressionView expression={result.expression} emphasizeBytes={this.props.appState.emphasizeBytes} />
}
if(result instanceof WhatsnewResult) {
return <WhatsnewResultView />
}
if(result instanceof StringResult) {
return <p>{result.value}</p>
}
if (result instanceof UnhandledErrorResult) {
return <div className="result">
<div className="error">(X_X) Ooops.. Something ain' right: <strong>{result.error.message}</strong></div>
</div>
}
if (result instanceof ErrorResult) {
return <div className="result">
<div className="error">{result.errorMessage}</div>
</div>
}
if(result instanceof IpAddressResult) {
const ipResult = result as IpAddressResult;
return <IpAddressView ipAddresses={ipResult.ipAddresses} />
}
return <div className="result">
<div className="error">¯\_()_/¯ Sorry, i don&prime;t know what <strong>{this.props.content.input}</strong> is</div>
</div>
}
}

View File

@@ -0,0 +1,10 @@
import React from 'react';
function ErrorResultView(props : {errorMessage:string}) {
return <div className="result">
<div className="error">{props.errorMessage}</div>
</div>;
}
export default ErrorResultView;

View File

@@ -0,0 +1,7 @@
import React from 'react';
function TextResultView(props : { text: string }) {
return <p>{props.text}</p>;
}
export default TextResultView;

View File

@@ -0,0 +1,10 @@
import React from 'react';
function UnknownInputResultView(props : {input:string}) {
return <div className="result">
<div className="error">¯\_()_/¯ Sorry, i don&prime;t know what <strong>{props.input}</strong> is</div>
</div>;
}
export default UnknownInputResultView;

View File

@@ -9,6 +9,12 @@ export type PersistedAppData = {
debugMode: boolean | null;
}
export type CommandResultView = {
key: number,
input: string,
view: JSX.Element
};
export type AppStateChangeHandler = (state: AppState) => void;
export default class AppState {
@@ -17,15 +23,15 @@ export default class AppState {
emphasizeBytes: boolean;
debugMode: boolean = false;
uiTheme: string;
handlers: AppStateChangeHandler[];
commandResults: any[];
changeHandlers: AppStateChangeHandler[];
commandResults: CommandResultView[];
persistedVersion: number;
wasOldVersion: boolean;
env: string;
constructor(persistData : PersistedAppData, env: string) {
this.commandResults = [];
this.handlers = [];
this.changeHandlers = [];
this.uiTheme = persistData.uiTheme || 'midnight';
this.env = env;
@@ -35,9 +41,10 @@ export default class AppState {
this.debugMode = env !== 'prod' || persistData.debugMode === true;
}
addCommandResult(result : any) {
this.commandResults.unshift(result);
log.debug("result added", result);
addCommandResult(input : string, view : JSX.Element) {
const key = generateKey();
this.commandResults.unshift({key, input, view});
log.debug(`command result added: ${input}`);
this.triggerChanged();
}
@@ -52,11 +59,11 @@ export default class AppState {
}
onChange(handler : AppStateChangeHandler) {
this.handlers.push(handler);
this.changeHandlers.push(handler);
}
triggerChanged() {
this.handlers.forEach(h => h(this));
this.changeHandlers.forEach(h => h(this));
}
setUiTheme(theme: string) {
@@ -77,4 +84,8 @@ export default class AppState {
debugMode: this.debugMode
}
}
};
};
function generateKey() : number {
return Math.ceil(Math.random()*10000000) ^ Date.now(); // Because why the hell not...
}

View File

@@ -1,7 +0,0 @@
import CommandResult from './CommandResult';
export default class AboutResult extends CommandResult {
constructor(input:string) {
super(input);
}
}

View File

@@ -1,13 +0,0 @@
export default class CommandResult {
input: string;
inputHash: string;
constructor(input: string) {
this.input = input;
this.inputHash = this.encodeHash(input);
}
encodeHash (input: string) {
return encodeURI(input.trim().replace(/\s/g,','));
}
}

View File

@@ -1,17 +0,0 @@
import CommandResult from './CommandResult';
export class UnhandledErrorResult extends CommandResult {
error: Error;
constructor(input: string, error : Error) {
super(input);
this.error = error;
}
}
export class ErrorResult extends CommandResult {
errorMessage: string;
constructor(input: string, errorMessage : string) {
super(input);
this.errorMessage = errorMessage;
}
}

View File

@@ -1,10 +0,0 @@
import CommandResult from './CommandResult';
import { ExpressionInput } from '../expression/expression-interfaces';
export default class ExpressionResult extends CommandResult {
expression: ExpressionInput;
constructor(input: string, expression: ExpressionInput) {
super(input);
this.expression = expression;
}
}

View File

@@ -1,7 +0,0 @@
import CommandResult from './CommandResult';
export default class HelpResult extends CommandResult {
constructor(input: string) {
super(input);
}
}

View File

@@ -1,10 +0,0 @@
import { IpAddress, ipAddressParser, IpAddressWithSubnetMask } from '../ipaddress/ip';
import CommandResult from './CommandResult';
export default class IpAddressResult extends CommandResult {
ipAddresses: IpAddress[];
constructor(input: string, ipAddresses: IpAddress[]) {
super(input);
this.ipAddresses = ipAddresses;
}
}

View File

@@ -1,9 +0,0 @@
import CommandResult from './CommandResult';
export default class StringResult extends CommandResult {
value:string;
constructor(input: string, value : string) {
super(input);
this.value = value;
}
}

View File

@@ -1,9 +0,0 @@
import CommandResult from './CommandResult';
export default class UnknownCommandResult extends CommandResult {
message:string;
constructor(input : string) {
super(input);
this.message = `Sorry, i don''t know what ${input} is :(`;
}
}

View File

@@ -1,7 +0,0 @@
import CommandResult from './CommandResult';
export default class WhatsnewResult extends CommandResult {
constructor(input: string) {
super(input);
}
}