X.P.OrgMode: Linkify URLs in orgPromptPrimary

If we have a URL in the clipboard and we use `orgPromptPrimary`, it
would be nice if

    message +s 11 jan 2013

would result in

    * TODO [[_URL_][message]]
      SCHEDULED: <2013-01-11 Fri>

instead of the current

    * TODO message
      SCHEDULED: <2013-01-11 Fri>
      _URL_

This has the advantage that if one shows scheduled or deadlines items in
the org-agenda, it is possible to immediately follow this link with
`C-c C-o` or similar functionality.

The URL detection is very rudimentary right now.  One use `parseURI`
from `network-uri`, but that would be an additional dependency that I
didn't think was worth it.
This commit is contained in:
slotThe 2021-06-10 15:46:48 +02:00
parent 5da9b26142
commit c9ca4ce026

View File

@ -145,6 +145,11 @@ data ClipboardSupport
= PrimarySelection = PrimarySelection
| NoClpSupport | NoClpSupport
-- | How one should display the clipboard string.
data Clp
= Header String -- ^ In the header as a link: @* [[clp][message]]@
| Body String -- ^ In the body as additional text: @* message \n clp@
instance XPrompt OrgMode where instance XPrompt OrgMode where
showXPrompt :: OrgMode -> String showXPrompt :: OrgMode -> String
showXPrompt OrgMode{ todoHeader, orgFile, clpSupport } = showXPrompt OrgMode{ todoHeader, orgFile, clpSupport } =
@ -163,8 +168,12 @@ orgPrompt
-> X () -> X ()
orgPrompt xpc = mkOrgPrompt xpc .: OrgMode NoClpSupport orgPrompt xpc = mkOrgPrompt xpc .: OrgMode NoClpSupport
-- | Like 'orgPrompt', but fill in the primary selection as the contents -- | Like 'orgPrompt', but additionally make use of the primary
-- of the note. The prompt will display a little @+ PS@ in the window -- selection. If it is a URL, then use an org-style link
-- @[[primary-selection][entered message]]@ as the heading. Otherwise,
-- use the primary selection as the content of the note.
--
-- The prompt will display a little @+ PS@ in the window
-- after the type of note. -- after the type of note.
orgPromptPrimary :: XPConfig -> String -> FilePath -> X () orgPromptPrimary :: XPConfig -> String -> FilePath -> X ()
orgPromptPrimary xpc = mkOrgPrompt xpc .: OrgMode PrimarySelection orgPromptPrimary xpc = mkOrgPrompt xpc .: OrgMode PrimarySelection
@ -179,8 +188,12 @@ mkOrgPrompt xpc oc@OrgMode{ todoHeader, orgFile, clpSupport } =
appendNote :: String -> X () appendNote :: String -> X ()
appendNote input = io $ do appendNote input = io $ do
clpStr <- case clpSupport of clpStr <- case clpSupport of
NoClpSupport -> pure "" NoClpSupport -> pure $ Body ""
PrimarySelection -> ("\n " <>) <$> getSelection PrimarySelection -> do
sel <- getSelection
pure $ if any (`isPrefixOf` sel) ["http://", "https://"]
then Header sel
else Body $ "\n " <> sel
-- Expand relative path with $HOME -- Expand relative path with $HOME
fp <- case orgFile of fp <- case orgFile of
@ -295,16 +308,20 @@ data Note
| NormalMsg String | NormalMsg String
-- | Pretty print a given 'Note'. -- | Pretty print a given 'Note'.
ppNote :: String -> String -> Note -> IO String ppNote :: Clp -> String -> Note -> IO String
ppNote clp todo = \case ppNote clp todo = \case
Scheduled str time -> mkLine str "SCHEDULED: " time Scheduled str time -> mkLine str "SCHEDULED: " (Just time)
Deadline str time -> mkLine str "DEADLINE: " time Deadline str time -> mkLine str "DEADLINE: " (Just time)
NormalMsg str -> pure . mconcat $ ["* ", todo, " ", str, clp] NormalMsg str -> mkLine str "" Nothing
where where
mkLine :: String -> String -> Time -> IO String mkLine :: String -> String -> Maybe Time -> IO String
mkLine inp sched mkLine str sched time = do
= fmap (\d -> mconcat ["* ", todo, " ", inp, "\n ", sched, d, clp]) t <- case time of
. ppDate Nothing -> pure ""
Just ti -> (("\n " <> sched) <>) <$> ppDate ti
pure $ case clp of
Body c -> mconcat ["* ", todo, " ", str, t, c]
Header c -> mconcat ["* ", todo, " [[", c, "][", str,"]]", t]
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- Parsing -- Parsing