diff --git a/js/views/editor/editor.ts b/js/views/editor/editor.ts index d7bf865..9c70ee0 100644 --- a/js/views/editor/editor.ts +++ b/js/views/editor/editor.ts @@ -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('#dbstdout') + if (stdout) { + this.output.display({}, { + stdout: stdout.value, + stderr: document.querySelector('#dbstderr').value, + status: +document.querySelector('#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('#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) } diff --git a/js/views/editor/output.ts b/js/views/editor/output.ts index 89481a4..f350f35 100644 --- a/js/views/editor/output.ts +++ b/js/views/editor/output.ts @@ -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 = '' } diff --git a/migrations/2019-11-23-192058_store-program-input-output/down.sql b/migrations/2019-11-23-192058_store-program-input-output/down.sql new file mode 100644 index 0000000..380e176 --- /dev/null +++ b/migrations/2019-11-23-192058_store-program-input-output/down.sql @@ -0,0 +1,5 @@ +ALTER TABLE pastes + DROP COLUMN stdin, + DROP COLUMN exit_code, + DROP COLUMN stdout, + DROP COLUMN stderr; diff --git a/migrations/2019-11-23-192058_store-program-input-output/up.sql b/migrations/2019-11-23-192058_store-program-input-output/up.sql new file mode 100644 index 0000000..ef6f4f6 --- /dev/null +++ b/migrations/2019-11-23-192058_store-program-input-output/up.sql @@ -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; diff --git a/package-lock.json b/package-lock.json index fdb15e8..4968521 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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": { diff --git a/package.json b/package.json index f95f1b7..c08654b 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/src/models/paste.rs b/src/models/paste.rs index f3b7ea6..4030532 100644 --- a/src/models/paste.rs +++ b/src/models/paste.rs @@ -18,6 +18,10 @@ pub struct Paste { pub language_id: i32, pub delete_at: Option>, pub identifier: String, + pub stdin: String, + pub exit_code: Option, + pub stdout: Option, + pub stderr: Option, } impl Paste { @@ -42,6 +46,10 @@ struct InsertPaste { delete_at: Option>, language_id: i32, paste: String, + stdin: String, + stdout: Option, + stderr: Option, + exit_code: Option, } pub fn insert( @@ -49,6 +57,10 @@ pub fn insert( delete_at: Option>, language: &str, paste: String, + stdin: String, + stdout: Option, + stderr: Option, + exit_code: Option, ) -> Result { 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>, pub markdown: String, + pub stdin: String, + pub exit_code: Option, + pub stdout: Option, + pub stderr: Option, } 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, } } } diff --git a/src/routes/api_v1/pastes.rs b/src/routes/api_v1/pastes.rs index 1a49d21..cba54c1 100644 --- a/src/routes/api_v1/pastes.rs +++ b/src/routes/api_v1/pastes.rs @@ -69,6 +69,10 @@ pub fn insert_paste( expiration.map(|expiration| Utc::now() + expiration.0), &language, code, + "".into(), + None, + None, + None, ) }) .compat() diff --git a/src/routes/display_paste.rs b/src/routes/display_paste.rs index ddf4019..5c1d8a4 100644 --- a/src/routes/display_paste.rs +++ b/src/routes/display_paste.rs @@ -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) diff --git a/src/routes/insert_paste.rs b/src/routes/insert_paste.rs index 1aeb264..8cd3195 100644 --- a/src/routes/insert_paste.rs +++ b/src/routes/insert_paste.rs @@ -15,6 +15,11 @@ pub struct PasteForm { language: String, code: String, autodelete: Option, + #[serde(default)] + stdin: String, + stdout: Option, + stderr: Option, + status: Option, } pub fn insert_paste( @@ -22,12 +27,25 @@ pub fn insert_paste( language, code, autodelete, + stdin, + stdout, + stderr, + status, }: PasteForm, connection: Connection, ) -> impl Future { 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, diff --git a/src/schema.rs b/src/schema.rs index 4e33a01..14ed564 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -37,6 +37,10 @@ table! { created_at -> Timestamptz, language_id -> Int4, paste -> Text, + stdin -> Text, + exit_code -> Nullable, + stdout -> Nullable, + stderr -> Nullable, } } diff --git a/static/style.css b/static/style.css index fd60e80..816d82f 100644 --- a/static/style.css +++ b/static/style.css @@ -47,6 +47,9 @@ textarea { height: 372px; resize: vertical; } +[name=stdin] { + height: 124px; +} #right-buttons { float: right; } diff --git a/templates/display_paste.rs.html b/templates/display_paste.rs.html index 8fae668..ee82b81 100644 --- a/templates/display_paste.rs.html +++ b/templates/display_paste.rs.html @@ -22,4 +22,14 @@

@:buttons() + +@if let Some(exit_code) = paste.exit_code { + +} +@if let Some(stdout) = paste.stdout { + +} +@if let Some(stderr) = paste.stderr { + +} @:footer(session)