Compare commits
1 Commits
master
...
pipe_to_cl
Author | SHA1 | Date |
---|---|---|
Manos Pitsidianakis | f5fd051a2c |
|
@ -2294,7 +2294,9 @@ impl Component for MailView {
|
|||
UIEvent::Input(ref key)
|
||||
if !self.cmd_buf.is_empty()
|
||||
&& self.mode == ViewMode::Url
|
||||
&& shortcut!(key == shortcuts[MailView::DESCRIPTION]["go_to_url"]) =>
|
||||
&& (shortcut!(key == shortcuts[MailView::DESCRIPTION]["go_to_url"])
|
||||
|| shortcut!(key == shortcuts[MailView::DESCRIPTION]["copy_url"])
|
||||
|| shortcut!(key == shortcuts[MailView::DESCRIPTION]["pipe_url"])) =>
|
||||
{
|
||||
let lidx = self.cmd_buf.parse::<usize>().unwrap();
|
||||
self.cmd_buf.clear();
|
||||
|
@ -2330,40 +2332,144 @@ impl Component for MailView {
|
|||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
let url_launcher = mailbox_settings!(
|
||||
context[self.coordinates.0][&self.coordinates.1]
|
||||
.pager
|
||||
.url_launcher
|
||||
)
|
||||
.as_ref()
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or(
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
"open"
|
||||
},
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
"xdg-open"
|
||||
},
|
||||
eprintln!("key is {:?}", key);
|
||||
eprintln!(
|
||||
"shotrctu key is {:?}",
|
||||
shortcuts[MailView::DESCRIPTION]["pipe_url"]
|
||||
);
|
||||
match Command::new(url_launcher)
|
||||
.arg(url)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(child) => {
|
||||
context.children.push(child);
|
||||
if shortcut!(key == shortcuts[MailView::DESCRIPTION]["go_to_url"]) {
|
||||
let url_launcher = mailbox_settings!(
|
||||
context[self.coordinates.0][&self.coordinates.1]
|
||||
.pager
|
||||
.url_launcher
|
||||
)
|
||||
.as_ref()
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or(
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
"open"
|
||||
},
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
"xdg-open"
|
||||
},
|
||||
);
|
||||
match Command::new(url_launcher)
|
||||
.arg(url)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(child) => {
|
||||
context.children.push(child);
|
||||
}
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some(format!("Failed to launch {:?}", url_launcher)),
|
||||
err.to_string(),
|
||||
Some(NotificationType::Error(melib::ErrorKind::External)),
|
||||
));
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some(format!("Failed to launch {:?}", url_launcher)),
|
||||
err.to_string(),
|
||||
Some(NotificationType::Error(melib::ErrorKind::External)),
|
||||
));
|
||||
} else if shortcut!(key == shortcuts[MailView::DESCRIPTION]["copy_url"]) {
|
||||
let pipe_to_clipboard = context
|
||||
.settings
|
||||
.terminal
|
||||
.pipe_to_clipboard
|
||||
.as_ref()
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or(
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
"pbcopy"
|
||||
},
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
"xclip -selection clipboard"
|
||||
},
|
||||
);
|
||||
match Command::new(pipe_to_clipboard)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(mut child) => {
|
||||
let mut stdin = child.stdin.as_mut().unwrap();
|
||||
stdin
|
||||
.write_all(url.as_bytes())
|
||||
.chain_err_summary(|| {
|
||||
format!(
|
||||
"Failed to write to stdin of `{}`",
|
||||
pipe_to_clipboard
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
stdin.flush().unwrap();
|
||||
context.children.push(child);
|
||||
}
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some(format!("Failed to launch {:?}", pipe_to_clipboard)),
|
||||
err.to_string(),
|
||||
Some(NotificationType::Error(melib::ErrorKind::External)),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else if shortcut!(key == shortcuts[MailView::DESCRIPTION]["pipe_url"]) {
|
||||
let input_window = InputWindow::new("test".into(), context);
|
||||
//context.replies.push_back(UIEvent::StatusEvent(
|
||||
// StatusEvent::DisplayMessage(format!("Running input_window")),
|
||||
//));
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::GlobalUIDialog(input_window));
|
||||
return true;
|
||||
|
||||
/*let pipe_to_clipboard = context
|
||||
.settings
|
||||
.terminal
|
||||
.pipe_to_clipboard
|
||||
.as_ref()
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or(
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
"pbcopy"
|
||||
},
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
"xclip -selection clipboard"
|
||||
},
|
||||
);
|
||||
match Command::new(pipe_to_clipboard)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(mut child) => {
|
||||
let mut stdin = child.stdin.as_mut().unwrap();
|
||||
stdin
|
||||
.write_all(url.as_bytes())
|
||||
.chain_err_summary(|| {
|
||||
format!(
|
||||
"Failed to write to stdin of `{}`",
|
||||
pipe_to_clipboard
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
stdin.flush().unwrap();
|
||||
context.children.push(child);
|
||||
}
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some(format!("Failed to launch {:?}", pipe_to_clipboard)),
|
||||
err.to_string(),
|
||||
Some(NotificationType::Error(melib::ErrorKind::External)),
|
||||
));
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -969,3 +969,133 @@ impl UIConfirmationDialog {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InputWindow {
|
||||
theme_default: ThemeAttribute,
|
||||
|
||||
vertical_alignment: Alignment,
|
||||
horizontal_alignment: Alignment,
|
||||
title: String,
|
||||
|
||||
mode: UIMode,
|
||||
field: Field,
|
||||
|
||||
/// If true, user has finished their selection
|
||||
done: bool,
|
||||
done_fn:
|
||||
Option<Box<dyn FnOnce(ComponentId, String) -> Option<UIEvent> + 'static + Sync + Send>>,
|
||||
dirty: bool,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl InputWindow {
|
||||
pub fn new(title: String, context: &Context) -> Box<dyn Component> {
|
||||
Box::new(Self {
|
||||
theme_default: crate::conf::value(context, "theme_default"),
|
||||
|
||||
vertical_alignment: Alignment::Center,
|
||||
horizontal_alignment: Alignment::Center,
|
||||
title,
|
||||
mode: UIMode::Normal,
|
||||
|
||||
field: Field::default(),
|
||||
|
||||
/// If true, user has finished their selection
|
||||
done: false,
|
||||
done_fn: Some(Box::new(
|
||||
|id: ComponentId, result: String| -> Option<UIEvent> {
|
||||
let _ = id;
|
||||
let _ = result;
|
||||
None
|
||||
},
|
||||
)),
|
||||
dirty: true,
|
||||
id: ComponentId::new_v4(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for InputWindow {
|
||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
std::dbg!(area);
|
||||
if self.dirty {
|
||||
let height = height!(area);
|
||||
if height < 4 {
|
||||
return;
|
||||
}
|
||||
let height = std::cmp::max(4, height / 3);
|
||||
let dialog_area = align_area(
|
||||
area,
|
||||
/* add box perimeter padding */
|
||||
pos_inc((width!(area), height), (2, 2)),
|
||||
/* vertical */
|
||||
Alignment::Center,
|
||||
/* horizontal */
|
||||
Alignment::Center,
|
||||
);
|
||||
std::dbg!(dialog_area);
|
||||
clear_area(grid, dialog_area, self.theme_default);
|
||||
let inner_area = create_box(grid, dialog_area);
|
||||
self.field.draw(grid, inner_area, context);
|
||||
context.dirty_areas.push_back(dialog_area);
|
||||
self.dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
match (self.mode, &event) {
|
||||
(_, UIEvent::Resize) => {
|
||||
self.set_dirty(true);
|
||||
false
|
||||
}
|
||||
(UIMode::Normal, UIEvent::Input(Key::Char('\n'))) => {
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::ChangeMode(UIMode::Insert));
|
||||
true
|
||||
}
|
||||
(UIMode::Insert, UIEvent::InsertInput(Key::Esc)) => {
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::ChangeMode(UIMode::Normal));
|
||||
true
|
||||
}
|
||||
(UIMode::Insert, _) => self.field.process_event(event, context),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_shortcuts(&self, context: &Context) -> ShortcutMaps {
|
||||
let mut map = ShortcutMaps::default();
|
||||
map.insert("general", context.settings.shortcuts.general.key_values());
|
||||
map
|
||||
}
|
||||
|
||||
fn is_dirty(&self) -> bool {
|
||||
self.dirty || self.field.is_dirty()
|
||||
}
|
||||
|
||||
fn set_dirty(&mut self, value: bool) {
|
||||
self.dirty = value;
|
||||
self.field.set_dirty(value);
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for InputWindow {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt("InputWindow", f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for InputWindow {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt("InputWindow", f)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -225,6 +225,7 @@ impl Component for Field {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
match *event {
|
||||
UIEvent::InsertInput(Key::Char('\t')) => {
|
||||
|
|
|
@ -222,6 +222,8 @@ shortcut_key_values! { "envelope-view",
|
|||
add_addresses_to_contacts |> "Select addresses from envelope to add to contacts." |> Key::Char('c'),
|
||||
edit |> "Open envelope in composer." |> Key::Char('e'),
|
||||
go_to_url |> "Go to url of given index" |> Key::Char('g'),
|
||||
copy_url |> "Copy url of given index to system clipboard" |> Key::Char('G'),
|
||||
pipe_url |> "Pipe url of given index to specific command" |> Key::Char('w'),
|
||||
open_attachment |> "Opens selected attachment with xdg-open." |> Key::Char('a'),
|
||||
open_mailcap |> "Opens selected attachment according to its mailcap entry." |> Key::Char('m'),
|
||||
reply |> "Reply to envelope." |> Key::Char('R'),
|
||||
|
|
|
@ -52,6 +52,8 @@ pub struct TerminalSettings {
|
|||
/// Default: 0
|
||||
#[serde(default)]
|
||||
pub progress_spinner_sequence: Option<ProgressSpinnerSequence>,
|
||||
#[serde(deserialize_with = "non_empty_string")]
|
||||
pub pipe_to_clipboard: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for TerminalSettings {
|
||||
|
@ -66,6 +68,7 @@ impl Default for TerminalSettings {
|
|||
window_title: Some("meli".to_string()),
|
||||
file_picker_command: None,
|
||||
progress_spinner_sequence: None,
|
||||
pipe_to_clipboard: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +102,7 @@ impl DotAddressable for TerminalSettings {
|
|||
"progress_spinner_sequence" => {
|
||||
self.progress_spinner_sequence.lookup(field, tail)
|
||||
}
|
||||
"pipe_to_clipboard" => self.pipe_to_clipboard.lookup(field, tail),
|
||||
other => Err(MeliError::new(format!(
|
||||
"{} has no field named {}",
|
||||
parent_field, other
|
||||
|
|
|
@ -1168,6 +1168,7 @@ impl State {
|
|||
return;
|
||||
}
|
||||
UIEvent::GlobalUIDialog(dialog) => {
|
||||
eprint!("global ui dialog push");
|
||||
self.overlay.push(dialog);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue