miv 0.4.4 → 0.4.5
raw patch · 4 files changed
+139/−45 lines, 4 files
Files
- miv.cabal +2/−1
- src/Cmdline.hs +51/−0
- src/Plugin.hs +3/−0
- src/VimScript.hs +83/−44
miv.cabal view
@@ -1,5 +1,5 @@ name: miv-version: 0.4.4+version: 0.4.5 author: itchyny <https://github.com/itchyny> maintainer: itchyny <https://github.com/itchyny> license: MIT@@ -19,6 +19,7 @@ , Setting , Mode , Command+ , Cmdline , Mapping , ShowText , ReadText
+ src/Cmdline.hs view
@@ -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 = "@"
src/Plugin.hs view
@@ -6,6 +6,7 @@ import qualified Data.Text as T import Data.Text (Text, unpack) +import Cmdline import ShowText data Plugin =@@ -15,6 +16,7 @@ , functions :: [Text] , mappings :: [Text] , mapmodes :: [Text]+ , cmdlines :: [Cmdline] , insert :: Bool , enable :: Text , sync :: Bool@@ -50,6 +52,7 @@ 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" .!= ""
src/VimScript.hs view
@@ -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@@ -33,7 +34,7 @@ hashWithSalt a Plugin = a `hashWithSalt` (0 :: Int) `hashWithSalt` ("" :: Text) hashWithSalt a (Autoload s) = a `hashWithSalt` (1 :: Int) `hashWithSalt` s hashWithSalt a (Ftplugin s) = a `hashWithSalt` (2 :: Int) `hashWithSalt` s- hashWithSalt a (Syntax s) = a `hashWithSalt` (2 :: Int) `hashWithSalt` s+ hashWithSalt a (Syntax s) = a `hashWithSalt` (3 :: Int) `hashWithSalt` s instance ShowText Place where show Plugin = "plugin/miv.vim"@@ -71,13 +72,15 @@ <> gather' "dependedby" P.dependedby P.loadafter plugins <> gather "mappings" P.mappings plugins <> gather "mapmodes" P.mapmodes plugins- <> gatherFuncUndefined setting+ <> gather "functions" P.functions plugins <> pluginLoader <> mappingLoader <> commandLoader <> foldl' (<>) mempty (map pluginConfig plugins) <> filetypeLoader setting- <> gatherInsertEnter setting+ <> funcUndefinedLoader setting+ <> cmdlineEnterLoader setting+ <> insertEnterLoader setting <> filetypeScript (S.filetype setting) <> syntaxScript (S.syntax setting) <> afterScript setting@@ -150,7 +153,7 @@ 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 = [] @@ -179,7 +182,7 @@ <> singleQuote (show mode) <> ")<CR>" , M.mapMode = mode } | c <- P.mappings plg] escape m = if m `elem` [ InsertMode, OperatorPendingMode ] then "<ESC>" else ""- modes = if null (P.mapmodes plg) then [NormalMode, VisualMode] else map read (P.mapmodes plg)+ modes = if null (P.mapmodes plg) then [NormalMode] else map read (P.mapmodes plg) in concat [map (show . f) modes | f <- genMapping] | otherwise = [] @@ -201,11 +204,12 @@ in val <> VimScript (HM.singleton (Autoload (singleton c)) (("function! " <> funcname <> "() abort")- : " setl ft="+ : " setlocal filetype=" : concat [wrapEnable b [ " call miv#load(" <> singleQuote (show b) <> ")"] | b <- plg] <> [ " autocmd! miv-file-type-" <> ft- , " setl ft=" <> ft+ , " augroup! miv-file-type-" <> ft+ , " setlocal filetype=" <> ft , " silent! doautocmd FileType " <> ft , "endfunction" ]))@@ -223,40 +227,6 @@ | otherwise = filetypeLoadPlugins plugins fts filetypeLoadPlugins [] fts = fts -gatherInsertEnter :: S.Setting -> VimScript-gatherInsertEnter setting- = VimScript (HM.singleton Plugin (f [ p | p <- S.plugins setting, P.insert p ]))- where f [] = []- f plgs = "\" InsertEnter"- : "function! s:insertEnter() abort"- : [ " call miv#load(" <> singleQuote (show p) <> ")" | p <- plgs :: [P.Plugin] ]- <> [ " autocmd! miv-insert-enter"- , " silent! doautocmd InsertEnter"- , "endfunction"- , ""- , "augroup miv-insert-enter"- , " autocmd!"- , " autocmd InsertEnter * call s:insertEnter()"- , "augroup END" ]--gatherFuncUndefined :: S.Setting -> VimScript-gatherFuncUndefined setting- = VimScript (HM.singleton Plugin (f [ p | p <- S.plugins setting, not (null (P.functions p))]))- where f [] = []- f plgs = "\" FuncUndefined"- : "function! s:funcUndefined() abort"- : " let f = expand('<amatch>')"- : concat [- [ " if f =~# " <> singleQuote q- , " call miv#load(" <> singleQuote (show p) <> ")"- , " endif" ] | (p, q) <- concatMap (\q -> map ((,) q) (P.functions q)) plgs]- <> [ "endfunction"- , ""- , "augroup miv-func-undefined"- , " autocmd!"- , " autocmd FuncUndefined * call s:funcUndefined()"- , "augroup END" ]- wrapEnable :: P.Plugin -> [Text] -> [Text] wrapEnable plg str | null str = []@@ -318,6 +288,72 @@ , "endfunction" ]) +funcUndefinedLoader :: S.Setting -> VimScript+funcUndefinedLoader setting | all (null . P.functions) (S.plugins setting) = mempty+funcUndefinedLoader _ = VimScript (HM.singleton Plugin+ [ "\" FuncUndefined"+ , "augroup miv-func-undefined"+ , " autocmd!"+ , " autocmd FuncUndefined * call miv#func_undefined(expand('<amatch>'))"+ , "augroup END" ])+ <> VimScript (HM.singleton (Autoload "")+ [ "function! miv#func_undefined(pattern) abort"+ , " if empty(s:functions)"+ , " autocmd! miv-func-undefined"+ , " augroup! miv-func-undefined"+ , " return"+ , " endif"+ , " for [name, fs] in items(s:functions)"+ , " for f in fs"+ , " if a:pattern =~# f"+ , " call miv#load(name)"+ , " return"+ , " endif"+ , " endfor"+ , " endfor"+ , "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"+ , "augroup miv-insert-enter"+ , " autocmd!"+ , " autocmd InsertEnter * call miv#insert_enter()"+ , "augroup END" ])+ <> VimScript (HM.singleton (Autoload "")+ $ "function! miv#insert_enter() abort" :+ [ " call miv#load(" <> singleQuote (show p) <> ")" | p <- plugins ]+ <> [ " autocmd! miv-insert-enter"+ , " augroup! miv-insert-enter"+ , " silent! doautocmd InsertEnter"+ , "endfunction"+ ])+ where plugins = filter P.insert (S.plugins setting)+ pluginLoader :: VimScript pluginLoader = VimScript (HM.singleton (Autoload "") [ "let s:loaded = {}"@@ -328,10 +364,13 @@ , " return" , " endif" , " let s:loaded[a:name] = 1"+ , " if has_key(s:functions, a:name)"+ , " call remove(s:functions, a:name)"+ , " endif" , " for n in get(s:dependon, a:name, [])" , " call miv#load(n)" , " endfor"- , " for mode in get(s:mapmodes, a:name, [ 'n', 'v' ])"+ , " for mode in get(s:mapmodes, a:name, ['n'])" , " for mapping in get(s:mappings, a:name, [])" , " silent! execute mode . 'unmap' mapping" , " endfor"