Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3,016 changes: 2,858 additions & 158 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ easing-function = "0.1.1"
strum = { version = "0.28.0", features = ["derive"] }
ctor = "1.0.7"
flycomp = { git = "https://github.com/HalFrgrd/flycomp.git", rev = "fd535f05fcc8c2d35d885688389288f602819494" }
atuin-client = "18.18.1"
atuin-common = "18.18.1"
tokio = { version = "1", features = ["rt", "rt-multi-thread"] }
time = "0.3"

[features]
pre_bash_4_4 = []
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,14 @@ Pressing `Up` will scroll through history entries that are a prefix match with t
**Zsh history entries:**
Optionally read Zsh history entries to make migrating to Bash easier.

## Atuin integration
Flyline ships with atuin support built in.
This allows for cross shell instance syncing.
TODO: more here.
```bash
flyline history --backend atuin
```

# Cursor animations and styles

Flyline can configure the cursor styling, color, and interpolation/easing animations. When moving the cursor or deleting/inserting characters, the cursor dynamically slides and animates to its new position.
Expand Down Expand Up @@ -740,7 +748,8 @@ flyline create-prompt-widget leader-mode --name FLYLINE_LEADER_MODE 'LEADER' ''
export RPS1='FLYLINE_LEADER_MODE'
```

# Integration with third party apps

# Launching third party apps
> [!CAUTION]
> This an experimental feature and might change. Feedback welcome

Expand Down
11 changes: 8 additions & 3 deletions src/app/actions/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,9 @@ impl KeyEventAction {
app.try_submit_current_buffer();
}
KeyEventAction::RunFuzzyHistorySearch => {
app.history_manager
app.settings.history_manager.refresh_history_backend();
app.settings
.history_manager
.warm_fuzzy_search_cache(app.buffer.buffer(), Some(0));
app.content_mode =
ContentMode::FuzzyHistorySearch(FuzzyHistorySource::PastCommands);
Expand Down Expand Up @@ -641,6 +643,7 @@ impl KeyEventAction {
app.buffer_before_history_navigation
.get_or_insert_with(|| app.buffer.buffer().to_string());
if let Some(entry) = app
.settings
.history_manager
.search_in_history(app.buffer.buffer(), HistorySearchDirection::Backward)
{
Expand All @@ -650,6 +653,7 @@ impl KeyEventAction {
KeyEventAction::NextHistoryEntry => {
app.buffer.clear_selection();
match app
.settings
.history_manager
.search_in_history(app.buffer.buffer(), HistorySearchDirection::Forward)
{
Expand Down Expand Up @@ -821,6 +825,7 @@ impl KeyEventAction {

// Get the last word of the history command we are currently looking at
let last_word_of_current_history_cmd = app
.settings
.history_manager
.get_last_word_insert_command()
.and_then(|cmd| crate::history::get_last_word(cmd));
Expand All @@ -833,11 +838,11 @@ impl KeyEventAction {
let is_continuation = target_sub.is_some();

if !is_continuation {
app.history_manager.last_word_insert_reset();
app.settings.history_manager.last_word_insert_reset();
}

// Move to the previous command with non-empty words
if let Some(cmd) = app.history_manager.last_word_insert_move_prev() {
if let Some(cmd) = app.settings.history_manager.last_word_insert_move_prev() {
if let Some(w) = crate::history::get_last_word(cmd) {
if let Some(sub) = &target_sub {
let _ = app.buffer.replace_word_under_cursor(&w, sub);
Expand Down
17 changes: 10 additions & 7 deletions src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,6 @@ pub(crate) struct App<'a> {
pub(super) term_has_focus: bool,
pub(super) unfinished_from_prev_command: bool,
pub(super) prompt_manager: PromptManager,
/// Parsed bash history available at startup.
pub(super) history_manager: HistoryManager,
pub(super) buffer_before_history_navigation: Option<String>,
pub(super) inline_history_suggestion: Option<(HistoryEntry, String)>,
/// Buffer contents at the time the user last dismissed the inline suggestion.
Expand Down Expand Up @@ -384,6 +382,10 @@ impl<'a> App<'a> {
let buffer = TextBuffer::new(&initial_buf_val);
let formatted_buffer_cache = FormattedBuffer::default();

if settings.history_manager.is_empty() {
settings.history_manager = HistoryManager::new(settings);
}

bash_funcs::reset_caches();

// Join any previous warming thread to prevent multiple active warming threads
Expand Down Expand Up @@ -479,7 +481,6 @@ impl<'a> App<'a> {
settings.last_app_closed_at,
)
),
history_manager: time_it!("startup: history manager", HistoryManager::new(settings)),
buffer_before_history_navigation: None,
inline_history_suggestion: None,
dismissed_inline_suggestion_buffer: None,
Expand Down Expand Up @@ -515,7 +516,7 @@ impl<'a> App<'a> {
source: &FuzzyHistorySource,
) -> &mut HistoryManager {
match source {
FuzzyHistorySource::PastCommands => &mut self.history_manager,
FuzzyHistorySource::PastCommands => &mut self.settings.history_manager,
FuzzyHistorySource::CancelledCommands => {
&mut self.settings.cancelled_command_history_manager
}
Expand All @@ -529,7 +530,7 @@ impl<'a> App<'a> {
source: &FuzzyHistorySource,
) -> &HistoryManager {
match source {
FuzzyHistorySource::PastCommands => &self.history_manager,
FuzzyHistorySource::PastCommands => &self.settings.history_manager,
FuzzyHistorySource::CancelledCommands => {
&self.settings.cancelled_command_history_manager
}
Expand Down Expand Up @@ -789,6 +790,7 @@ impl<'a> App<'a> {

match self.mode {
AppRunningState::Exiting(ExitState::WithCommand(cmd)) => {
self.settings.history_manager.push_entry(cmd.clone());
if self.settings.send_shell_integration_codes
== settings::ShellIntegrationLevel::Full
{
Expand Down Expand Up @@ -1174,7 +1176,7 @@ impl<'a> App<'a> {
log::warn!("Failed to parse cached AI output: {}", e);
self.content_mode = ContentMode::AgentError {
message: format!("Failed to parse cached AI output: {}", e),
raw_output: raw_output.clone(),
raw_output: raw_output.to_string(),
suggested_setup_command: None,
};
return;
Expand Down Expand Up @@ -1909,7 +1911,8 @@ impl<'a> App<'a> {
{
None
} else {
self.history_manager
self.settings
.history_manager
.get_command_suggestion_suffix(history_buffer)
};

Expand Down
2 changes: 1 addition & 1 deletion src/app/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1163,7 +1163,7 @@ impl<'a> App<'a> {
};
let (entries, fuzzy_results, fuzzy_search_index, num_results, num_searched) =
match source {
FuzzyHistorySource::PastCommands => &mut self.history_manager,
FuzzyHistorySource::PastCommands => &mut self.settings.history_manager,
FuzzyHistorySource::CancelledCommands => {
&mut self.settings.cancelled_command_history_manager
}
Expand Down
17 changes: 17 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,17 @@ enum Commands {
#[arg(long = "select-with-mouse", default_missing_value = "true", num_args = 0..=1)]
select_with_mouse: Option<bool>,
},
/// Configure history backend and behavior.
///
/// Examples:
/// flyline history --backend atuin
/// flyline history --backend bash
#[command(name = "history", verbatim_doc_comment)]
History {
/// Select the history storage backend (bash or atuin).
#[arg(long = "backend", value_enum)]
backend: Option<crate::settings::HistoryBackend>,
},
/// Configure suggestion behavior.
///
/// Examples:
Expand Down Expand Up @@ -1407,6 +1418,12 @@ impl Flyline {
self.settings.select_with_mouse = enabled;
}
}
Some(Commands::History { backend }) => {
if let Some(b) = backend {
log::info!("History backend set to {:?}", b);
self.settings.history_backend = b;
}
}
Some(Commands::Suggestions {
subcommand,
auto_suggest,
Expand Down
Loading
Loading