Skip to content

Commit

Permalink
feat: launch onagre with mode as cli parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
juanolon authored and oknozor committed Jan 25, 2024
1 parent 29bdc3a commit feb3249
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 134 deletions.
9 changes: 3 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ iced_style = "0.9.0"
tokio = { version = "1.29.1", features = ["process", "macros", "io-util"] }
sled = "0.34.7"

onagre-launcher-toolkit = "0.1.1"
onagre-launcher-toolkit = { git = "https://github.com/onagre-launcher/launcher" }
clap = { version = "^4", features = ["derive"] }
freedesktop-icons = "0.2.5"

Expand All @@ -53,4 +53,4 @@ shell-words = "^1"

[dev-dependencies]
speculoos = "0.11.0"
pretty_assertions = "1.2.1"
pretty_assertions = "1.2.1"
47 changes: 24 additions & 23 deletions src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ use once_cell::sync::Lazy;
use crate::app::entries::pop_entry::PopSearchResult;
use crate::app::entries::AsEntry;
use crate::app::mode::ActiveMode;
use crate::app::plugin_matchers::Plugin;
use crate::app::state::{Selection, State};
use crate::app::subscriptions::plugin_configs::PluginMatcherSubscription;
use crate::app::subscriptions::pop_launcher::{PopLauncherSubscription, SubscriptionMessage};
use crate::db::desktop_entry::DesktopEntryEntity;
use crate::db::plugin::PluginCommandEntity;
Expand All @@ -38,7 +36,7 @@ pub mod state;
pub mod style;
pub mod subscriptions;

pub fn run() -> iced::Result {
pub fn run(pre_value: Option<String>) -> iced::Result {
debug!("Starting Onagre in debug mode");

let default_font = THEME
Expand Down Expand Up @@ -68,7 +66,7 @@ pub fn run() -> iced::Result {
antialiasing: true,
exit_on_close_request: false,
default_font,
flags: (),
flags: OnagreFlags { pre_value },
})
}

Expand All @@ -84,25 +82,36 @@ pub enum Message {
InputChanged(String),
KeyboardEvent(KeyCode),
SubscriptionResponse(SubscriptionMessage),
PluginConfig(Plugin),
Unfocused,
}

static INPUT_ID: Lazy<text_input::Id> = Lazy::new(text_input::Id::unique);
static SCROLL_ID: Lazy<scrollable::Id> = Lazy::new(scrollable::Id::unique);

pub struct OnagreFlags {
pre_value: Option<String>,
}

impl Application for Onagre<'_> {
type Executor = iced::executor::Default;
type Message = Message;
type Theme = Theme;

type Flags = ();
type Flags = OnagreFlags;

fn new(_: Self::Flags) -> (Self, Command<Self::Message>) {
let onagre = Onagre {
state: Default::default(),
request_tx: Default::default(),
};
fn new(flags: OnagreFlags) -> (Self, Command<Self::Message>) {
let onagre;
if let Some(pre_value) = flags.pre_value {
onagre = Onagre {
state: State::with_mode(&pre_value),
request_tx: Default::default(),
};
} else {
onagre = Onagre {
state: Default::default(),
request_tx: Default::default(),
};
}

(
onagre,
Expand All @@ -127,12 +136,6 @@ impl Application for Onagre<'_> {
Command::none()
}
}
Message::PluginConfig(plugin) => {
self.state
.plugin_matchers
.insert(plugin.name.clone(), plugin);
Command::none()
}
}
}

Expand Down Expand Up @@ -285,12 +288,11 @@ impl Application for Onagre<'_> {
app_wrapper.into()
}

fn subscription(&self) -> iced::Subscription<Self::Message> {
fn subscription(&self) -> Subscription<Self::Message> {
let keyboard_event = Onagre::keyboard_event();
let pop_launcher = PopLauncherSubscription::create().map(Message::SubscriptionResponse);
let matchers = PluginMatcherSubscription::create().map(Message::PluginConfig);
let subs = vec![keyboard_event, pop_launcher, matchers];
iced::Subscription::batch(subs)
let subs = vec![keyboard_event, pop_launcher];
Subscription::batch(subs)
}
}

Expand Down Expand Up @@ -357,8 +359,7 @@ impl Onagre<'_> {
_ => Selection::PopLauncher(0),
};

let _: iced::Command<Message> =
scrollable::snap_to(SCROLL_ID.clone(), RelativeOffset::START);
let _: Command<Message> = scrollable::snap_to(SCROLL_ID.clone(), RelativeOffset::START);

match &self.state.get_active_mode() {
ActiveMode::History => {}
Expand Down
162 changes: 119 additions & 43 deletions src/app/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,44 @@ pub struct State<'a> {
pub plugin_matchers: PluginConfigCache,
}

#[derive(Debug, Default)]
#[derive(Debug)]
pub struct PluginConfigCache {
pub(crate) inner: HashMap<String, Plugin>,
}

