@@ -23,7 +23,7 @@ use helix_view::{
2323 Document, DocumentId, Editor, ViewId,
2424};
2525
26−use anyhow::anyhow;
26+use anyhow::{anyhow, bail};
2727use helix_lsp::{
2828 lsp,
2929 util::{lsp_pos_to_pos, lsp_range_to_range, pos_to_lsp_pos, range_to_lsp_range},
@@ -1161,34 +1161,52 @@ mod cmd {
11611161 pub alias: Option<&'static str>,
11621162 pub doc: &'static str,
11631163 // params, flags, helper, completer
1164− pub fun: fn(&mut compositor::Context, &[&str], PromptEvent),
1164+ pub fun: fn(&mut compositor::Context, &[&str], PromptEvent) -> anyhow::Result<()>,
11651165 pub completer: Option<Completer>,
11661166 }
11671167
1168− fn quit(cx: &mut compositor::Context, _args: &[&str], _event: PromptEvent) {
1168+ fn quit(
1169+ cx: &mut compositor::Context,
1170+ _args: &[&str],
1171+ _event: PromptEvent,
1172+ ) -> anyhow::Result<()> {
11691173 // last view and we have unsaved changes
1170− if cx.editor.tree.views().count() == 1 && buffers_remaining_impl(cx.editor) {
1171− return;
1174+ if cx.editor.tree.views().count() == 1 {
1175+ buffers_remaining_impl(cx.editor)?
11721176 }
1177+
11731178 cx.editor
11741179 .close(view!(cx.editor).id, /* close_buffer */ false);
1180+
1181+ Ok(())
11751182 }
11761183
1177− fn force_quit(cx: &mut compositor::Context, _args: &[&str], _event: PromptEvent) {
1184+ fn force_quit(
1185+ cx: &mut compositor::Context,
1186+ _args: &[&str],
1187+ _event: PromptEvent,
1188+ ) -> anyhow::Result<()> {
11781189 cx.editor
11791190 .close(view!(cx.editor).id, /* close_buffer */ false);
1191+
1192+ Ok(())
11801193 }
11811194
1182− fn open(cx: &mut compositor::Context, args: &[&str], _event: PromptEvent) {
1195+ fn open(
1196+ cx: &mut compositor::Context,
1197+ args: &[&str],
1198+ _event: PromptEvent,
1199+ ) -> anyhow::Result<()> {
11831200 match args.get(0) {
11841201 Some(path) => {
1185− // TODO: handle error
1186− let _ = cx.editor.open(path.into(), Action::Replace);
1202+ let _ = cx.editor.open(path.into(), Action::Replace)?;
1203+
1204+ Ok(())
11871205 }
11881206 None => {
1189− cx.editor.set_error("wrong argument count".to_string());
1207+ bail!("wrong argument count");
11901208 }
1191− };
1209+ }
11921210 }
11931211
11941212 fn write_impl<P: AsRef<Path>>(
@@ -1200,11 +1218,11 @@ mod cmd {
12001218
12011219 if let Some(path) = path {
12021220 if let Err(err) = doc.set_path(path.as_ref()) {
1203− return Err(anyhow!("invalid filepath: {}", err));
1221+ bail!("invalid filepath: {}", err);
12041222 };
12051223 }
12061224 if doc.path().is_none() {
1207− return Err(anyhow!("cannot write a buffer without a filename"));
1225+ bail!("cannot write a buffer without a filename");
12081226 }
12091227 let fmt = doc.auto_format().map(|fmt| {
12101228 let shared = fmt.shared();
@@ -1220,21 +1238,33 @@ mod cmd {
12201238 Ok(tokio::spawn(doc.format_and_save(fmt)))
12211239 }
12221240
1223− fn write(cx: &mut compositor::Context, args: &[&str], _event: PromptEvent) {
1224− match write_impl(cx, args.first()) {
1225− Err(e) => cx.editor.set_error(e.to_string()),
1226− Ok(handle) => {
1227− cx.jobs
1228− .add(Job::new(handle.unwrap_or_else(|e| Err(e.into()))).wait_before_exiting());
1229− }
1230− };
1241+ fn write(
1242+ cx: &mut compositor::Context,
1243+ args: &[&str],
1244+ _event: PromptEvent,
1245+ ) -> anyhow::Result<()> {
1246+ let handle = write_impl(cx, args.first())?;
1247+ cx.jobs
1248+ .add(Job::new(handle.unwrap_or_else(|e| Err(e.into()))).wait_before_exiting());
1249+
1250+ Ok(())
12311251 }
12321252
1233− fn new_file(cx: &mut compositor::Context, _args: &[&str], _event: PromptEvent) {
1253+ fn new_file(
1254+ cx: &mut compositor::Context,
1255+ _args: &[&str],
1256+ _event: PromptEvent,
1257+ ) -> anyhow::Result<()> {
12341258 cx.editor.new_file(Action::Replace);
1259+
1260+ Ok(())
12351261 }
12361262
1237− fn format(cx: &mut compositor::Context, _args: &[&str], _event: PromptEvent) {
1263+ fn format(
1264+ cx: &mut compositor::Context,
1265+ _args: &[&str],
1266+ _event: PromptEvent,
1267+ ) -> anyhow::Result<()> {
12381268 let (_, doc) = current!(cx.editor);
12391269
12401270 if let Some(format) = doc.format() {
@@ -1242,9 +1272,14 @@ mod cmd {
12421272 make_format_callback(doc.id(), doc.version(), Modified::LeaveModified, format);
12431273 cx.jobs.callback(callback);
12441274 }
1245− }
12461275
1247− fn set_indent_style(cx: &mut compositor::Context, args: &[&str], _event: PromptEvent) {
1276+ Ok(())
1277+ }
1278+ fn set_indent_style(
1279+ cx: &mut compositor::Context,
1280+ args: &[&str],
1281+ _event: PromptEvent,
1282+ ) -> anyhow::Result<()> {
12481283 use IndentStyle::*;
12491284
12501285 // If no argument, report current indent style.
@@ -1256,7 +1291,7 @@ mod cmd {
12561291 Spaces(n) if (2..=8).contains(&n) => format!("{} spaces", n),
12571292 _ => "error".into(), // Shouldn't happen.
12581293 });
1259− return;
1294+ return Ok(());
12601295 }
12611296
12621297 // Attempt to parse argument as an indent style.
@@ -1274,15 +1309,19 @@ mod cmd {
12741309 if let Some(s) = style {
12751310 let doc = doc_mut!(cx.editor);
12761311 doc.indent_style = s;
1312+
1313+ Ok(())
12771314 } else {
1278− // Invalid argument.
1279− cx.editor
1280− .set_error(format!("invalid indent style '{}'", args[0],));
1315+ bail!("invalid indent style '{}'", args[0]);
12811316 }
12821317 }
12831318
12841319 /// Sets or reports the current document's line ending setting.
1285− fn set_line_ending(cx: &mut compositor::Context, args: &[&str], _event: PromptEvent) {
1320+ fn set_line_ending(
1321+ cx: &mut compositor::Context,
1322+ args: &[&str],
1323+ _event: PromptEvent,
1324+ ) -> anyhow::Result<()> {
12861325 use LineEnding::*;
12871326
12881327 // If no argument, report current line ending setting.
@@ -1298,7 +1337,8 @@ mod cmd {
12981337 // These should never be a document's default line ending.
12991338 VT | LS | PS => "error".into(),
13001339 });
1301− return;
1340+
1341+ return Ok(());
13021342 }
13031343
13041344 // Attempt to parse argument as a line ending.
@@ -1314,70 +1354,66 @@ mod cmd {
13141354
13151355 if let Some(le) = line_ending {
13161356 doc_mut!(cx.editor).line_ending = le;
1357+ Ok(())
13171358 } else {
1318− // Invalid argument.
1319− cx.editor
1320− .set_error(format!("invalid line ending '{}'", args[0],));
1359+ bail!("invalid line ending '{}'", args[0]);
13211360 }
13221361 }
13231362
1324− fn earlier(cx: &mut compositor::Context, args: &[&str], _event: PromptEvent) {
1325− let uk = match args.join(" ").parse::<helix_core::history::UndoKind>() {
1326− Ok(uk) => uk,
1327− Err(msg) => {
1328− cx.editor.set_error(msg);
1329− return;
1330− }
1331− };
1363+ fn earlier(
1364+ cx: &mut compositor::Context,
1365+ args: &[&str],
1366+ _event: PromptEvent,
1367+ ) -> anyhow::Result<()> {
1368+ let uk = args
1369+ .join(" ")
1370+ .parse::<helix_core::history::UndoKind>()
1371+ .map_err(|s| anyhow!(s))?;
1372+
13321373 let (view, doc) = current!(cx.editor);
1333− doc.earlier(view.id, uk)
1374+ doc.earlier(view.id, uk);
1375+
1376+ Ok(())
13341377 }
13351378
1336− fn later(cx: &mut compositor::Context, args: &[&str], _event: PromptEvent) {
1337− let uk = match args.join(" ").parse::<helix_core::history::UndoKind>() {
1338− Ok(uk) => uk,
1339− Err(msg) => {
1340− cx.editor.set_error(msg);
1341− return;
1342− }
1343− };
1379+ fn later(
1380+ cx: &mut compositor::Context,
1381+ args: &[&str],
1382+ _event: PromptEvent,
1383+ ) -> anyhow::Result<()> {
1384+ let uk = args
1385+ .join(" ")
1386+ .parse::<helix_core::history::UndoKind>()
1387+ .map_err(|s| anyhow!(s))?;
13441388 let (view, doc) = current!(cx.editor);
1345− doc.later(view.id, uk)
1389+ doc.later(view.id, uk);
1390+
1391+ Ok(())
13461392 }
13471393
1348− fn write_quit(cx: &mut compositor::Context, args: &[&str], event: PromptEvent) {
1349− match write_impl(cx, args.first()) {
1350− Ok(handle) => {
1351− if let Err(e) = helix_lsp::block_on(handle) {
1352− cx.editor.set_error(e.to_string());
1353− } else {
1354− quit(cx, &[], event);
1355− }
1356− }
1357− Err(e) => {
1358− cx.editor.set_error(e.to_string());
1359− }
1360− }
1394+ fn write_quit(
1395+ cx: &mut compositor::Context,
1396+ args: &[&str],
1397+ event: PromptEvent,
1398+ ) -> anyhow::Result<()> {
1399+ let handle = write_impl(cx, args.first())?;
1400+ helix_lsp::block_on(handle)?;
1401+ quit(cx, &[], event)
13611402 }
13621403
1363− fn force_write_quit(cx: &mut compositor::Context, args: &[&str], event: PromptEvent) {
1364− match write_impl(cx, args.first()) {
1365− Ok(handle) => {
1366− if let Err(e) = helix_lsp::block_on(handle) {
1367− cx.editor.set_error(e.to_string());
1368− } else {
1369− force_quit(cx, &[], event);
1370− }
1371− }
1372− Err(e) => {
1373− cx.editor.set_error(e.to_string());
1374− }
1375− }
1404+ fn force_write_quit(
1405+ cx: &mut compositor::Context,
1406+ args: &[&str],
1407+ event: PromptEvent,
1408+ ) -> anyhow::Result<()> {
1409+ let handle = write_impl(cx, args.first())?;
1410+ helix_lsp::block_on(handle)?;
1411+ force_quit(cx, &[], event)
13761412 }
13771413
1378− /// Returns `true` if there are modified buffers remaining and sets editor error,
1379− /// otherwise returns `false`
1380− fn buffers_remaining_impl(editor: &mut Editor) -> bool {
1414+ /// Results an error if there are modified buffers remaining and sets editor error,
1415+ /// otherwise returns `Ok(())`
1416+ fn buffers_remaining_impl(editor: &mut Editor) -> anyhow::Result<()> {
13811417 let modified: Vec<_> = editor
13821418 .documents()
13831419 .filter(|doc| doc.is_modified())
@@ -1388,16 +1424,13 @@ mod cmd {
13881424 })
13891425 .collect();
13901426 if !modified.is_empty() {
1391− let err = format!(
1427+ bail!(
13921428 "{} unsaved buffer(s) remaining: {:?}",
13931429 modified.len(),
13941430 modified
13951431 );
1396− editor.set_error(err);
1397− true
1398− } else {
1399− false
14001432 }
1433+ Ok(())
14011434 }
14021435
14031436 fn write_all_impl(
@@ -1406,7 +1439,7 @@ mod cmd {
14061439 _event: PromptEvent,
14071440 quit: bool,
14081441 force: bool,
1409− ) {
1442+ ) -> anyhow::Result<()> {
14101443 let mut errors = String::new();
14111444
14121445 // save all documents
@@ -1419,11 +1452,10 @@ mod cmd {
14191452 // TODO: handle error.
14201453 let _ = helix_lsp::block_on(tokio::spawn(doc.save()));
14211454 }
1422− editor.set_error(errors);
14231455
14241456 if quit {
1425− if !force && buffers_remaining_impl(editor) {
1426− return;
1457+ if !force {
1458+ buffers_remaining_impl(editor)?;
14271459 }
14281460
14291461 // close all views
@@ -1432,23 +1464,42 @@ mod cmd {
14321464 editor.close(view_id, false);
14331465 }
14341466 }
1467+
1468+ bail!(errors)
14351469 }
14361470
1437− fn write_all(cx: &mut compositor::Context, args: &[&str], event: PromptEvent) {
1471+ fn write_all(
1472+ cx: &mut compositor::Context,
1473+ args: &[&str],
1474+ event: PromptEvent,
1475+ ) -> anyhow::Result<()> {
14381476 write_all_impl(&mut cx.editor, args, event, false, false)
14391477 }
14401478
1441− fn write_all_quit(cx: &mut compositor::Context, args: &[&str], event: PromptEvent) {
1479+ fn write_all_quit(
1480+ cx: &mut compositor::Context,
1481+ args: &[&str],
1482+ event: PromptEvent,
1483+ ) -> anyhow::Result<()> {
14421484 write_all_impl(&mut cx.editor, args, event, true, false)
14431485 }
14441486
1445− fn force_write_all_quit(cx: &mut compositor::Context, args: &[&str], event: PromptEvent) {
1487+ fn force_write_all_quit(
1488+ cx: &mut compositor::Context,
1489+ args: &[&str],
1490+ event: PromptEvent,
1491+ ) -> anyhow::Result<()> {
14461492 write_all_impl(&mut cx.editor, args, event, true, true)
14471493 }
14481494
1449− fn quit_all_impl(editor: &mut Editor, _args: &[&str], _event: PromptEvent, force: bool) {
1450− if !force && buffers_remaining_impl(editor) {
1451− return;
1495+ fn quit_all_impl(
1496+ editor: &mut Editor,
1497+ _args: &[&str],
1498+ _event: PromptEvent,
1499+ force: bool,
1500+ ) -> anyhow::Result<()> {
1501+ if !force {
1502+ buffers_remaining_impl(editor)?;
14521503 }
14531504
14541505 // close all views
@@ -1456,57 +1507,82 @@ mod cmd {
14561507 for view_id in views {
14571508 editor.close(view_id, false);
14581509 }
1510+
1511+ Ok(())
14591512 }
14601513
1461− fn quit_all(cx: &mut compositor::Context, args: &[&str], event: PromptEvent) {
1514+ fn quit_all(
1515+ cx: &mut compositor::Context,
1516+ args: &[&str],
1517+ event: PromptEvent,
1518+ ) -> anyhow::Result<()> {
14621519 quit_all_impl(&mut cx.editor, args, event, false)
14631520 }
14641521
1465− fn force_quit_all(cx: &mut compositor::Context, args: &[&str], event: PromptEvent) {
1522+ fn force_quit_all(
1523+ cx: &mut compositor::Context,
1524+ args: &[&str],
1525+ event: PromptEvent,
1526+ ) -> anyhow::Result<()> {
14661527 quit_all_impl(&mut cx.editor, args, event, true)
14671528 }
14681529
1469− fn theme(cx: &mut compositor::Context, args: &[&str], _event: PromptEvent) {
1530+ fn theme(
1531+ cx: &mut compositor::Context,
1532+ args: &[&str],
1533+ _event: PromptEvent,
1534+ ) -> anyhow::Result<()> {
14701535 let theme = if let Some(theme) = args.first() {
14711536 theme
14721537 } else {
1473− cx.editor.set_error("theme name not provided".into());
1474− return;
1538+ bail!("theme name not provided");
14751539 };
14761540
1477− cx.editor.set_theme_from_name(theme);
1541+ cx.editor.set_theme_from_name(theme)
14781542 }
14791543
14801544 fn yank_main_selection_to_clipboard(
14811545 cx: &mut compositor::Context,
14821546 _args: &[&str],
14831547 _event: PromptEvent,
1484− ) {
1485− yank_main_selection_to_clipboard_impl(&mut cx.editor);
1548+ ) -> anyhow::Result<()> {
1549+ yank_main_selection_to_clipboard_impl(&mut cx.editor)
14861550 }
14871551
1488− fn yank_joined_to_clipboard(cx: &mut compositor::Context, args: &[&str], _event: PromptEvent) {
1552+ fn yank_joined_to_clipboard(
1553+ cx: &mut compositor::Context,
1554+ args: &[&str],
1555+ _event: PromptEvent,
1556+ ) -> anyhow::Result<()> {
14891557 let (_, doc) = current!(cx.editor);
14901558 let separator = args
14911559 .first()
14921560 .copied()
14931561 .unwrap_or_else(|| doc.line_ending.as_str());
1494− yank_joined_to_clipboard_impl(&mut cx.editor, separator);
1562+ yank_joined_to_clipboard_impl(&mut cx.editor, separator)
14951563 }
14961564
1497− fn paste_clipboard_after(cx: &mut compositor::Context, _args: &[&str], _event: PromptEvent) {
1498− paste_clipboard_impl(&mut cx.editor, Paste::After);
1565+ fn paste_clipboard_after(
1566+ cx: &mut compositor::Context,
1567+ _args: &[&str],
1568+ _event: PromptEvent,
1569+ ) -> anyhow::Result<()> {
1570+ paste_clipboard_impl(&mut cx.editor, Paste::After)
14991571 }
15001572
1501− fn paste_clipboard_before(cx: &mut compositor::Context, _args: &[&str], _event: PromptEvent) {
1502− paste_clipboard_impl(&mut cx.editor, Paste::After);
1573+ fn paste_clipboard_before(
1574+ cx: &mut compositor::Context,
1575+ _args: &[&str],
1576+ _event: PromptEvent,
1577+ ) -> anyhow::Result<()> {
1578+ paste_clipboard_impl(&mut cx.editor, Paste::After)
15031579 }
15041580
15051581 fn replace_selections_with_clipboard(
15061582 cx: &mut compositor::Context,
15071583 _args: &[&str],
15081584 _event: PromptEvent,
1509− ) {
1585+ ) -> anyhow::Result<()> {
15101586 let (view, doc) = current!(cx.editor);
15111587
15121588 match cx.editor.clipboard_provider.get_contents() {
@@ -1520,71 +1596,89 @@ mod cmd {
15201596
15211597 doc.apply(&transaction, view.id);
15221598 doc.append_changes_to_history(view.id);
1599+ Ok(())
1600+ }
1601+ Err(e) => {
1602+ log::error!("Couldn't get system clipboard contents: {:?}", e);
1603+ bail!("Couldn't get system clipboard contents: {:?}", e);
15231604 }
1524− Err(e) => log::error!("Couldn't get system clipboard contents: {:?}", e),
15251605 }
15261606 }
15271607
1528− fn show_clipboard_provider(cx: &mut compositor::Context, _args: &[&str], _event: PromptEvent) {
1608+ fn show_clipboard_provider(
1609+ cx: &mut compositor::Context,
1610+ _args: &[&str],
1611+ _event: PromptEvent,
1612+ ) -> anyhow::Result<()> {
15291613 cx.editor
15301614 .set_status(cx.editor.clipboard_provider.name().into());
1615+ Ok(())
15311616 }
15321617
1533− fn change_current_directory(cx: &mut compositor::Context, args: &[&str], _event: PromptEvent) {
1534− let dir = match args.first() {
1535− Some(dir) => dir,
1536− None => {
1537− cx.editor.set_error("target directory not provided".into());
1538− return;
1539− }
1540− };
1618+ fn change_current_directory(
1619+ cx: &mut compositor::Context,
1620+ args: &[&str],
1621+ _event: PromptEvent,
1622+ ) -> anyhow::Result<()> {
1623+ let dir = args
1624+ .first()
1625+ .ok_or_else(|| anyhow!("target directory not provided"))?;
15411626
15421627 if let Err(e) = std::env::set_current_dir(dir) {
1543− cx.editor.set_error(format!(
1544− "Couldn't change the current working directory: {:?}",
1545− e
1546− ));
1547− return;
1628+ bail!("Couldn't change the current working directory: {:?}", e);
15481629 }
15491630
15501631 match std::env::current_dir() {
1551− Ok(cwd) => cx.editor.set_status(format!(
1552− "Current working directory is now {}",
1553− cwd.display()
1554− )),
1555− Err(e) => cx
1556− .editor
1557− .set_error(format!("Couldn't get the new working directory: {}", e)),
1632+ Ok(cwd) => {
1633+ cx.editor.set_status(format!(
1634+ "Current working directory is now {}",
1635+ cwd.display()
1636+ ));
1637+ Ok(())
1638+ }
1639+ Err(e) => bail!("Couldn't get the new working directory: {}", e),
15581640 }
15591641 }
15601642
1561− fn show_current_directory(cx: &mut compositor::Context, _args: &[&str], _event: PromptEvent) {
1643+ fn show_current_directory(
1644+ cx: &mut compositor::Context,
1645+ _args: &[&str],
1646+ _event: PromptEvent,
1647+ ) -> anyhow::Result<()> {
15621648 match std::env::current_dir() {
1563− Ok(cwd) => cx
1564− .editor
1565− .set_status(format!("Current working directory is {}", cwd.display())),
1566− Err(e) => cx
1567− .editor
1568− .set_error(format!("Couldn't get the current working directory: {}", e)),
1649+ Ok(cwd) => {
1650+ cx.editor
1651+ .set_status(format!("Current working directory is {}", cwd.display()));
1652+ Ok(())
1653+ }
1654+ Err(e) => bail!("Couldn't get the current working directory: {}", e),
15691655 }
15701656 }
15711657
15721658 /// Sets the [`Document`]'s encoding..
1573− fn set_encoding(cx: &mut compositor::Context, args: &[&str], _: PromptEvent) {
1659+ fn set_encoding(
1660+ cx: &mut compositor::Context,
1661+ args: &[&str],
1662+ _event: PromptEvent,
1663+ ) -> anyhow::Result<()> {
15741664 let (_, doc) = current!(cx.editor);
15751665 if let Some(label) = args.first() {
15761666 doc.set_encoding(label)
1577− .unwrap_or_else(|e| cx.editor.set_error(e.to_string()));
15781667 } else {
15791668 let encoding = doc.encoding().name().to_string();
1580− cx.editor.set_status(encoding)
1669+ cx.editor.set_status(encoding);
1670+ Ok(())
15811671 }
15821672 }
15831673
15841674 /// Reload the [`Document`] from its source file.
1585− fn reload(cx: &mut compositor::Context, _args: &[&str], _: PromptEvent) {
1675+ fn reload(
1676+ cx: &mut compositor::Context,
1677+ _args: &[&str],
1678+ _event: PromptEvent,
1679+ ) -> anyhow::Result<()> {
15861680 let (view, doc) = current!(cx.editor);
1587− doc.reload(view.id).unwrap();
1681+ doc.reload(view.id)
15881682 }
15891683
15901684 pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
@@ -1849,7 +1943,9 @@ fn command_mode(cx: &mut Context) {
18491943 }
18501944
18511945 if let Some(cmd) = cmd::COMMANDS.get(parts[0]) {
1852− (cmd.fun)(cx, &parts[1..], event);
1946+ if let Err(e) = (cmd.fun)(cx, &parts[1..], event) {
1947+ cx.editor.set_error(format!("{}", e));
1948+ }
18531949 } else {
18541950 cx.editor
18551951 .set_error(format!("no such command: '{}'", parts[0]));
@@ -2758,7 +2854,7 @@ fn yank(cx: &mut Context) {
27582854 cx.editor.set_status(msg)
27592855}
27602856
2761−fn yank_joined_to_clipboard_impl(editor: &mut Editor, separator: &str) {
2857+fn yank_joined_to_clipboard_impl(editor: &mut Editor, separator: &str) -> anyhow::Result<()> {
27622858 let (view, doc) = current!(editor);
27632859
27642860 let values: Vec<String> = doc
@@ -2776,17 +2872,20 @@ fn yank_joined_to_clipboard_impl(editor: &mut Editor, separator: &str) {
27762872
27772873 if let Err(e) = editor.clipboard_provider.set_contents(joined) {
27782874 log::error!("Couldn't set system clipboard content: {:?}", e);
2875+ bail!("Couldn't set system clipboard content: {:?}", e);
27792876 }
27802877
27812878 editor.set_status(msg);
2879+
2880+ Ok(())
27822881}
27832882
27842883fn yank_joined_to_clipboard(cx: &mut Context) {
27852884 let line_ending = current!(cx.editor).1.line_ending;
2786− yank_joined_to_clipboard_impl(&mut cx.editor, line_ending.as_str());
2885+ let _ = yank_joined_to_clipboard_impl(&mut cx.editor, line_ending.as_str());
27872886}
27882887
2789−fn yank_main_selection_to_clipboard_impl(editor: &mut Editor) {
2888+fn yank_main_selection_to_clipboard_impl(editor: &mut Editor) -> anyhow::Result<()> {
27902889 let (view, doc) = current!(editor);
27912890
27922891 let value = doc
@@ -2796,13 +2895,15 @@ fn yank_main_selection_to_clipboard_impl(editor: &mut Editor) {
27962895
27972896 if let Err(e) = editor.clipboard_provider.set_contents(value.into_owned()) {
27982897 log::error!("Couldn't set system clipboard content: {:?}", e);
2898+ bail!("Couldn't set system clipboard content: {:?}", e);
27992899 }
28002900
28012901 editor.set_status("yanked main selection to system clipboard".to_owned());
2902+ Ok(())
28022903}
28032904
28042905fn yank_main_selection_to_clipboard(cx: &mut Context) {
2805− yank_main_selection_to_clipboard_impl(&mut cx.editor);
2906+ let _ = yank_main_selection_to_clipboard_impl(&mut cx.editor);
28062907}
28072908
28082909#[derive(Copy, Clone)]
@@ -2850,7 +2951,7 @@ fn paste_impl(
28502951 Some(transaction)
28512952}
28522953
2853−fn paste_clipboard_impl(editor: &mut Editor, action: Paste) {
2954+fn paste_clipboard_impl(editor: &mut Editor, action: Paste) -> anyhow::Result<()> {
28542955 let (view, doc) = current!(editor);
28552956
28562957 match editor
@@ -2861,18 +2962,22 @@ fn paste_clipboard_impl(editor: &mut Editor, action: Paste) {
28612962 Ok(Some(transaction)) => {
28622963 doc.apply(&transaction, view.id);
28632964 doc.append_changes_to_history(view.id);
2965+ Ok(())
2966+ }
2967+ Ok(None) => Ok(()),
2968+ Err(e) => {
2969+ log::error!("Couldn't get system clipboard contents: {:?}", e);
2970+ bail!("Couldn't get system clipboard contents: {:?}", e);
28642971 }
2865− Ok(None) => {}
2866− Err(e) => log::error!("Couldn't get system clipboard contents: {:?}", e),
28672972 }
28682973}
28692974
28702975fn paste_clipboard_after(cx: &mut Context) {
2871− paste_clipboard_impl(&mut cx.editor, Paste::After);
2976+ let _ = paste_clipboard_impl(&mut cx.editor, Paste::After);
28722977}
28732978
28742979fn paste_clipboard_before(cx: &mut Context) {
2875− paste_clipboard_impl(&mut cx.editor, Paste::Before);
2980+ let _ = paste_clipboard_impl(&mut cx.editor, Paste::Before);
28762981}
28772982
28782983fn replace_with_yanked(cx: &mut Context) {