diff --git a/README.md b/README.md index ddc16ba..f280f33 100644 --- a/README.md +++ b/README.md @@ -275,6 +275,7 @@ Shows the version of `miv`. - `function`: load the plugin on calling a function matching the value in regex - `mapping`: load the plugin on the mapping - `mapmode`: specify the mapmode for the `mapping` configuration (for example: `o`, `v`) +- `cmdline`: specify the cmdline character to load the plugin (for example: `:`, `/`) - `insert`: load the plugin on entering the insert mode for the first time - `enable`: enable the plugin when the expression (in Vim script) is 1 - `mapleader`: specify the mapleader (``) for the `script` configuration diff --git a/miv.cabal b/miv.cabal index b066158..70ae003 100644 --- a/miv.cabal +++ b/miv.cabal @@ -19,6 +19,7 @@ executable miv , Setting , Mode , Command + , Cmdline , Mapping , ShowText , ReadText diff --git a/src/Cmdline.hs b/src/Cmdline.hs new file mode 100644 index 0000000..d681da2 --- /dev/null +++ b/src/Cmdline.hs @@ -0,0 +1,51 @@ +{-# LANGUAGE OverloadedStrings #-} +module Cmdline where + +import Data.Aeson +import qualified Data.Aeson as Aeson +import Data.Hashable +import Data.Text (Text,unpack) +import Prelude hiding (show) +import qualified Prelude as Prelude + +import ReadText +import ShowText + +data Cmdline = CmdlineExCommand + | CmdlineForwardSearch + | CmdlineBackwardSearch + | CmdlineInput + deriving (Eq, Ord) + +instance ShowText Cmdline where + show CmdlineExCommand = ":" + show CmdlineForwardSearch = "/" + show CmdlineBackwardSearch = "?" + show CmdlineInput = "@" + +instance ReadText Cmdline where + read ":" = CmdlineExCommand + read "/" = CmdlineForwardSearch + read "?" = CmdlineBackwardSearch + read "@" = CmdlineInput + read m = error $ "unknown cmdline: " ++ unpack m + +instance Hashable Cmdline where + hashWithSalt a CmdlineExCommand = a `hashWithSalt` (0 :: Int) + hashWithSalt a CmdlineForwardSearch = a `hashWithSalt` (1 :: Int) + hashWithSalt a CmdlineBackwardSearch = a `hashWithSalt` (2 :: Int) + hashWithSalt a CmdlineInput = a `hashWithSalt` (3 :: Int) + +instance FromJSON Cmdline where + parseJSON (Aeson.String str) + | unpack str == ":" = return CmdlineExCommand + | unpack str == "/" = return CmdlineForwardSearch + | unpack str == "?" = return CmdlineBackwardSearch + | unpack str == "@" = return CmdlineInput + parseJSON o = error $ "failed to parse cmdline: " <> Prelude.show o + +cmdlinePattern :: Cmdline -> Text +cmdlinePattern CmdlineExCommand = ":" +cmdlinePattern CmdlineForwardSearch = "/" +cmdlinePattern CmdlineBackwardSearch = "\\?" +cmdlinePattern CmdlineInput = "@" diff --git a/src/Plugin.hs b/src/Plugin.hs index 4cdb861..99552cd 100644 --- a/src/Plugin.hs +++ b/src/Plugin.hs @@ -6,6 +6,7 @@ import Data.Aeson import qualified Data.Text as T import Data.Text (Text, unpack) +import Cmdline import ShowText data Plugin = @@ -15,6 +16,7 @@ data Plugin = , functions :: [Text] , mappings :: [Text] , mapmodes :: [Text] + , cmdlines :: [Cmdline] , insert :: Bool , enable :: Text , sync :: Bool @@ -50,6 +52,7 @@ instance FromJSON Plugin where functions <- o .: "function" <|> (fmap return <$> o .:? "function") .!= [] mappings <- o .: "mapping" <|> (fmap return <$> o .:? "mapping") .!= [] mapmodes <- o .: "mapmode" <|> (fmap return <$> o .:? "mapmode") .!= [] + cmdlines <- o .: "cmdline" <|> (fmap return <$> o .:? "cmdline") .!= [] mapleader <- o .:? "mapleader" .!= "" insert <- o .:? "insert" .!= False enable <- o .:? "enable" .!= "" diff --git a/src/VimScript.hs b/src/VimScript.hs index 19e519e..0e7bf28 100644 --- a/src/VimScript.hs +++ b/src/VimScript.hs @@ -1,17 +1,18 @@ {-# LANGUAGE DeriveGeneric, OverloadedStrings #-} module VimScript where -import Data.Char (isAlpha, isAlphaNum, toLower) +import Data.Char (isAlpha, isAlphaNum, ord, toLower) import Data.Function (on) import Data.Hashable import qualified Data.HashMap.Lazy as HM import Data.List (foldl', groupBy, sort, sortBy, nub) import Data.Maybe (mapMaybe) -import Data.Text (Text, unwords, singleton) +import Data.Text (Text, singleton, unpack, unwords) import qualified Data.Text as T import GHC.Generics (Generic) import Prelude hiding (show, unwords, read) +import Cmdline import qualified Command as C import qualified Mapping as M import Mode @@ -78,6 +79,7 @@ gatherScript setting = addAutoloadNames <> foldl' (<>) mempty (map pluginConfig plugins) <> filetypeLoader setting <> funcUndefinedLoader setting + <> cmdlineEnterLoader setting <> insertEnterLoader setting <> filetypeScript (S.filetype setting) <> syntaxScript (S.syntax setting) @@ -151,7 +153,7 @@ pluginConfig plg loadScript :: P.Plugin -> [Text] loadScript plg | all null [ P.commands plg, P.mappings plg, P.functions plg, P.filetypes plg - , P.loadafter plg, P.loadbefore plg ] && not (P.insert plg) + , P.loadafter plg, P.loadbefore plg ] && null (P.cmdlines plg) && not (P.insert plg) = ["call miv#load(" <> singleQuote (show plg) <> ")"] | otherwise = [] @@ -312,6 +314,29 @@ funcUndefinedLoader _ = VimScript (HM.singleton Plugin , "endfunction" ]) +cmdlineEnterLoader :: S.Setting -> VimScript +cmdlineEnterLoader setting + = HM.foldrWithKey f mempty $ + foldr (uncurry (HM.insertWith (<>))) HM.empty + [ (cmdline, [p]) | p <- S.plugins setting, cmdline <- P.cmdlines p ] + where + f :: Cmdline -> [P.Plugin] -> VimScript -> VimScript + f cmdline plugins val = val <> VimScript (HM.singleton Plugin + [ "\" CmdlineEnter " <> (show cmdline) + , "augroup " <> group + , " autocmd!" + , " autocmd CmdlineEnter " <> (cmdlinePattern cmdline) <> " call miv#cmdline_enter_" <> c <> "()" + , "augroup END" ]) + <> VimScript (HM.singleton (Autoload "") $ + ("function! miv#cmdline_enter_" <> c <> "() abort") : + [ " call miv#load(" <> singleQuote (show p) <> ")" | p <- plugins ] + <> [ " autocmd! " <> group + , " augroup! " <> group + , "endfunction" + ]) + where c = T.concat $ map (show . ord) (unpack (show cmdline)) + group = "miv-cmdline-enter-" <> c + insertEnterLoader :: S.Setting -> VimScript insertEnterLoader setting = if null plugins then mempty else VimScript (HM.singleton Plugin [ "\" InsertEnter"