hbb 0.3.0.1 → 0.4.0.0
raw patch · 4 files changed
+185/−35 lines, 4 filesdep ~libhbb
Dependency ranges changed: libhbb
Files
- README.md +82/−0
- editor-plugin/vim/hbb.vim +59/−0
- hbb.cabal +5/−2
- src/HBB.hs +39/−33
+ README.md view
@@ -0,0 +1,82 @@+# **hbb**: Extraordinary Haskell programming + +This project aims to create a tool which should be easily embeddable in text +editors to assist them to provide extraordinary editing features for the +Haskell programming language. To archieve this, the tool will is based on the +library of the Glasgow Haskell Compiler (GHC) and the tool *ghc-mod* which +already improves text editors with a certain number of features. + +The name **hbb** is short for *h*askell *b*usy *b*ee and should remind one of +the programmers using it. + +The central library of *hbb* has been split apart into its own cabal package +which has the name *libhbb*. This library also ships an executable (named +*libhbb-cli*) which has reduced functionality compared to *hbb*. *hbb* is able +to provide much more functionality because it builds upon the library of +*ghc-mod*. Altogether the following dependencies materialize: + + +---------+ + | hbb | + +---------+ + | (exe) | + | | + v v + +---------+ +--------+ + | ghc-mod | | libhbb | + +---------+ +--------+ + (lib & exe) (lib & exe) + +*hbb* as well as *ghc-mod* (as well as *libhbb-cli*) have different mode of +operations which are dictated by a command line parameter. The target of +*hbb* is it to extend *ghc-mod* which has currently (as of 2014-09-23) a total +of 16 modes (including things like *help*) by certain things. + +One outstanding feature *hbb* wants to add is the ability to replace the +occurence of a function name by an inlined version of its body (its lambda +representation). + +# Extract from the *hbb help* + + hbb version 0.4.0.0 compiled by GHC 7.6.3 + Usage: + hbb list [-g GHC_opt1 -g GHC_opt2 ...] [-l] [-d] + hbb lang [-l] + hbb flag [-l] + hbb browse [-g GHC_opt1 -g GHC_opt2 ...] [-l] [-o] [-d] [-q] [<package>:]<module> [[<package>:]<module> ...] + hbb check [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFiles...> + hbb expand [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFiles...> + hbb debug [-g GHC_opt1 -g GHC_opt2 ...] + hbb info [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFile> <module> <expression> + hbb type [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFile> <module> <line-no> <column-no> + hbb split [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFile> <module> <line-no> <column-no> + hbb sig [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFile> <module> <line-no> <column-no> + hbb refine [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFile> <module> <line-no> <column-no> <expression> + hbb auto [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFile> <module> <line-no> <column-no> + hbb find <symbol> + hbb lint [-h opt] <HaskellFile> + ---------- modes supported by libhbb ------------ + hbb locate [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFile> <line-no> <column-no> + hbb inline [-g GHC_opt1 -g GHC_opt2 ...] [--adapt-ind] <HaskellFile> <line-no> <column-no> [<line-no> <column-no>] + hbb smart-inline [-g GHC_opt1 -g GHC_opt2 ...] [--adapt-ind] <HaskellFile> <line-no> <column-no> [<line-no> <column-no>] + hbb occurrences-of [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFile> <line-no> <column-no> [<HaskellFile> ...] + hbb exprtype [-g GHC_opt1 -g GHC_opt2 ...] <HaskellFile> <expression> + hbb apply-to [-g GHC_opt1 -g GHC_opt2 ...] [-q] <Function of String to String> <Subject of String> + --- end of modes supported by libhbb ------------ + hbb root + hbb doc <module> + hbb boot + hbb version + hbb help + + <module> for "info" and "type" is not used, anything is OK. + It is necessary to maintain backward compatibility. + + -l --tolisp print as a list of Lisp + -h hlintOpt --hlintOpt=hlintOpt hlint options + -g ghcOpt --ghcOpt=ghcOpt GHC options + -v --verbose verbose + -o --operators print operators, too + -d --detailed print detailed info + -q --qualified, --quiet show qualified names / suppress warning (quiet) in mode apply-to + -b sep --boundary=sep specify line separator (default is Nul string) + --adapt-ind Adapt the indentation of non-first lines to the (possibly higher) ind of the target environment
+ editor-plugin/vim/hbb.vim view
@@ -0,0 +1,59 @@++:let g:hbb_executable_name = "hbb"++" ghc options must be written in the same way they are passed to hbb which+" means that each option must be prepended by '-g'. For example+" let g:hbb_ghc_options = '-g -isrc -g -packageghc -g -XFlexibleInstances'+:let g:hbb_ghc_options = ""++" This function inlines the currently selected function or prints an error+" message if inlining fails.+" If any argument is passed then the file is saved after inlining.+function! HBBInlineSelection( ... )+ :let curline = getline('.')+ :let startpos = getpos( "'<" )+ :let endpos = getpos( "'>" )+ :let curfile = expand('%')+ :let commandstr = g:hbb_executable_name . " " . g:hbb_ghc_options . " inline --adapt-ind " . curfile . " " . startpos[1] . " " . startpos[2] . " " . endpos[1] . " " . (endpos[2] + 1) . " 2>./.vim-hbb.log"+ :let fun = system( commandstr )+ :let errorreason = readfile( "./.vim-hbb.log" ) + :call delete("./.vim-hbb.log")+ :if len( fun ) == 0+ :let errorreason_copy = copy( errorreason )+ :let errorreason_copy[0] = "Inlining failed: " . errorreason[0]+ :echo join( errorreason_copy , "\n" )+ :else+ :let funnamelen = endpos[2] - startpos[2] + 1++ :if startpos[2] < 2+ :let curlineprefix = ""+ :else+ :let curlineprefix = curline[0:(startpos[2]-2)]+ :endif+ :let curlinesuffix = curline[startpos[2]+funnamelen-1:]+ :let content2insertAsList = split( fun , '\n' )+ :let firstlineEnd = content2insertAsList[0]+ :let lastlineStart = content2insertAsList[-1]+ :if len( content2insertAsList ) >= 2+ " This is a multiline entry...+ :call remove( content2insertAsList , 0 )+ :call remove( content2insertAsList , len( content2insertAsList ) - 1 )+ :call insert( content2insertAsList , curlineprefix . firstlineEnd )+ :call add( content2insertAsList , lastlineStart . curlinesuffix )+ :else+ " This is a single-line entry...+ :let content2insertAsList[0] = curlineprefix . content2insertAsList[0] . curlinesuffix+ :endif+ :call setline( '.' , content2insertAsList[0] )+ :call append( line('.') , content2insertAsList[1:] )++ :if len( a:000 ) != 0+ :w+ :endif++ :endif+ :call setpos( '.' , startpos )+endfunction++":vmap i :call HBBInlineSelection()<CR>+":vmap I :call HBBInlineSelection( "with saving" )<CR>
hbb.cabal view
@@ -9,7 +9,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.3.0.1+version: 0.4.0.0 -- A short (one-line) description of the package. synopsis: Haskell Busy Bee, a backend for text editors.@@ -45,6 +45,9 @@ -- Constraint on the version of Cabal needed to build this package. cabal-version: >= 1.10 +extra-source-files: README.md+ editor-plugin/vim/hbb.vim+ source-repository head type: git location: https://bitbucket.org/bhris/hbb.git@@ -60,5 +63,5 @@ Default-Extensions: ConstraintKinds, FlexibleContexts -- Other library packages from which modules are imported.- build-depends: base == 4.* , libhbb == 0.3.* , ghc, ghc-paths, directory >= 1.2, ghc-mod == 5.1.0.*+ build-depends: base == 4.* , libhbb == 0.4.* , ghc, ghc-paths, directory >= 1.2, ghc-mod == 5.1.0.*
src/HBB.hs view
@@ -53,11 +53,11 @@ ++ " hbb find <symbol>\n" ++ " hbb lint [-h opt] <HaskellFile>\n" ++ " ---------- modes supported by libhbb ------------\n"- ++ " hbb locate " ++ ghcOptHelp ++ "<HaskellFile> <line-no> <column-no>\n"- ++ " hbb inline " ++ ghcOptHelp ++ "<HaskellFile> <line-no> <column-no> [<line-no> <column-no>]\n"- ++ " hbb smart-inline " ++ ghcOptHelp ++ "<HaskellFile> <line-no> <column-no> [<line-no> <column-no>]\n"- ++ " hbb occurrences-of" ++ ghcOptHelp ++ "<HaskellFile> <line-no> <column-no> [<HaskellFile> ...]\n"- ++ " hbb exprtype " ++ ghcOptHelp ++ "<HaskellFile> <expression>\n"+ ++ " hbb locate " ++ ghcOptHelp ++ " <HaskellFile> <line-no> <column-no>\n"+ ++ " hbb inline " ++ ghcOptHelp ++ "[--adapt-ind] <HaskellFile> <line-no> <column-no> [<line-no> <column-no>]\n"+ ++ " hbb smart-inline " ++ ghcOptHelp ++ "[--adapt-ind] <HaskellFile> <line-no> <column-no> [<line-no> <column-no>]\n"+ ++ " hbb occurrences-of" ++ ghcOptHelp ++ " <HaskellFile> <line-no> <column-no> [<HaskellFile> ...]\n"+ ++ " hbb exprtype " ++ ghcOptHelp ++ " <HaskellFile> <expression>\n" ++ " hbb apply-to " ++ ghcOptHelp ++ "[-q] <Function of String to String> <Subject of String>\n" ++ " --- end of modes supported by libhbb ------------\n" ++ " hbb root\n"@@ -71,37 +71,40 @@ ---------------------------------------------------------------- -argspec :: [OptDescr (Options -> Options)]+argspec :: [OptDescr ((Options,HBBOptions) -> (Options,HBBOptions))] argspec = [ Option "l" ["tolisp"]- (NoArg (\opts -> opts { outputStyle = LispStyle }))+ (NoArg (\(opts,hbbopts) -> (opts { outputStyle = LispStyle },hbbopts))) "print as a list of Lisp" , Option "h" ["hlintOpt"]- (ReqArg (\h opts -> opts { hlintOpts = h : hlintOpts opts }) "hlintOpt")+ (ReqArg (\h (opts,hbbopts) -> (opts { hlintOpts = h : hlintOpts opts },hbbopts)) "hlintOpt") "hlint options" , Option "g" ["ghcOpt"]- (ReqArg (\g opts -> opts { ghcUserOptions = g : ghcUserOptions opts }) "ghcOpt")+ (ReqArg (\g (opts,hbbopts) -> (opts { ghcUserOptions = g : ghcUserOptions opts },hbbopts)) "ghcOpt") "GHC options" , Option "v" ["verbose"]- (NoArg (\opts -> opts { ghcUserOptions = "-v" : ghcUserOptions opts }))+ (NoArg (\(opts,hbbopts) -> (opts { ghcUserOptions = "-v" : ghcUserOptions opts },hbbopts))) "verbose" , Option "o" ["operators"]- (NoArg (\opts -> opts { operators = True }))+ (NoArg (\(opts,hbbopts) -> (opts { operators = True },hbbopts))) "print operators, too" , Option "d" ["detailed"]- (NoArg (\opts -> opts { detailed = True }))+ (NoArg (\(opts,hbbopts) -> (opts { detailed = True },hbbopts))) "print detailed info" , Option "q" ["qualified","quiet"]- (NoArg (\opts -> opts { qualified = True }))+ (NoArg (\(opts,hbbopts) -> (opts { qualified = True },hbbopts { quietApplyTo = True }))) "show qualified names / suppress warning (quiet) in mode apply-to" , Option "b" ["boundary"]- (ReqArg (\s opts -> opts { lineSeparator = LineSeparator s }) "sep")+ (ReqArg (\s (opts,hbbopts) -> (opts { lineSeparator = LineSeparator s },hbbopts)) "sep") "specify line separator (default is Nul string)"+ , Option [] ["adapt-ind"]+ (NoArg (\(opts,hbbopts) -> (opts,hbbopts { adaptInd = AdaptIndToTargetEnv })))+ "Adapt the indentation of non-first lines to the (possibly higher) ind of the target environment" ] -parseArgs :: [OptDescr (Options -> Options)] -> [String] -> (Options, [String])+parseArgs :: [OptDescr ((Options,HBBOptions) -> (Options,HBBOptions))] -> [String] -> ((Options,HBBOptions), [String]) parseArgs spec argv = case O.getOpt Permute spec argv of- (o,n,[] ) -> (foldr id defaultOptions o, n)+ (o,n,[] ) -> (foldr id (defaultOptions,defaultHBBOptions) o, n) (_,_,errs) -> E.throw (CmdArg errs) ----------------------------------------------------------------@@ -112,7 +115,7 @@ hSetEncoding stdout utf8 -- #endif args <- getArgs- let (opt,cmdArg) = parseArgs argspec args+ let ((opt,hbbopts),cmdArg) = parseArgs argspec args let cmdArg0 = cmdArg !. 0 cmdArg1 = cmdArg !. 1 cmdArg2 = cmdArg !. 2@@ -140,22 +143,25 @@ "check" -> checkSyntax remainingArgs "expand" -> expandTemplate remainingArgs "debug" -> debugInfo- "info" -> bArgs 3 3 info cmdArg1 cmdArg3- "type" -> bArgs 4 4 $ types cmdArg1 (read cmdArg3) (read cmdArg4)- "split" -> bArgs 4 4 $ splits cmdArg1 (read cmdArg3) (read cmdArg4)- "sig" -> bArgs 4 4 $ sig cmdArg1 (read cmdArg3) (read cmdArg4)- "refine" -> bArgs 5 5 $ refine cmdArg1 (read cmdArg3) (read cmdArg4) cmdArg5- "auto" -> bArgs 4 4 $ auto cmdArg1 (read cmdArg3) (read cmdArg4)- "find" -> bArgs 1 1 $ findSymbol cmdArg1- "lint" -> bArgs 1 1 $ withFile lint cmdArg1- "locate" -> bArgs 3 3 $ hbb_locate cmdArg1 (read cmdArg2) (read cmdArg3)- "inline" -> bArgs 3 5 $ hbb_inline cmdArg1 (read cmdArg2) (read cmdArg3) (reMb 4) (reMb 5)- "smart-inline" -> bArgs 3 5 $ hbb_smartinline cmdArg1 (read cmdArg2) (read cmdArg3) (reMb 4) (reMb 5)- "occurrences-of"-> bArgs 3 999 $ hbb_occursof cmdArg1 (read cmdArg2) (read cmdArg3) (drop 3 remainingArgs)- "exprtype" -> bArgs 2 2 $ hbb_exprtype cmdArg1 cmdArg2- "apply-to" -> bArgs 2 2 $ hbb_applyto cmdArg1 cmdArg2 opt- "root" -> rootInfo- "doc" -> bArgs 1 1 $ pkgDoc cmdArg1+ "info" -> bArgs 3 3 info cmdArg1 cmdArg3+ "type" -> bArgs 4 4 $ types cmdArg1 (read cmdArg3) (read cmdArg4)+ "split" -> bArgs 4 4 $ splits cmdArg1 (read cmdArg3) (read cmdArg4)+ "sig" -> bArgs 4 4 $ sig cmdArg1 (read cmdArg3) (read cmdArg4)+ "refine" -> bArgs 5 5 $ refine cmdArg1 (read cmdArg3) (read cmdArg4) cmdArg5+ "auto" -> bArgs 4 4 $ auto cmdArg1 (read cmdArg3) (read cmdArg4)+ "find" -> bArgs 1 1 $ findSymbol cmdArg1+ "lint" -> bArgs 1 1 $ withFile lint cmdArg1+ -- The type Option to specify command line arguments is a ghc-mod+ -- specific type which is passed to the ghc-mod-specific GhcMonad+ -- instance. This forces 'hbb' to pass the options explicitely.+ "inline" -> bArgs 3 5 $ hbb_inline hbbopts cmdArg1 (read cmdArg2) (read cmdArg3) (reMb 4) (reMb 5)+ "smart-inline" -> bArgs 3 5 $ hbb_smartinline hbbopts cmdArg1 (read cmdArg2) (read cmdArg3) (reMb 4) (reMb 5)+ "locate" -> bArgs 3 3 $ hbb_locate cmdArg1 (read cmdArg2) (read cmdArg3)+ "occurrences-of"-> bArgs 3 999 $ hbb_occursof cmdArg1 (read cmdArg2) (read cmdArg3) (drop 3 remainingArgs)+ "exprtype" -> bArgs 2 2 $ hbb_exprtype cmdArg1 cmdArg2+ "apply-to" -> bArgs 2 2 $ hbb_applyto hbbopts cmdArg1 cmdArg2+ "root" -> rootInfo + "doc" -> bArgs 1 1 $ pkgDoc cmdArg1 "dumpsym" -> dumpSymbol "boot" -> boot "version" -> return progVersion