Store program output
This commit is contained in:
parent
b3a473bef7
commit
1bb1782eea
|
@ -18,7 +18,7 @@ class Editor {
|
|||
currentLanguage: string | null = null
|
||||
abortEval: AbortController | null = null
|
||||
|
||||
async initialize(form) {
|
||||
initialize(form) {
|
||||
this.languageSelector = form.querySelector('#language')
|
||||
this.wrapperButtons = new WrapperButtons(form.querySelector('#wrapper-buttons'), this.run.bind(this))
|
||||
this.codeElement = form.querySelector('#code')
|
||||
|
@ -26,16 +26,45 @@ class Editor {
|
|||
onChange(editor => this.changeEditor(editor))
|
||||
this.initConfiguredEditor()
|
||||
this.output = new Output(form.querySelector('#output'))
|
||||
const stdout = document.querySelector<HTMLInputElement>('#dbstdout')
|
||||
if (stdout) {
|
||||
this.output.display({}, {
|
||||
stdout: stdout.value,
|
||||
stderr: document.querySelector<HTMLInputElement>('#dbstderr').value,
|
||||
status: +document.querySelector<HTMLInputElement>('#dbstatus')?.value,
|
||||
})
|
||||
}
|
||||
this.autodeleteText = form.querySelector('#autodelete-text')
|
||||
this.autodeleteCheckbox = form.querySelector('#automatically-hidden-label')
|
||||
this.submit = form.querySelector('[type=submit]')
|
||||
this.submit.disabled = true
|
||||
form.addEventListener('submit', () => {
|
||||
if (this.output.json && !this.output.wrapper.isFormatter) {
|
||||
for (const name of ['stdout', 'stderr', 'status']) {
|
||||
const elem = form.querySelector(`#${name}`) || document.createElement('input')
|
||||
elem.type = 'hidden'
|
||||
elem.name = name
|
||||
elem.value = this.output.json[name]
|
||||
form.append(elem)
|
||||
}
|
||||
} else {
|
||||
this.stdinElement.value = ''
|
||||
}
|
||||
})
|
||||
this.detailsElement = document.createElement('details')
|
||||
const summary = document.createElement('summary')
|
||||
summary.textContent = 'Standard input'
|
||||
this.stdinElement = document.createElement('textarea')
|
||||
this.stdinElement.name = 'stdin'
|
||||
this.stdinElement.addEventListener('change', () => this.changeToLookLikeNewPaste())
|
||||
this.detailsElement.append(summary, this.stdinElement)
|
||||
this.detailsElement.style.display = 'none'
|
||||
const dbStdin = document.querySelector<HTMLInputElement>('#dbstdin')?.value
|
||||
if (dbStdin) {
|
||||
this.stdinElement.value = dbStdin
|
||||
this.detailsElement.open = true
|
||||
} else {
|
||||
this.detailsElement.style.display = 'none'
|
||||
}
|
||||
form.querySelector('#buttons').append(this.detailsElement)
|
||||
if (this.autodeleteText) {
|
||||
this.autodeleteCheckbox.style.display = 'none'
|
||||
|
@ -71,6 +100,7 @@ class Editor {
|
|||
this.autodeleteCheckbox.style.display = ''
|
||||
}
|
||||
this.submit.disabled = false
|
||||
this.output.clear()
|
||||
}
|
||||
|
||||
assignEvents() {
|
||||
|
@ -134,5 +164,5 @@ class Editor {
|
|||
}
|
||||
|
||||
export default function createEditor(form) {
|
||||
return new Editor().initialize(form)
|
||||
new Editor().initialize(form)
|
||||
}
|
||||
|
|
|
@ -4,19 +4,13 @@ const filterRegex = /(?:\t\.(?:text|file|section|globl|p2align|type|cfi_.*|size|
|
|||
|
||||
export default class Output {
|
||||
output: HTMLDivElement
|
||||
filterAsm: HTMLLabelElement
|
||||
filterAsmCheckbox: HTMLInputElement
|
||||
wrapper: Wrapper
|
||||
json: {
|
||||
stdout: string,
|
||||
stderr: string,
|
||||
status: number | null,
|
||||
}
|
||||
filterAsm = document.createElement('label')
|
||||
filterAsmCheckbox = document.createElement('input')
|
||||
wrapper: Wrapper | null = null
|
||||
json: { stdout: string, stderr: string, status: number | null } | null = null
|
||||
|
||||
constructor(output) {
|
||||
this.output = output
|
||||
this.filterAsm = document.createElement('label')
|
||||
this.filterAsmCheckbox = document.createElement('input')
|
||||
this.filterAsmCheckbox.type = 'checkbox'
|
||||
this.filterAsmCheckbox.checked = true
|
||||
this.filterAsmCheckbox.addEventListener('change', () => this.update())
|
||||
|
@ -24,6 +18,7 @@ export default class Output {
|
|||
}
|
||||
|
||||
clear() {
|
||||
this.json = null
|
||||
this.output.textContent = ''
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE pastes
|
||||
DROP COLUMN stdin,
|
||||
DROP COLUMN exit_code,
|
||||
DROP COLUMN stdout,
|
||||
DROP COLUMN stderr;
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE pastes
|
||||
ADD COLUMN stdin text NOT NULL DEFAULT '',
|
||||
ADD COLUMN exit_code integer,
|
||||
ADD COLUMN stdout text,
|
||||
ADD COLUMN stderr text;
|
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -4061,9 +4061,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.6.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.4.tgz",
|
||||
"integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==",
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz",
|
||||
"integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==",
|
||||
"dev": true
|
||||
},
|
||||
"union-value": {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"prismjs": "^1.17.1",
|
||||
"style-loader": "^1.0.0",
|
||||
"ts-loader": "^6.2.0",
|
||||
"typescript": "^3.6.4",
|
||||
"typescript": "^3.7.2",
|
||||
"webpack": "^4.40.2",
|
||||
"webpack-cli": "^3.3.9",
|
||||
"webpack-stats-plugin": "^0.3.0"
|
||||
|
|
|
@ -18,6 +18,10 @@ pub struct Paste {
|
|||
pub language_id: i32,
|
||||
pub delete_at: Option<DateTime<Utc>>,
|
||||
pub identifier: String,
|
||||
pub stdin: String,
|
||||
pub exit_code: Option<i32>,
|
||||
pub stdout: Option<String>,
|
||||
pub stderr: Option<String>,
|
||||
}
|
||||
|
||||
impl Paste {
|
||||
|
@ -42,6 +46,10 @@ struct InsertPaste {
|
|||
delete_at: Option<DateTime<Utc>>,
|
||||
language_id: i32,
|
||||
paste: String,
|
||||
stdin: String,
|
||||
stdout: Option<String>,
|
||||
stderr: Option<String>,
|
||||
exit_code: Option<i32>,
|
||||
}
|
||||
|
||||
pub fn insert(
|
||||
|
@ -49,6 +57,10 @@ pub fn insert(
|
|||
delete_at: Option<DateTime<Utc>>,
|
||||
language: &str,
|
||||
paste: String,
|
||||
stdin: String,
|
||||
stdout: Option<String>,
|
||||
stderr: Option<String>,
|
||||
exit_code: Option<i32>,
|
||||
) -> Result<String, Rejection> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let identifier: String = (0..10)
|
||||
|
@ -66,6 +78,10 @@ pub fn insert(
|
|||
delete_at,
|
||||
language_id,
|
||||
paste,
|
||||
stdin,
|
||||
stdout,
|
||||
stderr,
|
||||
exit_code,
|
||||
};
|
||||
diesel::insert_into(pastes::table)
|
||||
.values(&insert_paste)
|
||||
|
@ -79,6 +95,10 @@ pub struct ExternPaste {
|
|||
pub language_id: i32,
|
||||
pub delete_at: Option<DateTime<Utc>>,
|
||||
pub markdown: String,
|
||||
pub stdin: String,
|
||||
pub exit_code: Option<i32>,
|
||||
pub stdout: Option<String>,
|
||||
pub stderr: Option<String>,
|
||||
}
|
||||
|
||||
impl ExternPaste {
|
||||
|
@ -88,6 +108,10 @@ impl ExternPaste {
|
|||
language_id,
|
||||
identifier,
|
||||
delete_at,
|
||||
stdin,
|
||||
exit_code,
|
||||
stdout,
|
||||
stderr,
|
||||
} = paste;
|
||||
let markdown = if identifier == "markdown" {
|
||||
render_markdown(&paste)
|
||||
|
@ -99,6 +123,10 @@ impl ExternPaste {
|
|||
language_id,
|
||||
delete_at,
|
||||
markdown,
|
||||
stdin,
|
||||
exit_code,
|
||||
stdout,
|
||||
stderr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,10 @@ pub fn insert_paste(
|
|||
expiration.map(|expiration| Utc::now() + expiration.0),
|
||||
&language,
|
||||
code,
|
||||
"".into(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
})
|
||||
.compat()
|
||||
|
|
|
@ -24,6 +24,10 @@ pub fn display_paste(
|
|||
pastes::language_id,
|
||||
pastes::delete_at,
|
||||
languages::identifier,
|
||||
pastes::stdin,
|
||||
pastes::exit_code,
|
||||
pastes::stdout,
|
||||
pastes::stderr,
|
||||
))
|
||||
.filter(pastes::identifier.eq(requested_identifier))
|
||||
.get_result(connection)
|
||||
|
|
|
@ -15,6 +15,11 @@ pub struct PasteForm {
|
|||
language: String,
|
||||
code: String,
|
||||
autodelete: Option<IgnoredAny>,
|
||||
#[serde(default)]
|
||||
stdin: String,
|
||||
stdout: Option<String>,
|
||||
stderr: Option<String>,
|
||||
status: Option<i32>,
|
||||
}
|
||||
|
||||
pub fn insert_paste(
|
||||
|
@ -22,12 +27,25 @@ pub fn insert_paste(
|
|||
language,
|
||||
code,
|
||||
autodelete,
|
||||
stdin,
|
||||
stdout,
|
||||
stderr,
|
||||
status,
|
||||
}: PasteForm,
|
||||
connection: Connection,
|
||||
) -> impl Future<Item = impl Reply, Error = Rejection> {
|
||||
blocking::run(move || {
|
||||
let delete_at = autodelete.map(|_| Utc::now() + Duration::hours(24));
|
||||
let identifier = paste::insert(&connection, delete_at, &language, code)?;
|
||||
let identifier = paste::insert(
|
||||
&connection,
|
||||
delete_at,
|
||||
&language,
|
||||
code,
|
||||
stdin,
|
||||
stdout,
|
||||
stderr,
|
||||
status,
|
||||
)?;
|
||||
Ok(reply::with_header(
|
||||
StatusCode::SEE_OTHER,
|
||||
LOCATION,
|
||||
|
|
|
@ -37,6 +37,10 @@ table! {
|
|||
created_at -> Timestamptz,
|
||||
language_id -> Int4,
|
||||
paste -> Text,
|
||||
stdin -> Text,
|
||||
exit_code -> Nullable<Int4>,
|
||||
stdout -> Nullable<Text>,
|
||||
stderr -> Nullable<Text>,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ textarea {
|
|||
height: 372px;
|
||||
resize: vertical;
|
||||
}
|
||||
[name=stdin] {
|
||||
height: 124px;
|
||||
}
|
||||
#right-buttons {
|
||||
float: right;
|
||||
}
|
||||
|
|
|
@ -22,4 +22,14 @@
|
|||
<p><textarea id=code name=code>@('\n')@paste.paste</textarea></p>
|
||||
@:buttons()
|
||||
</form>
|
||||
<input type=hidden id=dbstdin value="@paste.stdin">
|
||||
@if let Some(exit_code) = paste.exit_code {
|
||||
<input type=hidden id=dbstatus value="@exit_code">
|
||||
}
|
||||
@if let Some(stdout) = paste.stdout {
|
||||
<input type=hidden id=dbstdout value="@stdout">
|
||||
}
|
||||
@if let Some(stderr) = paste.stderr {
|
||||
<input type=hidden id=dbstderr value="@stderr">
|
||||
}
|
||||
@:footer(session)
|
||||
|
|
Loading…
Reference in New Issue
Block a user