Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4f71b89
basic sqlite history
phiresky Apr 1, 2022
dd93aba
fix test compilation
phiresky Apr 1, 2022
4c03e68
final touches for MVP
phiresky Apr 1, 2022
a669fb3
better documentation
phiresky Apr 1, 2022
187f867
fix for empty history
phiresky Apr 2, 2022
01b62e7
partial change to non-generic history
phiresky Apr 16, 2022
3e76ae7
mostly working
phiresky Apr 16, 2022
317a69f
fix tests and ci
phiresky Apr 18, 2022
7d4b7ca
fixes, format
phiresky Apr 18, 2022
5fc904e
move history item to new file
phiresky Apr 18, 2022
f756189
fix some comments, fix test compile errors
phiresky Apr 20, 2022
4d60705
ci features matrix
phiresky Apr 20, 2022
13b32b9
fix index creation
phiresky Apr 18, 2022
56a210c
fix file-based tests
phiresky May 8, 2022
7c6b09a
move logic for not saving empty entries to engine
phiresky May 8, 2022
9cab40f
fix update last command on empty, set up application_id and check ver…
phiresky May 8, 2022
37afda0
Merge remote-tracking branch 'origin/main' into sqlite-history-2
phiresky May 8, 2022
556115b
add specific error variants
phiresky May 8, 2022
285ea4b
format
phiresky May 11, 2022
c772fad
fix compile errors
phiresky May 11, 2022
74c8f71
fix fmt
fdncred May 11, 2022
d84fd86
sqlite with bashisms
elferherrera May 21, 2022
a9c9d3a
Merge branch 'main' of https://github.com/nushell/reedline into sqlit…
elferherrera May 21, 2022
428544d
hide with features
elferherrera May 21, 2022
014bd48
cargo fmt
elferherrera May 21, 2022
a8d8703
improve performance of bashisms selectors
phiresky Jun 6, 2022
33b7610
Merge remote-tracking branch 'origin/main' into sqlite-history-2
phiresky Jun 6, 2022
6d803bb
Style: Remove commented out code
sholderbach Jun 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
move history item to new file
  • Loading branch information
phiresky committed Apr 18, 2022
commit 5fc904e0750f54a065720c1b74acecc6d208f890
67 changes: 5 additions & 62 deletions src/history/base.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::time::Duration;

use chrono::Utc;
use serde::{de::DeserializeOwned, Serialize};

use crate::core_editor::LineBuffer;
use crate::{core_editor::LineBuffer, HistoryItem};

use super::{HistoryItemId, HistorySessionId};

