Add option to export to stdout
This commit is contained in:
parent
0ceaffc608
commit
ca10ca277b
4 changed files with 47 additions and 40 deletions
|
|
@ -17,6 +17,7 @@ Procedure when bumping the version number:
|
|||
### Added
|
||||
- `--verbose` flag
|
||||
- `json-stream` room export format
|
||||
- Option to export to stdout
|
||||
|
||||
### Changed
|
||||
- Respect colon-delimited emoji when calculating nick hue
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ mod json;
|
|||
mod text;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::io::{self, BufWriter, Write};
|
||||
|
||||
use crate::vault::EuphVault;
|
||||
use crate::vault::{EuphRoomVault, EuphVault};
|
||||
|
||||
#[derive(Debug, Clone, Copy, clap::ValueEnum)]
|
||||
pub enum Format {
|
||||
|
|
@ -57,12 +57,28 @@ pub struct Args {
|
|||
/// If the value ends with a `/`, it is assumed to point to a directory and
|
||||
/// `%r.%e` will be appended.
|
||||
///
|
||||
/// If the value is a literal `-`, the export will be written to stdout. To
|
||||
/// write to a file named `-`, you can use `./-`.
|
||||
///
|
||||
/// Must be a valid utf-8 encoded string.
|
||||
#[arg(long, short, default_value_t = Into::into("%r.%e"))]
|
||||
#[arg(verbatim_doc_comment)]
|
||||
out: String,
|
||||
}
|
||||
|
||||
async fn export_room<W: Write>(
|
||||
vault: &EuphRoomVault,
|
||||
out: &mut W,
|
||||
format: Format,
|
||||
) -> anyhow::Result<()> {
|
||||
match format {
|
||||
Format::Text => text::export(vault, out).await?,
|
||||
Format::Json => json::export(vault, out).await?,
|
||||
Format::JsonStream => json::export_stream(vault, out).await?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn export(vault: &EuphVault, mut args: Args) -> anyhow::Result<()> {
|
||||
if args.out.ends_with('/') {
|
||||
args.out.push_str("%r.%e");
|
||||
|
|
@ -79,21 +95,24 @@ pub async fn export(vault: &EuphVault, mut args: Args) -> anyhow::Result<()> {
|
|||
};
|
||||
|
||||
if rooms.is_empty() {
|
||||
println!("No rooms to export");
|
||||
eprintln!("No rooms to export");
|
||||
}
|
||||
|
||||
for room in rooms {
|
||||
let out = format_out(&args.out, &room, args.format);
|
||||
println!("Exporting &{room} as {} to {out}", args.format.name());
|
||||
|
||||
let vault = vault.room(room);
|
||||
let mut file = BufWriter::new(File::create(out)?);
|
||||
match args.format {
|
||||
Format::Text => text::export_to_file(&vault, &mut file).await?,
|
||||
Format::Json => json::export_to_file(&vault, &mut file).await?,
|
||||
Format::JsonStream => json::export_stream_to_file(&vault, &mut file).await?,
|
||||
if args.out == "-" {
|
||||
eprintln!("Exporting &{room} as {} to stdout", args.format.name());
|
||||
let vault = vault.room(room);
|
||||
let mut stdout = BufWriter::new(io::stdout());
|
||||
export_room(&vault, &mut stdout, args.format).await?;
|
||||
stdout.flush()?;
|
||||
} else {
|
||||
let out = format_out(&args.out, &room, args.format);
|
||||
eprintln!("Exporting &{room} as {} to {out}", args.format.name());
|
||||
let vault = vault.room(room);
|
||||
let mut file = BufWriter::new(File::create(out)?);
|
||||
export_room(&vault, &mut file, args.format).await?;
|
||||
file.flush()?;
|
||||
}
|
||||
file.flush()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
use std::fs::File;
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::io::Write;
|
||||
|
||||
use crate::vault::EuphRoomVault;
|
||||
|
||||
const CHUNK_SIZE: usize = 10000;
|
||||
|
||||
pub async fn export_to_file(
|
||||
vault: &EuphRoomVault,
|
||||
file: &mut BufWriter<File>,
|
||||
) -> anyhow::Result<()> {
|
||||
pub async fn export<W: Write>(vault: &EuphRoomVault, file: &mut W) -> anyhow::Result<()> {
|
||||
write!(file, "[")?;
|
||||
|
||||
let mut total = 0;
|
||||
|
|
@ -39,14 +35,10 @@ pub async fn export_to_file(
|
|||
write!(file, "\n]")?;
|
||||
|
||||
println!(" {total} messages in total");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn export_stream_to_file(
|
||||
vault: &EuphRoomVault,
|
||||
file: &mut BufWriter<File>,
|
||||
) -> anyhow::Result<()> {
|
||||
pub async fn export_stream<W: Write>(vault: &EuphRoomVault, file: &mut W) -> anyhow::Result<()> {
|
||||
let mut total = 0;
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
|
|
@ -69,6 +61,5 @@ pub async fn export_stream_to_file(
|
|||
}
|
||||
|
||||
println!(" {total} messages in total");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use std::fs::File;
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::io::Write;
|
||||
|
||||
use euphoxide::api::MessageId;
|
||||
use time::format_description::FormatItem;
|
||||
|
|
@ -14,16 +13,13 @@ const TIME_FORMAT: &[FormatItem<'_>] =
|
|||
format_description!("[year]-[month]-[day] [hour]:[minute]:[second]");
|
||||
const TIME_EMPTY: &str = " ";
|
||||
|
||||
pub async fn export_to_file(
|
||||
vault: &EuphRoomVault,
|
||||
file: &mut BufWriter<File>,
|
||||
) -> anyhow::Result<()> {
|
||||
pub async fn export<W: Write>(vault: &EuphRoomVault, out: &mut W) -> anyhow::Result<()> {
|
||||
let mut exported_trees = 0;
|
||||
let mut exported_msgs = 0;
|
||||
let mut root_id = vault.first_root_id().await;
|
||||
while let Some(some_root_id) = root_id {
|
||||
let tree = vault.tree(some_root_id).await;
|
||||
write_tree(file, &tree, some_root_id, 0)?;
|
||||
write_tree(out, &tree, some_root_id, 0)?;
|
||||
root_id = vault.next_root_id(some_root_id).await;
|
||||
|
||||
exported_trees += 1;
|
||||
|
|
@ -38,8 +34,8 @@ pub async fn export_to_file(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_tree(
|
||||
file: &mut BufWriter<File>,
|
||||
fn write_tree<W: Write>(
|
||||
out: &mut W,
|
||||
tree: &Tree<SmallMessage>,
|
||||
id: MessageId,
|
||||
indent: usize,
|
||||
|
|
@ -47,22 +43,22 @@ fn write_tree(
|
|||
let indent_string = "| ".repeat(indent);
|
||||
|
||||
if let Some(msg) = tree.msg(&id) {
|
||||
write_msg(file, &indent_string, msg)?;
|
||||
write_msg(out, &indent_string, msg)?;
|
||||
} else {
|
||||
write_placeholder(file, &indent_string)?;
|
||||
write_placeholder(out, &indent_string)?;
|
||||
}
|
||||
|
||||
if let Some(children) = tree.children(&id) {
|
||||
for child in children {
|
||||
write_tree(file, tree, *child, indent + 1)?;
|
||||
write_tree(out, tree, *child, indent + 1)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_msg(
|
||||
file: &mut BufWriter<File>,
|
||||
fn write_msg<W: Write>(
|
||||
file: &mut W,
|
||||
indent_string: &str,
|
||||
msg: &SmallMessage,
|
||||
) -> anyhow::Result<()> {
|
||||
|
|
@ -85,7 +81,7 @@ fn write_msg(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_placeholder(file: &mut BufWriter<File>, indent_string: &str) -> anyhow::Result<()> {
|
||||
fn write_placeholder<W: Write>(file: &mut W, indent_string: &str) -> anyhow::Result<()> {
|
||||
writeln!(file, "{TIME_EMPTY} {indent_string}[...]")?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue