LCOV - code coverage report
Current view: top level - dashql-core-shell/src - lib.rs Coverage Total Hit
Test: DashQL d805a4b Lines: 87.5 % 16 14
Test Date: 2026-11-09 20:22:13

            Line data    Source code
       1              : //! The DashQL shell: a readline-like prompt with SQL highlighting and completion, a VT100
       2              : //! terminal renderer, and the execution protocol of queries and dot commands.
       3              : //!
       4              : //! Queries and commands are pending effects: starting an operation returns
       5              : //! [`ShellStatus::Pending`] with an effect envelope (version, type, id, payload), and the host
       6              : //! completes or cancels the effect by id, which yields the rendered output.
       7              : //!
       8              : //! The session does not own its catalog, operations that read it take `&Catalog` (see [`ShellSession`]).
       9              : //!
      10              : //! Inputs that must be valid UTF-8 are byte slices so that invalid input is reported as an error,
      11              : //! and outputs are terminal bytes.
      12              : 
      13              : pub mod prompt_buffer;
      14              : mod session;
      15              : pub mod unicode;
      16              : pub mod vt100;
      17              : 
      18              : pub use prompt_buffer::PromptBuffer;
      19              : pub use session::ShellSession;
      20              : 
      21              : /// The status of a shell operation
      22              : #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
      23              : #[repr(u32)]
      24              : pub enum ShellStatus {
      25              :     Ok = 0,
      26              :     InvalidArgument = 1,
      27              :     InternalError = 2,
      28              :     Pending = 3,
      29              :     StaleEffect = 4,
      30              :     Busy = 5,
      31              : }
      32              : 
      33              : /// The type of an effect
      34              : #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
      35              : #[repr(u32)]
      36              : pub enum EffectType {
      37              :     ExecuteQuery = 1,
      38              :     ExecuteCommand = 2,
      39              : }
      40              : 
      41              : /// How the host finished an effect
      42              : #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
      43              : #[repr(u32)]
      44              : pub enum EffectCompletionStatus {
      45              :     Success = 0,
      46              :     Error = 1,
      47              :     Cancelled = 2,
      48              : }
      49              : 
      50              : impl EffectCompletionStatus {
      51            2 :     pub fn from_u32(value: u32) -> Option<Self> {
      52            2 :         Some(match value {
      53            0 :             0 => Self::Success,
      54            0 :             1 => Self::Error,
      55            1 :             2 => Self::Cancelled,
      56            1 :             _ => return None,
      57              :         })
      58            2 :     }
      59              : }
      60              : 
      61              : /// A semantic input key
      62              : #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
      63              : #[repr(u32)]
      64              : pub enum PromptInputKey {
      65              :     Text = 0,
      66              :     Enter = 1,
      67              :     ForceSubmit = 2,
      68              :     Tab = 3,
      69              :     Backspace = 4,
      70              :     Delete = 5,
      71              :     Left = 6,
      72              :     Right = 7,
      73              :     HistoryPrevious = 8,
      74              :     HistoryNext = 9,
      75              :     Cancel = 10,
      76              :     Escape = 11,
      77              :     Up = 12,
      78              :     Down = 13,
      79              :     Start = 14,
      80              :     End = 15,
      81              :     LineStart = 16,
      82              :     LineEnd = 17,
      83              :     WordLeft = 18,
      84              :     WordRight = 19,
      85              :     KillLine = 20,
      86              :     BackwardKillLine = 21,
      87              :     KillWord = 22,
      88              :     BackwardKillWord = 23,
      89              :     Yank = 24,
      90              :     Transpose = 25,
      91              :     ClearScreen = 26,
      92              :     Eof = 27,
      93              :     Abort = 28,
      94              : }
      95              : 
      96              : impl PromptInputKey {
      97              :     pub const ALL: [PromptInputKey; 29] = [
      98              :         Self::Text,
      99              :         Self::Enter,
     100              :         Self::ForceSubmit,
     101              :         Self::Tab,
     102              :         Self::Backspace,
     103              :         Self::Delete,
     104              :         Self::Left,
     105              :         Self::Right,
     106              :         Self::HistoryPrevious,
     107              :         Self::HistoryNext,
     108              :         Self::Cancel,
     109              :         Self::Escape,
     110              :         Self::Up,
     111              :         Self::Down,
     112              :         Self::Start,
     113              :         Self::End,
     114              :         Self::LineStart,
     115              :         Self::LineEnd,
     116              :         Self::WordLeft,
     117              :         Self::WordRight,
     118              :         Self::KillLine,
     119              :         Self::BackwardKillLine,
     120              :         Self::KillWord,
     121              :         Self::BackwardKillWord,
     122              :         Self::Yank,
     123              :         Self::Transpose,
     124              :         Self::ClearScreen,
     125              :         Self::Eof,
     126              :         Self::Abort,
     127              :     ];
     128              : 
     129              :     /// The key of a numeric value, None for values past `ABORT`
     130            2 :     pub fn from_u32(value: u32) -> Option<Self> {
     131            2 :         Self::ALL.get(value as usize).copied()
     132            2 :     }
     133              : }
     134              : 
     135              : /// What the host should do after an input
     136              : #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
     137              : #[repr(u32)]
     138              : pub enum PromptInputAction {
     139              :     #[default]
     140              :     None = 0,
     141              :     Submit = 1,
     142              :     Complete = 2,
     143              :     Exit = 3,
     144              : }
     145              : 
     146              : /// The result of an operation: rendered output, an effect envelope or an error message
     147              : #[derive(Clone, Debug, PartialEq, Eq)]
     148              : pub struct ShellOperation {
     149              :     /// The status of the operation
     150              :     pub status: ShellStatus,
     151              :     /// The rendered output, the encoded effect envelope or the error message
     152              :     pub data: Vec<u8>,
     153              : }
     154              : 
     155              : impl ShellOperation {
     156          432 :     pub fn new(status: ShellStatus, data: impl Into<Vec<u8>>) -> Self {
     157          432 :         Self { status, data: data.into() }
     158          432 :     }
     159              : 
     160          394 :     pub fn ok(data: impl Into<Vec<u8>>) -> Self {
     161          394 :         Self::new(ShellStatus::Ok, data)
     162          394 :     }
     163              : }
     164              : 
     165              : /// Terminal output with the action of the input
     166              : #[derive(Clone, Debug, PartialEq, Eq)]
     167              : pub struct TerminalOutput {
     168              :     /// The status of the input
     169              :     pub status: ShellStatus,
     170              :     /// What the host should do after the input
     171              :     pub action: PromptInputAction,
     172              :     /// The terminal output with VT100 escape sequences, or the error message
     173              :     pub data: Vec<u8>,
     174              : }
     175              : 
     176              : /// A completion candidate of the prompt
     177              : #[derive(Clone, Debug, Default, PartialEq, Eq)]
     178              : pub struct CompletionCandidate {
     179              :     /// The text shown in the completion list
     180              :     pub display_text: String,
     181              :     /// The text that replaces the target, quoted if needed and with `()` for functions
     182              :     pub completion_text: String,
     183              :     /// The keywords that usually follow the completion, shown as hint, empty if none
     184              :     pub continuation_text: String,
     185              :     /// Whether this candidate only preserves the token already under the cursor
     186              :     pub is_identity: bool,
     187              :     /// The qualified names of the candidate objects that are shown as variants
     188              :     pub qualification_texts: Vec<String>,
     189              :     /// The cursor offset within the completion text after applying it
     190              :     pub completion_cursor_offset: u32,
     191              :     /// The byte offset of the replaced text in the prompt
     192              :     pub target_offset: u32,
     193              :     /// The byte length of the replaced text in the prompt
     194              :     pub target_length: u32,
     195              :     /// The byte offset of the text that a qualified name replaces
     196              :     pub qualification_target_offset: u32,
     197              :     /// The byte length of the text that a qualified name replaces
     198              :     pub qualification_target_length: u32,
     199              : }
     200              : 
     201              : /// The completion list that the host shows over the terminal
     202              : #[derive(Clone, Copy, Debug, PartialEq, Eq)]
     203              : pub struct TerminalCompletionList {
     204              :     /// Changes when the candidates change, the host only reads the buffer of the list then
     205              :     pub revision: u64,
     206              :     /// The index of the selected candidate
     207              :     pub selection: u32,
     208              :     /// The index of the selected catalog object of the selected candidate
     209              :     pub variant: u32,
     210              :     /// The terminal column of the start of the replaced text
     211              :     pub anchor_column: u32,
     212              : }
     213              : 
     214              : /// The state of the prompt after an edit
     215              : #[derive(Clone, Debug, PartialEq, Eq)]
     216              : pub struct PromptSnapshot {
     217              :     /// The status of the edit
     218              :     pub status: ShellStatus,
     219              :     /// The revision of the prompt text
     220              :     pub revision: u64,
     221              :     /// The byte offset of the cursor in the text
     222              :     pub cursor_byte_offset: u32,
     223              :     /// The prompt text
     224              :     pub text: String,
     225              :     /// The error message, empty on success
     226              :     pub message: String,
     227              :     /// What the host should do after the edit
     228              :     pub action: PromptInputAction,
     229              : }
     230              : 
     231              : /// The version of the effect envelope
     232              : pub const EFFECT_ENVELOPE_VERSION: u32 = 1;
     233              : /// The size of the effect envelope header: version (u32), type (u32), id (u64), all little-endian
     234              : pub const EFFECT_ENVELOPE_HEADER_SIZE: usize = 16;
        

Generated by: LCOV version 2.0-1