// todo: better error type
pub type Result<T> = std::result::Result<T, String>;
Expand All @@ -28,64 +27,6 @@ pub enum CommandLineSearch {
Exact(String),
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct HistoryItemId(pub(crate) i64);
impl HistoryItemId {
pub(crate) fn new(i: i64) -> HistoryItemId {
HistoryItemId(i)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct HistorySessionId(pub(crate) i64);
impl HistorySessionId {
pub(crate) fn new(i: i64) -> HistorySessionId {
HistorySessionId(i)
}
}
/// This trait represents additional context to be added to a history (see [HistoryItem])
pub trait HistoryItemExtraInfo: Serialize + DeserializeOwned + Default + Send {}
impl HistoryItemExtraInfo for () {}
/// Represents one run command with some optional historical context
#[derive(Clone, Debug, PartialEq)]
pub struct HistoryItem<ExtraInfo: HistoryItemExtraInfo = ()> {
/// primary key, unique across one history
pub id: Option<HistoryItemId>,
/// date-time when this command was started
pub start_timestamp: Option<chrono::DateTime<Utc>>,
/// the full command line as text
pub command_line: String,
/// a unique id for one shell session.
/// used so the history can be filtered to a single session
pub session_id: Option<HistorySessionId>,
/// the hostname the commands were run in
pub hostname: Option<String>,
/// the current working directory
pub cwd: Option<String>,
/// the duration the command took to complete
pub duration: Option<Duration>,
/// the exit status of the command
pub exit_status: Option<i64>,
/// arbitrary additional information that might be interesting
pub more_info: Option<ExtraInfo>,
}

impl HistoryItem {
/// create a history item purely from the command line with everything else set to None
pub fn from_command_line(cmd: impl Into<String>) -> HistoryItem {
HistoryItem {
id: None,
start_timestamp: None,
command_line: cmd.into(),
session_id: None,
hostname: None,
cwd: None,
duration: None,
exit_status: None,
more_info: None,
}
}
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SearchDirection {
Backward,
Expand Down Expand Up @@ -231,6 +172,8 @@ mod test {
more_info: None,
}
}
use std::time::Duration;

use super::*;
fn create_filled_example_history() -> Result<Box<dyn History>> {
#[cfg(feature = "sqlite")]
Expand Down
4 changes: 2 additions & 2 deletions src/history/file_backed.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{
base::{CommandLineSearch, HistorySessionId, Result},
History, HistoryItem, HistoryItemId, SearchDirection, SearchQuery,
base::{CommandLineSearch, Result},
History, HistoryItem, HistoryItemId, HistorySessionId, SearchDirection, SearchQuery,
};

use std::{
Expand Down
81 changes: 81 additions & 0 deletions src/history/item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use std::time::Duration;

use chrono::Utc;
use serde::{de::DeserializeOwned, Deserialize, Serialize};

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct HistoryItemId(pub(crate) i64);
impl HistoryItemId {
pub(crate) fn new(i: i64) -> HistoryItemId {
HistoryItemId(i)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct HistorySessionId(pub(crate) i64);
impl HistorySessionId {
pub(crate) fn new(i: i64) -> HistorySessionId {
HistorySessionId(i)
}
}
/// This trait represents additional arbitrary context to be added to a history (optional, see [HistoryItem])
pub trait HistoryItemExtraInfo: Serialize + DeserializeOwned + Default + Send {}
#[derive(Default, Debug, PartialEq, Eq)]
/// something that is serialized as null and deserialized by ignoring everything
pub struct Anything;
impl Serialize for Anything {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
Option::<Anything>::None.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Anything {
fn deserialize<D>(d: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
serde::de::IgnoredAny::deserialize(d).map(|_| Anything)
}
}
impl HistoryItemExtraInfo for Anything {}
/// Represents one run command with some optional additional context
#[derive(Clone, Debug, PartialEq)]
pub struct HistoryItem<ExtraInfo: HistoryItemExtraInfo = Anything> {
/// primary key, unique across one history
pub id: Option<HistoryItemId>,
/// date-time when this command was started
pub start_timestamp: Option<chrono::DateTime<Utc>>,
/// the full command line as text
pub command_line: String,
/// a unique id for one shell session.
/// used so the history can be filtered to a single session
pub session_id: Option<HistorySessionId>,
/// the hostname the commands were run in
pub hostname: Option<String>,
/// the current working directory
pub cwd: Option<String>,
/// the duration the command took to complete
pub duration: Option<Duration>,
/// the exit status of the command
pub exit_status: Option<i64>,
/// arbitrary additional information that might be interesting
pub more_info: Option<ExtraInfo>,
}

impl HistoryItem {
/// create a history item purely from the command line with everything else set to None
pub fn from_command_line(cmd: impl Into<String>) -> HistoryItem {
HistoryItem {
id: None,
start_timestamp: None,
command_line: cmd.into(),
session_id: None,
hostname: None,
cwd: None,
duration: None,
exit_status: None,
more_info: None,
}
}
}
7 changes: 3 additions & 4 deletions src/history/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
mod base;
mod cursor;
mod file_backed;
mod item;
#[cfg(feature = "sqlite")]
mod sqlite_backed;
#[cfg(feature = "sqlite")]
pub use sqlite_backed::SqliteBackedHistory;

pub use base::{
History, HistoryItem, HistoryItemId, HistoryNavigationQuery, Result, SearchDirection,
SearchQuery,
};
pub use base::{History, HistoryNavigationQuery, Result, SearchDirection, SearchQuery};
pub use cursor::HistoryCursor;
pub use item::{HistoryItem, HistoryItemId, HistorySessionId};

pub use file_backed::{FileBackedHistory, HISTORY_SIZE};
21 changes: 16 additions & 5 deletions src/history/sqlite_backed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use chrono::{TimeZone, Utc};
use rusqlite::{named_params, params, Connection, ToSql};

use super::{
base::{CommandLineSearch, HistorySessionId, SearchDirection, SearchQuery},
History, HistoryItem, HistoryItemId, Result,
base::{CommandLineSearch, SearchDirection, SearchQuery},
History, HistoryItem, HistoryItemId, HistorySessionId, Result,
};

use std::{path::PathBuf, time::Duration};
Expand All @@ -16,7 +16,7 @@ pub struct SqliteBackedHistory {
}

fn deserialize_history_item(row: &rusqlite::Row) -> rusqlite::Result<HistoryItem> {
let x: String = row.get("more_info")?;
let x: Option<String> = row.get("more_info")?;
Ok(HistoryItem {
id: Some(HistoryItemId::new(row.get("id")?)),
start_timestamp: row
Expand All @@ -32,7 +32,18 @@ fn deserialize_history_item(row: &rusqlite::Row) -> rusqlite::Result<HistoryItem
.get::<&str, Option<i64>>("duration_ms")?
.map(|e| Duration::from_millis(e as u64)),
exit_status: row.get("exit_status")?,
more_info: serde_json::from_str(&x).unwrap(),
more_info: x
.map(|x| {
serde_json::from_str(&x).map_err(|e| {
// hack
rusqlite::Error::InvalidColumnType(
0,
format!("could not deserialize more_info: {e}"),
rusqlite::types::Type::Text,
)
})
})
.transpose()?,
})
}

Expand Down Expand Up @@ -69,7 +80,7 @@ impl History for SqliteBackedHistory {
":cwd": entry.cwd,
":duration_ms": entry.duration.map(|e| e.as_millis() as i64),
":exit_status": entry.exit_status,
":more_info": &serde_json::to_string(&entry.more_info).unwrap()
":more_info": entry.more_info.as_ref().map(|e| serde_json::to_string(e).unwrap())
},
|row| row.get(0),
)
Expand Down
5 changes: 2 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

#[cfg(not(feature = "sqlite"))]
use reedline::FileBackedHistory;
use reedline::{DefaultValidator, ReedlineMenu};
Expand All @@ -14,8 +13,8 @@ use {
get_reedline_default_keybindings, get_reedline_edit_commands,
get_reedline_keybinding_modifiers, get_reedline_keycodes, get_reedline_prompt_edit_modes,
get_reedline_reedline_events, ColumnarMenu, DefaultCompleter, DefaultHinter, DefaultPrompt,
EditMode, Emacs, ExampleHighlighter, Keybindings, ListMenu, Reedline,
ReedlineEvent, Signal, Vi,
EditMode, Emacs, ExampleHighlighter, Keybindings, ListMenu, Reedline, ReedlineEvent,
Signal, Vi,
},
std::{
io::{stdout, Write},
Expand Down