unsable code rework, doesnt run
This commit is contained in:
0
src/lib/assets/locales/terminal/en_US.json
Normal file
0
src/lib/assets/locales/terminal/en_US.json
Normal file
@@ -1,68 +1,60 @@
|
||||
import { COMMANDS, GROUP, PASSWD, type CommandArgs, type ICommand, type Result } from './static';
|
||||
import { VirtualFS } from './fs';
|
||||
import { VirtualFS, type TreeNode } from './fs';
|
||||
import { Terminal, type PrintData } from '../terminal/terminal';
|
||||
import { Stack } from '../stack';
|
||||
|
||||
export type Permission = {
|
||||
r: boolean;
|
||||
w: boolean;
|
||||
x: boolean;
|
||||
};
|
||||
import { PASSWD, type User } from './etc/userData';
|
||||
import { ExitCode } from './metadata';
|
||||
import { COMMANDS, type CommandArgs, type CommandResultData, type ICommand } from './commandRegistry';
|
||||
import { GROUP, type Group } from './etc/groupData';
|
||||
|
||||
export type BashInitArgs = {
|
||||
stdio?: Terminal;
|
||||
user: User;
|
||||
fs: any;
|
||||
io?: Terminal;
|
||||
instanceId: number;
|
||||
user: {username: string, password: string};
|
||||
fs?: VirtualFS;
|
||||
};
|
||||
|
||||
export type TimeStamps = {
|
||||
modified: Date;
|
||||
changed: Date;
|
||||
accessed: Date;
|
||||
};
|
||||
|
||||
// TODO: Finish this
|
||||
// TODO: Change into a type instead of an enum for performance (low priority)
|
||||
export enum ExitCode {
|
||||
SUCCESS = 0,
|
||||
ERROR = 1
|
||||
}
|
||||
|
||||
export type User = {
|
||||
username: string;
|
||||
passwd: string; //HASHED PASSWORD //TODO: Make a formated type
|
||||
readonly uid: number; // Normal user 1000+ System user 1-999 root - 0 //TODO: Make a formated type
|
||||
readonly gid: number; // Primary group | 'Users' 1000 - Others - 1000+ root - 0 //TODO: Make a formated type
|
||||
home: string; //TODO: Make a formated type
|
||||
history: string[];
|
||||
cwd?: number; //TODO: Make a formated type
|
||||
pwd?: number; //TODO: Make a formated type
|
||||
};
|
||||
|
||||
export type Group = {
|
||||
groupname: string;
|
||||
gid: number; // Primary group 'Users' 1000 - Others - 1000+ root - 0
|
||||
members: number[]; //TODO: Make a formated type UID
|
||||
export type Result = {
|
||||
exitCode: ExitCode;
|
||||
path: number; //the inode of the place that the command was executed in
|
||||
resultData?: CommandResultData;
|
||||
};
|
||||
|
||||
export class Bash {
|
||||
private readonly _instanceId: number;
|
||||
private vfs: VirtualFS;
|
||||
private _passwd: User[];
|
||||
private _instances: Stack<User>;
|
||||
private _userInstances: Stack<User>;
|
||||
private _group: Group[];
|
||||
private _terminal!: Terminal;
|
||||
private user: User;
|
||||
private readonly _commands: Record<string, ICommand>;
|
||||
|
||||
constructor(args: BashInitArgs) {
|
||||
this.user = args.user;
|
||||
this._instanceId = args.instanceId
|
||||
this._commands = COMMANDS;
|
||||
this._passwd = PASSWD;
|
||||
this._group = GROUP;
|
||||
this._terminal = args.stdio!;
|
||||
this._instances = new Stack<User>();
|
||||
this._userInstances = new Stack<User>();
|
||||
this._terminal = args.io!;
|
||||
|
||||
this.vfs = new VirtualFS({ fs: args.fs, user: args.user });
|
||||
const loginResult = this.userLogin(args.user.username, args.user.password);
|
||||
if(loginResult == ExitCode.ERROR)
|
||||
this._terminal.throwExeption(
|
||||
`Failed to initialize bash instance - access denied for user ${args.user.username}`,
|
||||
ExitCode.ERROR
|
||||
)
|
||||
|
||||
|
||||
this.user = this._userInstances.peek()!
|
||||
this.vfs = this._terminal.fileSystem;
|
||||
}
|
||||
|
||||
private _initNewUserSession(user: User): User {
|
||||
if(!this._passwd.includes(user))
|
||||
this._terminal.throwExeption(`user not found under the name ${user.username}`, ExitCode.ERROR)
|
||||
|
||||
this._userInstances.push(user);
|
||||
return user
|
||||
}
|
||||
|
||||
private _appendNewResult(inode: number, output: any, cmd: string) {
|
||||
@@ -85,6 +77,10 @@ export class Bash {
|
||||
}
|
||||
}
|
||||
|
||||
clearTerminal(): void {
|
||||
this._terminal.clearTerminal();
|
||||
}
|
||||
|
||||
getCwd(): number {
|
||||
return this.vfs.cwd;
|
||||
}
|
||||
@@ -113,7 +109,7 @@ export class Bash {
|
||||
return this._group[1].members.includes(uid);
|
||||
}
|
||||
|
||||
executeCommand(commandName: string, args: CommandArgs): void {
|
||||
async executeCommand(commandName: string, args: CommandArgs) {
|
||||
let result: Result = { exitCode: ExitCode.ERROR, path: this.getCwd() };
|
||||
const command = this._commands[commandName];
|
||||
if (!command) this.throwError(result);
|
||||
@@ -128,7 +124,7 @@ export class Bash {
|
||||
|
||||
let out: Result = command.method.call(this, args);
|
||||
console.log(out);
|
||||
this._appendNewResult(out.path, out.data?.data, this.user.history[0]);
|
||||
this._appendNewResult(out.path, out.resultData?.data, this.user.history[0]);
|
||||
}
|
||||
|
||||
throwError(result: Result): void {
|
||||
@@ -140,14 +136,25 @@ export class Bash {
|
||||
}
|
||||
|
||||
userLogout() {
|
||||
this._instances.pop();
|
||||
if (this._instances.size() === 0) {
|
||||
this._userInstances.pop();
|
||||
if (this._userInstances.size() === 0) {
|
||||
//TODO: Implement system logout
|
||||
} else {
|
||||
//this.changeUser(this._instances.peek()!);
|
||||
}
|
||||
}
|
||||
|
||||
userLogin(username: string, passwd: string): ExitCode {
|
||||
const user: User | undefined =
|
||||
this._passwd.find((user) => user.username === username);
|
||||
|
||||
if(user && user.passwd === passwd) {
|
||||
this._initNewUserSession(user);
|
||||
return ExitCode.SUCCESS;
|
||||
}
|
||||
return ExitCode.ERROR;
|
||||
}
|
||||
|
||||
formatBytes(bytes: number, dPoint?: number, pow: 1024 | 1000 = 1024): string {
|
||||
if (!+bytes) return '0';
|
||||
|
||||
|
||||
84
src/lib/stores/bash/static.ts → src/lib/stores/bash/commandRegistry.ts
Executable file → Normal file
84
src/lib/stores/bash/static.ts → src/lib/stores/bash/commandRegistry.ts
Executable file → Normal file
@@ -1,80 +1,26 @@
|
||||
import { Bash, ExitCode, type Group, type User } from './bash';
|
||||
import { ls } from './commands/ls';
|
||||
import { cd } from './commands/cd';
|
||||
import { clear } from './commands/clear';
|
||||
import type { Bash, Result } from "./bash";
|
||||
import { cd } from "./commands/cd";
|
||||
import { clear } from "./commands/clear";
|
||||
import { ls } from "./commands/ls";
|
||||
|
||||
export type ICommand = {
|
||||
method: (this: Bash, args: CommandArgs) => Result;
|
||||
flags: string[];
|
||||
help: string;
|
||||
root: boolean;
|
||||
method: (this: Bash, args: CommandArgs) => Result;
|
||||
flags: string[];
|
||||
help: string;
|
||||
root: boolean;
|
||||
};
|
||||
|
||||
export type CommandArgs = {
|
||||
flags: string[];
|
||||
args: string[];
|
||||
flags: string[];
|
||||
args: string[];
|
||||
};
|
||||
|
||||
export type resultData = {
|
||||
cmd: string; //the string that contains the shorthand for the command that was executed - used in a switch statement in parseResult
|
||||
data: any; //the data that the commmand may have returned like TreeNodes[] from ls
|
||||
args?: CommandArgs;
|
||||
export type CommandResultData = {
|
||||
cmd: string; //the string that contains the shorthand for the command that was executed - used in a switch statement in parseResult
|
||||
data: any; //the data that the commmand may have returned like TreeNodes[] from ls
|
||||
args?: CommandArgs;
|
||||
};
|
||||
|
||||
export type Result = {
|
||||
exitCode: ExitCode;
|
||||
path: number; //the inode of the place that the command was executed in
|
||||
data?: resultData;
|
||||
};
|
||||
|
||||
export const GROUP: Group[] = [
|
||||
{
|
||||
groupname: 'sudo',
|
||||
gid: 69,
|
||||
members: [0, 1001]
|
||||
},
|
||||
{
|
||||
groupname: 'users',
|
||||
gid: 984,
|
||||
members: [1001, 1002]
|
||||
}
|
||||
] as const;
|
||||
|
||||
export const PASSWD: User[] = [
|
||||
{
|
||||
username: 'root',
|
||||
passwd: '123',
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
home: '/',
|
||||
history: [] //TODO: Delete this and declare a new history array when logging the user in.
|
||||
},
|
||||
{
|
||||
username: 'admin',
|
||||
passwd: '456',
|
||||
uid: 1000,
|
||||
gid: 1000,
|
||||
home: '/home/admin',
|
||||
history: [] //TODO: Delete this and declare a new history array when logging the user in.
|
||||
},
|
||||
{
|
||||
username: 'user',
|
||||
passwd: '789',
|
||||
uid: 1001,
|
||||
gid: 1000,
|
||||
home: '/home/user',
|
||||
history: [] //TODO: Delete this and declare a new history array when logging the user in.
|
||||
},
|
||||
{
|
||||
username: 'kamil',
|
||||
passwd: '000',
|
||||
uid: 1002,
|
||||
gid: 1000,
|
||||
home: '/home/kamil',
|
||||
history: [] //TODO: Delete this and declare a new history array when logging the user in.
|
||||
}
|
||||
];
|
||||
|
||||
export const COMMANDS = {
|
||||
cd,
|
||||
ls,
|
||||
@@ -197,4 +143,4 @@ export const COMMANDS = {
|
||||
flags: [],
|
||||
help: "",
|
||||
}
|
||||
} */
|
||||
} */
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ExitCode, type Bash } from '../bash';
|
||||
import type { Bash, Result } from '../bash';
|
||||
import type { CommandArgs, ICommand } from '../commandRegistry';
|
||||
import { Type, type TreeNode } from '../fs';
|
||||
import type { CommandArgs, ICommand, Result } from '../static';
|
||||
import { ExitCode } from '../metadata';
|
||||
|
||||
export const cmd_cd = function (this: Bash, args: CommandArgs): Result {
|
||||
let result: Result = { exitCode: ExitCode.ERROR, path: this.getCwd() };
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { CommandArgs, ICommand, Result } from "../static";
|
||||
|
||||
export const cmd_clear = function(this: Bash, args: CommandArgs): Result {
|
||||
let result: Result = { exitCode: ExitCode.ERROR, path: this.getCwd() };
|
||||
this.clearTerminal();
|
||||
result.exitCode = ExitCode.SUCCESS;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Bash, ExitCode, type Permission, type TimeStamps } from '../bash';
|
||||
import type { Bash, Result } from '../bash';
|
||||
import type { CommandArgs, CommandResultData, ICommand } from '../commandRegistry';
|
||||
import { Type, VirtualFS, type NodePerms, type TreeNode } from '../fs';
|
||||
import { ExitCode, type Permission } from '../metadata';
|
||||
import { Sort, SortNodeBy } from '../sort';
|
||||
import type { CommandArgs, ICommand, Result, resultData } from '../static';
|
||||
|
||||
type LsEntry = {
|
||||
inode: number | null;
|
||||
@@ -39,8 +40,8 @@ const months: readonly string[] = [
|
||||
|
||||
export const cmd_ls = function (this: Bash, args: CommandArgs): Result {
|
||||
const Fs = this.getFs();
|
||||
const resultData: resultData = { cmd: 'ls', data: null, args: args };
|
||||
const result: Result = { exitCode: ExitCode.ERROR, path: this.getCwd(), data: resultData };
|
||||
const resultData: CommandResultData = { cmd: 'ls', data: null, args: args };
|
||||
const result: Result = { exitCode: ExitCode.ERROR, path: this.getCwd(), resultData: resultData };
|
||||
const nodes: TreeNode[] = [];
|
||||
|
||||
//Check if any args contain the long flags with value and are valid flags inside the ls const
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import type { ICommand } from "../static"
|
||||
import { cmd_ls } from "./ls"
|
||||
|
||||
type LsEntry
|
||||
|
||||
|
||||
|
||||
|
||||
export class ls {
|
||||
public const ls: ICommand = {
|
||||
method: ls.cmd_ls
|
||||
}
|
||||
}
|
||||
18
src/lib/stores/bash/etc/groupData.ts
Normal file
18
src/lib/stores/bash/etc/groupData.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export type Group = {
|
||||
groupname: string;
|
||||
gid: number; // Primary group 'Users' 1000 - Others - 1000+ root - 0
|
||||
members: number[]; //TODO: Make a formated type UID
|
||||
};
|
||||
|
||||
export const GROUP: Group[] = [
|
||||
{
|
||||
groupname: 'sudo',
|
||||
gid: 69,
|
||||
members: [0, 1001]
|
||||
},
|
||||
{
|
||||
groupname: 'users',
|
||||
gid: 984,
|
||||
members: [1001, 1002]
|
||||
}
|
||||
] as const;
|
||||
45
src/lib/stores/bash/etc/userData.ts
Normal file
45
src/lib/stores/bash/etc/userData.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
export type User = {
|
||||
username: string;
|
||||
passwd: string; //HASHED PASSWORD //TODO: Make a formated type
|
||||
readonly uid: number; // Normal user 1000+ System user 1-999 root - 0 //TODO: Make a formated type
|
||||
readonly gid: number; // Primary group | 'Users' 1000 - Others - 1000+ root - 0 //TODO: Make a formated type
|
||||
home: string; //TODO: Make a formated type
|
||||
history: string[];
|
||||
cwd?: number; //TODO: Make a formated type
|
||||
pwd?: number; //TODO: Make a formated type
|
||||
};
|
||||
|
||||
export const PASSWD: User[] = [
|
||||
{
|
||||
username: 'root',
|
||||
passwd: '123',
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
home: '/',
|
||||
history: []
|
||||
},
|
||||
{
|
||||
username: 'admin',
|
||||
passwd: '456',
|
||||
uid: 1000,
|
||||
gid: 1000,
|
||||
home: '/home/admin',
|
||||
history: []
|
||||
},
|
||||
{
|
||||
username: 'user',
|
||||
passwd: '789',
|
||||
uid: 1001,
|
||||
gid: 1000,
|
||||
home: '/home/user',
|
||||
history: []
|
||||
},
|
||||
{
|
||||
username: 'kamil',
|
||||
passwd: '000',
|
||||
uid: 1002,
|
||||
gid: 1000,
|
||||
home: '/home/kamil',
|
||||
history: []
|
||||
}
|
||||
];
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Permission, TimeStamps, User } from './bash';
|
||||
import type { Bash } from "./bash";
|
||||
import type { Permission, TimeStamps } from "./metadata";
|
||||
|
||||
export enum Type {
|
||||
Directory = 16384,
|
||||
@@ -14,7 +15,7 @@ export type NodePerms = {
|
||||
|
||||
export type FsInitArgs = {
|
||||
fs: any;
|
||||
user: User;
|
||||
bash: Bash;
|
||||
};
|
||||
|
||||
export type TreeNode = {
|
||||
@@ -37,6 +38,7 @@ export type TreeNode = {
|
||||
export class VirtualFS {
|
||||
private FsTable: Map<number, TreeNode>;
|
||||
private rootINode: number;
|
||||
private _Bash: Bash;
|
||||
|
||||
home: number;
|
||||
cwd: number;
|
||||
@@ -45,9 +47,10 @@ export class VirtualFS {
|
||||
constructor(args: FsInitArgs) {
|
||||
this.FsTable = args.fs;
|
||||
this.rootINode = 1;
|
||||
this.home = this._pathStringToINode(args.user.home);
|
||||
this.cwd = args.user.cwd ? args.user.cwd : this.home;
|
||||
this.pwd = args.user.pwd ? args.user.pwd : this.cwd;
|
||||
this._Bash = args.bash;
|
||||
this.home = this._pathStringToINode(args.bash.getUser().home);
|
||||
this.cwd = args.bash.getUser().cwd ? args.bash.getUser().cwd! : this.home;
|
||||
this.pwd = args.bash.getUser().pwd ? args.bash.getUser().pwd! : this.cwd;
|
||||
|
||||
console.log(this.home);
|
||||
console.log(this.cwd);
|
||||
|
||||
17
src/lib/stores/bash/metadata.ts
Normal file
17
src/lib/stores/bash/metadata.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export type TimeStamps = {
|
||||
modified: Date;
|
||||
changed: Date;
|
||||
accessed: Date;
|
||||
};
|
||||
|
||||
// TODO: Finish this
|
||||
export enum ExitCode {
|
||||
SUCCESS = 0,
|
||||
ERROR = 1
|
||||
}
|
||||
|
||||
export type Permission = {
|
||||
r: boolean;
|
||||
w: boolean;
|
||||
x: boolean;
|
||||
};
|
||||
@@ -4,10 +4,13 @@ import deFlag from '$lib/assets/deFlag.svg';
|
||||
import frFlag from '$lib/assets/frFlag.svg';
|
||||
import jaFlag from '$lib/assets/jaFlag.svg';
|
||||
|
||||
export const langs = {
|
||||
pl: {},
|
||||
en: {},
|
||||
de: {},
|
||||
ja: {},
|
||||
fr: {}
|
||||
};
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
function getInitalLocale(): string {
|
||||
if (typeof navigator === 'undefined') return 'en-US';
|
||||
|
||||
const sysPrefLocale = navigator.language
|
||||
return sysPrefLocale
|
||||
}
|
||||
|
||||
export const locale = writable(getInitalLocale());
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { User } from '../bash/bash';
|
||||
import type { User } from '../bash/etc/userData';
|
||||
import type { TreeNode } from '../bash/fs';
|
||||
import { Terminal, type TermInitArgs } from './terminal';
|
||||
import { type ILocale } from './localeRegistry';
|
||||
import { Terminal, type PageCallbacks, type TermInitArgs } from './terminal';
|
||||
|
||||
let initializing = $state(true);
|
||||
|
||||
@@ -99,16 +100,34 @@ async function fetchFileSystem(path: string): Promise<any> {
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function initTerminal(user: User, callbackInit: any): Promise<Terminal> {
|
||||
async function fetchLocale(id: string): Promise<any> {
|
||||
const response = await fetch(`/src/lib/assets/locales/terminal/${id}.json`);
|
||||
if(!response.ok) throw new Error('Failed to fetch the chosen locale');
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function initTerminal(
|
||||
user: {username: string, password: string},
|
||||
callbackInit: PageCallbacks,
|
||||
localeId: string
|
||||
): Promise<Terminal> {
|
||||
try {
|
||||
const sig = await fetchFsSignature('/src/lib/assets/fs/signature');
|
||||
const fsJson = await fetchFsJson(sig);
|
||||
const fs: Map<number, TreeNode> = jsonToNodeTable(fsJson);
|
||||
const locale: ILocale = {
|
||||
id: localeId,
|
||||
keys: fetchLocale(localeId)
|
||||
};
|
||||
|
||||
const args: TermInitArgs = {
|
||||
fs,
|
||||
locale,
|
||||
bash: {
|
||||
user,
|
||||
fs
|
||||
instanceId: 0
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
13
src/lib/stores/terminal/localeRegistry.ts
Normal file
13
src/lib/stores/terminal/localeRegistry.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export interface ILocale {
|
||||
id: string;
|
||||
keys?: {};
|
||||
}
|
||||
|
||||
const en: ILocale = {
|
||||
id: 'en_US',
|
||||
keys: {}
|
||||
}
|
||||
|
||||
export const LOCALES = {
|
||||
en
|
||||
} as const satisfies Record<string, ILocale>;
|
||||
@@ -1,7 +1,7 @@
|
||||
import { mount, unmount } from 'svelte';
|
||||
import Output from '../../../modules/terminal/Output.svelte';
|
||||
import { isInitializing } from './init.svelte';
|
||||
import type { PrintData } from './terminal';
|
||||
import Output from '../../../../modules/terminal/Output.svelte';
|
||||
import { isInitializing } from '../init.svelte';
|
||||
import type { PrintData } from '../terminal';
|
||||
|
||||
interface OutputProps {
|
||||
path: string;
|
||||
@@ -23,6 +23,8 @@ function appendOutput(container: HTMLElement, props: OutputProps): Output | unde
|
||||
}
|
||||
|
||||
export function print(e: HTMLElement, data: PrintData): void {
|
||||
if(data.cmd == 'clear') return;
|
||||
|
||||
if (isInitializing()) {
|
||||
console.error('Terminal is initializing! Skipping Print');
|
||||
return;
|
||||
@@ -35,6 +37,7 @@ export function print(e: HTMLElement, data: PrintData): void {
|
||||
}
|
||||
|
||||
export function clear(): void {
|
||||
console.log("outInstances", outputInstances);
|
||||
unmount(outputInstances);
|
||||
for(const instance of outputInstances) {
|
||||
unmount(instance, {});
|
||||
}
|
||||
}
|
||||
4
src/lib/stores/terminal/stdio/keystrokeRegistry.ts
Normal file
4
src/lib/stores/terminal/stdio/keystrokeRegistry.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface KeyStroke {
|
||||
keys: KeyboardEvent[];
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { Bash, ExitCode, type BashInitArgs, type User } from '../bash/bash';
|
||||
import type { VirtualFS } from '../bash/fs';
|
||||
import type { CommandArgs } from '../bash/static';
|
||||
import { Char } from '../char';
|
||||
import { Bash, type BashInitArgs } from '../bash/bash';
|
||||
import type { CommandArgs } from '../bash/commandRegistry';
|
||||
import type { User } from '../bash/etc/userData';
|
||||
import { VirtualFS, type TreeNode } from '../bash/fs';
|
||||
import type { ExitCode } from '../bash/metadata';
|
||||
import type { ILocale } from './localeRegistry';
|
||||
|
||||
export type TerminalMode = {};
|
||||
|
||||
export type TermInitArgs = {
|
||||
fs: Map<number, TreeNode>;
|
||||
bash: BashInitArgs;
|
||||
locale: ILocale
|
||||
};
|
||||
|
||||
export type ParsedInput = {
|
||||
@@ -28,12 +32,28 @@ export type PageCallbacks = {
|
||||
};
|
||||
|
||||
export class Terminal {
|
||||
private bash: Bash;
|
||||
private callbacks: Partial<PageCallbacks> = {};
|
||||
private _bashInstanceId: number;
|
||||
private _bashInstances: Bash[];
|
||||
private _callbacks: Partial<PageCallbacks> = {};
|
||||
public fileSystem: VirtualFS;
|
||||
public locale: ILocale;
|
||||
|
||||
constructor(args: TermInitArgs) {
|
||||
args.bash.stdio = this;
|
||||
this.bash = new Bash(args.bash);
|
||||
args.bash.io = this;
|
||||
this._bashInstanceId = 0;
|
||||
this._bashInstances = [];
|
||||
|
||||
this._initializeBashInstance(args.bash);
|
||||
|
||||
this.fileSystem = new VirtualFS({ fs: args.fs, bash: this._bashInstances[this._bashInstanceId] });
|
||||
this.locale = args.locale;
|
||||
|
||||
}
|
||||
|
||||
private _initializeBashInstance(init: BashInitArgs) {
|
||||
const instance: Bash = new Bash(init);
|
||||
this._bashInstances.push(instance);
|
||||
|
||||
}
|
||||
|
||||
private _parseInput(input: string): ParsedInput {
|
||||
@@ -89,47 +109,50 @@ export class Terminal {
|
||||
return result;
|
||||
}
|
||||
|
||||
throwExeption(message: string, exitCode: ExitCode) {
|
||||
console.error(message, exitCode);
|
||||
}
|
||||
|
||||
executeCommand(input: string): void {
|
||||
this.bash.updateHistory(input);
|
||||
this._bashInstances[this._bashInstanceId].updateHistory(input);
|
||||
const parsed: ParsedInput = this._parseInput(input);
|
||||
console.log(parsed, 'executeCommand output');
|
||||
this.bash.executeCommand(parsed.command, parsed.args);
|
||||
this._bashInstances[this._bashInstanceId].executeCommand(parsed.command, parsed.args);
|
||||
}
|
||||
|
||||
registerCallbacks(callbacks: PageCallbacks): void {
|
||||
this.callbacks = callbacks;
|
||||
this._callbacks = callbacks;
|
||||
}
|
||||
|
||||
clearTerminal() {
|
||||
this._callbacks.clear?.();
|
||||
}
|
||||
|
||||
getUser(): User {
|
||||
return this.bash.getUser();
|
||||
return this._bashInstances[this._bashInstanceId].getUser();
|
||||
}
|
||||
|
||||
getTerminalWidth(): number {
|
||||
const width = this.callbacks.getWidth?.();
|
||||
const width = this._callbacks.getWidth?.();
|
||||
if(!width) { throw new Error('somehow width is undefined still after all the checks'); }
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
getFontSize(): number {
|
||||
const size = this.callbacks.getFontSize?.();
|
||||
const size = this._callbacks.getFontSize?.();
|
||||
if(!size) { throw new Error('somehow font size is undefined still after all the checks'); }
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
getCwd(): string {
|
||||
const fs: VirtualFS = this.bash.getFs();
|
||||
console.log(fs.getPathByInode(this.bash.getCwd()));
|
||||
return fs.formatPath(fs.getPathByInode(this.bash.getCwd()));
|
||||
const fs: VirtualFS = this._bashInstances[this._bashInstanceId].getFs();
|
||||
console.log(fs.getPathByInode(this._bashInstances[this._bashInstanceId].getCwd()));
|
||||
return fs.formatPath(fs.getPathByInode(this._bashInstances[this._bashInstanceId].getCwd()));
|
||||
}
|
||||
|
||||
//TODO: Later reimplement the backend helper methods
|
||||
/* userLogin(username: string, passwd: string): ExitCode {
|
||||
return this.bash.userLogin(username, passwd);
|
||||
} */
|
||||
|
||||
PrintOutput(data: PrintData) {
|
||||
this.callbacks.print?.(data);
|
||||
this._callbacks.print?.(data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Languages, Settings2, SunMoon } from '@lucide/svelte';
|
||||
import { theme } from '$lib/stores/theme';
|
||||
import { locale } from '$lib/stores/lang';
|
||||
import plFlag from '$lib/assets/plFlag.svg';
|
||||
import enFlag from '$lib/assets/enFlag.svg';
|
||||
import deFlag from '$lib/assets/deFlag.svg';
|
||||
@@ -18,6 +19,10 @@
|
||||
const langsMenu = window.document.getElementById('langs-menu');
|
||||
langsMenu?.classList.toggle('hide');
|
||||
}
|
||||
|
||||
function setLang(id: string) {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
@@ -50,19 +55,21 @@
|
||||
<label
|
||||
class="border-primary-dark duration-100 hover:ml-1 hover:pl-1 has-checked:border-l-3 has-checked:hover:m-0 has-checked:hover:p-0 light:border-primary-light"
|
||||
>
|
||||
<input name="langs" type="radio" class="lang hidden" id="pl" autocomplete="off" />
|
||||
<input name="langs" type="radio" class="lang hidden" id="pl-PL" autocomplete="off" onclick={() => {console.log($locale)}}/>
|
||||
<img class="flags mx-2" src={plFlag} alt="PL" height="26" width="26" />
|
||||
</label>
|
||||
<label
|
||||
class="border-primary-dark duration-100 hover:ml-1 hover:pl-1 has-checked:border-l-3 has-checked:hover:m-0 has-checked:hover:p-0 light:border-primary-light"
|
||||
>
|
||||
<input name="langs" type="radio" class="lang hidden" id="en" autocomplete="off" />
|
||||
<input name="langs" type="radio" class="lang hidden" id="en-US" autocomplete="off" onclick={(id) => {
|
||||
console.log(id);
|
||||
}}/>
|
||||
<img class="flags mx-2" src={enFlag} alt="EN" height="26" width="26" />
|
||||
</label>
|
||||
<label
|
||||
class="border-primary-dark duration-100 hover:ml-1 hover:pl-1 has-checked:border-l-3 has-checked:hover:m-0 has-checked:hover:p-0 light:border-primary-light"
|
||||
>
|
||||
<input name="langs" type="radio" class="lang hidden" id="en" autocomplete="off" />
|
||||
<input name="langs" type="radio" class="lang hidden" id="fr-FR" autocomplete="off" />
|
||||
<img class="flags mx-2" src={deFlag} alt="DE" height="26" width="26" />
|
||||
</label>
|
||||
<label
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type { User } from '$lib/stores/bash/bash';
|
||||
import { Terminal, type PrintData } from '$lib/stores/terminal/terminal';
|
||||
import { onMount } from 'svelte';
|
||||
import Input from './terminal/Input.svelte';
|
||||
import { initTerminal, isInitializing } from '$lib/stores/terminal/init.svelte';
|
||||
import { clear, print } from '$lib/stores/terminal/stdio';
|
||||
import { clear, print } from '$lib/stores/terminal/stdio/io';
|
||||
import type { User } from '$lib/stores/bash/etc/userData';
|
||||
|
||||
const clearTerminal = (): void => clear();
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
return ctx.measureText('M').width;
|
||||
}
|
||||
|
||||
function handleInput(event: KeyboardEvent) {
|
||||
function inputHandler(event: KeyboardEvent) {
|
||||
switch (event.key) {
|
||||
case 'Enter': {
|
||||
terminal.executeCommand(inputValue);
|
||||
@@ -73,7 +73,7 @@
|
||||
if (!e) return;
|
||||
printOutput(e, data);
|
||||
},
|
||||
clear: clear,
|
||||
clear: clearTerminal,
|
||||
getWidth: getWidth,
|
||||
getFontSize: getFontSize
|
||||
};
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
onMount(async () => {
|
||||
try {
|
||||
terminal = await initTerminal(testUser, callbackInit);
|
||||
terminal = await initTerminal({ username: 'root', password: '123'}, callbackInit, 'en_US');
|
||||
updateTerminal();
|
||||
} catch (error) {
|
||||
console.error('onMount trycatch failed', error);
|
||||
@@ -105,7 +105,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<label for="input" onkeydowncapture={(e) => handleInput(e)} class="w-11/12">
|
||||
<label for="input" onkeydowncapture={(event) => inputHandler(event)} class="w-11/12">
|
||||
<div id="terminal" class="terminal-window shadow-() h-full w-full rounded-md shadow-bg">
|
||||
<div
|
||||
class="terminal-bar flex h-9 w-full flex-row items-center rounded-t-md bg-bg-dark text-center font-terminal text-sm font-bold text-primary-dark light:bg-bg-dark-light light:text-primary-light"
|
||||
|
||||
Reference in New Issue
Block a user