_ _ ____ | | | | __ _ | _ \ ___ | |_| |/ _` | | |_) / _ \ | _ | (_| | | _ < __/ |_| |_|\__,_| |_| \_\___| HaRe, the Haskell Refactorer a snapshot of our current prototype 27/01/2004 http://www.cs.kent.ac.uk/projects/refactor-fp/hare.html -------------------------------------------------------------------------------- This snapshot includes most dependencies (version A below), and should build and work on Windows/Cygwin and Unix, with either gvim 6.2 or with emacs 21.2.1. HaRe_27012004 (aka HaRe 0.2) is still a prototype, made available so you can play with basic refactoring support for Haskell, and give us feedback or bug reports (see below for changes since HaRe 0.1 and known remaining issues). The major new feature in this 0.2 release - apart from bug fixes and other improvements such as initial support for literate Haskell - is that all refactorings are now module-aware. WE DO NOT RECOMMEND TO USE THIS PROTOTYPE ON YOUR PRODUCTION SOURCES JUST YET! -------------------------------------------------------------------------------- --------------- what you need 0 basics: 1. ghc (we've tested with ghc-6.0.1) 2. unix/gnu tools (or cygwin tools, if on windows) 3. vim or emacs (we've tested with gvim 6.2 and with emacs 21.2.1) A [recommended] partial build (fewer tools needed, but tied to particular snapshot): 1. fetch refactorer snapshot. this includes: - modified Programatica snapshot (includes happy output) - refactorer sources (includes DrIFT output) - patched DrIFT-Strafunski-1.7 (shouldn't be needed for partial build) and StrategyLib-4.0-beta --------------- one easy way to arrange these things the following text assumes this directory structure and unix/cygwin tools (adapt makefile if necessary): README.txt <- you're reading this makefile editors <- editor interface scripts for Vim/Emacs refactorer <- refactorer (what else?-) doc <- initial catalogue of refactorings driftit <- script to run DrIFT over tools junk <- little hack for DrIFT (not needed for A) DriftStructUtils <- DrIFT output (included in A) DrIFT-Strafunski-1.7 <- patched StrategyLib-4.0-beta <- Strafunski's library for strategic programming diffs <- modified files for tools tools <- programatica snapshot You might want to check the paths in makefile, driftit, refactorer/HuMakefile and refactorer/myghc--make for sanity wrt to your system (you should not actually need Happy for A). They should work without change on windows/cygwin (windows/mingw has also been reported to work), and feedback from the first release suggests the same for unixish systems, from Max OS X to Linux (please let us know if not, or if you can add new platforms). If on Suns, the call to ghc in refactorer/myghc--make needs a little looking after: in principle, you could remove the SunOS*) case and use the default case *). In practice, at least on Suns, you will want to make sure that ghc uses the linker from binutils instead of the Sun linker (order of magnitude difference in linking time..), which is what setting GCC_EXEC_PREFIX before calling ghc does - just put in the path to your local binutils installation. --------------- how to build 1. run: make (GNU make) --------------- how to use 2. load the scripted interface into your favourite editor (you may or may not want to include this in your standard startup files for Haskell) - emacs: M-x load-file editors/haskell-refac.el M-x turn-on-haskell-refac (to switch off: M-x turn-off-haskell-refac) - gvim: :source editors/refactor.vim :RefacStart (or select start from menu) :RefacStop (or select stop from menu) 3. this should give you a menu with refactoring commands, and a separate refactoring process. 4. the Programatica frontend we use is project-based. before doing any refactorings, you have to start a project (select "new" to start a project with only the current module in it, then select "chase" to add the Prelude modules). project settings are kept in a "hi" directory, created in the current directory (it is recommended to edit files from within the directory they reside in). 5. for most refactorings, the editor interface will pass the current filename (should be the module name, as well), the refactoring command, and the current cursor position. For some refactorings, you'll also need to highlight an expression, or enter a new name. Here's the current list: removeDef : place cursor at start of identifier whose definition is to be removed duplicateDef : place cursor at start of identifier whose definition is to be duplicated, you'll be prompted for a new name liftToTopLevel : place cursor at start of identifier whose definition is to be moved liftOneLevel : place cursor at start of identifier whose definition is to be moved demote : place cursor at start of identifier whose definition is to be moved rename : place cursor at start of identifier to be renamed, you'll be prompted for a new name introNewDef : highlight expression to be named, you'll be prompted for a new name unfoldDef : place cursor at start of identifier where its definition is to be unfolded addOneParameter: place cursor at start of identifier whose definition is to be modified, you'll be prompted for a new name rmOneParameter : place cursor in formal parameter which is to be removed generaliseDef : highlight expression to be named, you'll be prompted for a new name --------------- known issues - the editor interface still needs improvement, although all known bugs have been fixed (windows vim users: it is recommended to install vim in its standard location). - no use of type info yet => some of the existing refactorings are problematic wrt types, e.g., monomorphic vs polymorphic bindings - the list of refactorings is just a beginning.. - there is no standard for associating comments with semantic entities. we use heuristics to decide when to move/remove comments together with definitions => these heuristics may not match everyone's commenting style outline: when (re-)moving a definition, we also (re-)move the last consecutive comments right before this definition (with at most one empty line between the comments and the definition); we also (re-)move the comment whose start location is in the same line as the definition's last line of code. Example: .... --Comment1 --Comment2 --Comment3 fun1 x = x+1 --Comment4 --Comment 5 ... In this case, Comment2, Comment3 and Comment4 belong to function fun1. - if you're routinely working in a mixed Windows/Unix setup, you'll notice that the file-format (encoding of line endings) of HaRe output depends on whether you're using a Windows or a Unix HaRe, not on whether the input is in Windows or Unix format. - the Programatica frontend is currently limited to Haskell 98 --------------- changes from 01/10/2003 - general: - Programatica and HaRe have added workarounds for the Template Haskell syntax problems in ghc-6.0, so HaRe now builds with ghc-6.0.1 (ghc-6.2.1 has introduced yet another change, so does not work yet..) - upgraded to StrategyLib-4.0-beta - refactoring: - Programatica frontend does now give source location information for all literals => refactorings should no longer have problems with String and Char literals - HaRe is now module-aware: all refactorings have been updated to try and take import/export relations into account. - following your requests, HaRe can now work with literate Haskell files. This relies on some guesswork, so expect to find some rough corners - please report your experience so we can try to fix problems. Might also interact oddly with our heuristics for attaching comments to definitions. - Automatic renaming has been disabled during liftOneLevel, liftToTopLevel, demote and generaliseDef. In the case that one of these refactorings will cause name clash/capture, the user will be prompted to do renaming first. - refactoring bugfixes: + introNewDef and generaliseDef now replace the marked expression itself, not the first occurrence of the marked expression + wrong layout during liftOneLevel + non-exhaustive case in RefacLocUtils.hs + missing parentheses during generaliseDef + a parameter can be now be removed from a direct recursive definition if it is not used in the definition. + when adding an parameter to a direct recursive definition, use the new formal parameter name, instead of the default actual argument name, as the actual argument inside this function. + the way to created a new name has been changed. For example add a new parameter 'y' to a definition 'f', the default argument name is f_y instead of 'f_y_1'. + erroneous caching of export list + multi-module undo ... - editor interfaces: - Emacs now reloads files modified by the refactorer without prompting the user, and warns when a refactoring has changed files not currently opened. - editor interface bugfixes: Emacs: + the error-in-mini-buffer effects preventing file reloading in some Emacs configurations were finally traced and eliminated (the stopwatch issue also seems to be gone). + refac buffer now automatically scrolls to last line + refactorings are now blocked while there are unsaved buffers