Skip to main content

vortex_tui/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! Vortex TUI library for interactively browsing and inspecting Vortex files.
5//!
6//! This crate provides both a CLI tool (`vx`) and a library API for working with Vortex files.
7//! Users can bring their own `VortexSession` to enable custom encodings and extensions.
8//!
9//! # Example
10//!
11//! ```ignore
12//! use vortex::session::VortexSession;
13//! use vortex::io::session::RuntimeSessionExt;
14//! use vortex_tui::browse;
15//!
16//! #[tokio::main]
17//! async fn main() -> anyhow::Result<()> {
18//!     let session = VortexSession::default().with_tokio();
19//!     browse::exec_tui(&session, "my_file.vortex").await?;
20//!     Ok(())
21//! }
22//! ```
23
24#![deny(clippy::missing_errors_doc)]
25#![deny(clippy::missing_panics_doc)]
26#![deny(clippy::missing_safety_doc)]
27#![deny(missing_docs)]
28
29#[cfg_attr(
30    all(not(feature = "native"), not(target_arch = "wasm32")),
31    allow(dead_code, unused_imports)
32)]
33pub mod browse;
34pub mod segment_tree;
35
36#[cfg(feature = "native")]
37pub mod convert;
38#[cfg(feature = "native")]
39pub mod datafusion_helper;
40#[cfg(feature = "native")]
41pub mod inspect;
42#[cfg(feature = "native")]
43pub mod query;
44#[cfg(feature = "native")]
45pub mod segments;
46#[cfg(feature = "native")]
47pub mod tree;
48
49#[cfg(target_arch = "wasm32")]
50pub mod wasm;
51
52#[cfg(feature = "native")]
53mod native_cli {
54    use std::ffi::OsString;
55    use std::path::PathBuf;
56
57    use clap::CommandFactory;
58    use clap::Parser;
59    use vortex::error::VortexExpect;
60    use vortex::session::VortexSession;
61
62    #[derive(clap::Parser)]
63    #[command(version)]
64    struct Cli {
65        #[clap(subcommand)]
66        command: Commands,
67    }
68
69    #[derive(Debug, clap::Subcommand)]
70    enum Commands {
71        /// Print tree views of a Vortex file (layout tree or array tree)
72        Tree(super::tree::TreeArgs),
73        /// Convert a Parquet file to a Vortex file. Chunking occurs on Parquet RowGroup boundaries.
74        Convert(#[command(flatten)] super::convert::ConvertArgs),
75        /// Interactively browse the Vortex file.
76        Browse { file: PathBuf },
77        /// Inspect Vortex file footer and metadata
78        Inspect(super::inspect::InspectArgs),
79        /// Execute a SQL query against a Vortex file using DataFusion
80        Query(super::query::QueryArgs),
81        /// Display segment information for a Vortex file
82        Segments(super::segments::SegmentsArgs),
83    }
84
85    impl Commands {
86        fn file_path(&self) -> &PathBuf {
87            match self {
88                Commands::Tree(args) => match &args.mode {
89                    super::tree::TreeMode::Array { file, .. } => file,
90                    super::tree::TreeMode::Layout { file, .. } => file,
91                },
92                Commands::Browse { file } => file,
93                Commands::Convert(flags) => &flags.file,
94                Commands::Inspect(args) => &args.file,
95                Commands::Query(args) => &args.file,
96                Commands::Segments(args) => &args.file,
97            }
98        }
99    }
100
101    /// Main entrypoint for `vx` that launches a [`VortexSession`].
102    ///
103    /// Parses arguments from [`std::env::args_os`]. See [`launch_from`] to supply explicit arguments.
104    ///
105    /// # Errors
106    ///
107    /// Raises any errors from subcommands.
108    pub async fn launch(session: &VortexSession) -> anyhow::Result<()> {
109        launch_from(session, std::env::args_os()).await
110    }
111
112    /// Launch `vx` with explicit command-line arguments.
113    ///
114    /// This is useful when embedding the TUI inside another process (e.g. Python) where
115    /// [`std::env::args`] may not reflect the intended arguments.
116    ///
117    /// # Errors
118    ///
119    /// Raises any errors from subcommands.
120    pub async fn launch_from(
121        session: &VortexSession,
122        args: impl IntoIterator<Item = impl Into<OsString> + Clone>,
123    ) -> anyhow::Result<()> {
124        let _ = env_logger::try_init();
125
126        let cli = Cli::parse_from(args);
127
128        let path = cli.command.file_path();
129        if !std::fs::exists(path)? {
130            Cli::command()
131                .error(
132                    clap::error::ErrorKind::Io,
133                    format!(
134                        "File '{}' does not exist.",
135                        path.to_str().vortex_expect("file path")
136                    ),
137                )
138                .exit()
139        }
140
141        match cli.command {
142            Commands::Tree(args) => super::tree::exec_tree(session, args).await?,
143            Commands::Convert(flags) => super::convert::exec_convert(session, flags).await?,
144            Commands::Browse { file } => super::browse::exec_tui(session, file).await?,
145            Commands::Inspect(args) => super::inspect::exec_inspect(session, args).await?,
146            Commands::Query(args) => super::query::exec_query(session, args).await?,
147            Commands::Segments(args) => super::segments::exec_segments(session, args).await?,
148        };
149
150        Ok(())
151    }
152}
153
154#[cfg(feature = "native")]
155pub use native_cli::launch;
156#[cfg(feature = "native")]
157pub use native_cli::launch_from;