impl PluginConfigCache {
pub fn load() -> Self {
let mut cache = HashMap::new();
for (path, config, regex) in onagre_launcher_toolkit::service::load::from_paths() {
let icon: Option<IconPath> = THEME.icon_theme.as_ref().and_then(|theme| {
config
.icon
.as_ref()
.map(|source| (source, theme))
.and_then(|(source, theme)| IconPath::from_source(source, theme))
});

let name = path
.parent()
.expect("Plugin config should have a parent directory")
.file_name()
.expect("Plugin directory should have an utf8 filename")
.to_string_lossy()
.to_string();

let plugin = Plugin {
name: name.clone(),
icon,
history: config.history,
help: config.query.help.map(|h| h.to_string()),
regex,
};

cache.insert(name, plugin);
}

PluginConfigCache { inner: cache }
}
pub fn get_plugin_icon(&self, plugin_name: &str) -> Option<IconPath> {
self.inner.get(plugin_name).and_then(|de| de.icon.clone())
}
Expand Down Expand Up @@ -62,52 +94,51 @@ impl State<'_> {
}
}

// TODO: refactor me please
pub fn with_mode(mode_query: &str) -> Self {
let plugin_matchers = PluginConfigCache::load();
let plugin_split = match_web_plugins(mode_query).or_else(|| {
plugin_matchers
.inner
.values()
.map(|matcher| matcher.try_match(mode_query))
.find_map(|match_| match_)
});

let mode = plugin_split
.as_ref()
.map(|split| ActiveMode::from(split.clone()))
.unwrap_or_default();
let modifier_display = plugin_split
.as_ref()
.map(|query_data| query_data.modifier.clone())
.unwrap_or_default();
let input_display = plugin_split
.map(|query_data| query_data.query)
.unwrap_or_default();

State {
selected: Selection::History(0),
cache: Default::default(),
pop_search: Default::default(),
scroll: Default::default(),
input_value: SearchInput {
mode,
modifier_display, // dgg
input_display, // <search str>
pop_query: mode_query.to_string(), // dgg <search str>
},
exec_on_next_search: false,
plugin_matchers,
}
}

pub fn set_input(&mut self, input: &str) {
let previous_modi = self.input_value.modifier_display.clone();

if !previous_modi.is_empty() {
if input.is_empty() {
self.input_value.modifier_display = "".to_string();
self.input_value.input_display = if THEME.plugin_hint().is_none() {
input.to_string()
} else {
previous_modi
};
self.input_value.mode = ActiveMode::DesktopEntry;
let _: iced::Command<Message> = text_input::move_cursor_to_end(INPUT_ID.clone());
} else {
self.input_value.input_display = input.to_string();
}
self.set_input_with_modifier(input, previous_modi);
} else {
let terms = &format!("{}{}", previous_modi, input);
let plugin_split = match_web_plugins(terms).or_else(|| {
self.plugin_matchers
.inner
.values()
.map(|matcher| matcher.try_match(terms))
.find_map(|match_| match_)
});

if let Some(query_data) = plugin_split {
self.input_value.modifier_display = query_data.modifier.clone();
self.input_value.mode = ActiveMode::from(query_data.clone());
// If plugin-hint is disabled use the full input,
// otherwise use the split value
self.input_value.input_display = if THEME.plugin_hint().is_none() {
input.to_string()
} else {
query_data.query
};
} else {
self.input_value.input_display = input.to_string();

if input.is_empty() {
self.input_value.mode = ActiveMode::History
} else {
self.input_value.mode = ActiveMode::DesktopEntry
}
}
self.set_input_without_modifier(input);
};

let pop_query = match &self.input_value.mode {
Expand All @@ -128,6 +159,51 @@ impl State<'_> {
self.input_value.mode, self.input_value.input_display
);
}

fn set_input_without_modifier(&mut self, input: &str) {
let plugin_split = match_web_plugins(input).or_else(|| {
self.plugin_matchers
.inner
.values()
.map(|matcher| matcher.try_match(input))
.find_map(|match_| match_)
});

if let Some(query_data) = plugin_split {
self.input_value.modifier_display = query_data.modifier.clone();
self.input_value.mode = ActiveMode::from(query_data.clone());
// If plugin-hint is disabled use the full input,
// otherwise use the split value
self.input_value.input_display = if THEME.plugin_hint().is_none() {
input.to_string()
} else {
query_data.query
};
} else {
self.input_value.input_display = input.to_string();

if input.is_empty() {
self.input_value.mode = ActiveMode::History
} else {
self.input_value.mode = ActiveMode::DesktopEntry
}
}
}

fn set_input_with_modifier(&mut self, input: &str, previous_modi: String) {
if input.is_empty() {
self.input_value.modifier_display = "".to_string();
self.input_value.input_display = if THEME.plugin_hint().is_none() {
input.to_string()
} else {
previous_modi
};
self.input_value.mode = ActiveMode::DesktopEntry;
let _: iced::Command<Message> = text_input::move_cursor_to_end(INPUT_ID.clone());
} else {
self.input_value.input_display = input.to_string();
}
}
}

#[derive(Debug, Default)]
Expand All @@ -147,7 +223,7 @@ impl Default for State<'_> {
scroll: Default::default(),
input_value: SearchInput::default(),
exec_on_next_search: false,
plugin_matchers: PluginConfigCache::default(),
plugin_matchers: PluginConfigCache::load(),
}
}
}
1 change: 0 additions & 1 deletion src/app/subscriptions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
pub mod plugin_configs;
pub mod pop_launcher;
Loading

0 comments on commit feb3249

Please sign in to comment.