nushell on your web browser
nushell wasm terminal

fix errors being eaten by table

ptr.pet 3984b06c 2ede1a12

verified
Changed files
+61 -22
src
+61 -22
src/lib.rs
··· 5 use nu_engine::{command_prelude::*, eval_block}; 6 use nu_parser::{FlatShape, TokenContents, flatten_block, lex, parse}; 7 use nu_protocol::{ 8 - Config, PipelineData, Span, 9 engine::{Call, EngineState, Stack, StateWorkingSet}, 10 }; 11 use serde::Serialize; 12 use std::{ 13 sync::{Arc, Mutex, OnceLock}, 14 time::UNIX_EPOCH, 15 }; ··· 146 ); 147 148 let mut working_set = StateWorkingSet::new(engine_state); 149 - 150 - // Capture the start offset *before* adding the file, as this is the global offset 151 - // where our file begins. 152 let start_offset = working_set.next_span_start(); 153 let block = parse(&mut working_set, Some("entry"), input.as_bytes(), false); 154 ··· 180 PipelineData::Empty, 181 ); 182 183 - let pipeline_data = result.map_err(cmd_err)?; 184 - let table_command = nu_command::Table; 185 let call = Call::new(pipeline_data.span().unwrap_or_else(Span::unknown)); 186 187 let res = table_command 188 - .run(engine_state, stack, &call, pipeline_data.body) 189 .map_err(cmd_err)?; 190 191 match res { ··· 195 } 196 PipelineData::ByteStream(s, _) => { 197 for line in s.lines().into_iter().flatten() { 198 - let out = line.map_err(|e| CommandError { 199 - error: Report::new(e), 200 - start_offset, 201 - })?; 202 print_to_console(&out, true); 203 } 204 } ··· 224 STACK.get().unwrap().lock().expect("stack initialized"), 225 ); 226 227 - let result = std::panic::catch_unwind(move || { 228 - match run_command_internal(&mut engine_guard, &mut stack_guard, input) { 229 - Ok(_) => None, 230 - Err(cmd_err) => Some(format_error( 231 - cmd_err.error, 232 - input.to_owned(), 233 - cmd_err.start_offset, 234 - )), 235 - } 236 - }); 237 - result.unwrap_or_else(|err| Some(format!("panicked: {err:?}"))) 238 } 239 240 #[wasm_bindgen]
··· 5 use nu_engine::{command_prelude::*, eval_block}; 6 use nu_parser::{FlatShape, TokenContents, flatten_block, lex, parse}; 7 use nu_protocol::{ 8 + Config, ListStream, PipelineData, Span, 9 engine::{Call, EngineState, Stack, StateWorkingSet}, 10 }; 11 use serde::Serialize; 12 use std::{ 13 + io::Cursor, 14 sync::{Arc, Mutex, OnceLock}, 15 time::UNIX_EPOCH, 16 }; ··· 147 ); 148 149 let mut working_set = StateWorkingSet::new(engine_state); 150 let start_offset = working_set.next_span_start(); 151 let block = parse(&mut working_set, Some("entry"), input.as_bytes(), false); 152 ··· 178 PipelineData::Empty, 179 ); 180 181 + let pipeline_data = result.map_err(cmd_err)?.body; 182 + let signals = engine_state.signals().clone(); 183 + 184 + // this is annoying but we have to collect here so we can uncover errors 185 + // before passing the data off to Table, because otherwise Table 186 + // can't properly handle the errors and panics (something about ShellErrorBridge 187 + // having a non IO error in it somehow idk i dont care really) 188 + // TODO: see if there is a way to do this without collecting the pipeline 189 + let pipeline_data = match pipeline_data { 190 + PipelineData::Empty => return Ok(()), 191 + PipelineData::Value(Value::Error { error, .. }, _) => { 192 + return Err(cmd_err(*error)); 193 + } 194 + PipelineData::ByteStream(s, m) => match (s.span(), s.type_(), s.reader()) { 195 + (span, ty, Some(r)) => { 196 + use std::io::Read; 197 + let v = r 198 + .bytes() 199 + .collect::<Result<Vec<u8>, _>>() 200 + .map_err(|e| cmd_err(ShellError::Io(IoError::new(e, span, None))))?; 201 + (v.len() > 0) 202 + .then(|| { 203 + PipelineData::byte_stream( 204 + ByteStream::read(Cursor::new(v), span, signals, ty), 205 + m, 206 + ) 207 + }) 208 + .unwrap_or(PipelineData::Empty) 209 + } 210 + (_, _, None) => PipelineData::Empty, 211 + }, 212 + PipelineData::ListStream(s, m) => { 213 + let span = s.span(); 214 + let v = s 215 + .into_iter() 216 + .map(|val| val.unwrap_error().map_err(cmd_err)) 217 + .collect::<Result<Vec<Value>, _>>()?; 218 + PipelineData::list_stream(ListStream::new(v.into_iter(), span, signals), m) 219 + } 220 + x => x, 221 + }; 222 + 223 + // TODO: idk what this does i copied it from PipelineData::print_table 224 + // dunno if it matters, we can just use nu_command::Table and it works fine i think 225 + let table_command = engine_state 226 + .table_decl_id 227 + .map(|decl_id| engine_state.get_decl(decl_id)) 228 + .filter(|command| command.block_id().is_some()) 229 + .unwrap_or(&nu_command::Table); 230 let call = Call::new(pipeline_data.span().unwrap_or_else(Span::unknown)); 231 232 let res = table_command 233 + .run(engine_state, stack, &call, pipeline_data) 234 .map_err(cmd_err)?; 235 236 match res { ··· 240 } 241 PipelineData::ByteStream(s, _) => { 242 for line in s.lines().into_iter().flatten() { 243 + let out = line.map_err(cmd_err)?; // TODO: do we turn this into a Value ??? or is returning err fine 244 print_to_console(&out, true); 245 } 246 } ··· 266 STACK.get().unwrap().lock().expect("stack initialized"), 267 ); 268 269 + match run_command_internal(&mut engine_guard, &mut stack_guard, input) { 270 + Ok(_) => None, 271 + Err(cmd_err) => Some(format_error( 272 + cmd_err.error, 273 + input.to_owned(), 274 + cmd_err.start_offset, 275 + )), 276 + } 277 } 278 279 #[wasm_bindgen]