CSV
CSV in and out: rows as maps keyed by the header, with quotes, commas and line breaks in cells handled.
Version 1.0.0 · 4 functions · 1 crate
Functions
What use csv.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use csv_parse, csv_read_file from csv (Quillo 0.6).
csv_parse(text: str) → listor an errorCSV text as a list of maps, keyed by the first row. Cells are text; rows may be short.
csv_read_file(path: str) → listor an errorA CSV file as a list of maps, read straight from the disk: for exports too big to read as text first.
csv_rows(text: str, delimiter: str) → listor an errorCSV text as lists of cells, the first row too; delimiter is one character: ",", ";", "\t" or "|".
csv_write(rows: list, columns: list) → stror an errorMaps as CSV text: columns are the header and the order. null is an empty cell; lists and maps are written as JSON.
Get it
$ quillo install csv # csv.qwer into this folder$ quillo install csv --example # and its example, csv.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/csv.qwer$ curl -O https://quillolang.org/plugins/files/csv.qweThen, in your program, all of it or only what you call:
use csv.qweruse csv_parse, csv_read_file from csv // Quillo 0.6: only theseIt uses this crate, which cargo fetches the first time the plugin is built:
csv = "1"Example
// A CSV export, and an import that reads it back.//// quillo run csv.qwe then open http://localhost:8080/orders.csvuse "csv.qwer"let orders = [ { id: 1, customer: "Ada Lovelace", total: 120.5, note: "gift, wrap it" }, { id: 2, customer: "Grace \"Amazing\" Hopper", total: 99, note: null },]route GET /orders.csv = respond(200, csv_write(orders, ["id", "customer", "total", "note"])?, { "content-type": "text/csv; charset=utf-8", "content-disposition": "attachment; filename=orders.csv" })route GET /import { let rows = csv_parse(csv_write(orders, ["id", "customer", "total", "note"])?)? rows | map((r) => { id: int(r.id), customer: r.customer, total: float(r.total) })}$ quillo run csv.qwe$ curl 'localhost:8080/orders.csv'$ curl 'localhost:8080/import'Source
//! CSV in and out: rows as maps keyed by the header, quotes, commas and line breaks in cells handled.//! version: 1.0.0//!//! [dependencies]//! csv = "1"use serde_json::Value;use std::collections::HashMap;fn maps<R: std::io::Read>(mut r: csv::Reader<R>) -> Result<Vec<HashMap<String, String>>, String> { let headers: Vec<String> = r.headers().map_err(|e| e.to_string())?.iter().map(|h| h.trim().to_string()).collect(); let mut out = Vec::new(); for rec in r.records() { let rec = rec.map_err(|e| e.to_string())?; out.push(headers.iter().cloned().zip(rec.iter().map(str::to_string)).collect()); } Ok(out)}fn delim(d: &str) -> Result<u8, String> { match d.as_bytes() { [b] => Ok(*b), _ => Err(format!("the delimiter is one character, not `{}`", d)), }}/// CSV text as a list of maps, keyed by the first row. Cells are text; rows may be short.pub fn csv_parse(text: &str) -> Result<Vec<HashMap<String, String>>, String> { maps(csv::ReaderBuilder::new().flexible(true).from_reader(text.as_bytes()))}/// A CSV file as a list of maps, read straight from the disk: for exports too big to read as text first.pub fn csv_read_file(path: &str) -> Result<Vec<HashMap<String, String>>, String> { maps(csv::ReaderBuilder::new().flexible(true).from_path(path).map_err(|e| format!("{}: {}", path, e))?)}/// CSV text as lists of cells, the first row too; `delimiter` is one character: ",", ";", "\t" or "|".pub fn csv_rows(text: &str, delimiter: &str) -> Result<Vec<Vec<String>>, String> { let mut r = csv::ReaderBuilder::new().has_headers(false).flexible(true).delimiter(delim(delimiter)?).from_reader(text.as_bytes()); r.records().map(|rec| rec.map(|r| r.iter().map(str::to_string).collect()).map_err(|e| e.to_string())).collect()}fn cell(v: Option<&Value>) -> String { match v { None | Some(Value::Null) => String::new(), Some(Value::String(s)) => s.clone(), Some(v) => v.to_string(), }}/// Maps as CSV text: `columns` are the header and the order. `null` is an empty cell; lists and maps are written as JSON.pub fn csv_write(rows: Vec<std::collections::HashMap<String, serde_json::Value>>, columns: Vec<String>) -> Result<String, String> { let mut w = csv::Writer::from_writer(Vec::new()); w.write_record(&columns).map_err(|e| e.to_string())?; for row in &rows { w.write_record(columns.iter().map(|c| cell(row.get(c)))).map_err(|e| e.to_string())?; } String::from_utf8(w.into_inner().map_err(|e| e.to_string())?).map_err(|e| e.to_string())}Related
csv_sniff.qwer · 1.0.0Guess how an uploaded CSV is written before importing it: delimiter, quote, header row, decimal commas and line endings.9 views · 7 downloadsAvro avro.qwer · 1.0.0Apache Avro data files: rows written with a schema, as Kafka, Hadoop and BigQuery use, and read back with the schema they carry.9 views · 6 downloadsBibTeX bibtex.qwer · 1.0.0BibTeX and BibLaTeX bibliographies read, with LaTeX accents and macros resolved; reference lists in APA or IEEE style, CSL-JSON for Zotero and pandoc, and entries written back.7 views · 6 downloadsFixed width fixed_width.qwer · 1.0.0Fixed-width records read and written from a column spec: bank payment files, payroll exports and mainframe formats.8 views · 8 downloadsINI ini.qwer · 1.0.0INI files read and written, sections and keys: php.ini, setup.cfg, .gitconfig and the settings of older software.8 views · 7 downloadsJSON Lines ndjson.qwer · 1.0.0JSON Lines (NDJSON) read a page at a time from files of any size, searched by field, appended to and written: logs, exports and imports.7 views · 6 downloadsThread 0 posts
On CSV: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.