leksah 0.12.1.3 → 0.13.3.0
raw patch · 162 files changed
+27965/−5823 lines, 162 filesdep +blaze-htmldep +conduitdep +executable-pathdep −enumeratordep ~Cabaldep ~QuickCheckdep ~Win32setup-changednew-component:exe:bewleksahbinary-added
Dependencies added: blaze-html, conduit, executable-path, ghcjs-codemirror, ghcjs-dom, gtk3, gtk3-mac-integration, gtksourceview3, hamlet, haskell-src-exts, hgettext, hlint, jsaddle, lens, monad-loops, pretty-show, setlocale, vado, vcsgui, vcswrapper, webkit, webkit-javascriptcore, webkitgtk3, webkitgtk3-javascriptcore
Dependencies removed: enumerator
Dependency ranges changed: Cabal, QuickCheck, Win32, array, base, binary, bytestring, containers, ghc, glib, gtk, gtk-mac-integration, hslogger, leksah, leksah-server, ltk, regex-tdfa, text, transformers, unix, yi
Files
- Readme +0/−30
- Readme.md +33/−0
- Setup.lhs +0/−1
- SetupLocale.lhs +6/−0
- bew/Main.hs +16/−0
- data/.gtkrc-2.0 +13/−0
- data/current.lkshs +7/−5
- data/empty.lkshs +20/−0
- data/git.menu +10/−0
- data/keymap.lkshk +2/−1
- data/leksah.menu +23/−4
- data/prefs.lkshp +9/−8
- data/prefscoll.lkshp +6/−6
- data/styles/leksah-dark.xml +106/−0
- data/styles/leksah.xml +106/−0
- data/svn.menu +9/−0
- doc/Keybindings.svg +3894/−0
- doc/leksah_manual.lyx +5814/−0
- doc/screenshots2/screenshot_buffer_menu.png binary
- doc/screenshots2/screenshot_completion.png binary
- doc/screenshots2/screenshot_config_menu.png binary
- doc/screenshots2/screenshot_construct_module.png binary
- doc/screenshots2/screenshot_debug_menu.png binary
- doc/screenshots2/screenshot_debug_pane.png binary
- doc/screenshots2/screenshot_edit_menu.png binary
- doc/screenshots2/screenshot_error_pane.png binary
- doc/screenshots2/screenshot_file_menu.png binary
- doc/screenshots2/screenshot_findbar.png binary
- doc/screenshots2/screenshot_first_start.png binary
- doc/screenshots2/screenshot_grep.png binary
- doc/screenshots2/screenshot_help_menu.png binary
- doc/screenshots2/screenshot_metadata_prefs.png binary
- doc/screenshots2/screenshot_module_browser.png binary
- doc/screenshots2/screenshot_package_editor_1.png binary
- doc/screenshots2/screenshot_package_flags.png binary
- doc/screenshots2/screenshot_package_menu.png binary
- doc/screenshots2/screenshot_panes_menu.png binary
- doc/screenshots2/screenshot_prefs_editor.png binary
- doc/screenshots2/screenshot_serach_pane.png binary
- doc/screenshots2/screenshot_source_candy.png binary
- doc/screenshots2/screenshot_view_menu.png binary
- doc/screenshots2/screenshot_welcome.png binary
- doc/screenshots2/screenshot_workspace_menu.png binary
- language-specs/cabal.lang +300/−0
- language-specs/haskell.lang +68/−14
- language-specs/jmacro.lang +374/−0
- leksah.cabal +216/−70
- linux/applications/leksah.desktop +11/−0
- linux/applications/leksah.xml +45/−0
- linux/icons/hicolor/48x48/apps/leksah_48x48.png binary
- linux/specfiles/fedora/12/ghc-binary-shared.spec +137/−0
- linux/specfiles/fedora/12/ghc-deepseq.spec +137/−0
- linux/specfiles/fedora/12/ghc-hslogger.spec +136/−0
- linux/specfiles/fedora/12/ghc-ltk.spec +137/−0
- linux/specfiles/fedora/12/ghc-process-leksah.spec +137/−0
- linux/specfiles/fedora/12/ghc-regex-base.spec +136/−0
- linux/specfiles/fedora/12/ghc-regex-tdfa.spec +137/−0
- linux/specfiles/fedora/12/leksah.spec +118/−0
- linux/specfiles/fedora/12/leksah_server.spec +145/−0
- linux/specfiles/fedora/13/ghc-binary-shared.spec +68/−0
- linux/specfiles/fedora/13/ghc-hslogger.spec +62/−0
- linux/specfiles/fedora/13/ghc-ltk.spec +70/−0
- linux/specfiles/fedora/13/ghc-process-leksah.spec +69/−0
- linux/specfiles/fedora/13/ghc-regex-tdfa.spec +66/−0
- linux/specfiles/fedora/13/haddock.spec +62/−0
- linux/specfiles/fedora/13/leksah-server.spec +76/−0
- linux/specfiles/fedora/13/leksah.spec +68/−0
- linux/specfiles/fedora/14/ghc-binary-shared.spec +68/−0
- linux/specfiles/fedora/14/ghc-haddock.spec +68/−0
- linux/specfiles/fedora/14/ghc-ltk.spec +66/−0
- linux/specfiles/fedora/14/ghc-process-leksah.spec +65/−0
- linux/specfiles/fedora/14/ghc-regex-tdfa.spec +70/−0
- linux/specfiles/fedora/14/leksah-server.spec +71/−0
- linux/specfiles/fedora/14/leksah.spec +89/−0
- linux/specfiles/fedora/14/leksah.spec-darcs-backup0 +67/−0
- linux/specfiles/fedora/14/leksah.spec-darcs-backup1 +80/−0
- main/Main.hs +19/−0
- osx/Info.plist +30/−0
- osx/bundle.sh +3/−0
- osx/gtk.sh +10/−0
- osx/gtk2.sh +10/−0
- osx/launcher.sh +186/−0
- osx/leksah.bundle +196/−0
- osx/leksah.icns binary
- osx/makedmg.sh +62/−0
- osx/makedmgs.sh +24/−0
- osx/osxkeymap.lkshk +2/−0
- osx/settings.ini +5/−0
- po/messages.pot +2244/−0
- po/pt_BR.po +2258/−0
- scripts/clean.sh +34/−0
- scripts/stage.sh +54/−0
- src/IDE/BufferMode.hs +36/−29
- src/IDE/Build.hs +7/−4
- src/IDE/Command.hs +281/−222
- src/IDE/Command/Print.hs +46/−0
- src/IDE/Command/VCS.hs +20/−0
- src/IDE/Command/VCS/Common.hs +176/−0
- src/IDE/Command/VCS/Common/GUI.hs +59/−0
- src/IDE/Command/VCS/Common/Helper.hs +80/−0
- src/IDE/Command/VCS/Common/Workspaces.hs +85/−0
- src/IDE/Command/VCS/GIT.hs +50/−0
- src/IDE/Command/VCS/Mercurial.hs +46/−0
- src/IDE/Command/VCS/SVN.hs +84/−0
- src/IDE/Command/VCS/Types.hs +39/−0
- src/IDE/Completion.hs +98/−81
- src/IDE/Core/State.hs +51/−13
- src/IDE/Core/Types.hs +68/−12
- src/IDE/Debug.hs +91/−67
- src/IDE/Find.hs +117/−117
- src/IDE/ImportTool.hs +528/−417
- src/IDE/Keymap.hs +2/−0
- src/IDE/Leksah.hs +82/−34
- src/IDE/LogRef.hs +184/−89
- src/IDE/Metainfo/Provider.hs +15/−6
- src/IDE/NotebookFlipper.hs +5/−5
- src/IDE/Package.hs +202/−133
- src/IDE/Pane/Breakpoints.hs +52/−44
- src/IDE/Pane/Errors.hs +40/−58
- src/IDE/Pane/Files.hs +26/−23
- src/IDE/Pane/Grep.hs +58/−51
- src/IDE/Pane/HLint.hs +277/−0
- src/IDE/Pane/Info.hs +78/−99
- src/IDE/Pane/Log.hs +333/−149
- src/IDE/Pane/Modules.hs +209/−177
- src/IDE/Pane/PackageEditor.hs +1604/−1388
- src/IDE/Pane/PackageFlags.hs +17/−16
- src/IDE/Pane/Preferences.hs +163/−111
- src/IDE/Pane/Search.hs +65/−80
- src/IDE/Pane/SourceBuffer.hs +395/−260
- src/IDE/Pane/Trace.hs +52/−54
- src/IDE/Pane/Variables.hs +70/−62
- src/IDE/Pane/WebKit/Documentation.hs +157/−0
- src/IDE/Pane/WebKit/Output.hs +175/−0
- src/IDE/Pane/Workspace.hs +92/−77
- src/IDE/PaneGroups.hs +10/−3
- src/IDE/Session.hs +170/−27
- src/IDE/SourceCandy.hs +10/−10
- src/IDE/Statusbar.hs +9/−20
- src/IDE/SymbolNavigation.hs +111/−290
- src/IDE/TextEditor.hs +36/−1266
- src/IDE/TextEditor/Class.hs +205/−0
- src/IDE/TextEditor/CodeMirror.hs +525/−0
- src/IDE/TextEditor/GtkSourceView.hs +453/−0
- src/IDE/TextEditor/Yi.hs +325/−0
- src/IDE/Utils/ExternalTool.hs +109/−0
- src/IDE/Utils/GUIUtils.hs +114/−16
- src/IDE/Utils/ServerConnection.hs +1/−1
- src/IDE/Workspaces.hs +101/−169
- src/IDE/Workspaces/Writer.hs +162/−0
- tests/IDE/TextEditor/Tests.hs +165/−0
- tests/Tests.hs +24/−4
- win32/gtk2hsall.sh +30/−0
- win32/gtkrc +18/−0
- win32/leksah-rebuild-metadata.bat +27/−0
- win32/leksah-server.bat +20/−0
- win32/leksah.bat +30/−0
- win32/leksah.ico binary
- win32/leksah.nsi +194/−0
- win32/makeinstaller.sh +119/−0
- win32/makeinstallers.sh +35/−0
- win32/recache.sh +17/−0
@@ -1,30 +0,0 @@-Leksah, an Integrated Development Environment for Haskell-=========================================================--This is Leksah, a hopefully practical tool to support the Haskell development process.--Leksah uses GTK+ as GUI Toolkit with the gtk2hs binding. It is plattform independend-and should run on any plattform where GTK+, gtk2hs and ghc can be installed.-It is currently been tested on Linux, Mac OS X and Windows. It uses the Cabal package management-and build system for Package Management. It currently only supports the Glasgow Haskell Compiler (ghc).--Documentation can be found on leksah.org.--System Requirements-===================--Leksah currently requires:- GHC- gtk2hs- For more details see the leksah.cabal file--If you are a user or just test Leksah, we would appreciate to here from you.--Please send questions and suggestions to the developers-info(at)leksah(dot)org------
@@ -0,0 +1,33 @@+# Leksah, an Integrated Development Environment for Haskell++[](http://travis-ci.org/leksah/leksah)++This is [Leksah](http://leksah.org/), a hopefully practical tool to support the Haskell development process.++Leksah uses GTK+ as GUI Toolkit with the gtk2hs binding. It is plattform independend+and should run on any plattform where GTK+, gtk2hs and ghc can be installed.+It is currently been tested on Linux, Mac OS X and Windows. It uses the Cabal package management+and build system for Package Management. It currently only supports the Glasgow Haskell Compiler (ghc).++Documentation can be found on [leksah.org](http://leksah.org/).++## System Requirements++Leksah currently requires:++* GHC+* gtk2hs+* For more details see the leksah.cabal file++To build the latest development version of Leksah follow the+steps in the [.travis.yml](.travis.yml) file.++If you are a user or just test Leksah, we would appreciate to hear from you.++Please send questions and suggestions to+the [Leksah group](https://groups.google.com/forum/#!forum/leksah)+++++
@@ -3,4 +3,3 @@ > import Distribution.Simple > main :: IO () > main = defaultMain-
@@ -0,0 +1,6 @@+#!/usr/bin/runhaskell +> module Main where+> import Distribution.Simple+> import Distribution.Simple.I18N.GetText+> main :: IO ()+> main = gettextDefaultMain
@@ -0,0 +1,16 @@+module Main (+ main+) where++import Graphics.UI.Gtk (postGUIAsync)+import GHCJS.DOM.Document (documentGetBody)+import GHCJS.DOM (runWebGUI, webViewGetDomDocument)++main = do+ runWebGUI $ \ webView -> postGUIAsync $ do+ Just doc <- webViewGetDomDocument webView+ Just body <- documentGetBody doc+ putStrLn "Bewleksah is a version of Leksah that can run in a web browser."+ putStrLn "Nothing working yet."++
@@ -0,0 +1,13 @@+# leksah specific .gtkrc-2.0 adds+style "leksah-close-button-style"+{+ GtkWidget::focus-padding = 0+ GtkWidget::focus-line-width = 0+ xthickness = 0 + ythickness = 0 +}+widget "*.leksah-close-button" style "leksah-close-button-style"++# Maybe you wish to uncomment this if the beep is annoying+# gtk-error-bell = 0+
@@ -1,17 +1,19 @@ Version of session file format: 1 Time of storage:- "Sun Apr 17 22:14:23 CEST 2011"-Layout: VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = -1, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Browser",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 198) 137)], paneTabs = Just BottomP, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) 494) 540-Population: [(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP BottomP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (ModulesSt (ModulesState 286 (SystemScope,False) (Nothing,Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP BottomP,SplitP TopP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP TopP,GroupP "Browser",SplitP TopP])]+ "Sun Oct 27 02:21:33 NZDT 2013"+Layout: VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = -1, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Debug",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = -1, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = -1, detachedId = Nothing, detachedSize = Nothing}) 167)], paneTabs = Just TopP, currentPage = 2, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 1, detachedId = Nothing, detachedSize = Nothing}) 456) 693+Population: [(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP BottomP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (ModulesSt (ModulesState 200 (SystemScope,False) (Nothing,Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP BottomP])] Window size: (1076,728)+Full screen: False+Dark: False Completion size: (750,400) Workspace: Nothing-Active pane: Nothing+Active pane: Just "Modules" Toolbar visible: True-FindbarState: (True,FindState {entryStr = "", entryHist = [""], replaceStr = "", replaceHist = [], caseSensitive = False, entireWord = False, wrapAround = False, regex = False, lineNr = 1})+FindbarState: (True,FindState {entryStr = "", entryHist = [], replaceStr = "", replaceHist = [], caseSensitive = False, entireWord = False, wrapAround = False, regex = False, lineNr = 1}) Recently opened files: [] Recently opened workspaces:
@@ -0,0 +1,20 @@+Version of session file format:+ 1+Time of storage:+ "Fri Feb 26 17:11:46 CET 2010"+Layout: VerticalP (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 1, detachedId = Nothing, detachedSize = Nothing}) (HorizontalP (TerminalP {paneGroups = fromList [("Browser",TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}), ("Debug",HorizontalP (TerminalP {paneGroups = fromList [], paneTabs = Nothing, currentPage = 0, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 1, detachedId = Nothing, detachedSize = Nothing}) 206)], paneTabs = Just TopP, currentPage = 2, detachedId = Nothing, detachedSize = Nothing}) (TerminalP {paneGroups = fromList [], paneTabs = Just TopP, currentPage = 1, detachedId = Nothing, detachedSize = Nothing}) 547) 733+Population: [(Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP BottomP]),(Just (LogSt LogState),[SplitP RightP,SplitP BottomP]),(Just (ModulesSt (ModulesState 286 (SystemScope,False) (Nothing,Nothing) (ExpanderState {packageExp = ([],[]), packageExpNoBlack = ([],[]), packageDExp = ([],[]), packageDExpNoBlack = ([],[]), workspaceExp = ([],[]), workspaceExpNoBlack = ([],[]), workspaceDExp = ([],[]), workspaceDExpNoBlack = ([],[]), systemExp = ([],[]), systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP,GroupP "Browser"]),(Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP BottomP])]+Window size: (1076,728)+Full screen: True+Dark: True+Completion size:+ (750,400)+Workspace: Nothing+Active pane: Nothing+Toolbar visible:+ True+FindbarState: (True,FindState {entryStr = "", entryHist = [], replaceStr = "", replaceHist = [], caseSensitive = False, entireWord = False, wrapAround = False, regex = False, lineNr = 1})+Recently opened files:+ []+Recently opened workspaces:+ []
@@ -0,0 +1,10 @@+ <ui>+ <menubar>+ <menu name="Version Con_trol" action="vcs">+ <menuitem name="_Commit" action="GitCommit" />+ <menuitem name="_View Log" action="GitViewLog" />+ <menuitem name="_Push" action="GitPush" />+ <menuitem name="P_ull" action="GitPull" />+ </menu>+ </menubar>+ </ui>
@@ -34,7 +34,7 @@ <ctrl>z -> EditUndo "Undos the last user action" --<ctrl>x/u -> EditUndo "Undos the last user action" -<shift><ctrl>y -> EditRedo "Redos the last user action"+<shift><ctrl>z -> EditRedo "Redos the last user action" --<ctrl>x/r -> EditRedo "Redos the last user action" --<ctrl>x -> EditCut@@ -72,6 +72,7 @@ -> ViewTabsUp "Shows the tabs of the current notebook on the top" -> ViewTabsDown "Shows the tabs of the current notebook on the bottom" -> ViewSwitchTabs "Switches if tabs for the current notebook are visible"+<ctrl><shift>f -> ViewFullScreen "Toggle fullscreen mode" <ctrl>t -> ToggleToolbar -> HelpDebug -> HelpAbout
@@ -10,6 +10,7 @@ <menuitem name="Save _All" action="FileSaveAll" /> <menuitem name="_Revert" action="FileRevert" /> <menuitem name="_Close" action="FileClose" />+ <menuitem name="_Print File" action="FilePrint" /> <separator/> <menuitem name="Close All" action="FileCloseAll" /> <menuitem name="Close All but Package" action="FileCloseAllButPackage" />@@ -38,8 +39,8 @@ <menuitem name="Shift Right" action="EditShiftRight" /> <separator/> <menuitem name="Align =" action="EditAlignEqual" />- <menuitem name="Align <-" action="EditAlignLeftArrow" />- <menuitem name="Align ->" action="EditAlignRightArrow" />+ <menuitem name="Align <-" action="EditAlignLeftArrow" />+ <menuitem name="Align ->" action="EditAlignRightArrow" /> <menuitem name="Align ::" action="EditAlignTypeSig" /> </menu> <menu name="_Workspace" action="Workspace">@@ -58,8 +59,12 @@ <menu name="_Package" action="Package"> <menuitem name="_New..." action="NewPackage" /> <menuitem name="_Add..." action="AddPackage" />- <menuitem name="_Edit" action="EditPackage" />- <menuitem name="Edit _Flags" action="PackageFlags" />+ <menuitem name="_Add From Source Repository..." action="ClonePackage" />+ <menu name="_Edit" action="PackageEdit">+ <menuitem name="With _Package Editor" action="EditPackage" />+ <menuitem name="With _Text Editor" action="EditPackageText" />+ <menuitem name="Package _Flags" action="PackageFlags" />+ </menu> <separator/> <menuitem name="Clea_n" action="CleanPackage" /> <menuitem name="_Configure" action="ConfigPackage" />@@ -92,10 +97,20 @@ </menu> <menu name="_Panes" action="Panes"> <menuitem name="_Browser" action="ShowBrowser" />+ <menuitem name="_Modules" action="ShowModules" />+ <menuitem name="_Info" action="ShowInfo" />+ <separator/> <menuitem name="_Debugger" action="ShowDebugger" />+ <menuitem name="_Breakpoints" action="ShowBreakpointsPane" />+ <menuitem name="_Trace" action="ShowTrace" />+ <menuitem name="_Variables" action="ShowVariables" />+ <menuitem name="_Output" action="ShowOutput" />+ <separator/> <menuitem name="_Errors" action="ShowErrors" /> <menuitem name="_Files" action="ShowFiles" /> <menuitem name="_Grep" action="ShowGrep" />+ <menuitem name="_HLint" action="ShowHLint" />+ <menuitem name="_Documentation" action="ShowDocumentation" /> <menuitem name="_Log" action="ShowLog" /> <menuitem name="_Search" action="ShowSearch" /> <menuitem name="_Workspace" action="ShowWorkspace" />@@ -108,6 +123,8 @@ <separator/> <menuitem name="_Group" action="ViewNest" /> <menuitem name="_Detach" action="ViewDetach" />+ <menuitem name="_Full Screen" action="ViewFullScreen" />+ <menuitem name="Dark" action="ViewDark" /> <separator/> <menuitem name="Move _Left" action="ViewMoveLeft" /> <menuitem name="Move _Right" action="ViewMoveRight" />@@ -135,6 +152,8 @@ <menuitem name="Save Session" action="SaveSession" /> <menuitem name="Load Session" action="LoadSession" /> <menuitem name="Forget Session" action="ForgetSession" />+ </menu>+ <menu name="Version Con_trol" action="vcs"> </menu> <menu name="_Help" action="Help"> <menuitem name="_Homepage" action="HelpHomepage" />
@@ -16,15 +16,16 @@ True Source candy: (False,"candy") --Pair with True or False for use and name of a candy file in a config dir-Editor Style: ""+Editor Style: "leksah" Found Text Background:- Color 65535 65535 32768+ Color 50372 41120 0+Selection Match Text Background:+ Color 32768 32768 32768 Execution Context Text Background:- Color 65535 49152 49152+ Color 31675 10875 10875 Breakpoint Text Background:- Color 65535 49152 32768-Use Yi - Experimental feature (could wipe your files):- False+ Color 20752 15778 6640+Text Editor: "GtkSourceView" LogView Font: "Sans 12" Window default size: (1024,800)@@ -37,7 +38,7 @@ keymap --The name of a keymap file in a config dir Categories for panes:- [("*Debug","ToolCategory"),("*Files","ToolCategory"),("*Grep","ToolCategory"),("*Log","LogCategory"),("*Search","ToolCategory"),("*Browser","ToolCategory"),("*Package","EditorCategory"),("*Flags","EditorCategory"),("*References","LogCategory"),("*Workspace","LogCategory"),("*Errors","ToolCategory")]+ [("*Breakpoints","LogCategory"),("*Browser","ToolCategory"),("*Debug","ToolCategory"),("*Errors","ToolCategory"),("*Files","ToolCategory"),("*Flags","ToolCategory"),("*Grep","ToolCategory"),("*HLint","ToolCategory"),("*Doc","ToolCategory"),("*Info","LogCategory"),("*Log","LogCategory"),("*Modules","ToolCategory"),("*Out","ToolCategory"),("*Package","EditorCategory"),("*Prefs","EditorCategory"),("*Search","ToolCategory"),("*Trace","LogCategory"),("*Variables","LogCategory"),("*Workspace","LogCategory")] Pane path for category: [("EditorCategory",[SplitP LeftP]),("ToolCategory",[SplitP RightP,SplitP TopP]),("LogCategory",[SplitP RightP,SplitP BottomP])] Default pane path:@@ -45,7 +46,7 @@ Paths under which haskell sources for packages may be found: [] Unpack source for cabal packages to:- Just "~/.leksah-0.12/packageSources"+ Just "~/.leksah-0.13/packageSources" URL from which to download prebuilt metadata: "http://www.leksah.org" Strategy for downloading prebuilt metadata:
@@ -1,12 +1,12 @@ Paths under which haskell sources for packages may be found: []-Maybe a directory for unpacking cabal packages:- Just "~/.leksah-0.12/packageSources"-An URL to load prebuild metadata:+Unpack source for cabal packages to:+ Just "~/.leksah-0.13/packageSources"+URL from which to download prebuilt metadata: "http://www.leksah.org"-A strategy for downloading prebuild metadata:+Strategy for downloading prebuilt metadata: RetrieveThenBuild-Port number for server connection:+Port number for leksah to comunicate with leksah-server: 11111-End the server with last connection:+Stop the leksah-server process when leksah disconnects: True
@@ -0,0 +1,106 @@+<?xml version="1.0" encoding="UTF-8"?>+<!--++ This file is part of GtkSourceView++ Copyright (C) 2006-2007 GtkSourceView team+ Authors: Yevgen Muntyan <muntyan@tamu.edu>, Hamish Mackenzie++ GtkSourceView is free software; you can redistribute it and/or+ modify it under the terms of the GNU Lesser General Public+ License as published by the Free Software Foundation; either+ version 2.1 of the License, or (at your option) any later version.++ GtkSourceView is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU+ Lesser General Public License for more details.++ You should have received a copy of the GNU Lesser General Public+ License along with this library; if not, write to the Free Software+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA++-->+<style-scheme id="leksah-dark" _name="Leksah Dark" version="1.0">+ <author>GtkSourceView team</author>+ <_description>Classic color scheme</_description>++ <!-- Palette -->+ <color name="white" value="#FFFFFF"/>+ <color name="comment" value="#888888"/>+ <color name="magenta" value="#5387CC"/>+ <color name="violet" value="#6A5ACD"/>+ <color name="cyan" value="#448A8C"/>+ <color name="gray" value="#444444"/>+ <color name="green" value="#4EAB57"/>+ <color name="statement" value="#CC7733"/>+ <color name="red" value="#FF0000"/>+ <color name="yellow" value="#FFFF88"/>+ <color name="preproc" value="#B54A6A"/>++ <!-- Global Settings -->+ <style name="current-line" background="#000000"/>+ <style name="draw-spaces" foreground="#babdb6"/>++ <!-- Bracket Matching -->+ <style name="bracket-match" foreground="white" background="gray" bold="true"/>+ <style name="bracket-mismatch" foreground="white" background="red" bold="true"/>++ <!-- Right Margin -->+ <style name="right-margin" foreground="gray"/>++ <!-- Search Matching -->+ <style name="search-match" background="yellow"/>++ <!-- Comments -->+ <style name="def:comment" foreground="comment"/>+ <style name="def:shebang" foreground="comment" bold="true"/>+ <style name="def:doc-comment-element" italic="true"/>++ <!-- Constants -->+ <style name="def:constant" foreground="magenta"/>+ <style name="def:special-char" foreground="violet"/>++ <!-- Identifiers -->+ <style name="def:identifier" foreground="cyan"/>++ <!-- Statements -->+ <style name="def:statement" foreground="statement" bold="true"/>++ <!-- Types -->+ <style name="def:type" foreground="green" bold="true"/>++ <!-- Others -->+ <style name="def:preprocessor" foreground="preproc"/>+ <style name="def:error" background="red" bold="true"/>+ <style name="def:warning" background="yellow"/>+ <style name="def:note" foreground="comment" background="yellow" bold="true"/>+ <style name="def:underlined" italic="true" underline="true"/>++ <!-- Language specific styles -->+ <style name="diff:added-line" foreground="#008B8B"/>+ <style name="diff:removed-line" foreground="#6A5ACD"/>+ <style name="diff:changed-line" use-style="def:preprocessor"/>+ <style name="diff:special-case" use-style="def:constant"/>+ <style name="diff:location" use-style="def:statement"/>+ <style name="diff:diff-file" use-style="def:type"/>++ <style name="xml:tags" foreground="cyan"/>+ <style name="xml:attribute-name" foreground="violet"/>+ <style name="xml:namespace" foreground="green" bold="true"/>++ <style name="js:object" foreground="#2E8B57" bold="true"/>+ <style name="js:constructors" foreground="#008B8B"/>++ <style name="latex:display-math" foreground="#6A5ACD"/>+ <style name="latex:command" foreground="#2E8B57" bold="true"/>+ <style name="latex:include" use-style="def:preprocessor"/>++ <style name="sh:variable" foreground="#6A5ACD"/>++ <!-- legacy styles for old lang files -->+ <style name="Others" foreground="#2E8B57" bold="true"/>+ <style name="Others 2" foreground="#008B8B"/>+ <style name="Others 3" foreground="#6A5ACD"/>++</style-scheme>
@@ -0,0 +1,106 @@+<?xml version="1.0" encoding="UTF-8"?>+<!--++ This file is part of GtkSourceView++ Copyright (C) 2006-2007 GtkSourceView team+ Authors: Yevgen Muntyan <muntyan@tamu.edu>, Hamish Mackenzie++ GtkSourceView is free software; you can redistribute it and/or+ modify it under the terms of the GNU Lesser General Public+ License as published by the Free Software Foundation; either+ version 2.1 of the License, or (at your option) any later version.++ GtkSourceView is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU+ Lesser General Public License for more details.++ You should have received a copy of the GNU Lesser General Public+ License along with this library; if not, write to the Free Software+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA++-->+<style-scheme id="leksah" _name="Leksah" version="1.0">+ <author>GtkSourceView team</author>+ <_description>Classic color scheme</_description>++ <!-- Palette -->+ <color name="white" value="#FFFFFF"/>+ <color name="comment" value="#777777"/>+ <color name="magenta" value="#0057DC"/>+ <color name="violet" value="#7A00CD"/>+ <color name="cyan" value="#008A8C"/>+ <color name="gray" value="#DDDDDD"/>+ <color name="green" value="#1E9B27"/>+ <color name="statement" value="#CC6700"/>+ <color name="red" value="#EF0000"/>+ <color name="yellow" value="#EFEF00"/>+ <color name="preproc" value="#A50010"/>++ <!-- Global Settings -->+ <style name="current-line" background="#EEEEEE"/>+ <style name="draw-spaces" foreground="#aaada6"/>++ <!-- Bracket Matching -->+ <style name="bracket-match" foreground="white" background="gray" bold="true"/>+ <style name="bracket-mismatch" foreground="white" background="red" bold="true"/>++ <!-- Right Margin -->+ <style name="right-margin" foreground="gray"/>++ <!-- Search Matching -->+ <style name="search-match" background="yellow"/>++ <!-- Comments -->+ <style name="def:comment" foreground="comment"/>+ <style name="def:shebang" foreground="comment" bold="true"/>+ <style name="def:doc-comment-element" italic="true"/>++ <!-- Constants -->+ <style name="def:constant" foreground="magenta"/>+ <style name="def:special-char" foreground="violet"/>++ <!-- Identifiers -->+ <style name="def:identifier" foreground="cyan"/>++ <!-- Statements -->+ <style name="def:statement" foreground="statement" bold="true"/>++ <!-- Types -->+ <style name="def:type" foreground="green" bold="true"/>++ <!-- Others -->+ <style name="def:preprocessor" foreground="preproc"/>+ <style name="def:error" background="red" bold="true"/>+ <style name="def:warning" background="yellow"/>+ <style name="def:note" foreground="comment" background="yellow" bold="true"/>+ <style name="def:underlined" italic="true" underline="true"/>++ <!-- Language specific styles -->+ <style name="diff:added-line" foreground="#008B8B"/>+ <style name="diff:removed-line" foreground="#6A5ACD"/>+ <style name="diff:changed-line" use-style="def:preprocessor"/>+ <style name="diff:special-case" use-style="def:constant"/>+ <style name="diff:location" use-style="def:statement"/>+ <style name="diff:diff-file" use-style="def:type"/>++ <style name="xml:tags" foreground="cyan"/>+ <style name="xml:attribute-name" foreground="violet"/>+ <style name="xml:namespace" foreground="green" bold="true"/>++ <style name="js:object" foreground="#2E8B57" bold="true"/>+ <style name="js:constructors" foreground="#008B8B"/>++ <style name="latex:display-math" foreground="#6A5ACD"/>+ <style name="latex:command" foreground="#2E8B57" bold="true"/>+ <style name="latex:include" use-style="def:preprocessor"/>++ <style name="sh:variable" foreground="#6A5ACD"/>++ <!-- legacy styles for old lang files -->+ <style name="Others" foreground="#2E8B57" bold="true"/>+ <style name="Others 2" foreground="#008B8B"/>+ <style name="Others 3" foreground="#6A5ACD"/>++</style-scheme>
@@ -0,0 +1,9 @@+ <ui>+ <menubar>+ <menu name="Version Con_trol" action="vcs">+ <menuitem name="_Commit" action="SvnCommit" />+ <menuitem name="_View Log" action="SvnViewLog" />+ <menuitem name="_Update" action="SvnUpdate" />+ </menu>+ </menubar>+ </ui>
@@ -0,0 +1,3894 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="1024"+ height="640"+ id="svg2"+ sodipodi:version="0.32"+ inkscape:version="0.47 r22583"+ version="1.0"+ sodipodi:docname="Keybindings.svg"+ inkscape:output_extension="org.inkscape.output.svg.inkscape"+ inkscape:export-filename="/home/vav/images/xmonad/xmbindings_lg.png"+ inkscape:export-xdpi="112.5"+ inkscape:export-ydpi="112.5">+ <defs+ id="defs4">+ <pattern+ inkscape:collect="always"+ xlink:href="#Strips1_1"+ id="pattern5757"+ patternTransform="matrix(10,0,0,10,1,68)" />+ <pattern+ inkscape:stockid="Stripes 1:1"+ id="Strips1_1"+ patternTransform="translate(0,0) scale(10,10)"+ height="1"+ width="2"+ patternUnits="userSpaceOnUse"+ inkscape:collect="always">+ <rect+ id="rect4867"+ height="2"+ width="1"+ y="-0.5"+ x="0"+ style="fill:black;stroke:none" />+ </pattern>+ <inkscape:perspective+ sodipodi:type="inkscape:persp3d"+ inkscape:vp_x="0 : 320 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_z="1024 : 320 : 1"+ inkscape:persp3d-origin="512 : 213.33333 : 1"+ id="perspective554" />+ <inkscape:perspective+ id="perspective5602"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective5664"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective5695"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective5734"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective5767"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6056"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6095"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6128"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6156"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6156-3"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6218"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6246"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6278"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6339"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6370"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6417"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6456"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6541"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6572"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6597"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6634"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6668"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6705"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6741"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6778"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6841"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6888"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6940"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective6975"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7006"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7034"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7080"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7111"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7142"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7173"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7210"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7210-2"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7255"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7288"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7325"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7366"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7401"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7426"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7457"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7492"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7525"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7559"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7590"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ <inkscape:perspective+ id="perspective7590-1"+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"+ inkscape:vp_z="1 : 0.5 : 1"+ inkscape:vp_y="0 : 1000 : 0"+ inkscape:vp_x="0 : 0.5 : 1"+ sodipodi:type="inkscape:persp3d" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ gridtolerance="10000"+ guidetolerance="10"+ objecttolerance="10"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="1"+ inkscape:cx="455.37417"+ inkscape:cy="322.32716"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ width="1024px"+ height="640px"+ showgrid="false"+ inkscape:window-width="1918"+ inkscape:window-height="1152"+ inkscape:window-x="1920"+ inkscape:window-y="14"+ showguides="true"+ inkscape:guide-bbox="true"+ inkscape:snap-grids="true"+ inkscape:window-maximized="0">+ <inkscape:grid+ id="GridFromPre046Settings"+ type="xygrid"+ originx="0px"+ originy="0px"+ spacingx="2px"+ spacingy="2px"+ color="#0000ff"+ empcolor="#0000ff"+ opacity="0.2"+ empopacity="0.4"+ empspacing="5" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ id="layer1">+ <g+ id="g7271-0"+ transform="translate(-67.951295,149.5)"+ style="fill:#eeeeec;fill-opacity:1">+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3378-4"+ width="59.494934"+ height="60"+ x="370.45383"+ y="138"+ ry="4.480969" />+ <rect+ ry="2.2778258"+ y="138"+ x="370.45383"+ height="30.5"+ width="59.494934"+ id="rect7269-6"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 370.54685,168.5 c 19.9363,0 39.87259,0 59.80889,0"+ id="path3484-1" />+ </g>+ <text+ sodipodi:linespacing="89.999998%"+ id="text10763"+ y="227.65041"+ x="185.58366"+ style="font-size:7px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ xml:space="preserve"><tspan+ id="tspan10765"+ y="227.65041"+ x="185.58366"+ sodipodi:role="line">Move window</tspan><tspan+ y="233.95041"+ x="185.58366"+ sodipodi:role="line"+ id="tspan10767">to second</tspan><tspan+ y="240.25041"+ x="185.58366"+ sodipodi:role="line"+ id="tspan10769">workspace</tspan></text>+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3878"+ width="59.494934"+ height="60"+ x="151.45648"+ y="217.55692"+ ry="4.480969" />+ <text+ sodipodi:linespacing="89.999998%"+ id="text10699"+ y="256.94482"+ x="116.8933"+ style="font-size:7px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ xml:space="preserve"><tspan+ id="tspan10701"+ y="256.94482"+ x="116.8933"+ sodipodi:role="line">Switch to</tspan><tspan+ y="263.24481"+ x="116.8933"+ sodipodi:role="line"+ id="tspan10703">first</tspan><tspan+ y="269.54483"+ x="116.8933"+ sodipodi:role="line"+ id="tspan10705">workspace</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:7px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="116.8933"+ y="226.64024"+ id="text10771"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="116.8933"+ y="226.64024"+ id="tspan10773">Move window</tspan><tspan+ id="tspan10775"+ sodipodi:role="line"+ x="116.8933"+ y="232.94025">to first</tspan><tspan+ id="tspan10777"+ sodipodi:role="line"+ x="116.8933"+ y="239.24025">workspace</tspan></text>+ <rect+ ry="4.480969"+ y="287.55692"+ x="11"+ height="60"+ width="70"+ id="rect3328"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3330"+ width="60"+ height="60"+ x="91"+ y="287.55692"+ ry="4.480969" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3382"+ width="59.494934"+ height="60"+ x="511.4538"+ y="287.55692"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="287.55692"+ x="581.45642"+ height="60"+ width="59.494934"+ id="rect3384"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ ry="4.480969"+ y="287.55692"+ x="441.45361"+ height="60"+ width="59.494934"+ id="rect3386"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ ry="4.480969"+ y="287.55692"+ x="721.4538"+ height="60"+ width="59.494934"+ id="rect3388"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3392"+ width="59.494934"+ height="60"+ x="651.45642"+ y="287.55692"+ ry="4.480969" />+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="94.516792"+ y="309.5993"+ id="text3444"><tspan+ sodipodi:role="line"+ id="tspan3446"+ x="94.516792"+ y="309.5993">Q</tspan></text>+ <text+ id="text3448"+ y="309.87833"+ x="303.95746"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="309.87833"+ x="303.95746"+ id="tspan3450"+ sodipodi:role="line">R</tspan></text>+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect7301"+ width="59.494934"+ height="60"+ x="161.45648"+ y="287.55692"+ ry="4.480969" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 161.5446,318.55692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path7305" />+ <text+ id="text3464"+ y="310.17899"+ x="165.66309"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace"+ xml:space="preserve"><tspan+ y="310.17899"+ x="165.66309"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono"+ id="tspan3498">W</tspan></text>+ <text+ id="text3468"+ y="336.77765"+ x="94.295898"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="336.77765"+ x="94.295898"+ id="tspan3470"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">q</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="163.72855"+ y="340.66086"+ id="text3472"><tspan+ sodipodi:role="line"+ id="tspan3474"+ x="163.72855"+ y="340.66086"+ style="font-size:18px;font-family:DejaVu Sans Mono">w</tspan></text>+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 91.598089,317.55692 c 19.936301,0 39.872591,0 59.808891,0"+ id="path3476" />+ <g+ id="g7271"+ transform="translate(1,150.05692)"+ style="fill:#eeeeec;fill-opacity:1">+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3378"+ width="59.494934"+ height="60"+ x="370.45383"+ y="138"+ ry="4.480969" />+ <rect+ ry="2.2778258"+ y="138"+ x="370.45383"+ height="30.5"+ width="59.494934"+ id="rect7269"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ style="font-size:18px;fill:#eeeeec;fill-rule:evenodd;stroke:#000000;stroke-width:1.09369910000000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"+ d="m 370.54685,168.5 c 19.9363,0 39.87259,0 59.80889,0"+ id="path3484" />+ </g>+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08917749px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 441.54459,318.55692 c 19.77181,0 39.54358,0 59.31538,0"+ id="path3486" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 511.54685,318.55692 c 19.9363,0 39.87259,0 59.80889,0"+ id="path3488" />+ <path+ id="path3490"+ d="m 581.5446,318.05692 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ id="path3492"+ d="m 651.5446,318.55692 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ id="path3494"+ d="m 721.54685,318.55692 c 19.9363,0 39.87259,0 59.80889,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <rect+ ry="4.480969"+ y="286"+ x="231.04858"+ height="60"+ width="59.494934"+ id="rect2735"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ id="path2737"+ d="m 231.13671,316.99999 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="234.23283"+ y="309.87833"+ id="text3502"><tspan+ sodipodi:role="line"+ id="tspan3504"+ x="234.23283"+ y="309.87833">E</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="234.10065"+ y="340.40598"+ id="text3506"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3508"+ x="234.10065"+ y="340.40598">e</tspan></text>+ <text+ id="text3510"+ y="340.138"+ x="302.84863"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="340.138"+ x="302.84863"+ id="tspan3512"+ sodipodi:role="line">r</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="371.84863"+ y="340.55695"+ id="text3532"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3534"+ x="371.84863"+ y="340.55695">t</tspan></text>+ <text+ id="text3536"+ y="338.31281"+ x="445.58594"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="338.31281"+ x="445.58594"+ id="tspan3538"+ sodipodi:role="line">y</tspan></text>+ <text+ id="text3540"+ y="340.15921"+ x="514.22791"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="340.15921"+ x="514.22791"+ id="tspan3542"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">u</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="584.43555"+ y="340.55695"+ id="text3544"><tspan+ sodipodi:role="line"+ id="tspan3546"+ x="584.43555"+ y="340.55695"+ style="font-size:18px;font-family:DejaVu Sans Mono">i</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="655.86719"+ y="340.138"+ id="text3548"><tspan+ sodipodi:role="line"+ id="tspan3550"+ x="655.86719"+ y="340.138"+ style="font-size:18px;font-family:DejaVu Sans Mono">o</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="724.76172"+ y="340.138"+ id="text3552"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3554"+ x="724.76172"+ y="340.138">p</tspan></text>+ <text+ id="text3556"+ y="188.60269"+ x="798.63989"+ style="font-size:22px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-family:DejaVu Sans Mono"+ y="188.60269"+ x="798.63989"+ id="tspan3558"+ sodipodi:role="line" /></text>+ <rect+ ry="4.480969"+ y="357.55695"+ x="100.59211"+ height="60"+ width="60"+ id="rect3616"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3618"+ width="59.494934"+ height="60"+ x="171.04858"+ y="357.55695"+ ry="4.480969" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3620"+ width="60.505096"+ height="60"+ x="240.5921"+ y="357.55695"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="357.55695"+ x="311.04858"+ height="60"+ width="59.494934"+ id="rect3622"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3624"+ width="59.494934"+ height="60"+ x="381.04593"+ y="357.55695"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="357.55695"+ x="521.0459"+ height="60"+ width="59.494934"+ id="rect3626"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3628"+ width="59.494934"+ height="60"+ x="591.04852"+ y="357.55695"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="357.55695"+ x="731.45642"+ height="60"+ width="59.951477"+ id="rect3634"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <text+ id="text3638"+ y="379.6998"+ x="104.64462"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="379.6998"+ x="104.64462"+ id="tspan3640"+ sodipodi:role="line">A</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="318.95215"+ y="381"+ id="text3642"><tspan+ sodipodi:role="line"+ id="tspan3644"+ x="318.95215"+ y="381">F</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace"+ x="174.7986"+ y="379.44492"+ id="text3646"><tspan+ id="tspan3648"+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ x="174.7986"+ y="379.44492">S</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="104.19238"+ y="410.638"+ id="text3650"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3652"+ x="104.19238"+ y="410.638">a</tspan></text>+ <text+ id="text3654"+ y="410.638"+ x="174.94727"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="410.638"+ x="174.94727"+ id="tspan3656"+ sodipodi:role="line">s</tspan></text>+ <path+ id="path3658"+ d="m 101.1902,387.55692 c 19.9363,0 39.87259,0 59.80889,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 171.13671,388.05692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3660" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:0.57072788px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 241.66724,387.20486 c 19.00094,0 38.00186,0 57.0028,0"+ id="path3662" />+ <path+ id="path3664"+ d="m 311.13671,388.55692 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 381.13896,388.05692 c 19.9363,0 39.87259,0 59.80889,0"+ id="path3666" />+ <g+ id="g10542"+ transform="translate(1,27.999989)"+ style="fill:#eeeeec;fill-opacity:1">+ <rect+ ry="4.480969"+ y="329.55695"+ x="450.04572"+ height="60"+ width="59.494934"+ id="rect3630"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect8437"+ width="59.494934"+ height="30.943054"+ x="450.04572"+ y="329.55695"+ ry="2.3109145" />+ <path+ style="font-size:18px;fill:#eeeeec;stroke:#000000;stroke-width:1.08917748999999997px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"+ d="m 450.1367,360.55693 c 19.77181,0 39.54358,0 59.31538,0"+ id="path3668" />+ </g>+ <path+ id="path3670"+ d="m 521.13896,388.55692 c 19.9363,0 39.87259,0 59.80889,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 591.13671,388.05692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3672" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 661.13671,388.55692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3674" />+ <path+ id="path3678"+ d="m 731.5446,388.05692 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <text+ id="text3680"+ y="379.6998"+ x="244.62431"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="379.6998"+ x="244.62431"+ id="tspan3682"+ sodipodi:role="line">D</tspan></text>+ <text+ id="text3684"+ y="411.23273"+ x="245.3418"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="411.23273"+ x="245.3418"+ id="tspan3686"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">d</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="317.80347"+ y="409.5882"+ id="text3688"><tspan+ sodipodi:role="line"+ id="tspan3690"+ x="317.80347"+ y="409.5882"+ style="font-size:18px;font-family:DejaVu Sans Mono">f</tspan></text>+ <text+ id="text3692"+ y="408.94226"+ x="389.0748"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="408.94226"+ x="389.0748"+ id="tspan3694"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">g</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="458.34314"+ y="408.17078"+ id="text3696"><tspan+ sodipodi:role="line"+ id="tspan3698"+ x="458.34314"+ y="408.17078"+ style="font-size:18px;font-family:DejaVu Sans Mono">h</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="528.9986"+ y="409.12097"+ id="text3700"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3702"+ x="528.9986"+ y="409.12097">j</tspan></text>+ <text+ id="text3704"+ y="413.64285"+ x="591.64008"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="413.64285"+ x="591.64008"+ id="tspan3706"+ sodipodi:role="line">k</tspan></text>+ <g+ id="g10537"+ transform="translate(1,27.999989)"+ style="fill:#eeeeec;fill-opacity:1">+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect8447"+ width="59.494934"+ height="60"+ x="660"+ y="329"+ ry="4.480969" />+ <rect+ ry="2.2404845"+ y="359"+ x="660"+ height="30"+ width="59.494934"+ id="rect8449"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ id="path8451"+ d="m 660.3186,359.97316 c 19.77181,0 39.54358,0 59.31538,0"+ style="font-size:18px;fill:#eeeeec;stroke:#000000;stroke-width:1.08917748999999997px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />+ </g>+ <text+ id="text3708"+ y="412.85968"+ x="665.90234"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="412.85968"+ x="665.90234"+ id="tspan3710"+ sodipodi:role="line">l</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="733.63672"+ y="407.93781"+ id="text3716"><tspan+ sodipodi:role="line"+ id="tspan3718"+ x="733.63672"+ y="407.93781"+ style="font-size:18px;font-family:DejaVu Sans Mono">;</tspan></text>+ <rect+ ry="4.480969"+ y="357.55695"+ x="801.86169"+ height="60"+ width="59.494934"+ id="rect3720"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ id="path3724"+ d="m 801.95474,388.55692 c 19.9363,0 39.87259,0 59.80889,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3722"+ width="129.00507"+ height="60"+ x="871.99487"+ y="357.55692"+ ry="4.480969" />+ <rect+ ry="2.2404845"+ y="387.55692"+ x="871.99487"+ height="30"+ width="129.00507"+ id="rect7133"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.49844062px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 887.74259,388.05692 c 37.4221,0 74.84417,0 112.26621,0"+ id="path3726" />+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="805.84375"+ y="411.7171"+ id="text3728"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3730"+ x="805.84375"+ y="411.7171">'</tspan></text>+ <text+ id="text3740"+ y="396.10226"+ x="872.17328"+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"+ xml:space="preserve"+ sodipodi:linespacing="125%"><tspan+ y="396.10226"+ x="872.17328"+ id="tspan3742"+ sodipodi:role="line">↲</tspan></text>+ <path+ id="path3758"+ d="m 41.400804,317.01007 c 13.350921,0 26.701835,0 40.052755,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:0.89501685px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3764"+ width="60"+ height="60"+ x="110.59211"+ y="427.55695"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="427.55695"+ x="181.04858"+ height="60"+ width="59.494934"+ id="rect3766"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3770"+ width="59.494934"+ height="60"+ x="321.04858"+ y="427.55695"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="427.55695"+ x="391.04593"+ height="60"+ width="59.494934"+ id="rect3772"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ ry="4.480969"+ y="427.55695"+ x="461.04572"+ height="60"+ width="59.494934"+ id="rect3778"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3780"+ width="59.951477"+ height="60"+ x="741.45642"+ y="427.55695"+ ry="4.480969" />+ <text+ id="text3796"+ y="479.65656"+ x="119.84034"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="479.65656"+ x="119.84034"+ id="tspan3798"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">z</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="187.63174"+ y="478.17078"+ id="text3800"><tspan+ sodipodi:role="line"+ id="tspan3802"+ x="187.63174"+ y="478.17078"+ style="font-size:18px;font-family:DejaVu Sans Mono">x</tspan></text>+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 111.1902,457.55692 c 19.9363,0 39.87259,0 59.80889,0"+ id="path3804" />+ <path+ id="path3806"+ d="m 181.13671,458.05692 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <rect+ ry="4.480969"+ y="427.55692"+ x="250.5921"+ height="60"+ width="60.505096"+ id="rect3768"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect7145"+ width="60.505096"+ height="30"+ x="250.5921"+ y="427.55692"+ ry="2.2404845" />+ <path+ id="path3808"+ d="m 251.66724,457.20486 c 19.00094,0 38.00186,0 57.0028,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 321.13671,458.55692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3810" />+ <path+ id="path3812"+ d="m 391.13896,458.05692 c 19.9363,0 39.87259,0 59.80889,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <rect+ style="font-size:18px;fill:none;stroke:none"+ id="rect10608"+ width="59.494934"+ height="28.556946"+ x="461.04572"+ y="459"+ ry="2.1327131" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08917749px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 461.1367,458.55692 c 19.77181,0 39.54358,0 59.31538,0"+ id="path3814" />+ <g+ id="g7140"+ transform="translate(1,149.55692)"+ style="fill:#eeeeec;fill-opacity:1">+ <rect+ ry="4.480969"+ y="278"+ x="530.0459"+ height="60"+ width="59.494934"+ id="rect3774"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect7131"+ width="59.494934"+ height="30"+ x="530.0459"+ y="308"+ ry="2.2404845" />+ <path+ id="path3816"+ d="m 530.13896,309 c 19.9363,0 39.87259,0 59.80889,0"+ style="font-size:18px;fill:#eeeeec;stroke:#000000;stroke-width:1.09369910000000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />+ </g>+ <g+ id="g7162"+ transform="translate(1,149.55692)"+ style="fill:#eeeeec;fill-opacity:1">+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3776"+ width="59.494934"+ height="60"+ x="600.04852"+ y="278"+ ry="4.480969" />+ <rect+ ry="2.2404845"+ y="308"+ x="600.04852"+ height="30"+ width="59.494934"+ id="rect7160"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ style="font-size:18px;fill:#eeeeec;stroke:#000000;stroke-width:1.08920788999999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"+ d="m 600.13671,308.5 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3818" />+ </g>+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 741.5446,458.05692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3822" />+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="255.6748"+ y="479.58105"+ id="text3828"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3830"+ x="255.6748"+ y="479.58105">c</tspan></text>+ <text+ id="text3832"+ y="479.5882"+ x="327.80347"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="479.5882"+ x="327.80347"+ id="tspan3834"+ sodipodi:role="line">v</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="399.0748"+ y="478.94226"+ id="text3836"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3838"+ x="399.0748"+ y="478.94226">b</tspan></text>+ <text+ id="text3840"+ y="479.05466"+ x="464.4288"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="479.05466"+ x="464.4288"+ id="tspan3842"+ sodipodi:role="line">n</tspan></text>+ <text+ id="text3844"+ y="479.12097"+ x="538.9986"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:url(#pattern5757);fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="479.12097"+ x="538.9986"+ id="tspan3846"+ sodipodi:role="line"+ style="font-size:18px;fill:url(#pattern5757);fill-opacity:1;font-family:DejaVu Sans Mono">m</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="604.58911"+ y="478.8739"+ id="text3848"><tspan+ sodipodi:role="line"+ id="tspan3850"+ x="604.58911"+ y="478.8739"+ style="font-size:18px;font-family:DejaVu Sans Mono">,</tspan></text>+ <g+ id="g7167"+ transform="translate(70.999996,149.55692)"+ style="fill:#eeeeec;fill-opacity:1">+ <rect+ ry="4.480969"+ y="278"+ x="600.04852"+ height="60"+ width="59.494934"+ id="rect7169"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect7171"+ width="59.494934"+ height="30"+ x="600.04852"+ y="308"+ ry="2.2404845" />+ <path+ id="path7173"+ d="m 600.13671,308.5 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:#eeeeec;stroke:#000000;stroke-width:1.08920788999999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />+ </g>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="674.70215"+ y="478.5"+ id="text3852"><tspan+ sodipodi:role="line"+ id="tspan3854"+ x="674.70215"+ y="478.5"+ style="font-size:18px;font-family:DejaVu Sans Mono">.</tspan></text>+ <text+ id="text3856"+ y="478.15964"+ x="749.63989"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="478.15964"+ x="749.63989"+ id="tspan3858"+ sodipodi:role="line">/</tspan></text>+ <rect+ ry="4.480969"+ y="217.55692"+ x="80.999992"+ height="60"+ width="60"+ id="rect3876"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect10511"+ width="59.494934"+ height="60"+ x="221.45648"+ y="217.55692"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="217.55692"+ x="291.45648"+ height="60"+ width="59.494934"+ id="rect3882"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3884"+ width="59.494934"+ height="60"+ x="361.45383"+ y="217.55692"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="217.55692"+ x="501.4538"+ height="60"+ width="59.494934"+ id="rect3886"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3888"+ width="59.494934"+ height="60"+ x="571.45642"+ y="217.55692"+ ry="4.480969" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3890"+ width="59.494934"+ height="60"+ x="431.45361"+ y="217.55692"+ ry="4.480969" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3892"+ width="59.494934"+ height="60"+ x="711"+ y="217.55692"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="217.55692"+ x="781.45642"+ height="60"+ width="59.494934"+ id="rect3894"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ ry="4.480969"+ y="217.55692"+ x="641.45642"+ height="60"+ width="59.494934"+ id="rect3896"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="84.176796"+ y="270.28568"+ id="text3910"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3912"+ x="84.176796"+ y="270.28568">1</tspan></text>+ <text+ id="text3914"+ y="269.85934"+ x="153.69238"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="269.85934"+ x="153.69238"+ id="tspan3916"+ sodipodi:role="line">2</tspan></text>+ <path+ id="path3918"+ d="m 81.598085,247.55692 c 19.936305,0 39.872595,0 59.808895,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 151.5446,248.05692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3920" />+ <path+ id="path3924"+ d="m 291.5446,248.55692 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 361.54685,248.05692 c 19.9363,0 39.87259,0 59.80889,0"+ id="path3926" />+ <path+ id="path3928"+ d="m 431.54459,248.55692 c 19.77181,0 39.54358,0 59.31538,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08917749px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ id="path3930"+ d="m 501.54685,248.55692 c 19.9363,0 39.87259,0 59.80889,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 571.5446,248.05692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3932" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 641.5446,248.55692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3934" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 711.54685,248.55692 c 19.9363,0 39.87259,0 59.80889,0"+ id="path3936" />+ <path+ id="path3938"+ d="m 781.5446,248.05692 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 221.5446,248.55692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path10513" />+ <text+ id="text3944"+ y="269.85934"+ x="225.5166"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="269.85934"+ x="225.5166"+ id="tspan3946"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">3</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="293.74707"+ y="270.28568"+ id="text3948"><tspan+ sodipodi:role="line"+ id="tspan3950"+ x="293.74707"+ y="270.28568"+ style="font-size:18px;font-family:DejaVu Sans Mono">4</tspan></text>+ <text+ id="text3952"+ y="269.74509"+ x="363.74316"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="269.74509"+ x="363.74316"+ id="tspan3954"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">5</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="433.33203"+ y="269.85934"+ id="text3956"><tspan+ sodipodi:role="line"+ id="tspan3958"+ x="433.33203"+ y="269.85934"+ style="font-size:18px;font-family:DejaVu Sans Mono">6</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="503.77832"+ y="269.99997"+ id="text3960"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3962"+ x="503.77832"+ y="269.99997">7</tspan></text>+ <text+ id="text3964"+ y="269.74509"+ x="573.84863"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="269.74509"+ x="573.84863"+ id="tspan3966"+ sodipodi:role="line">8</tspan></text>+ <text+ id="text3968"+ y="269.77789"+ x="644.64673"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="269.77789"+ x="644.64673"+ id="tspan3970"+ sodipodi:role="line">9</tspan></text>+ <text+ id="text3972"+ y="269.53793"+ x="713.83203"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="269.53793"+ x="713.83203"+ id="tspan3974"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">0</tspan></text>+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3976"+ width="59.494934"+ height="60"+ x="851.04852"+ y="217.55692"+ ry="4.480969" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 851.13671,248.05692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3978" />+ <rect+ ry="4.480969"+ y="217.55692"+ x="11.456417"+ height="60"+ width="59.494934"+ id="rect3980"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ id="path3982"+ d="m 11.544604,248.05692 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="788.75385"+ y="268.88504"+ id="text3988"><tspan+ sodipodi:role="line"+ id="tspan3990"+ x="788.75385"+ y="268.88504"+ style="font-size:18px;font-family:DejaVu Sans Mono">-</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="859.40649"+ y="269.83527"+ id="text3992"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3994"+ x="859.40649"+ y="269.83527">=</tspan></text>+ <rect+ ry="4.480969"+ y="217.55692"+ x="921.32385"+ height="60"+ width="89.135681"+ id="rect3996"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ id="path3998"+ d="m 921.6635,248.05692 c 29.34839,0 58.69676,0 88.0451,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.32699001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <text+ id="text4004"+ y="266.37692"+ x="931.37891"+ style="font-size:13px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="266.37692"+ x="931.37891"+ id="tspan4006"+ sodipodi:role="line"+ style="font-size:13px;font-family:DejaVu Sans Mono">Backspace</tspan></text>+ <text+ id="text4977"+ y="244.12206"+ x="84.680664"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="244.12206"+ x="84.680664"+ id="tspan4979"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">!</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="153.03964"+ y="243.17078"+ id="text4981"><tspan+ sodipodi:role="line"+ id="tspan4983"+ x="153.03964"+ y="243.17078"+ style="font-size:18px;font-family:DejaVu Sans Mono">@</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="224.98242"+ y="244.49998"+ id="text4985"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan4987"+ x="224.98242"+ y="244.49998">#</tspan></text>+ <text+ id="text4989"+ y="244.58817"+ x="293.21136"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="244.58817"+ x="293.21136"+ id="tspan4991"+ sodipodi:role="line">$</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="364.4827"+ y="243.94225"+ id="text4993"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan4995"+ x="364.4827"+ y="243.94225">%</tspan></text>+ <text+ id="text4997"+ y="243.17078"+ x="433.75104"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="243.17078"+ x="433.75104"+ id="tspan4999"+ sodipodi:role="line">^</tspan></text>+ <text+ id="text5001"+ y="244.12096"+ x="504.40649"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="244.12096"+ x="504.40649"+ id="tspan5003"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">&</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="572.49701"+ y="243.87389"+ id="text5005"><tspan+ sodipodi:role="line"+ id="tspan5007"+ x="572.49701"+ y="243.87389"+ style="font-size:18px;font-family:DejaVu Sans Mono">*</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="643.21814"+ y="243.17076"+ id="text5009"><tspan+ sodipodi:role="line"+ id="tspan5011"+ x="643.21814"+ y="243.17076"+ style="font-size:18px;font-family:DejaVu Sans Mono">(</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="715.29938"+ y="242.87096"+ id="text5013"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan5015"+ x="715.29938"+ y="242.87096">)</tspan></text>+ <rect+ ry="4.3646927"+ y="497.55695"+ x="239.30771"+ height="58.443066"+ width="361.69229"+ id="rect5017"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <text+ xml:space="preserve"+ style="font-size:13px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="246.32532"+ y="529.78864"+ id="text5021"><tspan+ sodipodi:role="line"+ id="tspan5023"+ x="246.32532"+ y="529.78864">Space</tspan></text>+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:0.86598694;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"+ d="m 289.69581,526.77845 c 103.63515,0 207.27032,0 310.90547,0"+ id="path5031" />+ <text+ id="text6971"+ y="451.98907"+ x="118.53249"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="451.98907"+ x="118.53249"+ id="tspan6973"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">Z</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="186.32391"+ y="450.50333"+ id="text6975"><tspan+ sodipodi:role="line"+ id="tspan6977"+ x="186.32391"+ y="450.50333"+ style="font-size:18px;font-family:DejaVu Sans Mono">X</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="255.77832"+ y="452.74512"+ id="text6979"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan6981"+ x="255.77832"+ y="452.74512">C</tspan></text>+ <text+ id="text6983"+ y="451.92072"+ x="326.49564"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="451.92072"+ x="326.49564"+ id="tspan6985"+ sodipodi:role="line">V</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="397.76697"+ y="451.27481"+ id="text6987"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan6989"+ x="397.76697"+ y="451.27481">B</tspan></text>+ <text+ id="text6991"+ y="451.13467"+ x="464.25739"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="451.13467"+ x="464.25739"+ id="tspan6993"+ sodipodi:role="line">N</tspan></text>+ <text+ id="text6995"+ y="451.45352"+ x="537.6908"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="451.45352"+ x="537.6908"+ id="tspan6997"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">M</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="605.78131"+ y="451.20645"+ id="text6999"><tspan+ sodipodi:role="line"+ id="tspan7001"+ x="605.78131"+ y="451.20645"+ style="font-size:18px;font-family:DejaVu Sans Mono"><</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="679.18103"+ y="449.78903"+ id="text7003"><tspan+ sodipodi:role="line"+ id="tspan7005"+ x="679.18103"+ y="449.78903"+ style="font-size:18px;font-family:DejaVu Sans Mono">></tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="749.83368"+ y="450.73923"+ id="text7007"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7009"+ x="749.83368"+ y="450.73923">?</tspan></text>+ <text+ id="text7027"+ y="381.57428"+ x="385.14008"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="381.57428"+ x="385.14008"+ id="tspan7029"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">G</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="454.40842"+ y="380.8028"+ id="text7031"><tspan+ sodipodi:role="line"+ id="tspan7033"+ x="454.40842"+ y="380.8028"+ style="font-size:18px;font-family:DejaVu Sans Mono">H</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="525.0639"+ y="381.75299"+ id="text7035"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7037"+ x="525.0639"+ y="381.75299">J</tspan></text>+ <text+ id="text7039"+ y="380.69351"+ x="592.94769"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="380.69351"+ x="592.94769"+ id="tspan7041"+ sodipodi:role="line">K</tspan></text>+ <text+ id="text7043"+ y="382.4007"+ x="665.31641"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="382.4007"+ x="665.31641"+ id="tspan7045"+ sodipodi:role="line">L</tspan></text>+ <text+ id="text7047"+ y="380.88547"+ x="733.49005"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="380.88547"+ x="733.49005"+ id="tspan7049"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">:</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="376.07617"+ y="310.17899"+ id="text7051"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7053"+ x="376.07617"+ y="310.17899">T</tspan></text>+ <text+ id="text7055"+ y="309.87833"+ x="445.88342"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="309.87833"+ x="445.88342"+ id="tspan7057"+ sodipodi:role="line">Y</tspan></text>+ <text+ id="text7059"+ y="309.62344"+ x="514.93176"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="309.62344"+ x="514.93176"+ id="tspan7061"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">U</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="583.9151"+ y="309.87833"+ id="text7063"><tspan+ sodipodi:role="line"+ id="tspan7065"+ x="583.9151"+ y="309.87833"+ style="font-size:18px;font-family:DejaVu Sans Mono">I</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="656.24341"+ y="309.62344"+ id="text7067"><tspan+ sodipodi:role="line"+ id="tspan7069"+ x="656.24341"+ y="309.62344"+ style="font-size:18px;font-family:DejaVu Sans Mono">O</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="724.47168"+ y="310.17899"+ id="text7071"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7073"+ x="724.47168"+ y="310.17899">P</tspan></text>+ <rect+ ry="4.480969"+ y="287.55692"+ x="791.0459"+ height="60"+ width="59.494934"+ id="rect7075"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect7077"+ width="59.494934"+ height="60"+ x="861.04852"+ y="287.55692"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="287.55692"+ x="931.04852"+ height="60"+ width="79.951477"+ id="rect7079"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ id="path7081"+ d="m 791.13896,318.55692 c 19.9363,0 39.87259,0 59.80889,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 861.13671,318.05692 c 19.7729,0 39.54579,0 59.31869,0"+ id="path7083" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.25664687px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 931.31702,318.55692 c 26.31936,0 52.63871,0 78.95808,0"+ id="path7085" />+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="793.43066"+ y="339.6839"+ id="text7087"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7089"+ x="793.43066"+ y="339.6839">[</tspan></text>+ <text+ id="text7091"+ y="339.6839"+ x="863.45898"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="339.6839"+ x="863.45898"+ id="tspan7093"+ sodipodi:role="line">]</tspan></text>+ <text+ id="text7095"+ y="340.17902"+ x="932.0166"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="340.17902"+ x="932.0166"+ id="tspan7097"+ sodipodi:role="line">\</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="793.10547"+ y="309.2327"+ id="text7099"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7101"+ x="793.10547"+ y="309.2327">{</tspan></text>+ <text+ id="text7103"+ y="309.2327"+ x="862.10547"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="309.2327"+ x="862.10547"+ id="tspan7105"+ sodipodi:role="line">}</tspan></text>+ <text+ id="text7107"+ y="307.8118"+ x="932.3418"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="307.8118"+ x="932.3418"+ id="tspan7109"+ sodipodi:role="line">|</tspan></text>+ <flowRoot+ xml:space="preserve"+ id="flowRoot7111"+ style="font-size:20px;font-family:DejaVu Sans Mono"><flowRegion+ id="flowRegion7113"><rect+ id="rect7115"+ width="12.121831"+ height="16.162441"+ x="806.10175"+ y="215.85266"+ style="font-size:20px;font-family:DejaVu Sans Mono" /></flowRegion><flowPara+ id="flowPara7117">'"l</flowPara></flowRoot> <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="804.70117"+ y="382.27374"+ id="text7119"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7121"+ x="804.70117"+ y="382.27374">"</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="19.835238"+ y="270.55493"+ id="text7123"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7125"+ x="19.835238"+ y="270.55493">`</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="18.527391"+ y="242.88747"+ id="text7127"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7129"+ x="18.527391"+ y="242.88747">~</tspan></text>+ <flowRoot+ xml:space="preserve"+ id="flowRoot7342"+ style="font-size:13px;font-family:DejaVu Sans Mono"><flowRegion+ id="flowRegion7344"><rect+ id="rect7346"+ width="16.362942"+ height="34.170197"+ x="13.637059"+ y="163.8298"+ style="font-size:13px;font-family:DejaVu Sans Mono" /></flowRegion><flowPara+ id="flowPara7348">TabTa</flowPara></flowRoot> <text+ id="text7358"+ y="320.61826"+ x="11.98186"+ style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="320.61826"+ x="11.98186"+ id="tspan7360"+ sodipodi:role="line"+ style="font-size:12px;font-family:DejaVu Sans Mono">Tab</tspan></text>+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1"+ id="rect10890"+ width="317.01669"+ height="39.126007"+ x="12.98332"+ y="35.686996"+ ry="2.9220402" />+ <text+ id="text7404"+ y="62.497929"+ x="17.641596"+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans"+ xml:space="preserve"+ sodipodi:linespacing="100%"><tspan+ y="62.497929"+ x="17.641596"+ id="tspan7406"+ sodipodi:role="line">leksah-0.8 default bindings</tspan></text>+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:0.94688416;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0.94688416, 2.84065247;stroke-dashoffset:0;stroke-opacity:1"+ id="rect11866"+ width="558.63818"+ height="39.017399"+ x="450.47345"+ y="36.009155"+ ry="2.9139295" />+ <rect+ ry="2.2404845"+ y="40.60714"+ x="522.39178"+ height="30"+ width="60.505096"+ id="rect8456"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:#000000;stroke-width:0.50000000000000000;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />+ <text+ id="text8458"+ y="58.433311"+ x="551.8833"+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans"+ xml:space="preserve"+ sodipodi:linespacing="125%"><tspan+ y="58.433311"+ x="551.8833"+ id="tspan8460"+ sodipodi:role="line"+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:DejaVu Sans">Ctrl</tspan></text>+ <rect+ style="font-size:18px;fill:#fcaf3e;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ id="rect8462"+ width="60.505096"+ height="30"+ x="592.39178"+ y="40.60714"+ ry="2.2404845" />+ <text+ sodipodi:linespacing="125%"+ xml:space="preserve"+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans"+ x="622.5976"+ y="58.433311"+ id="text8464"><tspan+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:DejaVu Sans"+ sodipodi:role="line"+ id="tspan8466"+ x="622.5976"+ y="58.433311">Alt</tspan><tspan+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:DejaVu Sans"+ sodipodi:role="line"+ x="622.5976"+ y="58.433311"+ id="tspan7352" /></text>+ <rect+ style="font-size:18px;fill:#ad7fa8;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ id="rect8468"+ width="60.505096"+ height="30"+ x="661.88666"+ y="40.60714"+ ry="2.2404845" />+ <text+ sodipodi:linespacing="125%"+ xml:space="preserve"+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans"+ x="692.09253"+ y="58.433311"+ id="text8470"><tspan+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:DejaVu Sans"+ sodipodi:role="line"+ id="tspan8472"+ x="692.09253"+ y="58.433311">Windows</tspan></text>+ <rect+ ry="2.2404845"+ y="40.60714"+ x="732.39172"+ height="30"+ width="60.505096"+ id="rect8480"+ style="font-size:18px;fill:#8ae234;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />+ <text+ id="text8482"+ y="58.433311"+ x="762.5976"+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans"+ xml:space="preserve"+ sodipodi:linespacing="125%"><tspan+ y="58.433311"+ x="762.5976"+ id="tspan8484"+ sodipodi:role="line"+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:DejaVu Sans">AltGr</tspan></text>+ <rect+ ry="2.2404845"+ y="40.60714"+ x="801.39172"+ height="30"+ width="60.505096"+ id="rect8486"+ style="font-size:18px;fill:#babdb6;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />+ <text+ id="text8488"+ y="58.433311"+ x="832.0976"+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans"+ xml:space="preserve"+ sodipodi:linespacing="125%"><tspan+ y="58.433311"+ x="832.0976"+ sodipodi:role="line"+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:DejaVu Sans"+ id="tspan8508">unmodified</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="481.83459"+ y="470.37329"+ id="text10610"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="481.83459"+ y="470.37329"+ id="tspan5592">New</tspan><tspan+ sodipodi:role="line"+ x="481.83459"+ y="478.4733"+ id="tspan5588">file</tspan><tspan+ sodipodi:role="line"+ x="481.83459"+ y="486.5733"+ id="tspan5590" /></text>+ <text+ sodipodi:linespacing="125%"+ xml:space="preserve"+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans"+ x="481.35913"+ y="58.356812"+ id="text11868"><tspan+ style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:DejaVu Sans"+ sodipodi:role="line"+ id="tspan11870"+ x="481.35913"+ y="58.356812">Modifiers</tspan></text>+ <g+ id="g14824"+ transform="translate(-202,130)">+ <path+ id="rect14799"+ d="m 885.46874,378.36166 c -14.1057,0 -25.46874,9.09042 -25.46874,20.375 l 0,19.625 100,0 0,-19.625 c 0,-11.28456 -11.36302,-20.375 -25.46876,-20.375 l -49.0625,0 z"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:0.88851714px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 925.55574,417.9174 c 0,-13.15772 0,-26.31543 0,-39.47314"+ id="path14801" />+ <path+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ d="M 885.46874,488.36166 C 871.36304,488.36166 860,472.45343 860,452.70541 l 0,-34.34375 100,0 0,34.34375 c 0,19.74798 -11.36302,35.65625 -25.46876,35.65625 l -49.0625,0 z"+ id="path14810" />+ <path+ id="path14822"+ d="m 894.44426,417.55574 c 0,-13.15772 0,-26.31543 0,-39.47314"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:0.88851714px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ </g>+ <text+ id="text14803"+ y="565.6424"+ x="689.66016"+ style="font-size:13px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="565.6424"+ x="689.66016"+ id="tspan14805"+ sodipodi:role="line">mouse</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="675.77704"+ y="330.5145"+ id="text10610-3"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="675.77704"+ y="330.5145"+ id="tspan5588-9">Open</tspan><tspan+ sodipodi:role="line"+ x="675.77704"+ y="338.6145"+ id="tspan5634">file</tspan><tspan+ sodipodi:role="line"+ x="675.77704"+ y="346.71451"+ id="tspan5590-2" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="195.96628"+ y="401.0015"+ id="text10610-0"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="195.96628"+ y="401.0015"+ id="tspan5592-5">Save</tspan><tspan+ sodipodi:role="line"+ x="195.96628"+ y="409.1015"+ id="tspan5588-5">file</tspan><tspan+ sodipodi:role="line"+ x="195.96628"+ y="417.20151"+ id="tspan5590-0" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="194.87178"+ y="367.56451"+ id="text10610-0-8"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="194.87178"+ y="367.56451"+ id="tspan5592-5-2">Save</tspan><tspan+ sodipodi:role="line"+ x="194.87178"+ y="375.66452"+ id="tspan5724">all</tspan><tspan+ sodipodi:role="line"+ x="194.87178"+ y="383.76453"+ id="tspan5588-5-0">files</tspan><tspan+ sodipodi:role="line"+ x="194.87178"+ y="391.8645"+ id="tspan5590-0-5" /></text>+ <text+ xml:space="preserve"+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"+ x="257.5"+ y="316.5"+ id="text5718"><tspan+ sodipodi:role="line"+ id="tspan5720"+ x="257.5"+ y="316.5"></tspan><tspan+ sodipodi:role="line"+ id="tspan5722" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="185.87177"+ y="330.56451"+ id="text10610-0-4"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="185.87177"+ y="330.56451"+ id="tspan5592-5-4">Close</tspan><tspan+ sodipodi:role="line"+ x="185.87177"+ y="338.66452"+ id="tspan5588-5-2">file</tspan><tspan+ sodipodi:role="line"+ x="185.87177"+ y="346.76453"+ id="tspan5590-0-9" /></text>+ <text+ sodipodi:linespacing="89.999998%"+ id="text10763-4"+ y="160.09349"+ x="186.8539"+ style="font-size:7px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ xml:space="preserve"><tspan+ id="tspan10765-4"+ y="160.09349"+ x="186.8539"+ sodipodi:role="line">Move window</tspan><tspan+ y="166.39349"+ x="186.8539"+ sodipodi:role="line"+ id="tspan10767-3">to second</tspan><tspan+ y="172.6935"+ x="186.8539"+ sodipodi:role="line"+ id="tspan10769-8">workspace</tspan></text>+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3878-1"+ width="59.494934"+ height="60"+ x="152.72672"+ y="150"+ ry="4.480969" />+ <text+ sodipodi:linespacing="89.999998%"+ id="text10699-9"+ y="189.38791"+ x="118.16354"+ style="font-size:7px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ xml:space="preserve"><tspan+ id="tspan10701-8"+ y="189.38791"+ x="118.16354"+ sodipodi:role="line">Switch to</tspan><tspan+ y="195.68791"+ x="118.16354"+ sodipodi:role="line"+ id="tspan10703-1">first</tspan><tspan+ y="201.98792"+ x="118.16354"+ sodipodi:role="line"+ id="tspan10705-5">workspace</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:7px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="118.16354"+ y="159.08333"+ id="text10771-6"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="118.16354"+ y="159.08333"+ id="tspan10773-6">Move window</tspan><tspan+ id="tspan10775-4"+ sodipodi:role="line"+ x="118.16354"+ y="165.38333">to first</tspan><tspan+ id="tspan10777-0"+ sodipodi:role="line"+ x="118.16354"+ y="171.68332">workspace</tspan></text>+ <rect+ ry="4.480969"+ y="150"+ x="82.270233"+ height="60"+ width="60"+ id="rect3876-4"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#babdb6;fill-opacity:1;stroke:none"+ id="rect10511-4"+ width="59.494934"+ height="60"+ x="222.72672"+ y="150"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="150"+ x="292.72672"+ height="60"+ width="59.494934"+ id="rect3882-0"+ style="font-size:18px;fill:#fcaf3e;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3884-3"+ width="59.494934"+ height="60"+ x="362.72406"+ y="150"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="150"+ x="502.72403"+ height="60"+ width="59.494934"+ id="rect3886-5"+ style="font-size:18px;fill:#babdb6;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#babdb6;fill-opacity:1;stroke:none"+ id="rect3888-9"+ width="59.494934"+ height="60"+ x="572.72662"+ y="150"+ ry="4.480969" />+ <rect+ style="font-size:18px;fill:#babdb6;fill-opacity:1;stroke:none"+ id="rect3890-6"+ width="59.494934"+ height="60"+ x="432.72385"+ y="150"+ ry="4.480969" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3892-7"+ width="59.494934"+ height="60"+ x="712.2702"+ y="150"+ ry="4.480969" />+ <rect+ ry="4.480969"+ y="150"+ x="782.72662"+ height="60"+ width="59.494934"+ id="rect3894-3"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ ry="4.480969"+ y="150"+ x="642.72662"+ height="60"+ width="59.494934"+ id="rect3896-3"+ style="font-size:18px;fill:#babdb6;fill-opacity:1;stroke:none" />+ <path+ id="path3918-6"+ d="m 82.86832,180.00001 c 19.9363,0 39.87259,0 59.80889,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 152.81483,180.50001 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3920-7" />+ <path+ id="path3924-6"+ d="m 292.81483,181.00001 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 362.81708,180.50001 c 19.9363,0 39.87259,0 59.80889,0"+ id="path3926-1" />+ <path+ id="path3928-3"+ d="m 432.81482,181.00001 c 19.77181,0 39.54358,0 59.31538,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08917749px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ id="path3930-0"+ d="m 502.81708,181.00001 c 19.9363,0 39.87259,0 59.80889,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 572.81483,180.50001 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3932-4" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 642.81483,181.00001 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3934-1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.0936991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 712.81708,181.00001 c 19.9363,0 39.87259,0 59.80889,0"+ id="path3936-3" />+ <path+ id="path3938-5"+ d="m 782.81483,180.50001 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 222.81483,181.00001 c 19.7729,0 39.54579,0 59.31869,0"+ id="path10513-9" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3976-0"+ width="59.494934"+ height="60"+ x="852.31873"+ y="150"+ ry="4.480969" />+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 852.40694,180.50001 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3978-0" />+ <rect+ ry="4.480969"+ y="150"+ x="12.726654"+ height="60"+ width="59.494934"+ id="rect3980-4"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ id="path3982-1"+ d="m 12.81484,180.50001 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="790.02405"+ y="201.32812"+ id="text3988-6"><tspan+ sodipodi:role="line"+ id="tspan3990-3"+ x="790.02405"+ y="201.32812"+ style="font-size:18px;font-family:DejaVu Sans Mono" /></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="860.6767"+ y="202.27835"+ id="text3992-9"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan3994-0"+ x="860.6767"+ y="202.27835" /></text>+ <rect+ ry="4.480969"+ y="84"+ x="921.59406"+ height="60"+ width="89.135681"+ id="rect3996-6"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ id="path3998-1"+ d="m 921.93373,114.50001 c 29.34839,0 58.69676,0 88.04507,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.32699001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <text+ id="text4004-6"+ y="198.82001"+ x="932.64911"+ style="font-size:13px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="198.82001"+ x="932.64911"+ id="tspan4006-8"+ sodipodi:role="line"+ style="font-size:13px;font-family:DejaVu Sans Mono" /></text>+ <text+ id="text4977-6"+ y="176.56514"+ x="85.950897"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="176.56514"+ x="85.950897"+ id="tspan4979-4"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">F1</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="154.30988"+ y="175.61386"+ id="text4981-9"><tspan+ sodipodi:role="line"+ id="tspan4983-4"+ x="154.30988"+ y="175.61386"+ style="font-size:18px;font-family:DejaVu Sans Mono">F2</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="226.25266"+ y="176.94307"+ id="text4985-7"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan4987-7"+ x="226.25266"+ y="176.94307">F3</tspan></text>+ <text+ id="text4989-9"+ y="177.03125"+ x="294.4816"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="177.03125"+ x="294.4816"+ id="tspan4991-4"+ sodipodi:role="line">F4</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="365.75293"+ y="176.38533"+ id="text4993-6"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan4995-3"+ x="365.75293"+ y="176.38533">F5</tspan></text>+ <text+ id="text4997-7"+ y="175.61386"+ x="435.02127"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ y="175.61386"+ x="435.02127"+ id="tspan4999-6"+ sodipodi:role="line">F6</tspan></text>+ <text+ id="text5001-9"+ y="176.56404"+ x="505.67673"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="176.56404"+ x="505.67673"+ id="tspan5003-8"+ sodipodi:role="line"+ style="font-size:18px;font-family:DejaVu Sans Mono">F7</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="573.76721"+ y="176.31697"+ id="text5005-8"><tspan+ sodipodi:role="line"+ id="tspan5007-2"+ x="573.76721"+ y="176.31697"+ style="font-size:18px;font-family:DejaVu Sans Mono">F8</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="644.48834"+ y="175.61385"+ id="text5009-6"><tspan+ sodipodi:role="line"+ id="tspan5011-4"+ x="644.48834"+ y="175.61385"+ style="font-size:18px;font-family:DejaVu Sans Mono">F9</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="716.56958"+ y="175.31404"+ id="text5013-8"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan5015-7"+ x="716.56958"+ y="175.31404">F10</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="21.105469"+ y="202.99802"+ id="text7123-4"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7125-4"+ x="21.105469"+ y="202.99802" /></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="19.797638"+ y="175.33055"+ id="text7127-0"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7129-3"+ x="19.797638"+ y="175.33055">Esc</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="316.58353"+ y="194.186"+ id="text10610-0-4-0"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="316.58353"+ y="194.186"+ id="tspan5588-5-2-5">Quit</tspan><tspan+ sodipodi:role="line"+ x="316.58353"+ y="202.28601"+ id="tspan6083">Leksah</tspan><tspan+ sodipodi:role="line"+ x="316.58353"+ y="210.386"+ id="tspan5590-0-9-9" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="138.15128"+ y="476.56451"+ id="text10610-0-7"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="138.15128"+ y="476.56451"+ id="tspan5588-5-04">Undo</tspan><tspan+ sodipodi:role="line"+ x="138.15128"+ y="484.66452"+ id="tspan5590-0-4" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="204.84927"+ y="475.73599"+ id="text10610-0-7-7"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="204.84927"+ y="475.73599"+ id="tspan5588-5-04-6">Cut</tspan><tspan+ sodipodi:role="line"+ x="204.84927"+ y="483.836"+ id="tspan5590-0-4-5" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="275.07452"+ y="476.6145"+ id="text10610-0-7-7-8"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="275.07452"+ y="476.6145"+ id="tspan5588-5-04-6-7">Copy</tspan><tspan+ sodipodi:role="line"+ x="275.07452"+ y="484.71451"+ id="tspan5590-0-4-5-1" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="347.57452"+ y="476.6145"+ id="text10610-0-7-7-2"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="347.57452"+ y="476.6145"+ id="tspan5588-5-04-6-8">Paste</tspan><tspan+ sodipodi:role="line"+ x="347.57452"+ y="484.71451"+ id="tspan5590-0-4-5-0" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="466.34927"+ y="307.23599"+ id="text10610-0-7-8"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="466.34927"+ y="307.23599"+ id="tspan5588-5-04-0">Redo</tspan><tspan+ sodipodi:role="line"+ x="466.34927"+ y="315.336"+ id="tspan5590-0-4-3" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="123.84927"+ y="397.23602"+ id="text10610-0-7-3"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="123.84927"+ y="397.23602"+ id="tspan5588-5-04-2">Select</tspan><tspan+ sodipodi:role="line"+ x="123.84927"+ y="405.33603"+ id="tspan6266">all</tspan><tspan+ sodipodi:role="line"+ x="123.84927"+ y="413.43604"+ id="tspan6268">text</tspan><tspan+ sodipodi:role="line"+ x="123.84927"+ y="421.53601"+ id="tspan5590-0-4-6" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="683.34924"+ y="401.73599"+ id="text10610-0-7-9"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="683.34924"+ y="401.73599"+ id="tspan6298">Goto</tspan><tspan+ sodipodi:role="line"+ x="683.34924"+ y="409.836"+ id="tspan6444">line</tspan><tspan+ sodipodi:role="line"+ x="683.34924"+ y="417.936"+ id="tspan5590-0-4-1" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="247.20529"+ y="160.53751"+ id="text10610-0-7-9-3"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="247.20529"+ y="160.53751"+ id="tspan5588-5-04-9-7">Text</tspan><tspan+ sodipodi:role="line"+ x="247.20529"+ y="168.63751"+ id="tspan6298-2">search</tspan><tspan+ sodipodi:role="line"+ x="247.20529"+ y="176.7375"+ id="tspan5590-0-4-1-5">prev.</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="245.79079"+ y="189.4875"+ id="text10610-0-7-9-3-6"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="245.79079"+ y="189.4875"+ id="tspan5588-5-04-9-7-2">Text</tspan><tspan+ sodipodi:role="line"+ x="245.79079"+ y="197.58751"+ id="tspan6298-2-6">search</tspan><tspan+ sodipodi:role="line"+ x="245.79079"+ y="205.6875"+ id="tspan5590-0-4-1-5-5">next</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="334.20529"+ y="401.53751"+ id="text10610-0-7-9-2"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="334.20529"+ y="401.53751"+ id="tspan5588-5-04-9-3">Text</tspan><tspan+ sodipodi:role="line"+ x="334.20529"+ y="409.63751"+ id="tspan6298-8">search</tspan><tspan+ sodipodi:role="line"+ x="334.20529"+ y="417.73752"+ id="tspan5590-0-4-1-4" /></text>+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3780-8"+ width="59.951477"+ height="60"+ x="949.45642"+ y="500"+ ry="4.480969" />+ <g+ id="g7162-6"+ transform="matrix(1,0,0,1.0083333,208.99999,219.68332)"+ style="fill:#eeeeec;fill-opacity:1">+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect3776-4"+ width="59.494934"+ height="60"+ x="600.04852"+ y="278"+ ry="4.480969" />+ <rect+ ry="2.2404845"+ y="308"+ x="600.04852"+ height="30"+ width="59.494934"+ id="rect7160-1"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 600.13671,308.5 c 19.7729,0 39.54579,0 59.31869,0"+ id="path3818-3" />+ </g>+ <path+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.08920789px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ d="m 949.54459,530.49999 c 19.7729,0 39.54579,0 59.31871,0"+ id="path3822-5" />+ <g+ id="g7167-0"+ transform="translate(278.99999,221.99999)"+ style="fill:#eeeeec;fill-opacity:1">+ <rect+ ry="4.480969"+ y="278"+ x="600.04852"+ height="60"+ width="59.494934"+ id="rect7169-4"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect7171-6"+ width="59.494934"+ height="30"+ x="600.04852"+ y="308"+ ry="2.2404845" />+ <path+ id="path7173-0"+ d="m 600.13671,308.5 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:#eeeeec;stroke:#000000;stroke-width:1.08920788999999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />+ </g>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="813.78131"+ y="523.64954"+ id="text6999-3"><tspan+ sodipodi:role="line"+ id="tspan7001-5"+ x="813.78131"+ y="523.64954"+ style="font-size:18px;font-family:DejaVu Sans Mono">←</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="887.18103"+ y="522.23212"+ id="text7003-7"><tspan+ sodipodi:role="line"+ id="tspan7005-4"+ x="887.18103"+ y="522.23212"+ style="font-size:18px;font-family:DejaVu Sans Mono">↓</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="957.83368"+ y="523.18231"+ id="text7007-9"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan7009-7"+ x="957.83368"+ y="523.18231">→</tspan></text>+ <g+ id="g7167-0-9"+ transform="translate(278.20394,153)"+ style="fill:#eeeeec;fill-opacity:1">+ <rect+ ry="4.480969"+ y="278"+ x="600.04852"+ height="60"+ width="59.494934"+ id="rect7169-4-4"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <rect+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none"+ id="rect7171-6-2"+ width="59.494934"+ height="30"+ x="600.04852"+ y="308"+ ry="2.2404845" />+ <path+ id="path7173-0-3"+ d="m 600.13671,308.5 c 19.7729,0 39.54579,0 59.31869,0"+ style="font-size:18px;fill:#eeeeec;stroke:#000000;stroke-width:1.08920788999999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />+ </g>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="887.58594"+ y="451.25488"+ id="text7003-7-5"><tspan+ sodipodi:role="line"+ id="tspan7005-4-6"+ x="887.58594"+ y="451.25488"+ style="font-size:18px;font-family:DejaVu Sans Mono">↑</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="966.78882"+ y="541.7605"+ id="text10610-0-7-9-35"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="966.78882"+ y="541.7605"+ id="tspan6444-3">Comment</tspan><tspan+ sodipodi:role="line"+ x="966.78882"+ y="549.86047"+ id="tspan6624">line</tspan><tspan+ sodipodi:role="line"+ x="966.78882"+ y="557.96051"+ id="tspan6622" /><tspan+ sodipodi:role="line"+ x="966.78882"+ y="566.06049"+ id="tspan5590-0-4-1-55" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="816.78156"+ y="543.06451"+ id="text10610-0-7-9-35-4"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="816.78156"+ y="543.06451"+ id="tspan6444-3-8">Uncomment</tspan><tspan+ sodipodi:role="line"+ x="816.78156"+ y="551.16449"+ id="tspan6624-4">line</tspan><tspan+ sodipodi:role="line"+ x="816.78156"+ y="559.26453"+ id="tspan6622-7" /><tspan+ sodipodi:role="line"+ x="816.78156"+ y="567.3645"+ id="tspan5590-0-4-1-55-9" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="96.651283"+ y="261.56451"+ id="text10610-0-0"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="96.651283"+ y="261.56451"+ id="tspan5588-5-1">Collapse</tspan><tspan+ sodipodi:role="line"+ x="96.651283"+ y="269.66452"+ id="tspan6693">panes</tspan><tspan+ sodipodi:role="line"+ x="96.651283"+ y="277.76453"+ id="tspan6695" /><tspan+ sodipodi:role="line"+ x="96.651283"+ y="285.8645"+ id="tspan5590-0-41" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="171.17331"+ y="258.33551"+ id="text10610-0-0-4"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="171.17331"+ y="258.33551"+ id="tspan5588-5-1-8">Split</tspan><tspan+ sodipodi:role="line"+ x="171.17331"+ y="266.43552"+ id="tspan6693-2">panes</tspan><tspan+ sodipodi:role="line"+ x="171.17331"+ y="274.53552"+ id="tspan6731">horiz.</tspan><tspan+ sodipodi:role="line"+ x="171.17331"+ y="282.6355"+ id="tspan6695-8" /><tspan+ sodipodi:role="line"+ x="171.17331"+ y="290.7355"+ id="tspan5590-0-41-7" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="237.85728"+ y="257.13599"+ id="text10610-0-0-4-7"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="237.85728"+ y="257.13599"+ id="tspan5588-5-1-8-2">Split</tspan><tspan+ sodipodi:role="line"+ x="237.85728"+ y="265.23599"+ id="tspan6693-2-3">panes</tspan><tspan+ sodipodi:role="line"+ x="237.85728"+ y="273.336"+ id="tspan6731-8">vertical</tspan><tspan+ sodipodi:role="line"+ x="237.85728"+ y="281.43597"+ id="tspan6695-8-5" /><tspan+ sodipodi:role="line"+ x="237.85728"+ y="289.53598"+ id="tspan5590-0-41-7-2" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="390.70529"+ y="331.53751"+ id="text10610-0-7-9-2-1"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="390.70529"+ y="331.53751"+ id="tspan6298-8-6">Toggle</tspan><tspan+ sodipodi:role="line"+ x="390.70529"+ y="339.63751"+ id="tspan6803">toolbar</tspan><tspan+ sodipodi:role="line"+ x="390.70529"+ y="347.73752"+ id="tspan5590-0-4-1-4-0" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="410.67352"+ y="470.58749"+ id="text10610-0-7-7-2-7"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="410.67352"+ y="470.58749"+ id="tspan5590-0-4-5-0-5">Build</tspan><tspan+ sodipodi:role="line"+ x="410.67352"+ y="478.6875"+ id="tspan6863">package</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="318.87155"+ y="331.33551"+ id="text10610-0-7-7-2-7-8"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="318.87155"+ y="331.33551"+ id="tspan6863-6">Add</tspan><tspan+ sodipodi:role="line"+ x="318.87155"+ y="339.43552"+ id="tspan6912">imports</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="536.96625"+ y="373.5015"+ id="text10610-08"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="536.96625"+ y="373.5015"+ id="tspan5588-0">Previous</tspan><tspan+ sodipodi:role="line"+ x="536.96625"+ y="381.6015"+ id="tspan6965">error</tspan><tspan+ sodipodi:role="line"+ x="536.96625"+ y="389.70151"+ id="tspan5590-00" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="544.17352"+ y="401.53751"+ id="text10610-08-4"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="544.17352"+ y="401.53751"+ id="tspan5588-0-2">Next</tspan><tspan+ sodipodi:role="line"+ x="544.17352"+ y="409.63751"+ id="tspan6965-8">error</tspan><tspan+ sodipodi:role="line"+ x="544.17352"+ y="417.73752"+ id="tspan5590-00-9" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="300.67352"+ y="540.08752"+ id="text10610-0-7-7-2-3"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="300.67352"+ y="540.08752"+ id="tspan5588-5-04-6-8-0">Start completion</tspan><tspan+ sodipodi:role="line"+ x="300.67352"+ y="548.1875"+ id="tspan5590-0-4-5-0-1" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="254.15128"+ y="304.76401"+ id="text10610-0-7-7-8-3"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="254.15128"+ y="304.76401"+ id="tspan5588-5-04-6-7-0">Align</tspan><tspan+ sodipodi:role="line"+ x="254.15128"+ y="312.86401"+ id="tspan7054">=</tspan><tspan+ sodipodi:role="line"+ x="254.15128"+ y="320.96402"+ id="tspan5590-0-4-5-1-8" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="323.23206"+ y="300.879"+ id="text10610-0-7-7-8-3-5"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="323.23206"+ y="300.879"+ id="tspan5588-5-04-6-7-0-4">Align</tspan><tspan+ sodipodi:role="line"+ x="323.23206"+ y="308.979"+ id="tspan7054-2">-></tspan><tspan+ sodipodi:role="line"+ x="323.23206"+ y="317.07901"+ id="tspan5590-0-4-5-1-8-7" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="681.73206"+ y="368.50101"+ id="text10610-0-7-7-8-3-5-0"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="681.73206"+ y="368.50101"+ id="tspan5588-5-04-6-7-0-4-3">Align</tspan><tspan+ sodipodi:role="line"+ x="681.73206"+ y="376.60101"+ id="tspan7054-2-9"><-</tspan><tspan+ sodipodi:role="line"+ x="681.73206"+ y="384.70099"+ id="tspan5590-0-4-5-1-8-7-5" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="394.73206"+ y="301.99649"+ id="text10610-0-7-7-8-3-5-2"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="394.73206"+ y="301.99649"+ id="tspan5588-5-04-6-7-0-4-6">Align</tspan><tspan+ sodipodi:role="line"+ x="394.73206"+ y="310.0965"+ id="tspan7054-2-7">::</tspan><tspan+ sodipodi:role="line"+ x="394.73206"+ y="318.1965"+ id="tspan5590-0-4-5-1-8-7-0" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="447.7908"+ y="191.9875"+ id="text10610-0-7-9-3-6-2"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="447.7908"+ y="191.9875"+ id="tspan5590-0-4-1-5-5-6">Debug</tspan><tspan+ sodipodi:role="line"+ x="447.7908"+ y="200.08751"+ id="tspan7200">step</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="518.9845"+ y="190.33549"+ id="text10610-0-7-9-3-6-2-4"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="518.9845"+ y="190.33549"+ id="tspan5590-0-4-1-5-5-6-2">Debug</tspan><tspan+ sodipodi:role="line"+ x="518.9845"+ y="198.4355"+ id="tspan7200-2">step</tspan><tspan+ sodipodi:role="line"+ x="518.9845"+ y="206.53549"+ id="tspan7230">local</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="587.98456"+ y="190.33549"+ id="text10610-0-7-9-3-6-2-2"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="587.98456"+ y="190.33549"+ id="tspan5590-0-4-1-5-5-6-0">Debug</tspan><tspan+ sodipodi:role="line"+ x="587.98456"+ y="198.4355"+ id="tspan7200-9">step</tspan><tspan+ sodipodi:role="line"+ x="587.98456"+ y="206.53549"+ id="tspan7245">module</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="653.61926"+ y="190.636"+ id="text10610-0-7-9-3-6-2-2-7"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="653.61926"+ y="190.636"+ id="tspan5590-0-4-1-5-5-6-0-7">Debug</tspan><tspan+ sodipodi:role="line"+ x="653.61926"+ y="198.73601"+ id="tspan7245-0">continue</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="554.96631"+ y="468.0015"+ id="text10610-5"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="554.96631"+ y="468.0015"+ id="tspan5588-90">Update</tspan><tspan+ sodipodi:role="line"+ x="554.96631"+ y="476.1015"+ id="tspan7313">meta-</tspan><tspan+ sodipodi:role="line"+ x="554.96631"+ y="484.20151"+ id="tspan7315">dat</tspan><tspan+ sodipodi:role="line"+ x="554.96631"+ y="492.30148"+ id="tspan5590-6" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="910.24579"+ y="398.56451"+ id="text10610-0-7-9-6"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="910.24579"+ y="398.56451"+ id="tspan6444-8">Execute</tspan><tspan+ sodipodi:role="line"+ x="910.24579"+ y="406.66452"+ id="tspan7350">selection</tspan><tspan+ sodipodi:role="line"+ x="910.24579"+ y="414.76453"+ id="tspan5590-0-4-1-2" /></text>+ <text+ xml:space="preserve"+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"+ x="341"+ y="170"+ id="text7354"><tspan+ sodipodi:role="line"+ id="tspan7356"></tspan></text>+ <text+ xml:space="preserve"+ style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"+ x="865"+ y="628"+ id="text7389"+ sodipodi:linespacing="125%"><tspan+ sodipodi:role="line"+ id="tspan7391"+ x="865"+ y="628"+ style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Andale Mono;-inkscape-font-specification:Andale Mono">www.leksah.org</tspan></text>+ <text+ id="text4004-1"+ y="105.58643"+ x="926.6626"+ style="font-size:13px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="105.58643"+ x="926.6626"+ id="tspan4006-7"+ sodipodi:role="line"+ style="font-size:13px;font-family:DejaVu Sans Mono">PageUp</tspan></text>+ <rect+ ry="4.480969"+ y="151"+ x="920.59406"+ height="60"+ width="89.135681"+ id="rect3996-6-8"+ style="font-size:18px;fill:#eeeeec;fill-opacity:1;stroke:none" />+ <path+ id="path3998-1-4"+ d="m 920.93374,181.50001 c 29.34839,0 58.69676,0 88.04506,0"+ style="font-size:18px;fill:none;stroke:#000000;stroke-width:1.32699001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <text+ id="text4004-1-1"+ y="172.58643"+ x="925.6626"+ style="font-size:13px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ xml:space="preserve"><tspan+ y="172.58643"+ x="925.6626"+ id="tspan4006-7-7"+ sodipodi:role="line"+ style="font-size:13px;font-family:DejaVu Sans Mono">PageDown</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="41.583527"+ y="326.686"+ id="text10610-0-4-7"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="41.583527"+ y="326.686"+ id="tspan5588-5-2-0">Flip</tspan><tspan+ sodipodi:role="line"+ x="41.583527"+ y="334.78601"+ id="tspan7482">buffer</tspan><tspan+ sodipodi:role="line"+ x="41.583527"+ y="342.88602"+ id="tspan5590-0-9-1" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="39.975288"+ y="297.186"+ id="text10610-0-4-7-3"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="39.975288"+ y="297.186"+ id="tspan5588-5-2-0-4">Flip</tspan><tspan+ sodipodi:role="line"+ x="39.975288"+ y="305.28601"+ id="tspan7482-6">buffer</tspan><tspan+ sodipodi:role="line"+ x="39.975288"+ y="313.38602"+ id="tspan7515">reverse</tspan><tspan+ sodipodi:role="line"+ x="39.975288"+ y="321.48599"+ id="tspan5590-0-9-1-6" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="942.37152"+ y="191.136"+ id="text10610-0-4-7-3-5"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="942.37152"+ y="191.136"+ id="tspan5588-5-2-0-4-3">Flip</tspan><tspan+ sodipodi:role="line"+ x="942.37152"+ y="199.23601"+ id="tspan7482-6-9">buffer</tspan><tspan+ sodipodi:role="line"+ x="942.37152"+ y="207.336"+ id="tspan7515-7">reverse</tspan><tspan+ sodipodi:role="line"+ x="942.37152"+ y="215.436"+ id="tspan5590-0-9-1-6-5" /></text>+ <text+ xml:space="preserve"+ style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:89.99999762%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:TlwgTypewriter"+ x="941.97534"+ y="128.686"+ id="text10610-0-4-7-33"+ sodipodi:linespacing="89.999998%"><tspan+ sodipodi:role="line"+ x="941.97534"+ y="128.686"+ id="tspan5588-5-2-0-0">Flip</tspan><tspan+ sodipodi:role="line"+ x="941.97534"+ y="136.78601"+ id="tspan7482-1">buffer</tspan><tspan+ sodipodi:role="line"+ x="941.97534"+ y="144.886"+ id="tspan5590-0-9-1-9" /></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="790.31396"+ y="174.55225"+ id="text5013-8-8"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan5015-7-8"+ x="790.31396"+ y="174.55225">F11</tspan></text>+ <text+ xml:space="preserve"+ style="font-size:18px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans Mono"+ x="861.31396"+ y="173.55225"+ id="text5013-8-5"><tspan+ style="font-size:18px;font-family:DejaVu Sans Mono"+ sodipodi:role="line"+ id="tspan5015-7-0"+ x="861.31396"+ y="173.55225">F12</tspan></text>+ </g>+</svg>
@@ -0,0 +1,5814 @@+#LyX 1.6.5 created this file. For more info see http://www.lyx.org/+\lyxformat 345+\begin_document+\begin_header+\textclass scrartcl+\use_default_options false+\language english+\inputencoding auto+\font_roman default+\font_sans default+\font_typewriter default+\font_default_family default+\font_sc false+\font_osf false+\font_sf_scale 100+\font_tt_scale 100++\graphics default+\paperfontsize default+\spacing single+\use_hyperref false+\papersize a4paper+\use_geometry false+\use_amsmath 1+\use_esint 0+\cite_engine basic+\use_bibtopic false+\paperorientation portrait+\secnumdepth 3+\tocdepth 2+\paragraph_separation indent+\defskip medskip+\quotes_language english+\papercolumns 1+\papersides 1+\paperpagestyle default+\tracking_changes false+\output_changes false+\author "" +\author "" +\end_header++\begin_body++\begin_layout Title+Leksah: An Integrated Development Environment for Haskell+\begin_inset Newline newline+\end_inset++Version 0.8+\end_layout++\begin_layout Author+Jürgen Nicklisch-Franken+\begin_inset Newline newline+\end_inset++Hamish Mackenzie+\begin_inset Newline newline+\end_inset++edited for v.+ 0.8: Andrew U.+ Frank and Christian Gruber+\end_layout++\begin_layout Standard+\begin_inset CommandInset toc+LatexCommand tableofcontents++\end_inset+++\end_layout++\begin_layout Standard+\begin_inset FloatList figure++\end_inset+++\end_layout++\begin_layout Section*+License+\end_layout++\begin_layout Standard+Leksah has been put under the GNU GENERAL PUBLIC LICENSE Version 2.+ The full license text can be found in the file data/LICENSE in the distribution.+\end_layout++\begin_layout Standard+\begin_inset Newpage newpage+\end_inset+++\end_layout++\begin_layout Section+Introduction+\end_layout++\begin_layout Standard+Leksah is an IDE (Integrated Development Environment) for the programming+ language Haskell.+ It is written in Haskell and integrates various tools available for writing+ programs in Haskell: the GHC compiler and interpreter, the CABAL package+ management system (the Common Architecture for Building Applications and+ Libraries), Haddock for producing documentation, etc.+ in one, single, comprehensive and easy to use environment.+ It allows the developer to concentrate on writing the program and Leksah+ gives him easy access to all information she needs and helps with the necessary+ housekeeping for compiling, linking and package management.+ +\end_layout++\begin_layout Standard+A unified focus for translating source code to executable programs: Leksah+ introduces the notion of a workspace that can include several packages+ transparently: to the programmer it appears as if there were a single program+ with a simple +\begin_inset Quotes eld+\end_inset++make+\begin_inset Quotes erd+\end_inset++ command.+ Leksah manages rebuilding and installing packages as far as desired automatical+ly.+ +\end_layout++\begin_layout Standard+Support for writing source code: Leksah supports debugging with GHCi, evaluation+ of expressions, gathering type information, setting breakpoints, displays+ values at breakpoints, etc.+ is all possible from within Leksah.+\end_layout++\begin_layout Standard+Last, but not least, Leksah collects information about installed packages,+ helps to find function names and their type and offers an auto-completion+ feature while you type new code.+\end_layout++\begin_layout Standard+The features of Leksah often reflect directly features of the Haskell tools+ used; therefore, to understand behavior in special cases needs sometimes+ reading the specific documentation of GHC, Cabal or Haddock, (and this+ manual, to a degree repeats what is found, with more detail and authority,+ in the respective tool documentation).+\end_layout++\begin_layout Standard+Leksah is written in Haskell, which means the Leksah developers use Leksah+ to develop Leksah and users of Leksah can read the code and contribute+ improvements.+ Leksah uses GTK+ as GUI Toolkit with the gtk2hs binding.+ It is platform independent and runs on any platform where GTK+, gtk2hs+ and GHC can be installed.+ It is used on Linux, Windows and Mac.+ +\end_layout++\begin_layout Standard+This document is a reference to the functionality of Leksah, it is not intended+ to be a tutorial.+ Since Leksah is still under development the information may be incomplete+ or superseded.+\end_layout++\begin_layout Standard+The current version is 0.8.+\end_layout++\begin_layout Subsection+Further Information+\end_layout++\begin_layout Standard+The home page for Leksah is +\begin_inset CommandInset href+LatexCommand href+name "leksah.org"+target "http://leksah.org"++\end_inset++.+ Stable version of Leksah can be installed from Hackage +\begin_inset CommandInset href+LatexCommand href+name "hackage.haskell.org/package/leksah"+target "http://hackage.haskell.org/package/leksah"++\end_inset++using Cabal install.+ The source code for Leksah is hosted under +\begin_inset CommandInset href+LatexCommand href+name "code.haskell.org/leksah"+target "http://code.haskell.org/leksah"++\end_inset++ and +\begin_inset CommandInset href+LatexCommand href+name "code.haskell.org/leksah-head"+target "http://code.haskell.org/leksah-head"++\end_inset++.+ The Leksah user Wiki is +\begin_inset CommandInset href+LatexCommand href+name "haskell.org/haskellwiki/Leksah"+target "http://haskell.org/haskellwiki/Leksah"++\end_inset++.+ The Leksah forum can be accessed at +\begin_inset CommandInset href+LatexCommand href+name "groups.google.com/group/leksah/topics"+target "http://groups.google.com/group/leksah/topics"++\end_inset++.+ The current version of this manual can be found at +\begin_inset CommandInset href+LatexCommand href+name "leksah.org/leksah_manual.pdf"+target "http://leksah.org/leksah_manual.pdf"++\end_inset++.+ An issue tracker to collect bug reports and suggestions for improvements+ is at +\begin_inset CommandInset href+LatexCommand href+name "code.google.com/p/leksah/issues/list"+target "http://code.google.com/p/leksah/issues/list"++\end_inset++.+ You can contact the developers at +\begin_inset CommandInset href+LatexCommand href+name "info (at) leksah.org"+target "info@leksah.org"+type "mailto:"++\end_inset++.+ +\end_layout++\begin_layout Standard+For information about the Programming language Haskell go to +\begin_inset CommandInset href+LatexCommand href+name "www.haskell.org"+target "http://www.haskell.org"++\end_inset++.+ The GHC computer is found at +\begin_inset CommandInset href+LatexCommand href+name "www.haskell.org/ghc"+target "http://www.haskell.org/ghc"++\end_inset++.+ For information about gtk2hs +\begin_inset CommandInset href+LatexCommand href+name "www.haskell.org/gtk2hs/"+target "http://www.haskell.org/gtk2hs/"++\end_inset++.+ For information about GTK+ go to +\begin_inset CommandInset href+LatexCommand href+name "www.gtk.org"+target "http://www.gtk.org"++\end_inset++.+ +\end_layout++\begin_layout Subsection+Release Notes+\end_layout++\begin_layout Subsubsection+Version 0.8 Release March 2010+\end_layout++\begin_layout Standard+The 0.8 release adds the notion of workspaces to allow develop comfortably+ projects, where part of the code is in separate packages.+ This changes the handling of packages to a degree, which has been improved+ with introducing suitable defaults: a simple, single-shot program can be+ started with very few clicks and entering not much more than the name of+ the program; Leksah becomes usable even for just quickly testing an idea.+ Other changes include:+\end_layout++\begin_layout Itemize+Better metadata with non exported definitions for workspace packages+\end_layout++\begin_layout Itemize+Support for prebuild metadata packages+\end_layout++\begin_layout Itemize+Better completion (keywords, language extensions, module name, non exported+ definitions)+\end_layout++\begin_layout Itemize+Splittet in a client and server part (Client part doesn't import ghc-api)+\end_layout++\begin_layout Itemize+Added support for Ghc 6.12+\end_layout++\begin_layout Itemize+Prepared for Yi (Abstract TextEditor interface, not ready for use)+\end_layout++\begin_layout Itemize+Various other changes improve usability and stability of the platform.+ +\end_layout++\begin_layout Standard+A large number of bugs has been fixed, but there remain, probably a large+ number of, bugs - some old and not yet fixed and some new ones.+ We expect also to improve and streamline the user interface in the next+ minor release to achieve more consistency and make Leksah easier to learn.+ You may see comments to this effect in this document, suggesting possible+ changes in the interface.+ Your opinion on these and other possible improvements you see will be highly+ appreciated! +\end_layout++\begin_layout Standard+Version 0.8 works with GHC 6.10 and 6.12.+ The installation is described in +\begin_inset CommandInset ref+LatexCommand prettyref+reference "sec:Installing-Leksah"++\end_inset++ for the standard case, more up to date information on installation may+ be found on the Wiki +\begin_inset CommandInset href+LatexCommand href+name "haskell.org/haskellwiki/Leksah"+target "http://haskell.org/haskellwiki/Leksah"++\end_inset++.+ If you have any trouble installing, please check the Wiki, the forum or+ contact the developers to find a solution.+ A smooth implementation is a priority for us and we like to hear about+ difficulties you encounter to fix them; please report them on the bug and+ issues tracker +\begin_inset CommandInset href+LatexCommand href+name "code.google.com/p/leksah/issues/list"+target "http://code.google.com/p/leksah/issues/list"++\end_inset++.+\end_layout++\begin_layout Subsubsection+Version 0.6 Beta Release Juli 2009+\end_layout++\begin_layout Standard+The 0.6 version introduces an interpreter/debugger mode.+ This mode can be switched on and off from the toolbar.+ In interpreter/debugger mode expressions can be evaluated and the type+ of expressions can be dynamically shown.+ The GHCi debugger is integrated, so that breakpoints can be set, it is+ possible to step through the code, observe the values of variables and+ trace the execution history.+ +\end_layout++\begin_layout Standard+The other features of Leksah like building in the background and reporting+ errors on the fly work in debugger mode as in compiler mode (but not configurin+g, installing, etc.+ of packages).+\end_layout++\begin_layout Standard+Another new feature is integration of grep and text search with regular+ expression.+ This can be accessed from the findbar.+\end_layout++\begin_layout Standard+The GUI framework has been enhanced, so that layouts can be nested in so+ called group panes.+ This feature is used for the debugger pane.+ Furthermore notebooks can be detached, so that Leksah can be used on multiple+ screens.+\end_layout++\begin_layout Standard+A lot of little enhancements has been made and numerous bugs has been fixed.+\end_layout++\begin_layout Standard+Known bugs and problems:+\end_layout++\begin_layout Itemize+The package editor works only for cabal files without configurations.+\end_layout++\begin_layout Itemize+MS Windows: The check for external modifications of source files does not+ work.+\end_layout++\begin_layout Itemize+MS Windows: Interruption of a background build does not work.+\end_layout++\begin_layout Itemize+GUI History still not working.+\end_layout++\begin_layout Itemize+Traces pane of the Debugger does not work appropriately.+\end_layout++\begin_layout Subsubsection+Version 0.4 Beta Release February/March 2009+\end_layout++\begin_layout Standard+The 0.4 Release is the first beta release of Leksah.+ It should be usable for practical work for the ones that wants to engage+ with it.+\end_layout++\begin_layout Standard+It depends on GHC +\begin_inset Formula $\geq$+\end_inset++6.10.1 and gtk2hs +\begin_inset Formula $\geq$+\end_inset++ 0.10.0.+\end_layout++\begin_layout Standard+The class pane and the history feature are not quite ready, so we propose+ not to use it yet.+ +\end_layout++\begin_layout Subsubsection+Version 0.1 Alpha Release February 2008 +\end_layout++\begin_layout Standard+This is a pre-release of Leksah.+ The editor for Cabal Files is not ready, so we propose not to use it yet.+ w+\end_layout++\begin_layout Standard+\begin_inset Newpage pagebreak+\end_inset+++\end_layout++\begin_layout Section+Installing Leksah+\begin_inset CommandInset label+LatexCommand label+name "sec:Installing-Leksah"++\end_inset+++\end_layout++\begin_layout Subsection+How to Install: Brief Instructions +\end_layout++\begin_layout Standard+You can install from +\end_layout++\begin_layout Itemize+a binary installer for your operating system, which is typically Windows+ or Macintosh.+ +\end_layout++\begin_layout Itemize+a package for your platform, which is currently Arch Linux and Fedora Linux,+ and Debian(Ubuntu) is in preparation.+\end_layout++\begin_layout Itemize+install from sources from Hackage via +\family typewriter+\emph on+cabal install leksah+\end_layout++\begin_layout Itemize+leksah or leksah-head development repositories.+ (If you want the very last or want to help with Leksah development).+ +\end_layout++\begin_layout Standard+You can consult the Download page for up-to date information and try the+ user Wiki for further help.+\end_layout++\begin_layout Subsection+Microsoft Windows+\end_layout++\begin_layout Enumerate+Install Haskell Platform with an installer for Windows (alternatively install+ Ghc directly)+\end_layout++\begin_layout Enumerate+Make sure wget and grep are on the path of your Windows shell+\end_layout++\begin_layout Enumerate+Install Leksah from the most recent binary installer for Windows.+\end_layout++\begin_layout Enumerate+Go to the post installation section.+\end_layout++\begin_layout Subsection+Mac OS X+\end_layout++\begin_layout Enumerate+Install Haskell Platform with an installer for Mac OS X (alternatively install+ Ghc directly)+\end_layout++\begin_layout Enumerate+Make sure wget and grep are on the path.+\end_layout++\begin_layout Enumerate+Install Leksah from the most recent binary installer for Mac+\end_layout++\begin_layout Enumerate+Go to the post installation section.+\end_layout++\begin_layout Subsection+Linux from Distro Packages+\end_layout++\begin_layout Enumerate+Install Leksah with the package management system of your Linux platform,+ which should pull all prerequisites automatically.+\end_layout++\begin_layout Enumerate+Go to the post installation section.+\end_layout++\begin_layout Subsection+Install from Hackage+\end_layout++\begin_layout Enumerate+Install Haskell Platform (alternatively install Ghc directly, install Cabal+ and cabal-install)+\end_layout++\begin_layout Enumerate+Install gtk2hs in a version compatible with the installed Ghc compiler (Currentl+y gtk2hs can't be installed via Hackage, but this should be possible in+ the near future, so that you don't have to care about this step any more).+ Make sure the gtk2hs gtksourceview2 package gets built and installed.+\end_layout++\begin_layout Enumerate+open a Console and do:+\end_layout++\begin_deeper+\begin_layout LyX-Code+cabal update+\begin_inset Newline newline+\end_inset++cabal install leksah+\end_layout++\end_deeper+\begin_layout Enumerate+Go to the post installation section.+\end_layout++\begin_layout Subsection+Post Installation steps+\end_layout++\begin_layout Enumerate+Until the next release of gtk2hs, for a pleasant visual appearance, you+ have to copy or append the .gtkrc-2.0 file from the Leksah data folder or+ from the data folder in Leksah sources to your home folder.+ If you miss the step, the cross [x] buttons on tabs are almost invisible+ (or don't fit in tabs).+ This step may become obsolete during the 0.8 release cycle.+\end_layout++\begin_deeper+\begin_layout LyX-Code+cd ~ +\begin_inset Newline newline+\end_inset++wget http://code.haskell.org/leksah/leksah/data/.gtkrc-2.0 -O +\begin_inset Newline newline+\end_inset++ .gtkrc-2.0-leksah+\begin_inset Newline newline+\end_inset++echo -e '+\backslash+ninclude ".gtkrc-2.0-leksah"' >> .gtkrc-2.0 +\end_layout++\end_deeper+\begin_layout Enumerate+Before you start Leksah for the first time, do a:+\end_layout++\begin_deeper+\begin_layout LyX-Code+ghc-pkg recache+\end_layout++\begin_layout Standard+It has been observed, that a package recache is often necessary after installati+on.+ The symptom is an empty Module Browser, if you select the System scope.+\end_layout++\end_deeper+\begin_layout Subsection+First start of Leksah+\end_layout++\begin_layout Standard+The first time you start Leksah it will take you through the follow steps:+\end_layout++\begin_layout Enumerate+You are asked to fill in a form telling Leksah where your Haskell sources+ are (if you are not sure or just want to test, you can accept the defaults+ and correct them later in the +\begin_inset Quotes eld+\end_inset++metadata+\begin_inset Quotes erd+\end_inset++ preferences)+\end_layout++\begin_layout Enumerate+Leksah collects +\begin_inset Quotes eld+\end_inset++metadata+\begin_inset Quotes erd+\end_inset++, i.e.+ exported symbols and their type, comments explaining them etc.+ for all installed packages on your machine.+ This step may take a while and may give no feedback or a lot of strange+ errors and warnings, don't worry but be patient.+\end_layout++\begin_layout Enumerate+The Leksah IDE starts and you can start working.+\end_layout++\begin_layout Standard+Later starts will read in the previously collected metadata and check only+ for changes.+ After starting up, Leksah will open its Main window in a standard configuration.+\end_layout++\begin_layout Standard+Progress on your first contact with Leksah:+\end_layout++\begin_layout Enumerate+Start with the, infamous, +\begin_inset Quotes eld+\end_inset++Hello World+\begin_inset Quotes erd+\end_inset++ example.+ The next section gives you a step by step description.+\end_layout++\begin_layout Enumerate+Then it might be the best to construct a workspace and add an existing project+ and explore Leksah while you work on it.+ +\end_layout++\begin_layout Subsection+First start dialog+\end_layout++\begin_layout Standard+\begin_inset Float figure+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_first_start.png+ lyxscale 50+ width 90text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:FirstStart-dialog"++\end_inset++First-Start dialog+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+When you start Leksah for the first time it must collect the information+ about the packages you have on your computer and may use in your projects.+ The first start dialog let you enter settings about this process.+ Leksah then collects information about exported symbols, their type and+ possible comments (collectively called metadata) to support your work,+ e.g.+ by suggesting auto-completion and type information about functions you+ may use while you edit your source.+\end_layout++\begin_layout Standard+Later you can change this settings in the preferences pane in Leksah and+ you can rebuild the metadata at any time.+ +\family typewriter+leksah-server -sbo +RTS -N2+\family default+ from the console.+ Details about metadata collection can be found here: +\begin_inset CommandInset ref+LatexCommand ref+reference "sub:Metadata-collection"++\end_inset++.+\end_layout++\begin_layout Standard+If you want to start from scratch again delete or rename the .leksah-*.* folder+ in your home folder.+ Then you will see the first start dialog again.+\end_layout++\begin_layout Standard+In the first start dialog you are asked for:+\end_layout++\begin_layout Enumerate+The location of folders, where Haskell source code for installed packages+ can be found.+ This is important for packages which can't be found on Hackage.+ +\end_layout++\begin_layout Enumerate+Maybe a directory, where Leksah will unpack source files for packages.+ If you give no directory here, Leksah will not try to unpack the sources.+\end_layout++\begin_layout Enumerate+Some packages are difficult to process with Haddock.+ So we provide some prebuild metadata.+ If you allow this, Leksah will look for prebuild metadata, if sources are+ available, but Haddock fails to process.+ +\end_layout++\begin_layout Enumerate+The port number used for the local connection to the Leksah server.+ +\end_layout++\begin_layout Enumerate+By default the Leksah server terminates with the last connection.+ You can change this setting here.+\end_layout++\begin_layout Standard+Leksah collects information about all installed packages on your system+ that will take some time (minutes to half an hour) the first time.+ Errors occuring in this metadata collection step indicate only that Leksah+ has not succeeded to extract the source locations and comments from a module+ or package; they are not consequential, except that some metainformation+ may be missing.+ The metadata is cached and future starts only scan newly installed packages,+ starts only information for new packages will be installed.+\end_layout++\begin_layout Standard+\begin_inset Float figure+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_welcome.png+ lyxscale 50+ width 100text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+Leksah after first start+\end_layout++\end_inset+++\end_layout++\begin_layout Plain Layout++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+\begin_inset Newpage pagebreak+\end_inset+++\end_layout++\begin_layout Section+Hello World example+\end_layout++\begin_layout Itemize+Workspace -> New.+ Constructs a new workspace in a selected folder and give it a name (e.g.+ +\begin_inset Quotes eld+\end_inset++Hello+\begin_inset Quotes erd+\end_inset++).+ This produces a file Hello.lkshw.+\end_layout++\begin_layout Itemize+Package -> New and use the "Create Folder" button to make a new folder for+ the package.+ Make sure to be in this folder when you click +\begin_inset Quotes eld+\end_inset++Open+\begin_inset Quotes erd+\end_inset++.+ An editor opens up, which let you edit cabal files.+ The name proposed for your package is the name of the folder you just construct+ed.+ That is the convention with Cabal packages.+ The defaults are set for creating a simple executable.+ The base package is specified as build dependencies, and an executable+ with the name of the package will be constructed.+ The main module resides in a file +\begin_inset Quotes eld+\end_inset++Main.hs+\begin_inset Quotes erd+\end_inset++.+ The sources are in a +\begin_inset Quotes eld+\end_inset++src+\begin_inset Quotes erd+\end_inset++ subdirectory of the packages.+\end_layout++\begin_layout Itemize+Click Save to write the .cabal file.+\end_layout++\begin_layout Itemize+The main module gets automatically constructed and opens.+\end_layout++\begin_layout Itemize+Now add your code to the module +\end_layout++\begin_deeper+\begin_layout LyX-Code++\emph on+main = putStrLn "Hello World" .+ +\end_layout++\end_deeper+\begin_layout Itemize+By default, auto build is on and you can see that the file will be compiled+ in the Log pane.+\end_layout++\begin_layout Itemize+Choose Package -> Run or ctrl-alt-r, and you will see Hello World in the+ Log pane.+\end_layout++\begin_layout Itemize+Or: Choose Package -> Install, open a Shell and try out your newly created+ executable +\end_layout++\begin_layout Standard+Congratulations ! you have now entered, compiled, linked and run your first+ Haskell program with Leksah.+ It is as easy as: Create workspace / New package / enter your code/ Run.+ Remember: +\end_layout++\begin_layout Itemize+the project folder is the folder in which your .cabal file for the project+ is stored.+ +\end_layout++\begin_layout Itemize+A workspace is just a file, which contain information about included packages.+ +\end_layout++\begin_layout Itemize+You see what Leksah is doing by observing the output from the Log window.+ +\end_layout++\begin_layout Standard+Furthermore:+\end_layout++\begin_layout Itemize+You can add Packages with the context menu in the workspace pane.+ You can construct new packages with Package -> New, from the menubar.+ +\end_layout++\begin_layout Itemize+You can add other modules by selecting +\begin_inset Quotes eld+\end_inset++Add module+\begin_inset Quotes erd+\end_inset++ from the context menu of the modules pane of the browser group.+\end_layout++\begin_layout Itemize+You can open panes you need by selecting Panes -> Browser | Log | ...+ from the menubar.+\end_layout++\begin_layout Itemize+You can editing modules by selecting them in the Browser.+ You can search in the modules pane of the browser by typing text.+ +\end_layout++\begin_layout Standard+You may as easily debug it+\end_layout++\begin_layout Itemize+\begin_inset Graphics+ filename ../pics/ide_debug.png+ width 0.5cm++\end_inset++Switch debugger Mode on.+\end_layout++\begin_layout Itemize+Pane -> Debugger +\end_layout++\begin_layout Itemize+Select the word “main” in your code +\end_layout++\begin_layout Itemize+Right click and choose “Eval” from the pop-up menu or press ctrl-enter.+\end_layout++\begin_layout Itemize+Switch of debugger Mode if you want to compile an executable.+\end_layout++\begin_layout Standard+\begin_inset Box Boxed+position "t"+hor_pos "c"+has_inner_box 1+inner_pos "t"+use_parbox 0+width "100col%"+special "none"+height "1in"+height_special "totalheight"+status open++\begin_layout Plain Layout+It is probably counter productive for new users to use Candy mode (converts+ some common ASCII based operators to Unicode alternatives) because all+ the tutorials use ASCII.+ Switch it off when you get irritated.+ Deselect Configuration -> To Candy from the menubar.+\end_layout++\end_inset+++\end_layout++\begin_layout Standard+\begin_inset Newpage newpage+\end_inset+++\end_layout++\begin_layout Section+The Editor+\end_layout++\begin_layout Standard+\begin_inset Wrap figure+lines 0+placement O+overhang 0in+width "30col%"+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_file_menu.png+ lyxscale 50+ width 30text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:File-menu"++\end_inset++File menu+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+Most of the time programming is editing source code.+ To edit Haskell source files Leksah uses the GtkSourceView2 widget.+ It provides editing, undo/redo, syntax highlighting and similar features.+ In the file menu (+\begin_inset CommandInset ref+LatexCommand ref+reference "fig:File-menu"++\end_inset++) you find the customary functionality to open, save, close and revert files.+ To avoid confusion, it is useful to be able to close all files, or all+ files which are not stored in or below the top folder of the current project+ (this is the folder where the .cabal file resides) at once - this helps+ you focus on your project.+ This way it is as well possible to close all files, which don't belong+ to a workspace.+\end_layout++\begin_layout Standard+\begin_inset Wrap figure+lines 0+placement o+overhang 0in+width "30col%"+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_edit_menu.png+ lyxscale 50+ scale 40++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Edit-menu"++\end_inset++Edit menu+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+Leksah does not store backup files.+ Leksah detects if a file which is currently edited has changed on disk+ and queries the user if a reload is desired.+ (Attention: This don't currently work for Windows, so take care).+ When you open a file which is already open, a dialog pops up to inquire+ if you want to make the currently open file active, instead of opening+ it a second time (Leksah does not support multiple views on a file, but+ if you open a file a second time, it's like editing the file two times,+ which makes little sense).+ The list of files is shown as notebook tabs (on top or left of the files+ - as you prefer (Menu -> View -> Tabs Left).+\end_layout++\begin_layout Standard+When a file has changed compared to the stored version, the file name is+ shown in red in the notebook tab, reminding you that it needs to be saved+ before compilation.+ +\end_layout++\begin_layout Standard+If you want to change to a different file editor buffer you can open a list+ of all open files by pressing the right mouse button, while the mouse is+ over a notebook tab.+ You can then select an entry in this list to select this file.+ (See +\begin_inset CommandInset ref+LatexCommand ref+reference "sub:Using-the-Flipper"++\end_inset++ for a better way to switch between source files).+\end_layout++\begin_layout Standard+On the right side in the status bar at the bottom you can see the line and+ column, in which the cursor currently is; and if overwrite mode is switched+ on.+ In the second compartment from the left you can see the currently active+ pane, which is helpful if you want to be sure that you have selected the+ right pane for some operation.+\end_layout++\begin_layout Standard+In the edit menu (+\begin_inset CommandInset ref+LatexCommand ref+reference "fig:Edit-menu"++\end_inset++) you find the usual operations: undo, redo, cut, copy, paste and select+ all.+ In addition you can comment and un-comment selected lines in a per line+ style (--); however, the comment symbol must start in the first column+ (beware of illegal sequences like --# which may be automatically produced+ by inserting a comment in front of some symbol).+ +\end_layout++\begin_layout Standard+Selected blocks of code can be shifted left or right using the tab or Tab/Shift-+Tab keys.+ Furthermore, you can align some special characters (=,<-,->,::,|) in selected+ lines.+ The characters are never moved to the left, but the operation is very simple+ and takes the rightmost position of the special character in all lines,+ and inserts spaces before the first occurrence of this special characters+ in the other lines for alignment.+\end_layout++\begin_layout Subsection+Find and Replace in the current folder+\end_layout++\begin_layout Standard+Leksah supports searching in text files.+ When you select Edit/Find from the menu the find bar will open (+\begin_inset CommandInset ref+LatexCommand ref+reference "fig:Find-bar"++\end_inset++) and you can type in a text string.+ Alternatively you can hit Ctrl-F or select a text and hit Ctrl-F (a standard+ keystrokes binding, which can be configured, see +\begin_inset CommandInset ref+LatexCommand ref+reference "sub:Shortcuts"++\end_inset++).+ Pressing the up and down arrow will bring you to the next/previous occurrence+ of the search string.+ Hitting Enter has a similar effect as the down arrow.+ Hitting Escape will closes the find bar and sets the cursor to the current+ find position.+ You have options for case sensitive search (labeled +\begin_inset Quotes eld+\end_inset++c.S.+\begin_inset Quotes erd+\end_inset++), for searching only whole worlds (toggle Words) and for wrapping around+ (button Wrap), which means that the search will start at the beginning/end+ of the file, when the end/beginning is reached.+ If there is no occurrence of the search string in the currently open file+ the entry turns red.+ +\end_layout++\begin_layout Standard+You can search for regular expressions by switching on the Regex option.+ Leksah supports regular expressions in the Posix style (by using the regex-posi+x package).+ When the syntax of regular expressions is not legal, the background of+ the find pane turns orange.+\end_layout++\begin_layout Standard+\begin_inset Float figure+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_findbar.png+ lyxscale 40+ width 100text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Find-bar"++\end_inset++Find bar+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+To replace a text enter the new text in the replace entry and select replace+ or replace all.+\end_layout++\begin_layout Standard+The last field on the line gives you a mean to jump to a certain line number+ in the current text buffer.+\end_layout++\begin_layout Subsubsection+Search in the package: Grep+\end_layout++\begin_layout Standard+Searching for text in all files in a package is often useful For this feature+ the grep program must be on your path.+ You can then enter a search string in the find bar and search for all occurrenc+es for the string in the folder and sub-folder of the current package with+ pressing the Grep button.+ A pane will open (+\begin_inset CommandInset ref+LatexCommand ref+reference "fig:Grep-pane"++\end_inset++), and in every line show where the expression was found (with context).+ By clicking on the line, the file is opened in an editor and the focus+ is set to the selected line.+ You can navigate between lines with the up and down keys.+ +\end_layout++\begin_layout Standard+Greps supports the search for regular expressions.+\end_layout++\begin_layout Standard+\begin_inset Float figure+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_grep.png+ width 70text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Grep-pane"++\end_inset++Grep pane+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Subsection+Source Candy+\end_layout++\begin_layout Standard+\begin_inset Float figure+placement h+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_source_candy.png+ width 80text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+Source candy example+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+When using Source Candy, Leksah reads and writes pure ASCII Code files,+ but can nevertheless show you nice symbols like +\begin_inset Formula $\lambda.$+\end_inset++This is done by replacing certain character combinations by a Unicode character+ when loading a file or when typing, and replace it back when the file is+ saved.+\end_layout++\begin_layout Standard+The use of the candy feature can be switched on and off in the menu and+ the preferences dialog.+\end_layout++\begin_layout Standard+This feature can be configured by editing a .candy file in the .leksah folder+ or in the data folder.+ The name of the candy file to be used can be specified in the Preferences+ dialog.+\end_layout++\begin_layout Standard+Lines in the *.candy file looks like:+\end_layout++\begin_layout Standard+\begin_inset Box Frameless+position "t"+hor_pos "c"+has_inner_box 1+inner_pos "t"+use_parbox 1+width "100col%"+special "none"+height "1in"+height_special "totalheight"+status open++\begin_layout Plain Layout++\family typewriter+"+\backslash+" 0x03bb --GREEK SMALL LETTER LAMBDA+\end_layout++\begin_layout Plain Layout++\family typewriter+"->" 0x2192 Trimming --RIGHTWARDS ARROW+\end_layout++\end_inset+++\end_layout++\begin_layout Standard+The first entry in a line are the characters to replace.+ The second entry is the hexadecimal representation of the Unicode character+ to replace with.+ The third entry is an optional argument, which specifies, that the replacement+ should add and remove blanks to keep the number of characters.+ This is important because of the layout feature of Haskell.+ The last entry in the line is an optional comment, which is by convention+ the name of the Unicode character.+\end_layout++\begin_layout Standard+Using the source candy feature can give you problems with layout, because+ the alignment of characters with and without source candy may differ!+\end_layout++\begin_layout Standard+\begin_inset Box Framed+position "t"+hor_pos "c"+has_inner_box 0+inner_pos "t"+use_parbox 1+width "100col%"+special "none"+height "1in"+height_special "totalheight"+status open++\begin_layout Plain Layout+Leksah reads and writes files encoded in UTF-8.+ So you can edit Unicode Haskell source files.+ When you want to do this, switch of source candy, because otherwise Unicode+ characters may be converted to ASCII when saving the file.+\end_layout++\end_inset+++\end_layout++\begin_layout Subsection+\begin_inset CommandInset label+LatexCommand label+name "sub:Completion"++\end_inset++Completion+\end_layout++\begin_layout Standard+Leksah has the ability to auto complete identifiers in text you type.+ Additionally the Package, Module and Type of the id gets displayed if selected.+ The completion mode can either be always on, or only be activated on pressing+ Ctrl+Space (or a user defined keystroke).+ You can choose between these two possibilities in the Preferences.+\end_layout++\begin_layout Standard+\begin_inset Float figure+placement h+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_completion.png+ width 70text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+Completion+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+Autocompletion has currently limitations: +\end_layout++\begin_layout Itemize+locally defined names are not included+\end_layout++\begin_layout Itemize+Qualified imports are not handled+\end_layout++\begin_layout Itemize+All names from all packages imported are provided; this may be more than+ you want+\end_layout++\begin_layout Subsection+\begin_inset CommandInset label+LatexCommand label+name "sub:Using-the-Flipper"++\end_inset++Using the Flipper to Switch Between Editors+\end_layout++\begin_layout Standard+You can change the active pane using a keyboard shortcut to bring up the+ flipper.+ It lists the most recently used panes first so they are easier to get to.+ The default shortcuts for the flipper are Ctrl+Tab and Ctrl+Shift+Tab or+ Ctrl+Page Down and Ctrl+Page Up.+ +\end_layout++\begin_layout Standard+The approach in Leksah is comparable to the Alt+Tab and Alt+Shift+Tab used+ to switch between programs in the OS (Ubuntu, Windows).+\end_layout++\begin_layout Subsection+\begin_inset CommandInset label+LatexCommand label+name "sub:Editor-Preferences"++\end_inset++Change Your Preferences for the Editor+\end_layout++\begin_layout Standard+\begin_inset Float figure+placement h+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_prefs_editor.png+ width 80text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+Editor Preferences+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+When selecting Configuration / Edit Prefs the preferences pane opens, which+ has a selection called Editor (Figure 8), were you can edit preferences+ for the editor.+ Some of the options you find here refer to visual elements, like the display+ of line numbers, the font used, the display of a right margin and the use+ of a style file for colors and syntax highlighting.+ +\end_layout++\begin_layout Standard+You can set here the Tab size you want.+ Leksah always stores tabs as spaces.+ Using hard tabs is not recommended for Haskell and the Haskell compilers+ allow only tab size of 8.+\end_layout++\begin_layout Standard+Leksah offers as well to remove trailing blanks in lines, which you may+ choose as default, because blanks at the end of lines make no sense in+ source code.+\end_layout++\begin_layout Verse+\begin_inset Box Boxed+position "t"+hor_pos "c"+has_inner_box 1+inner_pos "t"+use_parbox 0+width "100col%"+special "none"+height "1in"+height_special "totalheight"+status open++\begin_layout Plain Layout+Leksah dialogs offer mostly a +\noun on+Apply, save+\noun default+ and a +\noun on+close+\noun default+ button.+ Be aware that the close button does not save your changes; press apply,+ save and then close! We will change this for the next version.+\end_layout++\begin_layout Plain Layout+In dialogs, where you select something, there is typically an +\noun on+add+\noun default+ button, selecting does not add, neither! Therefore: adding an item means+ select item, add, save, close.+\end_layout++\end_inset+++\end_layout++\begin_layout Subsection+Further info+\end_layout++\begin_layout Standard+The work with the editor is influenced by other features+\end_layout++\begin_layout Itemize+For background building, which may save your files automatically after every+ change refer to +\begin_inset CommandInset ref+LatexCommand ref+reference "sub:Background-Build"++\end_inset++.+\end_layout++\begin_layout Itemize+For information about editor preferences go to +\begin_inset CommandInset ref+LatexCommand ref+reference "sub:Editor-Preferences"++\end_inset++.+\end_layout++\begin_layout Standard+\begin_inset Newpage pagebreak+\end_inset+++\end_layout++\begin_layout Section+Working with Projects: Workspaces and Packages+\end_layout++\begin_layout Standard+Haskell organizes software projects in packages, which are managed independently.+ A package is compiled and linked as a unit to produce one or more executables+ or/and a library.+ It is installed with the package manager Cabal.+ A package can be uploaded to Hackage.+ And provided packages are downloaded from Hackage and installed.+ Packages have version numbers and specify version ranges for dependencies.+ Cabal assures that, if a packages is compiled, correct versions of other+ packages are selected.+\end_layout++\begin_layout Standard+The difficulties, when working with a project where source code under developmen+t is spread over several packages, are overcome in Leksah with the concept+ of a workspace.+ It combines several packages and allows smooth working with files from+ all packages.+ +\end_layout++\begin_layout Standard+Leksah always works in a workspace and always needs at least one package,+ to do anything useful.+ This seems overkill for very simple projects, where the workspace contains+ just one package and this package just one source module producing one+ executable, but Leksah provides defaults that reduce the effort to a minimum.+ The principle to always to work in a workspace and in a package is beneficial+ in the long run, because it gives a smooth transition from a one-shot idea+ to a complex projects and integrates the widely used cabal system fully.+\end_layout++\begin_layout Standard+Leksah, in addition, saves the state of your work environment with a workspace:+ so you can switch between workspaces and get exactly back to where you+ stopped working when leaving the workspace: the same files open in editors+ and the cursor in the same file and position.+ When you open a workspace, and a session is attached to it, Leksah prompts+ you, if you want to switch to the session associated with the workspace.+ Leksah silently always saves the session for the workspace you are closing.+\end_layout++\begin_layout Standard+If you have auto-build on and you change a file, Leksah detects if this+ file belongs to any project in your Workspace.+ If this is the case, it builds the package.+ So the source file you are working on, doesn't need to belong to the active+ package.+ Leksah will detect and compile the package for you.+ The active project is important for the menu items of the package menu,+ because they always work on the active package.+\end_layout++\begin_layout Itemize+Background build can be permanently set in Prefs -> Build -> Background+ build.+ You can temporarily enable and disable it from the toolbar with this button:+ +\begin_inset Graphics+ filename ../pics/ide_build.png+ width 0.5cm++\end_inset++.+\end_layout++\begin_layout Itemize+You can set, if Leksah automatically save all files before building, by+ the setting Prefs -> Build -> Automatically save all files before building.+\end_layout++\begin_layout Itemize+Linking can take a long time, and on Windows we can't interrupt the build+ process in the moment, so it may be an advantage to switch of linking.+ This can be done by: Prefs -> Build -> Include linking in background builds.+ You can temporarily enable and disable it from the toolbar with this button:+ +\begin_inset Graphics+ filename ../pics/ide_link.png+ width 0.5cm++\end_inset++.+\end_layout++\begin_layout Itemize+The same option (disable linking) can be used to disable cross package build+ temporarily.+\end_layout++\begin_layout Subsection+Cross package build+\end_layout++\begin_layout Standard+The following is valid in compiler mode: Depending on your settings the+ following may happen.+ After a library has been successfully build, it will be installed if:+\end_layout++\begin_layout Itemize+\begin_inset Quotes eld+\end_inset++Include linking in background builds+\begin_inset Quotes erd+\end_inset++ is on and either+\end_layout++\begin_deeper+\begin_layout Itemize+\begin_inset Quotes eld+\end_inset++Install always after a successful build+\begin_inset Quotes erd+\end_inset++ is selected or+\end_layout++\begin_layout Itemize+\begin_inset Quotes eld+\end_inset++Install if it's a library with depended packages in the workspace+\begin_inset Quotes erd+\end_inset++ is selected, and it has dependent packages+\end_layout++\end_deeper+\begin_layout Standard+After this, dependend packages will be build.+ If you want a background build, but only for the one package you're working+ on, you can temporarily disable this mechanism, by deselecting +\begin_inset Graphics+ filename ../pics/ide_link.png+ width 0.5cm++\end_inset++.+\end_layout++\begin_layout Subsection+File Organization with Workspaces+\end_layout++\begin_layout Standard+A workspace is represented by a file (+\emph on+workspace_name.lkshws+\emph default+) in a directory.+ You may choose a hierarchical folder structure with a workspace file at+ the top and the projects in sub-folders for complex projects, but you can+ as well put all +\emph on+workspaces+\emph default+ in one directory and put all packages flat.+ You have to use care when you create a new workspace file.+ +\end_layout++\begin_layout Standard+Each package directory contains at least a cabal file (+\emph on+packagename.cabal+\emph default+) and typically folders for the source files, following the usual Haskell+ ghc convention of hierarchical module names.+\end_layout++\begin_layout Standard+Cabal controls the compilation and linking of packages with GHC and puts+ the results in a dist folder in the package; this folder is reconstructed+ often and may be deleted without loss.+ In the folder package_name/dist/build/executable_name you find the executable,+ but it is also installed in the folder ~ /.cabal/bin (for a build with the+ --user flag.+ You may wish to add this folder to your search path).+ +\end_layout++\begin_layout Subsection+Workspace Operations+\end_layout++\begin_layout Standard+\begin_inset Wrap figure+lines 0+placement O+overhang 0in+width "30col%"+status open++\begin_layout Plain Layout+\begin_inset Graphics+ filename screenshots2/screenshot_workspace_menu.png+ width 25text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Workspace-Menu"++\end_inset++Workspace Menu+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Subsubsection+New workspace+\end_layout++\begin_layout Standard+Under the menu workspace you find commands to create a new workspace with+ a specific name and select the folder in which it should reside.+ The windows title and the 3.+ compartment of the status bar informs you always about the currently open+ workspace.+\end_layout++\begin_layout Subsubsection+Add packages to the workspace+\end_layout++\begin_layout Standard+Open the workspace pane (from menu (Panes → Workspace) and do a right-click+ to get the pop-up menu to add a package by selecting the corresponding+ cabal file.+ +\end_layout++\begin_layout Subsubsection+Open workspace+\end_layout++\begin_layout Standard+When starting, Leksah opens the last workspace used.+ You can change to another workspace by opening the corresponding workspace+ file, or by choosing from the list of recently used workspaces.+ When opening a Workspace you can choose to +\end_layout++\begin_layout Subsubsection+Clean and make workspace+\end_layout++\begin_layout Standard+A workspace can be cleaned, meaning all packages gets cleaned and must be+ recompiled from scratch.+ Make builds all the packages in a meaningful order, and installs libraries+ if needed.+ It only stops if an error occurs.+\end_layout++\begin_layout Subsubsection+Jump between errors+\end_layout++\begin_layout Standard+There are menu items to move to the next or the previous error the compiler+ found.+ You can as well use keyboard shortcuts for this: +\noun on+ctr-j+\noun default+ and +\noun on+shift-ctrl-j+\noun default+.+ It is as well possible to move by pointing to the error messages in the+ log pane or error pane.+\end_layout++\begin_layout Subsubsection+Add all imports+\end_layout++\begin_layout Standard+If you miss imports (given error messages (+\begin_inset Quotes eld+\end_inset++xx is not in scope+\begin_inset Quotes erd+\end_inset++) +\noun on+ctrl-r+\noun default+ is adding them automatically to your import list.+ Limitation: it does so only, if the modules they export are in a workspace+ package or are in a package listed in the build dependencies of the package.+\end_layout++\begin_layout Subsection+Packages+\end_layout++\begin_layout Standard+\begin_inset Wrap figure+lines 0+placement O+overhang 0in+width "30col%"+status open++\begin_layout Plain Layout+\begin_inset Graphics+ filename screenshots2/screenshot_package_menu.png+ width 25text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Package-Menu"++\end_inset++Package Menu+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+The concept of a package is used to handle a unit of work for the development+ of some library or executable.+ It is, in the first place, the unit Cabal deals with and is a standard+ in the Haskell community.+\end_layout++\begin_layout Standard+Leksah stores data for packages in the standard cabal files.+ The same files can be used outside of leksah: for example, you can issue+ the command cabal install in the folder that contains the cabal file and+ cabal will (as it would inside leksah) configures, compiles and links and+ install or register the library or executable produced.+ +\end_layout++\begin_layout Subsubsection+Opening and activating a package+\end_layout++\begin_layout Standard+Leksah uses Cabal for package management, and opening a package is done+ by opening the corresponding .+\emph on+cabal+\emph default+ file.+ To open a package select +\emph on+Add Package+\emph default+ from the context menu of the workspace, select the *.cabal file of the desired+ package.+ You must not have more than one *.cabal file in a folder!+\end_layout++\begin_layout Standard+For workspaces with more then one package, you can activate a package in+ the workspace pane, by double clicking on it or by selecting +\emph on+Activate Package+\emph default+ from the context menu.+ The active package is the one that the commands in the Package menu refers+ to.+ (e.g.+ configure, build, install).+ +\end_layout++\begin_layout Standard+Leksah shows the currently active package in the third compartment in the+ status bar and in the window title.+ The package file contains appropriate defaults and for a small program,+ you may just save and close it.+ +\end_layout++\begin_layout Subsubsection+New package+\end_layout++\begin_layout Standard+To start with a new package select Package / NewPackage from the menu.+ Then you have to select a folder for the project, this is by GHC convention+ the same name you will give to your package in the package editor (see+ +\begin_inset CommandInset ref+LatexCommand prettyref+reference "sub:Package-editor"++\end_inset++).+ Then the package editor will open to collect the package details.+ +\end_layout++\begin_layout Standard+This currently does not work, if an editor for a different package is open.+\end_layout++\begin_layout Subsubsection+Package editor+\begin_inset CommandInset label+LatexCommand label+name "sub:Package-editor"++\end_inset+++\end_layout++\begin_layout Standard+The package editor (+\begin_inset CommandInset ref+LatexCommand ref+reference "fig:PackageEditor-1"++\end_inset++) is an editor for cabal files and but you can edit the cabal files in your+ regular text editor as well.+ Leksah works (usually) with the cabal files you and others have already+ written, for example those you get when you install a package from Hackage.+ Since cabal files offer complex options the editor offers many separate+ sub-panes in a list on the right.+ For a complete description of all options see the +\begin_inset CommandInset href+LatexCommand href+name "Cabal User's Guide"+target "http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html"++\end_inset++.+ +\end_layout++\begin_layout Standard+The package editor does currently not support the cabal configurations feature.+ If you need cabal configurations, you need to edit the cabal files as a+ text file separately.+ Leksah uses standard cabal files with no modifications this is no problem+ just the package editor will not work for you.+ +\end_layout++\begin_layout Standard+\begin_inset Float figure+placement h+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_package_editor_1.png+ scale 33++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:PackageEditor-1"++\end_inset++PackageEditor 1+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Subsubsection+The most important parts of cabal files+\end_layout++\begin_layout Standard+A package has, as a minimal requirement, a +\bar under+name+\bar default+ and a +\bar under+version+\bar default+ (default is 0.0.1 -- meaning something like +\begin_inset Quotes eld+\end_inset++first idea+\begin_inset Quotes erd+\end_inset+++\begin_inset Quotes erd+\end_inset++).+ If your code uses other packages then they must be listed in +\bar under+dependencies+\bar default+.+ This will be at least the +\emph on+base+\emph default+ package (which is entered by default).+ This is independent whether you downloaded them, e.g., from Hackage produced+ them yourself.+ Version numbers are used to document (and enforce) that older versions+ of a program use the corresponding older versions of other packages with+ which it was developed originally.+ +\end_layout++\begin_layout Standard+The result of the packages can be an executable and you enter the name of+ the Haskell file that contains the main function in the executable pane+ and the name of the executable.+ The result of the package can be a library; in the corresponding pane you+ tick off the modules which should be exposed (i.e., their exports can be+ used in other packages).+ Cabal gives the possibility to build more then one executable from one+ package and to build a library and executables from one package.+ +\end_layout++\begin_layout Standard+You have to specify a build info.+ With build information you give additional +\begin_inset space \space{}+\end_inset++information, e.g: +\end_layout++\begin_layout Itemize+where the sources can be found (relative to the root folder of the project,+ which is the one with the cabal file).+ +\end_layout++\begin_layout Itemize+what additional non-exposed or non main modules your project includes+\end_layout++\begin_layout Itemize+compiler flags+\end_layout++\begin_layout Itemize+used language extensions in addition to Haskell 98 (These can also be specified+ in the source files with pragmas)+\end_layout++\begin_layout Itemize+and many more ...+\end_layout++\begin_layout Standard+Because more than one executable and a library can be build from one package,+ it is possible to have cabal files with more than one build info.+ The package editor deals with this by the buttons Add / Remove Build Info.+ Every build info gets an index number, and for executables and a library+ you specify the index of the build info.+ +\end_layout++\begin_layout Subsubsection+Initializing a package: Clean and configure operations+\end_layout++\begin_layout Standard+Before a package can be acted on it must be configured; you may clean a+ package (i.e., delete its +\emph on+dist+\emph default+ folder) to start afresh.+\end_layout++\begin_layout Standard+Configure checks that the packages the current packages depend on are installed+ in GHC package manager; it checks for name and version, if you specify+ them.+ If an Hackage package is missing, you can +\noun on+cabal install+\noun default+ it in a terminal window.+ +\end_layout++\begin_layout Standard+Two types of errors regarding packages may be reported:+\end_layout++\begin_layout Standard+While configuring, Cabal checks that the packages you have listed in the+ depends on section are installed on your computer.+ If one of your packages is missing (or missing the version that is needed)+ you can install it either -- for packages you have the source on your computer,+ e.g.+ because you wrote them -- by switching Leksah to the folder where this+ package is and configure, build and install them with the command +\emph on+cabal install+\emph default+.+ For packages that are on Hackage -- use a console, go to the directory+ where you keep such sources and type cabal install packageName (possibly+ package_name-version); cabal then recursively installs the package and+ all packages it depends on.+\end_layout++\begin_layout Standard+Separate from this error message the case, where the compiler misses a module+ you want to import.+ Ghc provides an error message, indicating what package you have to add+ to the depends on' section in the cabal file.+ Edit the package, add the dependency and do configure/build.+\end_layout++\begin_layout Standard+You have to take care as well, that there is a user and a global package+ db.+ Leksah uses the --user flag by default, to minimize errors.+ +\end_layout++\begin_layout Subsubsection+Building+\end_layout++\begin_layout Standard+The most frequently used functionality with packages is to make a build.+ If the package was not configured before, Leksah does that step automatically.+ When you start a build, you can see the standard output of the Cabal build+ procedure in the Log pane.+ +\end_layout++\begin_layout Standard+A build may produce errors and warnings.+ If this is the case the focus is set to the first error/warning in the+ Log and the corresponding source file will open with the focus at the point+ where the compiler reports the error.+ You can navigate to the next or previous errors by clicking on the error+ or warning in the log window, or by using the menu, the toolbar or a keystroke.+\end_layout++\begin_layout Standard+In the statusbar the state regarding to the build is displayed in the third+ compartment from the right.+ It reads +\emph on+Building+\emph default+ as long as a build is on the way and displays the numbers of errors and+ warnings after a build.+\end_layout++\begin_layout Standard+\begin_inset Graphics+ filename ../pics/ide_make.png+ width 0.5cm++\end_inset++This is the symbol, which initiates a +\noun on+build+\noun default+ when clicked on the toolbar (Ctrl-b).+\end_layout++\begin_layout Standard+The error pane (+\begin_inset CommandInset ref+LatexCommand ref+reference "fig:Error-Pane"++\end_inset++) shows the errors in the form of a table and provides the same functionality+ you find in the log, but it may be more convenient to use.+\end_layout++\begin_layout Standard+\begin_inset Float figure+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_error_pane.png+ width 50text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Error-Pane"++\end_inset++Error Pane+\end_layout++\end_inset+++\end_layout++\begin_layout Plain Layout++\end_layout++\end_inset+++\end_layout++\begin_layout Subsubsection+Run+\end_layout++\begin_layout Standard+You can run your program after the build operation has compiled and linked+ it.+ there is a convenient button +\begin_inset Graphics+ filename ../pics/ide_run.png+ width 0.5cm++\end_inset++ to start it!+\end_layout++\begin_layout Subsubsection+\begin_inset CommandInset label+LatexCommand label+name "sub:Background-Build"++\end_inset++Background build+\end_layout++\begin_layout Standard+Leksah can run builds while you work and highlight errors as it finds them.+ This works with a timer that runs continuously in the background.+ If there are changes made to any open file it \SpecialChar \ldots{}++\end_layout++\begin_layout Itemize+interrupts any running build by sending SIGINT (this step is OS X and Linux+ only at this point, it's not working on MS Windows)+\end_layout++\begin_layout Itemize+waits for any running build processes to finish+\end_layout++\begin_layout Itemize+saves all the modified files+\end_layout++\begin_layout Itemize+starts a new build+\end_layout++\begin_layout Standard+Current limitation: Because we can't interrupt the build on windows there+ is an option in the Leksah build preferences to have it skip the linking+ stage in background builds.+ This reduces the delay before a next build starts.+ Background build and linking can be configured in the preferences and as+ well switched on and off from the toolbar.+\end_layout++\begin_layout Standard+\begin_inset Graphics+ filename ../pics/ide_build.png+ width 0.5cm++\end_inset++This is the toggle, which switches +\noun on+background build+\noun default+ on or off in the toolbar.+\end_layout++\begin_layout Standard+\begin_inset Graphics+ filename ../pics/ide_link.png+ width 0.5cm++\end_inset++The+\noun on+ Linking+\noun default+ toggle that switches background build+\noun on+ +\noun default+on or off+\noun on+.+\end_layout++\begin_layout Subsubsection+Build system flags+\end_layout++\begin_layout Standard+Cabal allows more operations than just build; for example producing documentatio+n with Haddock (with The +\begin_inset Quotes eld+\end_inset++Build documentation+\begin_inset Quotes erd+\end_inset++ item in the package menu).+ For each of these operations you can enter the specific flags they require+ for you special case.+ We give here two often examples of flags, others work similarly and we+ recommend that you consult the respective documentations.+\end_layout++\begin_layout Standard+\begin_inset Float figure+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_package_flags.png+ width 50text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+Package Flags+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+(+\begin_inset CommandInset ref+LatexCommand ref+reference "fig:Workspace-Menu"++\end_inset++) consult the +\begin_inset CommandInset href+LatexCommand href+name "Cabal User's Guide"+target "http://www.haskell.org/ghc/docs/latest/html/Cabal/index.html"++\end_inset++.+ +\end_layout++\begin_layout Standard+Cabal needs the --user flag (which is set by default in Leksah) to install+ the result of a built in the user package database (the alternative is+ --global to put the resulting files in global space in ghc-pkg).+\end_layout++\begin_layout Standard+Haddock documentation for the leksah source will not be build, because it+ is not a library unless you pass the --executable flag.+ The flags are stored in a file called IDE.flags in the root folder of the+ project.+\end_layout++\begin_layout Subsection+Import Helper+\end_layout++\begin_layout Standard+A frequent and annoying error is the +\noun on+Not in scope+\noun default+ compiler error.+ In the majority of cases it means that an import statement is missing and+ to write import statements is a frequent and annoying task.+ In Leksah if the compiler informs about a missing import, you can choose+ +\emph on+Add import +\emph default+from the context menu in the log pane.+ Leksah will then add an import statement to the import list.+ If there is more than one module that exports this identifier, a dialog+ will appear which queries you about the module you want to import it from.+\end_layout++\begin_layout Standard+Leksah then adds a line or an entry to the import list of the affected module+ with the compiler error.+ Leksah imports individual elements, but imports all elements of a class+ or data structure if one of them is needed.+ The import helper can work with qualified identifiers and will add a correct+ import statement.+ You can as well select +\emph on+add all imports+\emph default+ from the context menu, in which case all +\emph on+Not in scope +\emph default+errors+\emph on+ +\emph default+will be treated sequentially.+ +\end_layout++\begin_layout Standard+\begin_inset Box Framed+position "t"+hor_pos "c"+has_inner_box 0+inner_pos "t"+use_parbox 0+width "100col%"+special "none"+height "1in"+height_special "totalheight"+status open++\begin_layout Plain Layout+When Leksah does not find an identifier update the Leksah database.+ +\end_layout++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_rebuild_meta.png+ width 0.5cm++\end_inset+++\noun on+Update Metadata or (Ctrl-m)+\end_layout++\end_inset+++\end_layout++\begin_layout Standard+The import helper just looks in imported packages, so if you miss a package+ import, you have to fix it manually.+ +\end_layout++\begin_layout Standard+Obviously some not in scope errors have other reasons, e.g.+ you have misspelled some identifier, which can't be resolved by adding+ imports.+ After adding all imports, you have to save the file and then start a new+ build.+ +\end_layout++\begin_layout Standard+\begin_inset Newpage newpage+\end_inset+++\end_layout++\begin_layout Section+Module Browser and Metadata+\end_layout++\begin_layout Standard+\begin_inset Wrap table+lines 0+placement o+overhang 0in+width "30col%"+status open++\begin_layout Plain Layout+\begin_inset Tabular+<lyxtabular version="3" rows="11" columns="2">+<features>+<column alignment="left" valignment="top" width="0">+<column alignment="center" valignment="top" width="0">+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+sort+\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+symbol+\end_layout++\end_inset+</cell>+</row>+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+function+\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_function.png+ width 0.5cm++\end_inset+++\end_layout++\end_inset+</cell>+</row>+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+data+\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_data.png++\end_inset+++\end_layout++\end_inset+</cell>+</row>+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset space ~+\end_inset+++\begin_inset space ~+\end_inset++constructor+\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_konstructor.png++\end_inset+++\end_layout++\end_inset+</cell>+</row>+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset space ~+\end_inset+++\begin_inset space ~+\end_inset++slot+\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_slot.png++\end_inset+++\end_layout++\end_inset+</cell>+</row>+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+type +\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_type.png++\end_inset+++\end_layout++\end_inset+</cell>+</row>+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+newtype+\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_newtype.png+ width 0.5cm++\end_inset+++\end_layout++\end_inset+</cell>+</row>+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+class+\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_class.png+ width 0.5cm++\end_inset+++\end_layout++\end_inset+</cell>+</row>+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset space ~+\end_inset+++\begin_inset space ~+\end_inset++member +\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_method.png++\end_inset+++\end_layout++\end_inset+</cell>+</row>+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+instance+\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_instance.png+ width 0.5cm++\end_inset+++\end_layout++\end_inset+</cell>+</row>+<row>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+rule+\end_layout++\end_inset+</cell>+<cell alignment="center" valignment="top" usebox="none">+\begin_inset Text++\begin_layout Plain Layout+\begin_inset Graphics+ filename ../pics/ide_rule.png++\end_inset+++\end_layout++\end_inset+</cell>+</row>+</lyxtabular>++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "tab:Sorts-of-identifiers"++\end_inset++Sorts of identifiers+\end_layout++\end_inset+++\end_layout++\end_inset++Leksah collects data about the modules of all installed Haskell packages+ on your system.+ It does this by reading the Haskell interface files .hi files (from GHC).+ It as well collects source positions and comments from sources.+ For this it looks in the source directories you specified in the preferences+ and downloads and unpacks sources from Hackage depending on your settings.+ Starting from the current version, Leksah can as well use prebuild metadata+ it might find on the web, to provide metadata for packages you have sources+ for, but the call to the Haddock library fails for some reason.+ +\end_layout++\begin_layout Standard+The packages in the workspace are treated differently, as not only external+ exported entities are collected, but all exports from all modules are collected.+ As well identifiers, which are not exported from a module get listed.+ The source symbol for them is shown in gray.+\end_layout++\begin_layout Standard+This metadata is used to answer questions like: +\end_layout++\begin_layout Itemize+Which packages and modules export this identifier?+\end_layout++\begin_layout Itemize+What is the type of the exported identifier?+\end_layout++\begin_layout Standard+If the source was found, it lists as well : +\end_layout++\begin_layout Itemize+The comment for this identifier +\end_layout++\begin_layout Itemize+and can mark the item in the source file at the correct position+\end_layout++\begin_layout Standard+If you like to get information about some identifier in the code, the easiest+ way is to press +\noun on+Ctrl +\noun default+and+\noun on+ double click+\noun default+ on it.+\end_layout++\begin_layout Standard+More precisely the operation starts with a release of the left mouse button+ with a selection with +\noun on+Ctrl+\noun default+ pressed; You can use this if the double click doesn't select the intended+ area.+ If the identifier is known unambiguously the modules and info pane will+ show information about it.+ If more than one possibility exist the search pane will open and present+ the alternatives.+\end_layout++\begin_layout Standard+The sorts of the identifiers shown are differentiated by the symbols you+ find in Table +\begin_inset CommandInset ref+LatexCommand ref+reference "tab:Sorts-of-identifiers"++\end_inset++.+ Note as well the special symbol for identifiers exposed, but only indirectly,+ because the definition is imported from another module.+ +\begin_inset Graphics+ filename /home/jutaro/Develop/lws/leksah/pics/ide_reexported.png+ width 0.5cm++\end_inset+++\end_layout++\begin_layout Subsection+The Module Browser+\end_layout++\begin_layout Standard+\begin_inset Float figure+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_module_browser.png+ width 80text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Modules-browser"++\end_inset++Module browser+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+The module browser (+\begin_inset CommandInset ref+LatexCommand ref+reference "fig:Modules-browser"++\end_inset++) shows information about modules and their interface separated in scopes:+ package, workspace, and system.+ If no package or workspace is open only the system scope has information.+ (If a workspace/package is open, it's name(s) are displayed in the third+ subdivision from the left of the status and in the title bar.)+\end_layout++\begin_layout Standard+The scope of the displayed information is selected with the radio button+ on top of the modules pane: The +\emph on+Package+\emph default+ scope shows only modules which are part of the active project.+ The +\emph on+Workspace+\emph default+ scope shows all modules of all packages in the workspace.+ The +\emph on+System+\emph default+ scope shows all modules of installed packages of the system.+ +\end_layout++\begin_layout Standard+(It lists all modules of installed packages.+ These you would get with +\emph on+ghc-pkg+\emph default+ list.+ Leksah scans the user and the global package database, when both are present).+\end_layout++\begin_layout Standard+The amount of information displayed may overwhelm you with details from+ packages that are not of interest to you (Like e.g.+ like Haskell-98, ghc, or base-3.0*).+ Such packages can be excluded, by blacklisting them.+ The packages you want to hide can be specified in the preferences and you+ can use the radio button at the right to hide them.+\end_layout++\begin_layout Standard+If you select a module in the modules list, its interface is displayed in+ the interface list on the right.+ You can search for a module or package by selecting the modules list and+ typing some text.+ With the up and down arrows you find the next/previous matching item.+ With the escape key or by selecting any other GUI element you leave the+ search mode.+ +\end_layout++\begin_layout Standard+\begin_inset Graphics+ filename ../pics/ide_source.png+ width 0.5cm++\end_inset++If this icon shows up, Leksah has found a +\noun on+source+\noun default+ file or source position for this element.+ You can open the source file, or bring it to the front and display the+ source for the selected location with a +\emph on+double click+\emph default+ on the element.+ (the same is achieved with selecting +\emph on+Go to definition+\emph default+ from the context menu.+\end_layout++\begin_layout Standard+\begin_inset Graphics+ filename /home/jutaro/Develop/lws/leksah/pics/ide_source_local.png+ width 0.5cm++\end_inset++This is the same as before, but is used for definitions not exported from+ the module.+ +\end_layout++\begin_layout Standard+\begin_inset Graphics+ filename ../pics/ide_reexported.png+ width 0.5cm++\end_inset++This icon indicates that the symbol is +\noun on+reexported+\noun default+ from another module., because its long list is not much hierarchically structure+d.+\end_layout++\begin_layout Standard+By selecting an element in the Interface List the so called Info Pane is+ shown with detailed information (see next subsection).+\end_layout++\begin_layout Standard+The modules pane provides detailed information and are the quickest way+ to open a source file for edit.+ Go to the modules pane, select package or workspace scope, possibly find+ the module by entering some text, and double click on the module's name+ to open the file in the editor for editing the file.+\end_layout++\begin_layout Standard+\begin_inset Float figure+placement h+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_construct_module.png+ scale 37++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Construct-module-dialog"++\end_inset++Construct module dialog+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+From the context menu of (right-click) the modules pane you can add a new+ module by selecting +\emph on+Add modul+\emph default+e.+ The Construct Module dialog will open (+\begin_inset CommandInset ref+LatexCommand ref+reference "fig:Construct-module-dialog"++\end_inset++).+ You have to enter the name of the module, the source path to use if alternative+s exist.+ If the project is a library you have to specify if the module is exposed.+ Leksah will construct the directory, modify the cabal file and construct+ an empty module file from a template (The template is stored in the file+ module.lksht in the data folder of the project, and will be read from the+ .leksah-** folder if you want to provide a different template file there.+ +\end_layout++\begin_layout Standard+The modification of the cabal file will currently only happen, if it does+ not contain configurations.+ +\end_layout++\begin_layout Subsubsection*+The Info Pane+\end_layout++\begin_layout Standard+The Info Pane is the lower pane of the module browser and shows information+ about an interface element, which may be a function, a class, a data definition+ or a type (selected, for example, in the modules pane).+ It shows the identifier, the package and module that it is exported by,+ it's Haskell type and, if found, the Haddock documentation inserted in+ the source as a comment.+ +\end_layout++\begin_layout Standard+If you select and initiate an identifier search in an editor pane, the informati+on about this identifier is automatically displayed in the info pane (maybe+ nothing!).+ The easiest way to do this is to double click on an identifier while pressing+ +\noun on+Ctrl+\noun default+.+ +\end_layout++\begin_layout Standard+Only previously collected metadata is available this way.+ If the item has changed you could initiate an update of the information+ collected with update workspace metadata (menu configuration → update workspace+ data, or Ctrl-m).+\end_layout++\begin_layout Standard+If a source location is attached, you can go to the definition by clicking+ the +\emph on+Source+\emph default+ button.+ +\end_layout++\begin_layout Standard+You can select the module and the interface element in the modules pane+ by clicking the +\emph on+Modules+\emph default+ button.+\end_layout++\begin_layout Standard+With the +\emph on+Refs+\emph default+ button a pane opens which displays modules which uses this element.+\end_layout++\begin_layout Standard+With the +\emph on+Docu+\emph default+ button you can initiate an external search in a browser with e.g.+ Hayoo or Hoogle, depending on the configuration in the Preferences.+\end_layout++\begin_layout Standard+With the +\emph on+Search+\emph default+ button you can initiate a metadata search for the identifier.+\end_layout++\begin_layout Subsection+The Search Pane+\end_layout++\begin_layout Standard+\begin_inset Float figure+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_serach_pane.png+ width 80text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Search-pane"++\end_inset++Search pane+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+You can search for an identifier in the metadata by typing in characters+ in the entry at the bottom of the pane (not the search entry at the bottom+ of the window!).+ The search result depends on the settings in the search pane (+\begin_inset CommandInset ref+LatexCommand ref+reference "fig:Search-pane"++\end_inset++).+ You can choose:+\end_layout++\begin_layout Enumerate+The scope in which to search, which can be Package, Workspace or System.+ For Package and Workspace scopes you can search with or without imports,+ which gives 5 different scopes.+ +\end_layout++\begin_layout Enumerate+The way the search is executed, which can be exact, prefix or as a regular+ expression.+\end_layout++\begin_layout Enumerate+You can choose if the search shall be case sensitive or not.+\end_layout++\begin_layout Standard+The result of the search is displayed in the list part of the Search pane.+ +\end_layout++\begin_layout Standard+You can see if the module reexports the identifier, or if the source of+ the identifier is reachable.+ When you single click on a search result, the module browser shows the+ corresponding information.+ If you double click on an entry, the modules and info pane shows the correspond+ing information.+\end_layout++\begin_layout Standard+If you double click on an identifier while pressing Ctrl in an editor pane,+ a case sensitive and exact search in the is started.+\end_layout++\begin_layout Standard+\begin_inset Newpage newpage+\end_inset+++\end_layout++\begin_layout Section+Debugger and Interpreter mode+\end_layout++\begin_layout Standard+\begin_inset Wrap figure+lines 0+placement O+overhang 0in+width "30col%"+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_debug_menu.png+ lyxscale 50+ width 25text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset VSpace bigskip+\end_inset+++\end_layout++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_buffer_menu.png+ lyxscale 50+ width 25text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Debug-&-Buffer"++\end_inset++Debug & Buffer menu+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+You can switch Debugger mode on +\emph on+only+\emph default+ from the toolbar with the:+\end_layout++\begin_layout Standard+\begin_inset Graphics+ filename ../pics/ide_debug.png+ width 0.5cm++\end_inset++ toggle, which switches debugger Mode on or off.+ +\end_layout++\begin_layout Standard+In debugger mode the packages and modules for your current project are loaded+ into GHCi.+\end_layout++\begin_layout Standard+In debugger mode, the menu entries from the Debug menu are no longer disabled+ (Fig +\begin_inset CommandInset ref+LatexCommand ref+reference "fig:Debug-&-Buffer"++\end_inset++), and the context menu of source buffers have entries that were not meaningful+ in the regular (GHC) mode.+ There is also a group of panes specifically used for debugging, allowing+ you to manage breakpoints, observe variables, etc.+ +\end_layout++\begin_layout Standard+You can open the debugger group pane by choosing Panes / Debugger.+ Commands using the debugger are given mostly in the source editor pane+ with a context menu: You select some text and right-click to get the context+ menu.+ it lets you:+\end_layout++\begin_layout Itemize++\noun on+Evaluate+\noun default+ the selected expression in the interpreter and observe the result.+ If no text is selected the current line is taken as input.+ Select eval.+ The result of the evaluation is shown in the log window and as +\emph on+it +\emph default+in the variables pane.+ You can as well use the keystroke Ctrl-Enter.+ +\begin_inset Newline newline+\end_inset++Choose +\begin_inset Quotes eld+\end_inset++Eval & Insert+\begin_inset Quotes erd+\end_inset++, to insert a string representation of the result after the selected expression.+\end_layout++\begin_layout Itemize+Determine the +\noun on+type+\noun default+ of an expression: Select the expression in a source buffer and select Type+ from the context menu.+\end_layout++\begin_layout Itemize+Get+\noun on+ info+\noun default+ about an identifier select: Select Info from the context menu.+\end_layout++\begin_layout Itemize+Get +\noun on+the kind+\noun default+ of a type select: Select Kind+\end_layout++\begin_layout Itemize++\noun on+Step+\noun default+ through code: Select the expression in a source buffer.+ Select step from the context menu (or F7).+ Use the toolbar icons (or shortcuts) for stepping +\end_layout++\begin_layout Standard+\begin_inset Graphics+ filename ../pics/ide_step.png+ width 0.5cm++\end_inset++Step (F6), +\begin_inset Graphics+ filename ../pics/ide_local.png+ width 0.5cm++\end_inset++Step local (F7)+\end_layout++\begin_layout Standard+\begin_inset Graphics+ filename ../pics/ide_module.png+ width 0.5cm++\end_inset++Step in module (F8), +\begin_inset Graphics+ filename ../pics/ide_continue.png+ width 0.5cm++\end_inset++Continue (F9)+\end_layout++\begin_layout Itemize+Set +\noun on+breakpoints+\noun default+ by putting the cursor at the breakpoint and select +\emph on+set breakpoint +\emph default+from the context menu.+ Run your application or test cases and start stepping at the break point.+ After a break point is reached you use the operations of GHCi with convenient+ shortcuts.+ +\end_layout++\begin_layout Standard+The debugger has a pane in which you can enter expressions and have them+ evaluated.+ The pane is a Haskell source buffer, which has the reserved name _Eval.+ Its contents is saved with the session.+\end_layout++\begin_layout Standard+Note that:+\end_layout++\begin_layout Itemize+breakpoints are set on identifiers selected, not necessarily where you have+ found it in the source (e.g., used in an expression); +\end_layout++\begin_layout Itemize+current breakpoints are listed in the breakpoints pane; you can remove breakpoin+ts from this pane+\end_layout++\begin_layout Itemize+While stepping through code, you can observe +\noun on+variables+\noun default+ in the variables pane.+ You can print or force a variable from the context menu of the variables+ pane.+ You can update the pane from the context menu.+\end_layout++\begin_layout Itemize+You can observe an execution trace in the traces pane.+ Navigation in the traces pane is currently not supported (:back, :forward).+\end_layout++\begin_layout Itemize+You can query information about the current state of GHCi from the Debugger+ menu.+ E.g.+ +\emph on+Show loaded modules+\emph default+, +\emph on+Show packages+\emph default+ and +\emph on+Show languages+\emph default+.+ +\end_layout++\begin_layout Itemize+You can directly communicate with GHCi by evaluating commands entered as+ text in the source editor and select it.+ E.g.+ +\begin_inset Quotes eld+\end_inset++:set ...+\begin_inset Quotes erd+\end_inset+++\end_layout++\begin_layout Standard+For more information about debugging in GHCi read the GHCi section in the+ GHC manual.+ +\end_layout++\begin_layout Standard+\begin_inset Float figure+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_debug_pane.png+ width 70text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+Debug Pane+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Section+\begin_inset CommandInset label+LatexCommand label+name "sub:Metadata-collection"++\end_inset++Metadata collection+\end_layout++\begin_layout Standard+Remember, that metadata is the data Leksah has collected from all the Haskell+ code (including .hi files for installed packages) it could reach on your+ computer.+ +\end_layout++\begin_layout Standard+The initial scan may take a long time (some minutes); when Leksah starts+ later, it checks only for changes, but does not scan all files again.+ Metadata collection depends on the local configuration, especially the+ list of places where Haskell code may be found, which is entered in the+ preferences.+ Occasionally, you may find it useful to rebuild the metadata.+ +\end_layout++\begin_layout Standard+Metadata collection can be manually triggered: If you select+\emph on+ Configuration -> Update workspace data+\emph default+, the metadata for the current project is collected.+ This brings the metadata of the current project up-to-date.+ You can as well press Ctrl-m or hit this symbol in the toolbar: +\begin_inset Graphics+ filename /home/jutaro/Develop/lws/leksah/pics/ide_rebuild_meta.png+ width 0.5cm++\end_inset+++\end_layout++\begin_layout Standard+If you select+\emph on+ Configuration -> Rebuild workspace data+\emph default+, the metadata for the current project is rebuild.+\end_layout++\begin_layout Standard+If you select +\emph on+Configuration -> Update system data,+\emph default+ Leksah checks, if a new library has been installed and then collects metadata+ for additions.+\end_layout++\begin_layout Standard+If you select +\emph on+Configuration -> Rebuild system data,+\emph default+ Leksah rebuilds all metadata, which may take a long time.+ Currently the preferred way to do this is to call leksah-server -rbo +RTS+ -N2 from the command line.+ The reason for this is that the server process may allocate a lot of memory+ during collection.+ +\end_layout++\begin_layout Subsection+Background infos+\end_layout++\begin_layout Standard+The metadata collection itself proceeds different for workspace and system+ packages:+\end_layout++\begin_layout Itemize+For workspace packages Leksah just uses the parser without typechecking+ and maybe .hi files if available.+\end_layout++\begin_layout Itemize+For system packages Leksah uses .hi files and if sources are available Haddock+ as a library.+ +\end_layout++\begin_layout Standard+Collection for system packages works as follows:+\end_layout++\begin_layout Enumerate+Packages you installed with cabal from Hackage.+ If Leksah can't find sources, it does a +\emph on+cabal unpack+\emph default+ in the source directory you specified for this in the preferences (By default+ .+\emph on+leksah-**/packageSources+\emph default+).+\end_layout++\begin_layout Enumerate+Source files in the folders listed as source folder in the preferences.+ Leksah looks for all .cabal files it can find below the source folders.+ Therefore, Leksah collects source information only from +\begin_inset Quotes eld+\end_inset++Cabalized+\begin_inset Quotes erd+\end_inset++ projects (i.e., projects that have a .cabal file).+ From this information the file source_packages.txt in the .leksah folder+ is written.+ If you miss sources for a package in Leksah, consult this file if the source+ place of the package has been correctly found.+ You can run this step by typing in a terminal: +\emph on+leksah-server -o+\emph default+ (or +\emph on+--+\emph default+sources).+\end_layout++\begin_layout Enumerate+Problems may occur due to preprocessing, header files, language extensions,+ etc.+ Error message produced while metadata collection indicate that not all+ information for a package was found.+ If the Haddock call doesn't succeed, Leksah looks if it can download a+ prebuild metadata package from the server, if this option is selected in+ the preferences.+\end_layout++\begin_layout Enumerate+The result of metadata collection is stored in the folder +\emph on+.leksah-*.*/metadata+\emph default+ in files called +\emph on+*.lkshm.++\emph default+ In this folder for every package a metadata file is stored (e.g.+ binary-0.4.1.lkshm).+ These files are in binary format.+ If you want to rebuild just one package you can delete it here and update+ the system metadata.+ The files .lkshe specify the base path to sources, if the collection for+ sources was successfully or if a metdata file could be downloaded for this.+\end_layout++\begin_layout Standard+For the workspace packages a different procedure is used.+ +\end_layout++\begin_layout Enumerate+Metadata is collected from the source directories of the packages you are+ working on.+ The results are stored in a per module base in a folder with the package+ name (+\emph on+e.g .leksah-*.*/metadata/package-*.*.*).+ +\end_layout++\begin_layout Enumerate+Update happens on a per file base only for changed source files.+\end_layout++\begin_layout Standard+\begin_inset Float figure+wide false+sideways false+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_metadata_prefs.png+ width 60text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:Metadata-Preferences"++\end_inset++Metadata Preferences+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+\begin_inset Newpage newpage+\end_inset+++\end_layout++\begin_layout Section+Configuration+\end_layout++\begin_layout Standard+Leksah is highly customizable and can be adapted to your specific needs+ and work organization.+ What follows here is not needed for initial use of Leksah (and need not+ be read on a first lecture of the manual).+ Leksah works well with the default settings and a desire to adapt better+ to your work habits comes only with extended use of Leksah.+ However, with time, you may use one or the other option to tailor Leksah+ to your personal preference.+ It is easy! Here it is explained how this works.+\end_layout++\begin_layout Subsection+Layout+\end_layout++\begin_layout Standard+\begin_inset Wrap figure+lines 0+placement O+overhang 0in+width "30col%"+status open++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_panes_menu.png+ width 15text%++\end_inset+++\begin_inset VSpace bigskip+\end_inset+++\end_layout++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_view_menu.png+ lyxscale 50+ width 25text%++\end_inset+++\begin_inset VSpace bigskip+\end_inset+++\end_layout++\begin_layout Plain Layout+\align center+\begin_inset Graphics+ filename screenshots2/screenshot_config_menu.png+ width 25text%++\end_inset+++\end_layout++\begin_layout Plain Layout+\begin_inset Caption++\begin_layout Plain Layout+\begin_inset CommandInset label+LatexCommand label+name "fig:View-menu"++\end_inset++View and panes menus+\end_layout++\end_inset+++\end_layout++\end_inset+++\end_layout++\begin_layout Standard+Leksah has always one special pane, which is called the active pane, and+ its name is displayed in the second compartment from the left side in the+ status bar.+ Some actions like moving, splitting, closing panes or finding or replacing+ items in a text buffer act on the current pane, so check the display in+ the status bar to see if the pane you want to act on, is really the active+ one.+\end_layout++\begin_layout Standard+You can tailor the layout with the View menu to suit your work style better.+ Internally, the panes are arranged in a layout of a binary tree, where+ the leaves are horizontal or vertical splits.+ Every area can be split horizontally or vertically and panes can collapse.+ With the commands in the View menu you manipulate this tree to change the+ layout.+\end_layout++\begin_layout Standard+In the initial pane positions part of the Preferences, you can configure+ the placement of panes.+ Panes belongs to categories, and a category specify a path were a pane+ will open .+ +\end_layout++\begin_layout Standard+The layout of the Leksah window contains areas which contain notebooks which+ contain panes.+ The division between the two areas is adjustable by the user by dragging+ a handle.+\end_layout++\begin_layout Standard+Panes can be moved between areas in the window.+ This can be done by dragging the notebook tab, and release it on the frame+ of another notebook.+ Alternatively you can use keystrokes (Shift Alt Arrow) to move panes around.+ The tabs of notebooks can be positioned at any of the four directions,+ or the tabs can be switched off.+ +\end_layout++\begin_layout Standard+Note that holding the mouse over the tabs and selecting the right button+ brings up a menu of all panes in this area, so that you can for example+ quickly select one of many open source buffers.+\end_layout++\begin_layout Standard+The layout will be saved with sessions.+ The session mechanism will be explained in +\begin_inset CommandInset ref+LatexCommand ref+reference "sub:Session-handling"++\end_inset++.+\begin_inset Foot+status open++\begin_layout Plain Layout+ Currently there is no way to load different layouts independent of the+ other data stored in a sessions.+\end_layout++\end_inset+++\end_layout++\begin_layout Subsubsection+Advanced layout: Group panes+\end_layout++\begin_layout Standard+A notebook cannot only contain single panes, but it can as well contain+ group panes, which have a layout on their own and may contain arbitrary+ other panes; the debug pane is an example for a group pane.+ This gives you the possibility to arrange the subpanes in a debugger pane+ as it fits you best.+ +\end_layout++\begin_layout Standard+A new group starts by selecting +\noun on+View / Group +\noun default+from the menu.+ You have to give a unique name for the group.+ Then you can arrange panes in the group as you like.+ When closing a group, and the group is not empty, you have to confirm it.+\end_layout++\begin_layout Subsubsection+Using Leksah with multiple displays: Detached windows+\end_layout++\begin_layout Standard+This feature allows you to move panes to a separate window on a separate+ display.+ This is as simple as: You select a notebook and choose +\noun on+View / Detach+\noun default+ from the menu bar.+ Then the notebook is opened in a new window, which you can then move to+ another screen.+ +\end_layout++\begin_layout Standard+When you close the detached window, the pane goes back to the place where+ it was before detaching.+ The state of detached window is remembered, when you close Leksah, and+ they will be reopened when you restart Leksah.+\end_layout++\begin_layout Standard+It is possible to drag and drop panes between windows.+ But splitting and collapsing of panes is disabled for detached windows.+ So a recommended way to use this feature is to split a pane, arrange the+ panes that you want to detach in the area of the new notebook.+ Select the new notebook and detach.+\end_layout++\begin_layout Standard+The detached windows have no menu bar, toolbar and status bar on their own.+ This may be a problem, when you want to select a menu entry: the focus+ changes from a pane in the detached window to a pane in the main window,+ and you may not be able to do what you want.+ We recommend that you use keystrokes or context menus.+ +\end_layout++\begin_layout Subsection+\begin_inset CommandInset label+LatexCommand label+name "sub:Session-handling"++\end_inset++Session handling+\end_layout++\begin_layout Standard+When you close Leksah the current state is saved in the file +\emph on+current.lksks+\emph default+ in the +\emph on+~/.leksah-*.*+\emph default+ folder.+ A session contains the layout of the window, its content, the active package+ and some other state.+ When you restart Leksah it recovers the state from this information.+ +\end_layout++\begin_layout Standard+When you close a workspace, the session is saved in the folder of the workspace+ +\emph on+in +\emph default+a file named+\emph on+ workspacename.lksks+\emph default+.+ When you open a workspace and Leksah finds a +\emph on+workspacename.lksks+\emph default+ file together with the workspace file you are going to open, you get prompted+ if you want to open this session (this means mostly opening the files you+ had open before in the editor).+ This helps you to switch between different workspaces you are working on.+\end_layout++\begin_layout Standard+In addition, sessions can be stored and loaded with a name manually by using+ the session menu, but the need to use these features occurs rarely.+ The menu Configuration -> Forget Session is useful if you inadvertently+ changed the layout drastically and do not want the current session to be+ stored.+ +\end_layout++\begin_layout Subsection+\begin_inset CommandInset label+LatexCommand label+name "sub:Shortcuts"++\end_inset++Shortcuts+\end_layout++\begin_layout Standard+You can configure the keystrokes by providing a keymap file, which should+ be be in the ~/.leksah-0.8 folder.+ The name of the key map file to be used can be specified in the Preferences+ dialog (without extension!).+ +\end_layout++\begin_layout Standard+A line in the .keymap file looks like:+\end_layout++\begin_layout Standard+<ctrl>o -> FileOpen "Opens an existing file"+\end_layout++\begin_layout Standard+Description of the key or key combination: Allowed modifiers are <shift>+ <ctrl> <alt> <apple> <compose>.+ <apple> is on a Microsoft keyboard the windows key (and on a Mac, obviously,+ the apple key!).+ <compose> is right ALT key, often labeled Alt Gr.+ It is as well possible to specify Emacs like keystrokes in the following+ way: <ctrl>x/<ctrl>f -> FileOpen "Opens an existing file"+\end_layout++\begin_layout Standard+The name of the action can be any one of the +\emph on+ActionDescr's+\emph default+ given in the +\emph on+action+\emph default+ function in the Module +\emph on+IDE.+\emph default+Command.+ The comment following will be displayed as tool tip for the toolbar button,+ if one exists for this action.+ +\end_layout++\begin_layout Standard+Every keystroke must at most be associated with one action, and every action+ may only have one associated keystroke.+\end_layout++\begin_layout Standard+Simple keystrokes are shown in the menu, but Emacs like keystrokes are not.+ This is because simple keystrokes are handled by the standard GTK mechanism,+ while other keystrokes are handled by Leksah.+\end_layout++\begin_layout Standard+Independently how you initiated an action, by a menu, a toolbar button or+ a keystroke, the keystroke with its associated ActionsString is displayed+ in the Status bar in the leftmost compartment.+ +\end_layout++\begin_layout Subsection+Configuration files+\end_layout++\begin_layout Standard+Leksah stores its configuration in a directory called ~/.leksah-*.* under+ your home folder.+ Indexing the hidden Leksah directory with the version number avoids that+ changes to preferences file layout from version to version cause difficulties.+ Moving your preferences from a previous version can potentially be automatic.+\end_layout++\begin_layout Standard+The file +\emph on+prefs.lkshp+\emph default+ stores the general preferences.+ It is a text file you could edit with a text editor, but more comfortable+ and safer is to do it in Leksah with the menu +\noun on+Configuration / Edit Prefs+\noun default+ from the menu.+ +\end_layout++\begin_layout Standard+If no preference file is found in your .leksah-*.* folder then the global+ prefs.lkshp in the installed data folder will be used.+ If a preference file get corrupted, which means Leksah does not start;+ it is then often sufficient to just delete the preference file.+\end_layout++\begin_layout Standard+The source_packages.txt file stores source locations for installed packages.+ It can be rebuild by calling leksah-server in a terminal with the -o or+ --sources argument .+ Do this after you moved your source or added sources for previous installed+ packages without sources.+ +\end_layout++\begin_layout Standard+Files for Keymaps (keymap.lkshk) and SourceCandy(candy.lkshc) may be stored+ in the ~/.leksah-*.* folder and will be found according to the name selected+ in the Preferences Dialog.+ Leksah first searches in this folder and after this in the /data folder.+ +\begin_inset Newpage pagebreak+\end_inset+++\end_layout++\begin_layout Section+The Leksah Project+\end_layout++\begin_layout Standard+The development of an integrated Development Environment is a major undertaking+ and Leksah should become increasingly supported by the user community.+ If you are a user or just test Leksah, we would appreciate to here from+ you.+ Do not miss to report bugs, unclear or wrong information in the documentation+ and suggestion for improvements on the Leksah issue tracker.+\end_layout++\begin_layout Standard+Everyone is invited to contribute.+ Spreading the word, supplying error reports, providing keymap and candy+ files, providing a tutorial, caring for a platform will develop are all+ helpful and meaningful ways to contribute.+\end_layout++\begin_layout Standard+Leksah will advance over time and become more useful.+ Possible extension and enhancements are:+\end_layout++\begin_layout Itemize+Package editor with configurations+\end_layout++\begin_layout Itemize+Add traces to the Debugger+\end_layout++\begin_layout Itemize+Support for some kind of plug-ins or extensions+\end_layout++\begin_layout Itemize+Context enriched completion+\end_layout++\begin_layout Itemize+Version Control (Darcs, ...)+\end_layout++\begin_layout Itemize+Testing (Quick check,...)+\end_layout++\begin_layout Itemize+Object browser+\end_layout++\begin_layout Itemize+Coverage (HPC,...)+\end_layout++\begin_layout Itemize+Profiling (Ghc Profiler,...)+\end_layout++\begin_layout Itemize+Re-factoring (HaRe,...)+\end_layout++\begin_layout Itemize+FAD (Functional Analysis and Design,...)+\end_layout++\begin_layout Standard+Acknowledgment +\end_layout++\begin_layout Standard+Thanks to Ricardo Herrmann for making the new Leksah logo.+ +\end_layout++\begin_layout Standard+Thanks to Fabian Emmes, who created the icons for the module browser.+\end_layout++\begin_layout Standard+Thanks to Lakshmi Narasimhan for packaging for Fedora.+\end_layout++\begin_layout Standard+Thanks to all others who helped us with patches, bug reports and helpful+ feedback.+ +\end_layout++\begin_layout Standard+\begin_inset Newpage newpage+\end_inset+++\end_layout++\begin_layout Section+Appendix+\end_layout++\begin_layout Subsection+Command line arguments+\end_layout++\begin_layout Standard+for leksah-server:+\end_layout++\begin_layout LyX-Code++\size scriptsize+Leksah Haskell IDE (server) Usage: leksah-server [OPTION...] files...+ +\end_layout++\begin_layout LyX-Code++\size scriptsize+-s --system Collects new information for installed+ packages +\end_layout++\begin_layout LyX-Code++\size scriptsize+-r[Maybe Port] --server[=Maybe Port] Start as server.+ +\end_layout++\begin_layout LyX-Code++\size scriptsize+-b --rebuild Modifier for -s and -p: Rebuild metadata+ +\end_layout++\begin_layout LyX-Code++\size scriptsize+-o --sources Modifier for -s: Gather info about+ pathes to sources +\end_layout++\begin_layout LyX-Code++\size scriptsize+-v --version Show the version number of ide + +\end_layout++\begin_layout LyX-Code++\size scriptsize+-h --help Display command line options +\end_layout++\begin_layout LyX-Code++\size scriptsize+-d --debug Write ascii pack files +\end_layout++\begin_layout LyX-Code++\size scriptsize+-e Verbosity --verbosity=Verbosity One of DEBUG, INFO, NOTICE, WARNING,+ ERROR, CRITICAL, ALERT, EMERGENCY +\end_layout++\begin_layout LyX-Code++\size scriptsize+-l LogFile --logfile=LogFile File path for logging messages + +\end_layout++\begin_layout LyX-Code++\size scriptsize+-f --forever Don't end the server when last connection+ ends +\end_layout++\begin_layout LyX-Code++\size scriptsize+-c --endWithLast End the server when last connection+ ends +\size default+ +\end_layout++\begin_layout Standard+for leksah:+\end_layout++\begin_layout LyX-Code++\size scriptsize+Usage: leksah [OPTION...] files...+ +\end_layout++\begin_layout LyX-Code++\size scriptsize+-v --Version Show the version number of ide +\end_layout++\begin_layout LyX-Code++\size scriptsize+-l NAME --LoadSession=NAME Load session +\end_layout++\begin_layout LyX-Code++\size scriptsize+-h --Help Display command line options +\end_layout++\begin_layout LyX-Code++\size scriptsize+-e Verbosity --verbosity=Verbosity One of DEBUG, INFO, NOTICE, WARNING,+ +\end_layout++\begin_layout LyX-Code++\size scriptsize+ ERROR, CRITICAL, ALERT, EMERGENCY+\end_layout++\begin_layout Subsection+The Candy file+\end_layout++\begin_layout LyX-Code++\size scriptsize+"->" 0x2192 Trimming --RIGHTWARDS ARROW +\end_layout++\begin_layout LyX-Code++\size scriptsize+"<-" 0x2190 Trimming --LEFTWARDS ARROW +\end_layout++\begin_layout LyX-Code++\size scriptsize+"=>" 0x21d2 --RIGHTWARDS DOUBLE ARROW +\end_layout++\begin_layout LyX-Code++\size scriptsize+">=" 0x2265 --GREATER-THAN OR EQUAL TO +\end_layout++\begin_layout LyX-Code++\size scriptsize+"<=" 0x2264 --LESS-THAN OR EQUAL TO +\end_layout++\begin_layout LyX-Code++\size scriptsize+"/=" 0x2260 --NOT EQUAL TO +\end_layout++\begin_layout LyX-Code++\size scriptsize+"&&" 0x2227 --LOGICAL AND +\end_layout++\begin_layout LyX-Code++\size scriptsize+"||" 0x2228 --LOGICAL OR +\end_layout++\begin_layout LyX-Code++\size scriptsize+"++" 0x2295 --CIRCLED PLUS +\end_layout++\begin_layout LyX-Code++\size scriptsize+-- "::" 0x2237 Trimming --PROPORTION +\end_layout++\begin_layout LyX-Code++\size scriptsize+-- ".." 0x2025 --TWO DOT LEADER +\end_layout++\begin_layout LyX-Code++\size scriptsize+"^" 0x2191 --UPWARDS ARROW +\end_layout++\begin_layout LyX-Code++\size scriptsize+"==" 0x2261 --IDENTICAL TO +\end_layout++\begin_layout LyX-Code++\size scriptsize+" .+ " 0x2218 --RING OPERATOR +\end_layout++\begin_layout LyX-Code++\size scriptsize+"+\backslash+" 0x03bb --GREEK SMALL LETTER LAMBDA +\end_layout++\begin_layout LyX-Code++\size scriptsize+"=<<" 0x291e -- +\end_layout++\begin_layout LyX-Code++\size scriptsize+">>=" 0x21a0 -- +\end_layout++\begin_layout LyX-Code++\size scriptsize+-- "$" 0x25ca -- +\end_layout++\begin_layout LyX-Code++\size scriptsize+">>" 0x226b -- MUCH GREATER THEN +\end_layout++\begin_layout LyX-Code++\size scriptsize+"forall" 0x2200 --FOR ALL +\end_layout++\begin_layout LyX-Code++\size scriptsize+-- "exist" 0x2203 --THERE EXISTS +\end_layout++\begin_layout LyX-Code++\size scriptsize+"not" 0x00ac --NOT SIGN+\end_layout++\begin_layout LyX-Code++\size scriptsize+"alpha" 0x03b1 --ALPHA +\end_layout++\begin_layout LyX-Code++\size scriptsize+"beta" 0x03b2 --BETA +\end_layout++\begin_layout LyX-Code++\size scriptsize+"gamma" 0x03b3 --GAMMA +\end_layout++\begin_layout LyX-Code++\size scriptsize+"delta" 0x03b4 --DELTA +\end_layout++\begin_layout LyX-Code++\size scriptsize+"epsilon" 0x03b5 --EPSILON +\end_layout++\begin_layout LyX-Code++\size scriptsize+"zeta" 0x03b6 --ZETA +\end_layout++\begin_layout LyX-Code++\size scriptsize+"eta" 0x03b7 --ETA +\end_layout++\begin_layout LyX-Code++\size scriptsize+"theta" 0x03b8 --THETA+\end_layout++\begin_layout Subsection+The Keymap file+\end_layout++\begin_layout LyX-Code++\size tiny+--Default Keymap file for Leksah+\end_layout++\begin_layout LyX-Code++\size tiny+--Allowed Modifiers are <shift> <ctrl> <alt> <apple> <compose>+\end_layout++\begin_layout LyX-Code++\size tiny+--<apple> is the Windows key on PC keyboards+\end_layout++\begin_layout LyX-Code++\size tiny+--<compose> is often labelled Alt Gr.+\end_layout++\begin_layout LyX-Code++\size tiny+--The defined values for the keys can can be found at+\end_layout++\begin_layout LyX-Code++\size tiny+-- http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymde+f.h.+\end_layout++\begin_layout LyX-Code++\size tiny+-- The names of the keys are the names of the macros without the prefix.+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+--File+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>n -> FileNew "Opens a new empty+ buffer"+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>o -> FileOpen "Opens an existing+ file"+\end_layout++\begin_layout LyX-Code++\size tiny+--<ctrl>x/<ctrl>f -> FileOpen "Opens an existing+ file"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>s -> FileSave "Saves the current+ buffer"+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl><shift>s -> FileSaveAll "Saves all modified+ buffers"+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>w -> FileClose "Closes the current+ buffer"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<alt>F4 -> Quit "Quits this program"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+--Edit+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>z -> EditUndo "Undos the last user+ action"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<shift><ctrl>y -> EditRedo "Redos the last user+ action"+\end_layout++\begin_layout LyX-Code++\size tiny+--<ctrl>x/r -> EditRedo "Redos the last user+ action"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>a -> EditSelectAll "Select the whole+ text in the current buffer"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>f -> EditFind "Search for a text+ string (Toggles the "+\end_layout++\begin_layout LyX-Code++\size tiny+F3 -> EditFindNext "Find the next+ occurence of the text string"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<shift>F3 -> EditFindPrevious "Find the previous+ occurence of the text string"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>l -> EditGotoLine "Go to line with+ a known index"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl><alt>Right -> EditComment "Add a line style+ comment to the selected lies"+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl><alt>Left -> EditUncomment "Remove a line style+ comment"+\end_layout++\begin_layout LyX-Code++\size tiny+<alt>Right -> EditShiftRight "Shift right"+\end_layout++\begin_layout LyX-Code++\size tiny+<alt>Left -> EditShiftLeft "Shift Left"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+--View+\end_layout++\begin_layout LyX-Code++\size tiny+<alt><shift>Left -> ViewMoveLeft "Move the current+ pane left"+\end_layout++\begin_layout LyX-Code++\size tiny+<alt><shift>Right -> ViewMoveRight "Move the current+ pane right"+\end_layout++\begin_layout LyX-Code++\size tiny+<alt><shift>Up -> ViewMoveUp "Move the current+ pane up"+\end_layout++\begin_layout LyX-Code++\size tiny+<alt><shift>Down -> ViewMoveDown "Move the current+ pane down"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>2 -> ViewSplitHorizontal+\end_layout++\begin_layout LyX-Code++\size tiny+ "Split the current pane+ in horizontal direction"+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>3 -> ViewSplitVertical+\end_layout++\begin_layout LyX-Code++\size tiny+ "Split the current pane+ in vertical direction"+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>1 -> ViewCollapse "Collapse the panes+ around the currentla selected pane into one"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+ -> ViewTabsLeft "Shows the tabs of the+ current notebook on the left"+\end_layout++\begin_layout LyX-Code++\size tiny+ -> ViewTabsRight "Shows the tabs of the+ current notebook on the right"+\end_layout++\begin_layout LyX-Code++\size tiny+ -> ViewTabsUp "Shows the tabs of the+ current notebook on the top"+\end_layout++\begin_layout LyX-Code++\size tiny+ -> ViewTabsDown "Shows the tabs of the+ current notebook on the bottom"+\end_layout++\begin_layout LyX-Code++\size tiny+ -> ViewSwitchTabs "Switches if tabs for+ the current notebook are visible"+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>t -> ToggleToolbar+\end_layout++\begin_layout LyX-Code++\size tiny+ -> HelpDebug+\end_layout++\begin_layout LyX-Code++\size tiny+ -> HelpAbout+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>b -> BuildPackage+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>r -> AddAllImports+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl><alt>r -> RunPackage+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>j -> NextError+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl><shift>j -> PreviousError+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>o -> ShowModules+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+--<ctrl>i -> ShowInterface+\end_layout++\begin_layout LyX-Code++\size tiny+-- <ctrl>i -> ShowInfo+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl><shift>e -> EditAlignEqual+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl><shift>l -> EditAlignLeftArrow+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl><shift>r -> EditAlignRightArrow+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl><shift>t -> EditAlignTypeSig+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<alt>i -> AddOneImport+\end_layout++\begin_layout LyX-Code++\size tiny+<alt><shift>i -> AddAllImports+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+-- "For the next to entries the <ctrl> modifier is mandatory"+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>Page_Up -> FlipUp "Switch to next pane+ in reverse recently used oder"+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>Page_Down -> FlipDown "Switch to next pane+ in recently used oder"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>space -> StartComplete "Initiate complete in+ a source buffer"+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+F6 -> DebugStep+\end_layout++\begin_layout LyX-Code++\size tiny+F7 -> DebugStepLocal+\end_layout++\begin_layout LyX-Code++\size tiny+F8 -> DebugStepModule+\end_layout++\begin_layout LyX-Code++\size tiny+F9 -> DebugContinue+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>Return -> ExecuteSelection+\end_layout++\begin_layout LyX-Code++\size tiny+<ctrl>m -> UpdateMetadataCurrent+\end_layout++\begin_layout LyX-Code++\end_layout++\begin_layout LyX-Code++\end_layout++\end_body+\end_document
binary file changed (absent → 20899 bytes)
binary file changed (absent → 44944 bytes)
binary file changed (absent → 11280 bytes)
binary file changed (absent → 13750 bytes)
binary file changed (absent → 13557 bytes)
binary file changed (absent → 23853 bytes)
binary file changed (absent → 27508 bytes)
binary file changed (absent → 68766 bytes)
binary file changed (absent → 19782 bytes)
binary file changed (absent → 10400 bytes)
binary file changed (absent → 54948 bytes)
binary file changed (absent → 94039 bytes)
binary file changed (absent → 3249 bytes)
binary file changed (absent → 51760 bytes)
binary file changed (absent → 78083 bytes)
binary file changed (absent → 55153 bytes)
binary file changed (absent → 22767 bytes)
binary file changed (absent → 19896 bytes)
binary file changed (absent → 7113 bytes)
binary file changed (absent → 65463 bytes)
binary file changed (absent → 92625 bytes)
binary file changed (absent → 31551 bytes)
binary file changed (absent → 21466 bytes)
binary file changed (absent → 171095 bytes)
binary file changed (absent → 15935 bytes)
@@ -0,0 +1,300 @@+<?xml version="1.0" encoding="UTF-8"?>+<!--+ Autor: Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>+ Copyright (C) 2014 Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>++ This library is free software; you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation; either version 2 of the License, or+ (at your option) any later version.++ This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License for more details.++ You should have received a copy of the GNU General Public License+ along with this program; if not, write to the Free Software+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+-->+<language id="cabal" _name="Cabal" version="2.0" _section="Others">+ <metadata>+ <property name="mimetypes">text/x-cabal</property>+ <property name="globs">*.cabal</property>+ <property name="line-comment-start">--</property>+ </metadata>++ <styles>+ <style id="comment" _name="Comment" map-to="def:comment"/>+ <style id="field-name" _name="FieldName" map-to="def:type"/>+ <style id="keyword" _name="Keyword" map-to="def:keyword"/>+ </styles>++ <default-regex-options case-sensitive="false"/>++ <definitions>+ <context id="conditional" style-ref="keyword">+ <prefix>^ *</prefix>+ <keyword>if</keyword>+ <keyword>else</keyword>+ </context>++ <context id="custom" style-ref="field-name">+ <match>^ *x-[a-z0-9-]+ *:</match>+ </context>++ <context id="package-field-name" style-ref="field-name">+ <prefix>^</prefix>+ <suffix> *:</suffix>+ <!-- putStrLn $ concatMap (\f -> " <keyword>" ++ fieldName f ++ "</keyword>\n") pkgDescrFieldDescrs -->+ <keyword>name</keyword>+ <keyword>version</keyword>+ <keyword>cabal-version</keyword>+ <keyword>build-type</keyword>+ <keyword>license</keyword>+ <keyword>license-file</keyword>+ <keyword>copyright</keyword>+ <keyword>maintainer</keyword>+ <keyword>build-depends</keyword>+ <keyword>stability</keyword>+ <keyword>homepage</keyword>+ <keyword>package-url</keyword>+ <keyword>bug-reports</keyword>+ <keyword>synopsis</keyword>+ <keyword>description</keyword>+ <keyword>category</keyword>+ <keyword>author</keyword>+ <keyword>tested-with</keyword>+ <keyword>data-files</keyword>+ <keyword>data-dir</keyword>+ <keyword>extra-source-files</keyword>+ <keyword>extra-tmp-files</keyword>+ <keyword>extra-doc-files</keyword>+ </context>++ <context id="source-repo-field-name" style-ref="field-name">+ <prefix>^ +</prefix>+ <suffix> *:</suffix>+ <!-- putStrLn $ concatMap (\f -> " <keyword>" ++ fieldName f ++ "</keyword>\n") sourceRepoFieldDescrs -->+ <keyword>type</keyword>+ <keyword>location</keyword>+ <keyword>module</keyword>+ <keyword>branch</keyword>+ <keyword>tag</keyword>+ <keyword>subdir</keyword>+ </context>++ <context id="source-repo" end-parent="true">+ <start>^(source-repository+)( |$)</start>+ <include>+ <context sub-pattern="1" where="start" style-ref="keyword"/>+ <context ref="line-comment"/>+ <context ref="source-repo-field-name"/>+ <context ref="source-repo"/>+ <context ref="flag"/>+ <context ref="lib"/>+ <context ref="exe"/>+ <context ref="test"/>+ <context ref="custom"/>+ </include>+ </context>++ <context id="flag-field-name" style-ref="field-name">+ <prefix>^ +</prefix>+ <suffix>:</suffix>+ <!-- putStrLn $ concatMap (\f -> " <keyword>" ++ fieldName f ++ "</keyword>\n") flagFieldDescrs -->+ <keyword>description</keyword>+ <keyword>default</keyword>+ <keyword>manual</keyword>+ </context>++ <context id="flag" end-parent="true">+ <start>^(flag) </start>+ <include>+ <context sub-pattern="1" where="start" style-ref="keyword"/>+ <context ref="line-comment"/>+ <context ref="flag-field-name"/>+ <context ref="source-repo"/>+ <context ref="flag"/>+ <context ref="lib"/>+ <context ref="exe"/>+ <context ref="test"/>+ <context ref="custom"/>+ </include>+ </context>++ <context id="lib-field-name" style-ref="field-name">+ <prefix>^ +</prefix>+ <suffix>:</suffix>+ <keyword>build-depends</keyword>+ <!-- putStrLn $ concatMap (\f -> " <keyword>" ++ fieldName f ++ "</keyword>\n") libFieldDescrs -->+ <keyword>exposed-modules</keyword>+ <keyword>exposed</keyword>+ <keyword>buildable</keyword>+ <keyword>build-tools</keyword>+ <keyword>cpp-options</keyword>+ <keyword>cc-options</keyword>+ <keyword>ld-options</keyword>+ <keyword>pkgconfig-depends</keyword>+ <keyword>frameworks</keyword>+ <keyword>c-sources</keyword>+ <keyword>default-language</keyword>+ <keyword>other-languages</keyword>+ <keyword>default-extensions</keyword>+ <keyword>other-extensions</keyword>+ <keyword>extensions</keyword>+ <keyword>extra-libraries</keyword>+ <keyword>extra-lib-dirs</keyword>+ <keyword>includes</keyword>+ <keyword>install-includes</keyword>+ <keyword>include-dirs</keyword>+ <keyword>hs-source-dirs</keyword>+ <keyword>other-modules</keyword>+ <keyword>ghc-prof-options</keyword>+ <keyword>ghc-shared-options</keyword>+ <keyword>ghc-options</keyword>+ <keyword>hugs-options</keyword>+ <keyword>nhc98-options</keyword>+ <keyword>jhc-options</keyword>+ </context>++ <context id="lib" end-parent="true">+ <start>^(library)$</start>+ <include>+ <context sub-pattern="1" where="start" style-ref="keyword"/>+ <context ref="line-comment"/>+ <context ref="lib-field-name"/>+ <context ref="source-repo"/>+ <context ref="flag"/>+ <context ref="exe"/>+ <context ref="test"/>+ <context ref="conditional"/>+ <context ref="custom"/>+ </include>+ </context>++ <context id="exe-field-name" style-ref="field-name">+ <prefix>^ +</prefix>+ <suffix>:</suffix>+ <keyword>build-depends</keyword>+ <!-- putStrLn $ concatMap (\f -> " <keyword>" ++ fieldName f ++ "</keyword>\n") executableFieldDescrs -->+ <keyword>executable</keyword>+ <keyword>main-is</keyword>+ <keyword>buildable</keyword>+ <keyword>build-tools</keyword>+ <keyword>cpp-options</keyword>+ <keyword>cc-options</keyword>+ <keyword>ld-options</keyword>+ <keyword>pkgconfig-depends</keyword>+ <keyword>frameworks</keyword>+ <keyword>c-sources</keyword>+ <keyword>default-language</keyword>+ <keyword>other-languages</keyword>+ <keyword>default-extensions</keyword>+ <keyword>other-extensions</keyword>+ <keyword>extensions</keyword>+ <keyword>extra-libraries</keyword>+ <keyword>extra-lib-dirs</keyword>+ <keyword>includes</keyword>+ <keyword>install-includes</keyword>+ <keyword>include-dirs</keyword>+ <keyword>hs-source-dirs</keyword>+ <keyword>other-modules</keyword>+ <keyword>ghc-prof-options</keyword>+ <keyword>ghc-shared-options</keyword>+ <keyword>ghc-options</keyword>+ <keyword>hugs-options</keyword>+ <keyword>nhc98-options</keyword>+ <keyword>jhc-options</keyword>+ </context>++ <context id="exe" end-parent="true">+ <start>^(executable) </start>+ <include>+ <context sub-pattern="1" where="start" style-ref="keyword"/>+ <context ref="line-comment"/>+ <context ref="exe-field-name"/>+ <context ref="source-repo"/>+ <context ref="flag"/>+ <context ref="lib"/>+ <context ref="exe"/>+ <context ref="test"/>+ <context ref="conditional"/>+ <context ref="custom"/>+ </include>+ </context>++ <context id="test-field-name" style-ref="field-name">+ <prefix>^ +</prefix>+ <suffix>:</suffix>+ <keyword>build-depends</keyword>+ <!-- putStrLn $ concatMap (\f -> " <keyword>" ++ fieldName f ++ "</keyword>\n") testSuiteFieldDescrs -->+ <keyword>type</keyword>+ <keyword>main-is</keyword>+ <keyword>test-module</keyword>+ <keyword>buildable</keyword>+ <keyword>build-tools</keyword>+ <keyword>cpp-options</keyword>+ <keyword>cc-options</keyword>+ <keyword>ld-options</keyword>+ <keyword>pkgconfig-depends</keyword>+ <keyword>frameworks</keyword>+ <keyword>c-sources</keyword>+ <keyword>default-language</keyword>+ <keyword>other-languages</keyword>+ <keyword>default-extensions</keyword>+ <keyword>other-extensions</keyword>+ <keyword>extensions</keyword>+ <keyword>extra-libraries</keyword>+ <keyword>extra-lib-dirs</keyword>+ <keyword>includes</keyword>+ <keyword>install-includes</keyword>+ <keyword>include-dirs</keyword>+ <keyword>hs-source-dirs</keyword>+ <keyword>other-modules</keyword>+ <keyword>ghc-prof-options</keyword>+ <keyword>ghc-shared-options</keyword>+ <keyword>ghc-options</keyword>+ <keyword>hugs-options</keyword>+ <keyword>nhc98-options</keyword>+ <keyword>jhc-options</keyword>+ </context>++ <context id="test" end-parent="true">+ <start>^(test-suite) </start>+ <include>+ <context sub-pattern="1" where="start" style-ref="keyword"/>+ <context ref="line-comment"/>+ <context ref="test-field-name"/>+ <context ref="source-repo"/>+ <context ref="flag"/>+ <context ref="lib"/>+ <context ref="exe"/>+ <context ref="test"/>+ <context ref="conditional"/>+ <context ref="custom"/>+ </include>+ </context>++ <context id="line-comment" style-ref="comment" end-at-line-end="true">+ <start>--</start>+ <include>+ <context ref="def:in-comment"/>+ </include>+ </context>++ <context id="cabal">+ <include>+ <context ref="line-comment"/>+ <context ref="package-field-name"/>+ <context ref="source-repo"/>+ <context ref="flag"/>+ <context ref="lib"/>+ <context ref="exe"/>+ <context ref="test"/>+ <context ref="custom"/>+ </include>+ </context>++ </definitions>+</language>
@@ -123,6 +123,66 @@ </include> </context> + <context id="jmacro">+ <start>\[\$?jmacro\|</start>+ <end>\|\]</end>+ <include>+ <context sub-pattern="0" where="start" style-ref="preprocessor"/>+ <context sub-pattern="0" where="end" style-ref="preprocessor"/>+ <context ref="jmacro:jmacro"/>+ </include>+ </context>++ <context id="jmacroE">+ <start>\[\$?jmacroE\|</start>+ <end>\|\]</end>+ <include>+ <context sub-pattern="0" where="start" style-ref="preprocessor"/>+ <context sub-pattern="0" where="end" style-ref="preprocessor"/>+ <context ref="jmacro:jmacro"/>+ </include>+ </context>++ <context id="evalJM">+ <start>\[\$?evalJM\|</start>+ <end>\|\]</end>+ <include>+ <context sub-pattern="0" where="start" style-ref="preprocessor"/>+ <context sub-pattern="0" where="end" style-ref="preprocessor"/>+ <context ref="jmacro:jmacro"/>+ </include>+ </context>++ <context id="evalJME">+ <start>\[\$?evalJME\|</start>+ <end>\|\]</end>+ <include>+ <context sub-pattern="0" where="start" style-ref="preprocessor"/>+ <context sub-pattern="0" where="end" style-ref="preprocessor"/>+ <context ref="jmacro:jmacro"/>+ </include>+ </context>++ <context id="j">+ <start>\[\$?j\|</start>+ <end>\|\]</end>+ <include>+ <context sub-pattern="0" where="start" style-ref="preprocessor"/>+ <context sub-pattern="0" where="end" style-ref="preprocessor"/>+ <context ref="jmacro:j"/>+ </include>+ </context>++ <context id="je">+ <start>\[\$?je\|</start>+ <end>\|\]</end>+ <include>+ <context sub-pattern="0" where="start" style-ref="preprocessor"/>+ <context sub-pattern="0" where="end" style-ref="preprocessor"/>+ <context ref="jmacro:j"/>+ </include>+ </context>+ <context id="variable" style-ref="variable"> <match>\b[a-z_][0-9a-zA-Z_'#]*</match> </context>@@ -179,20 +239,8 @@ </include> </context> - <context id="char" style-ref="character" end-at-line-end="true">- <start>'</start>- <end>'</end>- <include>- <context style-ref="char-escape" once-only="true">- <match>\%{escaped-character}</match>- </context>- <context once-only="true" extend-parent="false">- <match>.</match>- </context>- <context style-ref="def:error" extend-parent="false">- <match>.</match>- </context>- </include>+ <context id="char" style-ref="character">+ <match extended="true">'\%{escaped-character}'|'.'</match> </context> <context id="float" style-ref="float">@@ -263,6 +311,12 @@ <context ref="cassius"/> <context ref="lucius"/> <context ref="julius"/>+ <context ref="jmacro"/>+ <context ref="jmacroE"/>+ <context ref="evalJM"/>+ <context ref="evalJME"/>+ <context ref="j"/>+ <context ref="je"/> </include> </context>
@@ -0,0 +1,374 @@+<?xml version="1.0" encoding="UTF-8"?>+<!--++ Author: Scott Martin <scott@coffeeblack.org>+ Copyright (C) 2004 Scott Martin <scott@coffeeblack.org>+ Copyright (C) 2005 Stef Walter (formerly Nate Nielsen) <stef@memberwebs.com>+ Copyright (C) 2005-2007 Marco Barisione <barisione@gmail.com>+ Copyright (C) 2005-2007 Emanuele Aina++ This library is free software; you can redistribute it and/or+ modify it under the terms of the GNU Library General Public+ License as published by the Free Software Foundation; either+ version 2 of the License, or (at your option) any later version.++ This library is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU+ Library General Public License for more details.++ You should have received a copy of the GNU Library General Public+ License along with this library; if not, write to the+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,+ Boston, MA 02111-1307, USA.++-->+<language id="jmacro" _name="JMacro" version="2.0" _section="Scripts">+ <metadata>+ <property name="mimetypes">application/x-jmacro;text/x-jmacro</property>+ <property name="globs">*.jmacro</property>+ <property name="line-comment-start">//</property>+ <property name="block-comment-start">/*</property>+ <property name="block-comment-end">*/</property>+ </metadata>++ <styles>+ <style id="haskell-embed" _name="Haskell" map-to="def:preprocessor"/>+ <style id="comment" _name="Comment" map-to="def:comment"/>+ <style id="error" _name="Error" map-to="def:error"/>+ <style id="string" _name="String" map-to="def:string"/>+ <style id="null-value" _name="Null Value" map-to="def:special-constant"/>+ <style id="undefined-value" _name="Undefined Value" map-to="def:special-constant"/>+ <style id="boolean" _name="Boolean value" map-to="def:boolean"/>+ <style id="keyword" _name="Keyword" map-to="def:keyword"/>+ <style id="object" _name="Object"/> <!--map-to="def:others"-->+ <style id="type" _name="Data Type" map-to="def:type"/>+ <style id="function" _name="Function" map-to="def:function"/>+ <style id="properties" _name="Properties" map-to="def:statement"/>+ <style id="constructors" _name="Constructors" map-to="def:type"/>+ <style id="future-words" _name="Future Reserved Keywords" map-to="def:error"/>+ </styles>++ <definitions>+ <context id="haskell-embed">+ <start>`\(</start>+ <end>\)`</end>+ <include>+ <context sub-pattern="0" where="start" style-ref="haskell-embed"/>+ <context sub-pattern="0" where="end" style-ref="haskell-embed"/>+ <context ref="haskell:body"/>+ </include>+ </context>++ <context id="short-haskell-embed">+ <start>`</start>+ <end>`</end>+ <include>+ <context sub-pattern="0" where="start" style-ref="haskell-embed"/>+ <context sub-pattern="0" where="end" style-ref="haskell-embed"/>+ <context ref="haskell:body"/>+ </include>+ </context>++ <context id="jmacro-base" class="no-spell-check">+ <include>++ <!-- Comments -->+ <context id="line-comment" style-ref="comment" class="comment" class-disabled="no-spell-check">+ <start>//</start>+ <end>$</end>+ <include>+ <context ref="def:line-continue"/>+ <context ref="def:in-comment"/>+ <context ref="haskell-embed"/>+ </include>+ </context>++ <context id="block-comment" style-ref="comment" class="comment" class-disabled="no-spell-check">+ <start>/\*</start>+ <end>\*/</end>+ <include>+ <context ref="def:in-comment"/>+ <context ref="haskell-embed"/>+ </include>+ </context>++ <context id="close-comment-outside-comment" style-ref="error">+ <match>\*/(?!\*)</match>+ </context>++ <!-- Strings -->+ <context id="string-double" end-at-line-end="true" style-ref="string" class="string" class-disabled="no-spell-check">+ <start>"</start>+ <end>"</end>+ <include>+ <context ref="def:line-continue"/>+ <context ref="def:escape"/>+ <context ref="haskell-embed"/>+ </include>+ </context>++ <context id="string-single" end-at-line-end="true" style-ref="string" class="string" class-disabled="no-spell-check">+ <start>'</start>+ <end>'</end>+ <include>+ <context ref="def:line-continue"/>+ <context ref="def:escape"/>+ <context ref="haskell-embed"/>+ </include>+ </context>++ <!-- Numbers -->+ <context ref="def:float"/>+ <context ref="def:decimal"/>+ <context ref="def:octal"/>+ <context ref="def:hexadecimal"/>++ <!-- Constants -->+ <context id="null-value" style-ref="null-value">+ <keyword>null</keyword>+ </context>+ <context id="undefined-value" style-ref="undefined-value">+ <keyword>undefined</keyword>+ </context>+ <context id="boolean" style-ref="boolean">+ <keyword>false</keyword>+ <keyword>true</keyword>+ </context>++ <!-- Keywords -->+ <context id="keywords" style-ref="keyword">+ <keyword>break</keyword>+ <keyword>case</keyword>+ <keyword>catch</keyword>+ <keyword>const</keyword>+ <keyword>continue</keyword>+ <keyword>default</keyword>+ <keyword>delete</keyword>+ <keyword>do</keyword>+ <keyword>else</keyword>+ <keyword>export</keyword>+ <keyword>finally</keyword>+ <keyword>for</keyword>+ <keyword>function</keyword>+ <keyword>if</keyword>+ <keyword>import</keyword>+ <keyword>instanceof</keyword>+ <keyword>in</keyword>+ <keyword>let</keyword>+ <keyword>new</keyword>+ <keyword>return</keyword>+ <keyword>switch</keyword>+ <keyword>this</keyword>+ <keyword>throw</keyword>+ <keyword>try</keyword>+ <keyword>typeof</keyword>+ <keyword>while</keyword>+ <keyword>with</keyword>+ <keyword>var</keyword>+ <keyword>void</keyword>+ </context>++ <context id="ojects" style-ref="object">+ <keyword>constructor</keyword>+ <keyword>prototype</keyword>+ </context>++ <context id="types" style-ref="type">+ <keyword>Infinity</keyword>+ <keyword>Math</keyword>+ <keyword>NaN</keyword>+ <keyword>NEGATIVE_INFINITY</keyword>+ <keyword>POSITIVE_INFINITY</keyword>+ </context>++ <context id="functions" style-ref="function">+ <keyword>abs</keyword>+ <keyword>acos</keyword>+ <keyword>apply</keyword>+ <keyword>asin</keyword>+ <keyword>atan2</keyword>+ <keyword>atan</keyword>+ <keyword>call</keyword>+ <keyword>ceil</keyword>+ <keyword>charAt</keyword>+ <keyword>charCodeAt</keyword>+ <keyword>concat</keyword>+ <keyword>cos</keyword>+ <keyword>decodeURIComponent</keyword>+ <keyword>decodeURI</keyword>+ <keyword>encodeURIComponent</keyword>+ <keyword>encodeURI</keyword>+ <keyword>escape</keyword>+ <keyword>eval</keyword>+ <keyword>exec</keyword>+ <keyword>exp</keyword>+ <keyword>floor</keyword>+ <keyword>fromCharCode</keyword>+ <keyword>getDate</keyword>+ <keyword>getDay</keyword>+ <keyword>getFullYear</keyword>+ <keyword>getHours</keyword>+ <keyword>getMilliseconds</keyword>+ <keyword>getMinutes</keyword>+ <keyword>getMonth</keyword>+ <keyword>getSeconds</keyword>+ <keyword>getTime</keyword>+ <keyword>getTimezoneOffset</keyword>+ <keyword>getUTCDate</keyword>+ <keyword>getUTCDay</keyword>+ <keyword>getUTCFullYear</keyword>+ <keyword>getUTCHours</keyword>+ <keyword>getUTCMilliseconds</keyword>+ <keyword>getUTCMinutes</keyword>+ <keyword>getUTCMonth</keyword>+ <keyword>getUTCSeconds</keyword>+ <keyword>getYear</keyword>+ <keyword>hasOwnProperty</keyword>+ <keyword>indexOf</keyword>+ <keyword>isFinite</keyword>+ <keyword>isNaN</keyword>+ <keyword>isPrototypeOf</keyword>+ <keyword>join</keyword>+ <keyword>lastIndexOf</keyword>+ <keyword>localeCompare</keyword>+ <keyword>log</keyword>+ <keyword>match</keyword>+ <keyword>max</keyword>+ <keyword>min</keyword>+ <keyword>parseFloat</keyword>+ <keyword>parseInt</keyword>+ <keyword>parse</keyword>+ <keyword>pop</keyword>+ <keyword>pow</keyword>+ <keyword>propertyIsEnumerable</keyword>+ <keyword>push</keyword>+ <keyword>random</keyword>+ <keyword>replace</keyword>+ <keyword>reverse</keyword>+ <keyword>round</keyword>+ <keyword>search</keyword>+ <keyword>setDate</keyword>+ <keyword>setFullYear</keyword>+ <keyword>setHours</keyword>+ <keyword>setMilliseconds</keyword>+ <keyword>setMinutes</keyword>+ <keyword>setMonth</keyword>+ <keyword>setSeconds</keyword>+ <keyword>setTime</keyword>+ <keyword>setUTCDate</keyword>+ <keyword>setUTCFullYear</keyword>+ <keyword>setUTCHours</keyword>+ <keyword>setUTCMilliseconds</keyword>+ <keyword>setUTCMinutes</keyword>+ <keyword>setUTCMonth</keyword>+ <keyword>setUTCSeconds</keyword>+ <keyword>setYear</keyword>+ <keyword>shift</keyword>+ <keyword>sin</keyword>+ <keyword>slice</keyword>+ <keyword>sort</keyword>+ <keyword>split</keyword>+ <keyword>sqrt</keyword>+ <keyword>substring</keyword>+ <keyword>substr</keyword>+ <keyword>tan</keyword>+ <keyword>toDateString</keyword>+ <keyword>toExponential</keyword>+ <keyword>toFixed</keyword>+ <keyword>toGMTString</keyword>+ <keyword>toLocaleDateString</keyword>+ <keyword>toLocaleLowerCase</keyword>+ <keyword>toLocaleString</keyword>+ <keyword>toLocaleTimeString</keyword>+ <keyword>toLocaleUpperCase</keyword>+ <keyword>toLowerCase</keyword>+ <keyword>toPrecision</keyword>+ <keyword>toString</keyword>+ <keyword>toTimeString</keyword>+ <keyword>toUpperCase</keyword>+ <keyword>toUTCString</keyword>+ <keyword>unescape</keyword>+ <keyword>unshift</keyword>+ <keyword>UTC</keyword>+ <keyword>valueOf</keyword>+ </context>++ <context id="properties" style-ref="properties">+ <keyword>global</keyword>+ <keyword>ignoreCase</keyword>+ <keyword>lastIndex</keyword>+ <keyword>length</keyword>+ <keyword>message</keyword>+ <keyword>multiline</keyword>+ <keyword>name</keyword>+ <keyword>source</keyword>+ </context>++ <context id="constructors" style-ref="constructors">+ <keyword>Array</keyword>+ <keyword>Boolean</keyword>+ <keyword>Date</keyword>+ <keyword>Error</keyword>+ <keyword>EvalError</keyword>+ <keyword>Function</keyword>+ <keyword>Number</keyword>+ <keyword>Object</keyword>+ <keyword>RangeError</keyword>+ <keyword>RegExp</keyword>+ <keyword>String</keyword>+ <keyword>SyntaxError</keyword>+ <keyword>TypeError</keyword>+ <keyword>URIError</keyword>+ </context>++ <context id="future-words" style-ref="future-words">+ <keyword>abstract</keyword>+ <keyword>boolean</keyword>+ <keyword>byte</keyword>+ <keyword>char</keyword>+ <keyword>class</keyword>+ <keyword>debugger</keyword>+ <keyword>double</keyword>+ <keyword>enum</keyword>+ <keyword>extends</keyword>+ <keyword>final</keyword>+ <keyword>float</keyword>+ <keyword>goto</keyword>+ <keyword>implements</keyword>+ <keyword>interface</keyword>+ <keyword>int</keyword>+ <keyword>long</keyword>+ <keyword>native</keyword>+ <keyword>package</keyword>+ <keyword>private</keyword>+ <keyword>protected</keyword>+ <keyword>public</keyword>+ <keyword>short</keyword>+ <keyword>static</keyword>+ <keyword>super</keyword>+ <keyword>synchronized</keyword>+ <keyword>throws</keyword>+ <keyword>transient</keyword>+ <keyword>volatile</keyword>+ </context>++ </include>+ </context>++ <context id="jmacro" class="no-spell-check">+ <include>+ <context ref="haskell-embed"/>+ <context ref="jmacro-base"/>+ </include>+ </context>++ <context id="j" class="no-spell-check">+ <include>+ <context ref="short-haskell-embed"/>+ <context ref="jmacro-base"/>+ </include>+ </context>++ </definitions>+</language>
@@ -1,10 +1,10 @@ name: leksah-version: 0.12.1.3+version: 0.13.3.0 cabal-version: >=1.10 build-type: Simple license: GPL license-file: LICENSE-copyright: 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+copyright: 2007-2014 Juergen Nicklisch-Franken, Hamish Mackenzie maintainer: maintainer@leksah.org stability: provisional homepage: http://www.leksah.org@@ -16,12 +16,14 @@ author: Juergen Nicklisch-Franken, Hamish Mackenzie tested-with: GHC == 7.2.2 data-files: LICENSE- Readme+ Readme.md data/current.lkshs data/candy.lkshc data/keymap.lkshk data/leksah.menu+ data/svn.menu+ data/git.menu data/prefs.lkshp data/prefscoll.lkshp data/emacs.lkshk@@ -32,13 +34,19 @@ data/leksah-welcome/Setup.lhs data/leksah-welcome/leksah-welcome.cabal data/leksah-welcome/src/Main.hs+ data/empty.lkshs+ data/.gtkrc-2.0+ data/styles/leksah.xml+ data/styles/leksah-dark.xml + language-specs/cabal.lang language-specs/haskell.lang language-specs/haskell-literate.lang language-specs/hamlet.lang language-specs/cassius.lang language-specs/lucius.lang language-specs/julius.lang+ language-specs/jmacro.lang pics/ide_class.png pics/ide_configure.png@@ -70,37 +78,136 @@ pics/ide_link.png pics/ide_rebuild_meta.png pics/ide_empty.png++ doc/Keybindings.svg+ doc/leksah_manual.lyx+ doc/screenshots2/screenshot_buffer_menu.png+ doc/screenshots2/screenshot_completion.png+ doc/screenshots2/screenshot_config_menu.png+ doc/screenshots2/screenshot_construct_module.png+ doc/screenshots2/screenshot_debug_menu.png+ doc/screenshots2/screenshot_debug_pane.png+ doc/screenshots2/screenshot_edit_menu.png+ doc/screenshots2/screenshot_error_pane.png+ doc/screenshots2/screenshot_file_menu.png+ doc/screenshots2/screenshot_findbar.png+ doc/screenshots2/screenshot_first_start.png+ doc/screenshots2/screenshot_grep.png+ doc/screenshots2/screenshot_help_menu.png+ doc/screenshots2/screenshot_metadata_prefs.png+ doc/screenshots2/screenshot_module_browser.png+ doc/screenshots2/screenshot_package_editor_1.png+ doc/screenshots2/screenshot_package_flags.png+ doc/screenshots2/screenshot_package_menu.png+ doc/screenshots2/screenshot_panes_menu.png+ doc/screenshots2/screenshot_prefs_editor.png+ doc/screenshots2/screenshot_serach_pane.png+ doc/screenshots2/screenshot_source_candy.png+ doc/screenshots2/screenshot_view_menu.png+ doc/screenshots2/screenshot_welcome.png+ doc/screenshots2/screenshot_workspace_menu.png++ scripts/clean.sh+ scripts/stage.sh+ osx/bundle.sh+ osx/gtk2.sh+ osx/gtk.sh+ osx/Info.plist+ osx/launcher.sh+ osx/leksah.bundle+ osx/leksah.icns+ osx/makedmg.sh+ osx/makedmgs.sh+ osx/osxkeymap.lkshk+ osx/settings.ini+ win32/gtk2hsall.sh+ win32/gtkrc+ win32/leksah.bat+ win32/leksah.ico+ win32/leksah.nsi+ win32/leksah-rebuild-metadata.bat+ win32/leksah-server.bat+ win32/makeinstaller.sh+ win32/makeinstallers.sh+ win32/recache.sh+ linux/applications/leksah.desktop+ linux/applications/leksah.xml+ linux/icons/hicolor/48x48/apps/leksah_48x48.png+ linux/specfiles/fedora/12/ghc-binary-shared.spec+ linux/specfiles/fedora/12/ghc-deepseq.spec+ linux/specfiles/fedora/12/ghc-hslogger.spec+ linux/specfiles/fedora/12/ghc-ltk.spec+ linux/specfiles/fedora/12/ghc-process-leksah.spec+ linux/specfiles/fedora/12/ghc-regex-base.spec+ linux/specfiles/fedora/12/ghc-regex-tdfa.spec+ linux/specfiles/fedora/12/leksah_server.spec+ linux/specfiles/fedora/12/leksah.spec+ linux/specfiles/fedora/13/ghc-binary-shared.spec+ linux/specfiles/fedora/13/ghc-hslogger.spec+ linux/specfiles/fedora/13/ghc-ltk.spec+ linux/specfiles/fedora/13/ghc-process-leksah.spec+ linux/specfiles/fedora/13/ghc-regex-tdfa.spec+ linux/specfiles/fedora/13/haddock.spec+ linux/specfiles/fedora/13/leksah-server.spec+ linux/specfiles/fedora/13/leksah.spec+ linux/specfiles/fedora/14/ghc-binary-shared.spec+ linux/specfiles/fedora/14/ghc-haddock.spec+ linux/specfiles/fedora/14/ghc-ltk.spec+ linux/specfiles/fedora/14/ghc-process-leksah.spec+ linux/specfiles/fedora/14/ghc-regex-tdfa.spec+ linux/specfiles/fedora/14/leksah-server.spec+ linux/specfiles/fedora/14/leksah.spec+ linux/specfiles/fedora/14/leksah.spec-darcs-backup0+ linux/specfiles/fedora/14/leksah.spec-darcs-backup1+ data-dir: ""-extra-source-files: Setup.lhs+extra-source-files: Setup.lhs SetupLocale.lhs po/*.pot po/*.po++x-gettext-po-files: po/*.po+x-gettext-domain-name: leksah++ extra-tmp-files: flag yi- Default: False Description: Experimental Yi support+ Default: False flag dyre- Default: True Description: Experimental Yi support+ Default: True flag threaded- default: False description: Build with support for multithreaded execution+ default: False +flag gtk3+ Description: Use GTK3 rather than GTK2+ Default: True++flag webkit+ Description: Use WebKitGTK++ Default: True++flag loc+ Description: Experimental localization support+ Default: False+ library if os(windows)- build-depends: Win32 >=2.2.0.0 && <2.3+ build-depends: Win32 >=2.2.0.0 && <2.4 extra-libraries: kernel32--- extra-lib-dirs: C:/cygwin/lib/w32api- includes: windows.h--- include-dirs: C:/cygwin/usr/include/w32api else- build-depends: unix >=2.3.1.0 && <2.6+ build-depends: unix >=2.3.1.0 && <2.8 if os(osx)- build-depends: gtk-mac-integration >= 0.0.0.2 && <0.2+ if flag(gtk3)+ build-depends: gtk3-mac-integration >= 0.2.0.0 && <0.3+ else+ build-depends: gtk-mac-integration >= 0.2.0.0 && <0.3 if flag(yi)- build-depends: yi >=0.6.1 && <0.7+ build-depends: yi >=0.6.6.1 && <0.7 cpp-options: -DLEKSAH_WITH_YI if flag(yi) && flag(dyre)@@ -110,21 +217,42 @@ if flag(threaded) ghc-options: -threaded + if flag(gtk3)+ build-depends: gtk3 >=0.12.4 && <0.13, gtksourceview3 >=0.10.0 && <0.13+ cpp-options: -DMIN_VERSION_gtk=MIN_VERSION_gtk3+ else+ build-depends: gtk >=0.12.4 && <0.13, gtksourceview2 >=0.10.0 && <0.13++ if flag(webkit)+ if flag(gtk3)+ build-depends: webkitgtk3 -any, webkitgtk3-javascriptcore -any+ else+ build-depends: webkit -any, webkit-javascriptcore -any+ build-depends: jsaddle -any, ghcjs-codemirror -any, hamlet -any, blaze-html -any,+ lens -any, pretty-show >=1.6.3 && <1.7+ cpp-options: -DWEBKITGTK -DLEKSAH_WITH_CODE_MIRROR++ if flag(loc) && os(linux)+ cpp-options: -DLOCALIZATION+ build-depends: hgettext, setlocale+ hs-source-dirs: src default-language: Haskell98 - build-depends: Cabal >=1.6.0.1 && <1.15, base >=4.0.0.0 && <4.6, binary >=0.5.0.0 && <0.6,- bytestring >=0.9.0.1 && <0.10, containers >=0.2.0.0 && <0.5, directory >=1.0.0.2 && <3.1,- filepath >=1.1.0.1 && <1.4, glib >=0.10 && <0.13, gtk >=0.10 && <0.13,- gtksourceview2 >=0.10.0 && <0.13, mtl >=1.1.0.2 && <2.2, old-time >=1.0.0.1 && <1.2,+ build-depends: Cabal >=1.6.0.1 && <1.20, base >=4.0.0.0 && <4.8, binary >=0.5.0.0 && <0.8,+ bytestring >=0.9.0.1 && <0.11, containers >=0.2.0.0 && <0.6, directory >=1.0.0.2 && <3.1,+ filepath >=1.1.0.1 && <1.4, glib >=0.10 && <0.13,+ mtl >=1.1.0.2 && <2.2, old-time >=1.0.0.1 && <1.2, parsec >=2.1.0.1 && <3.2, pretty >=1.0.1.0 && <1.2,- regex-tdfa ==1.1.*, regex-base ==0.93.*, utf8-string >=0.3.1.1 && <0.4, array >=0.2.0.0 && <0.5,- time >=0.1 && <1.5, ltk >= 0.12.1.0 && <0.13, binary-shared >= 0.8 && <0.9, deepseq >= 1.1.0.0 && <1.4,- hslogger >= 1.0.7 && <1.2, leksah-server >=0.12.1.2 && <0.13, network >= 2.2 && <3.0,- ghc >=6.10.1 && <7.5, strict >= 0.3.2 && <0.4, enumerator >=0.4.14 && <0.5, text >= 0.11.1.5 && < 0.12,+ regex-tdfa >=1.1 && <1.3, regex-base ==0.93.*, utf8-string >=0.3.1.1 && <0.4, array >=0.2.0.0 && <0.6,+ time >=0.1 && <1.5, ltk >= 0.13.1.0 && <0.14, binary-shared >= 0.8 && <0.9, deepseq >= 1.1.0.0 && <1.4,+ hslogger >= 1.0.7 && <1.3, leksah-server >=0.13.1.0 && <0.14, network >= 2.2 && <3.0,+ ghc >=6.10.1 && <7.9, strict >= 0.3.2 && <0.4, conduit >= 1.0.8 && <1.1, text >= 0.11.1.5 && < 1.2, gio >=0.12.2 && <0.13, transformers >=0.2.2.0 && <0.4,- QuickCheck >=2.4.2 && <2.5-+ executable-path >=0.0.3 && <0.1,+ vcsgui >=0.0.1 && < 0.1, vcswrapper >=0.0.1 && < 0.1,+ QuickCheck >=2.4.2 && <2.7, haskell-src-exts >=1.13.5 && <1.15,+ hlint >=1.8.39 && <1.9, vado >=0.0.1 && <0.1 exposed-modules: IDE.Leksah IDE.Completion IDE.ImportTool IDE.Find IDE.Session IDE.Command IDE.Keymap IDE.Utils.GUIUtils IDE.SymbolNavigation@@ -136,17 +264,30 @@ IDE.Pane.Info IDE.Pane.Log IDE.Pane.SourceBuffer IDE.Pane.Modules IDE.Pane.Search IDE.Pane.PackageFlags IDE.LogRef IDE.Debug IDE.Pane.Grep IDE.Pane.Files+ IDE.Pane.HLint IDE.Pane.Breakpoints IDE.Pane.Trace IDE.Pane.Variables- IDE.Pane.Errors IDE.TextEditor IDE.Workspaces+ IDE.Pane.Errors IDE.TextEditor IDE.Workspaces IDE.Workspaces.Writer IDE.Statusbar IDE.Pane.Workspace IDE.PaneGroups IDE.Utils.ServerConnection IDE.BufferMode IDE.Build+ IDE.Command.VCS IDE.Command.VCS.Common IDE.Command.VCS.SVN IDE.Command.VCS.GIT IDE.Command.VCS.Mercurial+ IDE.Command.VCS.Common.Workspaces+ IDE.Command.VCS.Common.GUI+ IDE.Command.VCS.Common.Helper+ IDE.Command.VCS.Types+ IDE.Command.Print+ IDE.Pane.WebKit.Documentation+ IDE.Pane.WebKit.Output+ IDE.TextEditor.Class+ IDE.TextEditor.CodeMirror+ IDE.TextEditor.Yi+ IDE.TextEditor.GtkSourceView+ IDE.Utils.ExternalTool - if (impl(ghc > 7))- other-modules:- Distribution.PackageDescription.PrettyPrintCopied- Distribution.PackageDescription.ParseCopied+ other-modules:+ Distribution.PackageDescription.PrettyPrintCopied+ Distribution.PackageDescription.ParseCopied if (impl(ghc >= 7.2)) binary-shared >=0.8.2@@ -155,68 +296,73 @@ ghc-prof-options: -auto-all -prof ghc-shared-options: -auto-all- ghc-options: -fwarn-missing-fields -fwarn-incomplete-patterns -ferror-spans+ ghc-options: -O2 -fwarn-missing-fields -fwarn-incomplete-patterns -ferror-spans Executable leksah if os(windows)- build-depends: Win32 >=2.2.0.0 && <2.3+ build-depends: Win32 >=2.2.0.0 && <2.4 extra-libraries: kernel32--- extra-lib-dirs: C:/cygwin/lib/w32api- includes: windows.h--- include-dirs: C:/cygwin/usr/include/w32api- else- build-depends: unix >=2.3.1.0 && <2.6 - if os(osx)- build-depends: gtk-mac-integration >= 0.0.0.2 && <0.2- if flag(yi) cpp-options: -DLEKSAH_WITH_YI if flag(yi) && flag(dyre) cpp-options: -DLEKSAH_WITH_DYRE - if impl(ghc < 7.0) && flag(yi)- build-depends: yi >=0.6.1 && <0.7-- if impl(ghc < 7.0) && flag(yi) && flag(dyre)- build-depends: dyre >= 0.8.3 && <0.9- if flag(threaded) ghc-options: -threaded - if impl(ghc < 7.0)- hs-source-dirs: src, main- build-depends: Cabal >=1.6.0.1 && <1.15, base >=4.0.0.0 && <4.6, binary >=0.5.0.0 && <0.6,- bytestring >=0.9.0.1 && <0.10, containers >=0.2.0.0 && <0.5, directory >=1.0.0.2 && <3.1,- filepath >=1.1.0.1 && <1.4, glib >=0.10 && <0.13, gtk >=0.10 && <0.13,- gtksourceview2 >=0.10.0 && <0.13, mtl >=1.1.0.2 && <2.2, old-time >=1.0.0.1 && <1.2,- parsec >=2.1.0.1 && <3.2, pretty >=1.0.1.0 && <1.2,- regex-tdfa ==1.1.*, regex-base ==0.93.*, utf8-string >=0.3.1.1 && <0.4, array >=0.2.0.0 && <0.5,- time >=0.1 && <1.5, ltk >=0.12.1.0 && <0.13, binary-shared >= 0.8 && <0.9, deepseq >= 1.1.0.0 && <1.4,- hslogger >= 1.0.7 && <1.2, leksah-server >=0.12.1.2 && <0.13, network >= 2.2 && <3.0,- ghc >=6.10.1 && <7.5, strict >= 0.3.2 && <0.4, enumerator >=0.4.14 && <0.5, text >= 0.11.1.5 && < 0.12,- gio >=0.12.2 && <0.13, transformers >=0.2.2.0 && <0.4,- QuickCheck >=2.4.2 && <2.5- else- hs-source-dirs: main- build-depends: leksah ==0.12.1.3, base >=4.0.0.0 && <= 5+ hs-source-dirs: main+ build-depends: leksah == 0.13.3.0, base >= 4.0.0.0 && <=4.8, gtk3 -any+ if os(linux) && flag(loc)+ cpp-options: -DLOCALIZATION+ build-depends: hgettext, setlocale + if os(osx)+ ghc-options: -optl-headerpad_max_install_names+ default-language: Haskell98 main-is: Main.hs buildable: True ghc-prof-options: -auto-all -prof ghc-shared-options: -auto-all- ghc-options: -fwarn-missing-fields -fwarn-incomplete-patterns -ferror-spans+ ghc-options: -rtsopts -O2 -fwarn-missing-fields -fwarn-incomplete-patterns -ferror-spans +executable bewleksah+ if !flag(webkit)+ buildable: False+ else+ build-depends: leksah ==0.13.3.0, base >=4.0.0.0 && <=4.8,+ jsaddle -any, ghcjs-dom -any+ if flag(gtk3)+ build-depends: gtk3 >=0.12.4 && <0.13, gtksourceview3 >=0.10.0 && <0.13,+ webkitgtk3 -any, webkitgtk3-javascriptcore -any+ cpp-options: -DMIN_VERSION_gtk=MIN_VERSION_gtk3+ else+ build-depends: gtk >=0.12.4 && <0.13, gtksourceview2 >=0.10.0 && <0.13,+ webkit -any, webkit-javascriptcore -any++ main-is: Main.hs+ buildable: True+ default-language: Haskell2010+ hs-source-dirs: bew+ test-suite tests+ build-depends: base >=4.0.0.0 && <4.8, Cabal >=1.6.0.1 && <1.19,+ QuickCheck >=2.4.2 && <2.7, leksah ==0.13.3.0,+ containers, ltk, leksah-server, hslogger,+ transformers, glib, monad-loops+ if flag(gtk3)+ build-depends: gtk3 >=0.12.4 && <0.13, gtksourceview3 >=0.10.0 && <0.13, webkitgtk3 -any+ cpp-options: -DMIN_VERSION_gtk=MIN_VERSION_gtk3+ else+ build-depends: gtk >=0.12.4 && <0.13, gtksourceview2 >=0.10.0 && <0.13, webkit -any+ if flag(yi)+ build-depends: yi >=0.6.6.1 && <0.7+ type: exitcode-stdio-1.0+ main-is: Tests.hs+ other-modules: IDE.TextEditor.Tests+ buildable: True default-language: Haskell2010- type: exitcode-stdio-1.0 hs-source-dirs: tests- main-is: Tests.hs- build-depends: base >= 4.0.0.0 && <4.6, Cabal >=1.6.0.1 && <1.15, QuickCheck >=2.4.2 && <2.5,- leksah ==0.12.1.3----+ ghc-options: -threaded
@@ -0,0 +1,11 @@+[Desktop Entry]+Encoding=UTF-8+Name=Leksah+GenericName=Haskell IDE+Comment=The Haskell development environment+Exec=leksah %F+Icon=leksah+Type=Application+Categories=GNOME;GTK;Development;+MimeType=text/x-haskell;text/x-literate-haskell;application/leksah-session;application/leksah-workspace;+
@@ -0,0 +1,45 @@+<?xml version="1.0" encoding="utf-8"?>+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">+<mime-type type="application/leksah-session">+<comment>leksah session file</comment>+<glob pattern="*.lkshs"/>+</mime-type>++<mime-type type="application/leksah-workspace">+<comment>leksah workspace file</comment>+<glob pattern="*.lkshw"/>+<generic-icon name="application-x-leksah"/>+</mime-type>++<mime-type type="text/leksah-preferences">+<comment>leksah preferences file</comment>+<glob pattern="*.lkshp"/>+</mime-type>++<mime-type type="text/leksah-candy">+<comment>leksah candy file</comment>+<glob pattern="*.lkshc"/>+</mime-type>++<mime-type type="text/leksah-keymap">+<comment>leksah keymap file</comment>+<glob pattern="*.lkshk"/>+</mime-type>++<mime-type type="x-contents/leksah-metadata">+<comment>leksah metadata file</comment>+<glob pattern="*.lkshm"/>+</mime-type>++<mime-type type="text/leksah-metadata-path">+<comment>leksah metadata file</comment>+<glob pattern="*.lkshp"/>++</mime-type>++<mime-type type="x-contents/leksah-metadata-ws">+<comment>leksah workspace metadata file</comment>+<glob pattern="*.lkshe"/>+</mime-type>++</mime-info>
binary file changed (absent → 3593 bytes)
@@ -0,0 +1,137 @@+%global pkg_name binary-shared++%bcond_without doc+%bcond_without prof+%bcond_without shared++# ghc does not emit debug information+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 0.8+Release: 1%{?dist}+Summary: Haskell binary manipulation shared files++Group: System Environment/Libraries+License: BSD+URL: http://hackage.haskell.org/package/%{pkg_name}-%{version}+Source0: %{pkg_name}-%{version}.tar.gz+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros+%if %{with doc}+BuildRequires: ghc-doc+%endif+%if %{with prof}+BuildRequires: ghc-prof+%endif++%description+Haskell %{pkg_name} library for ghc-%{ghc_version}.++%package devel+Summary: Haskell bytestring implementation+Group: Development/Libraries+Requires: ghc = %{ghc_version}, ghc-binary-devel >= 0.5.0.2+Requires(post): ghc = %{ghc_version}+Requires(postun): ghc = %{ghc_version}++%description devel+ghc-binary-shared library++This package contains the development files for %{name}+built for ghc-%{ghc_version}.+++%if %{with doc}+%package doc+Summary: Documentation for %{name}+Group: Development/Libraries+Requires: ghc-doc = %{ghc_version}+Requires(post): ghc-doc = %{ghc_version}+Requires(postun): ghc-doc = %{ghc_version}++%description doc+This package contains development documentation files+for the %{name} library.+%endif+++%if %{with prof}+%package prof+Summary: Profiling libraries for %{name}+Group: Development/Libraries+Requires: %{name}-devel = %{version}-%{release}+Requires: ghc-prof = %{ghc_version}++%description prof+This package contains profiling libraries for %{name}+built for ghc-%{ghc_version}.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc %{?with_prof:-p}+%cabal build+%ghc_gen_scripts+%if %{with doc}+%cabal haddock+%endif+++%install+%cabal_install+%ghc_install_scripts+%ghc_gen_filelists %{name}+++%clean+rm -rf $RPM_BUILD_ROOT+++%post devel+%ghc_register_pkg+++%if %{with doc}+%post doc+%ghc_reindex_haddock+%endif+++%if %{with doc}+%postun doc+if [ "$1" -eq 0 ] ; then+ %ghc_reindex_haddock+fi+%endif+++%preun devel+if [ "$1" -eq 0 ] ; then+ %ghc_unregister_pkg+fi++%files devel -f %{name}-devel.files+%defattr(-,root,root,-)+%{_docdir}/%{name}-%{version}++%if %{with doc}+%files doc -f %{name}-doc.files+%defattr(-,root,root,-)+%endif++%if %{with prof}+%files prof -f %{name}-prof.files+%defattr(-,root,root,-)+%endif+++%changelog+* Wed Dec 23 2009 Lakshmi Narasimhan <lakshminaras202@gmail.com> - 1.0.7+- Initial version for Fedora 12+
@@ -0,0 +1,137 @@+%global pkg_name deepseq++%bcond_without doc+%bcond_without prof+%bcond_without shared++# ghc does not emit debug information+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 1.1.0.0+Release: 1%{?dist}+Summary: Haskell deepseq++Group: System Environment/Libraries+License: BSD+URL: http://hackage.haskell.org/package/%{pkg_name}-%{version}+Source0: %{pkg_name}-%{version}.tar.gz+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros+%if %{with doc}+BuildRequires: ghc-doc+%endif+%if %{with prof}+BuildRequires: ghc-prof+%endif++%description+Haskell %{pkg_name} library for ghc-%{ghc_version}.++%package devel+Summary: Haskell deepseq implementation+Group: Development/Libraries+Requires: ghc = %{ghc_version}+Requires(post): ghc = %{ghc_version}+Requires(postun): ghc = %{ghc_version}++%description devel+ghc-deepseq library++This package contains the development files for %{name}+built for ghc-%{ghc_version}.+++%if %{with doc}+%package doc+Summary: Documentation for %{name}+Group: Development/Libraries+Requires: ghc-doc = %{ghc_version}+Requires(post): ghc-doc = %{ghc_version}+Requires(postun): ghc-doc = %{ghc_version}++%description doc+This package contains development documentation files+for the %{name} library.+%endif+++%if %{with prof}+%package prof+Summary: Profiling libraries for %{name}+Group: Development/Libraries+Requires: %{name}-devel = %{version}-%{release}+Requires: ghc-prof = %{ghc_version}++%description prof+This package contains profiling libraries for %{name}+built for ghc-%{ghc_version}.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc %{?with_prof:-p}+%cabal build+%ghc_gen_scripts+%if %{with doc}+%cabal haddock+%endif+++%install+%cabal_install+%ghc_install_scripts+%ghc_gen_filelists %{name}+++%clean+rm -rf $RPM_BUILD_ROOT+++%post devel+%ghc_register_pkg+++%if %{with doc}+%post doc+%ghc_reindex_haddock+%endif+++%if %{with doc}+%postun doc+if [ "$1" -eq 0 ] ; then+ %ghc_reindex_haddock+fi+%endif+++%preun devel+if [ "$1" -eq 0 ] ; then+ %ghc_unregister_pkg+fi++%files devel -f %{name}-devel.files+%defattr(-,root,root,-)+%{_docdir}/%{name}-%{version}++%if %{with doc}+%files doc -f %{name}-doc.files+%defattr(-,root,root,-)+%endif++%if %{with prof}+%files prof -f %{name}-prof.files+%defattr(-,root,root,-)+%endif+++%changelog+* Wed Dec 23 2009 Lakshmi Narasimhan <lakshminaras202@gmail.com> - 1.0.7+- Initial version for Fedora 12+
@@ -0,0 +1,136 @@+%global pkg_name hslogger++%bcond_without doc+%bcond_without prof+%bcond_without shared++# ghc does not emit debug information+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 1.0.10+Release: 1%{?dist}+Summary: Haskell logger implementation++Group: System Environment/Libraries+License: LGPL+URL: http://hackage.haskell.org/package/%{pkg_name}-%{version}+Source0: %{pkg_name}-%{version}.tar.gz+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros+%if %{with doc}+BuildRequires: ghc-doc+%endif+%if %{with prof}+BuildRequires: ghc-prof+%endif++%description+Haskell %{pkg_name} library for ghc-%{ghc_version}.++%package devel+Summary: Haskell hslogger implementation+Group: Development/Libraries+Requires: ghc = %{ghc_version}, ghc-network-devel >= 2.2.1.4+Requires(post): ghc = %{ghc_version}+Requires(postun): ghc = %{ghc_version}++%description devel+ghc-hslogger library++This package contains the development files for %{name}+built for ghc-%{ghc_version}.+++%if %{with doc}+%package doc+Summary: Documentation for %{name}+Group: Development/Libraries+Requires: ghc-doc = %{ghc_version}+Requires(post): ghc-doc = %{ghc_version}+Requires(postun): ghc-doc = %{ghc_version}++%description doc+This package contains development documentation files+for the %{name} library.+%endif+++%if %{with prof}+%package prof+Summary: Profiling libraries for %{name}+Group: Development/Libraries+Requires: %{name}-devel = %{version}-%{release}+Requires: ghc-prof = %{ghc_version}++%description prof+This package contains profiling libraries for %{name}+built for ghc-%{ghc_version}.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc %{?with_prof:-p}+%cabal build+%ghc_gen_scripts+%if %{with doc}+%cabal haddock+%endif+++%install+%cabal_install+%ghc_install_scripts+%ghc_gen_filelists %{name}+++%clean+rm -rf $RPM_BUILD_ROOT+++%post devel+%ghc_register_pkg+++%if %{with doc}+%post doc+%ghc_reindex_haddock+%endif+++%if %{with doc}+%postun doc+if [ "$1" -eq 0 ] ; then+ %ghc_reindex_haddock+fi+%endif+++%preun devel+if [ "$1" -eq 0 ] ; then+ %ghc_unregister_pkg+fi++%files devel -f %{name}-devel.files+%defattr(-,root,root,-)+%{_docdir}/%{name}-%{version}++%if %{with doc}+%files doc -f %{name}-doc.files+%defattr(-,root,root,-)+%endif++%if %{with prof}+%files prof -f %{name}-prof.files+%defattr(-,root,root,-)+%endif+++%changelog+* Wed Dec 23 2009 Lakshmi Narasimhan <lakshminaras202@gmail.com> - 1.0.7+- Initial version for Fedora 12
@@ -0,0 +1,137 @@+%global pkg_name ltk++%bcond_without doc+%bcond_without prof+%bcond_without shared++# ghc does not emit debug information+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 0.8+Release: 1%{?dist}+Summary: UI Framework used by leksah++Group: System Environment/Libraries+License: GPL+URL: http://hackage.haskell.org/package/%{pkg_name}-%{version}+Source0: %{pkg_name}-%{version}.tar.gz+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros+%if %{with doc}+BuildRequires: ghc-doc+%endif+%if %{with prof}+BuildRequires: ghc-prof+%endif ++%description+UI Framework used by leksah++%package devel+Summary: Haskell ltk implementation+Group: Development/Libraries+Requires: ghc = %{ghc_version}, ghc-glib-devel >= 0.10.1, ghc-gtk-devel >= 0.10.1+Requires(post): ghc = %{ghc_version}+Requires(postun): ghc = %{ghc_version}++%description devel+ghc-ltk library++This package contains the development files for %{name}+built for ghc-%{ghc_version}.+++%if %{with doc}+%package doc+Summary: Documentation for %{name}+Group: Development/Libraries+Requires: ghc-doc = %{ghc_version}+Requires(post): ghc-doc = %{ghc_version}+Requires(postun): ghc-doc = %{ghc_version}++%description doc+This package contains development documentation files+for the %{name} library.+%endif+++%if %{with prof}+%package prof+Summary: Profiling libraries for %{name}+Group: Development/Libraries+Requires: %{name}-devel = %{version}-%{release}+Requires: ghc-prof = %{ghc_version}++%description prof+This package contains profiling libraries for %{name}+built for ghc-%{ghc_version}.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc %{?with_prof:-p}+%cabal build+%ghc_gen_scripts+%if %{with doc}+%cabal haddock+%endif+++%install+%cabal_install+%ghc_install_scripts+%ghc_gen_filelists %{name}+++%clean+rm -rf $RPM_BUILD_ROOT+++%post devel+%ghc_register_pkg+++%if %{with doc}+%post doc+%ghc_reindex_haddock+%endif+++%if %{with doc}+%postun doc+if [ "$1" -eq 0 ] ; then+ %ghc_reindex_haddock+fi+%endif+++%preun devel+if [ "$1" -eq 0 ] ; then+ %ghc_unregister_pkg+fi++%files devel -f %{name}-devel.files+%defattr(-,root,root,-)+%{_docdir}/%{name}-%{version}++%if %{with doc}+%files doc -f %{name}-doc.files+%defattr(-,root,root,-)+%endif++%if %{with prof}+%files prof -f %{name}-prof.files+%defattr(-,root,root,-)+%endif+++%changelog+* Wed Dec 23 2009 Lakshmi Narasimhan <lakshminaras202@gmail.com> - 1.0.7+- Initial version for Fedora 12+
@@ -0,0 +1,137 @@+%global pkg_name process-leksah++%bcond_without doc+%bcond_without prof+%bcond_without shared++# ghc does not emit debug information+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 1.0.1.3+Release: 1%{?dist}+Summary: Leksah process manager++Group: System Environment/Libraries+License: BSD+URL: http://hackage.haskell.org/package/%{pkg_name}-%{version}+Source0: %{pkg_name}-%{version}.tar.gz+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros+%if %{with doc}+BuildRequires: ghc-doc+%endif+%if %{with prof}+BuildRequires: ghc-prof+%endif++%description+Haskell %{pkg_name} library for ghc-%{ghc_version}.++%package devel+Summary: Leksah process manager+Group: Development/Libraries+Requires: ghc = %{ghc_version}+Requires(post): ghc = %{ghc_version}+Requires(postun): ghc = %{ghc_version}++%description devel+Leksah process manager library++This package contains the development files for %{name}+built for ghc-%{ghc_version}.+++%if %{with doc}+%package doc+Summary: Documentation for %{name}+Group: Development/Libraries+Requires: ghc-doc = %{ghc_version}+Requires(post): ghc-doc = %{ghc_version}+Requires(postun): ghc-doc = %{ghc_version}++%description doc+This package contains development documentation files+for the %{name} library.+%endif+++%if %{with prof}+%package prof+Summary: Profiling libraries for %{name}+Group: Development/Libraries+Requires: %{name}-devel = %{version}-%{release}+Requires: ghc-prof = %{ghc_version}++%description prof+This package contains profiling libraries for %{name}+built for ghc-%{ghc_version}.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc %{?with_prof:-p}+%cabal build+%ghc_gen_scripts+%if %{with doc}+%cabal haddock+%endif+++%install+%cabal_install+%ghc_install_scripts+%ghc_gen_filelists %{name}+++%clean+rm -rf $RPM_BUILD_ROOT+++%post devel+%ghc_register_pkg+++%if %{with doc}+%post doc+%ghc_reindex_haddock+%endif+++%if %{with doc}+%postun doc+if [ "$1" -eq 0 ] ; then+ %ghc_reindex_haddock+fi+%endif+++%preun devel+if [ "$1" -eq 0 ] ; then+ %ghc_unregister_pkg+fi++%files devel -f %{name}-devel.files+%defattr(-,root,root,-)+%{_docdir}/%{name}-%{version}++%if %{with doc}+%files doc -f %{name}-doc.files+%defattr(-,root,root,-)+%endif++%if %{with prof}+%files prof -f %{name}-prof.files+%defattr(-,root,root,-)+%endif+++%changelog+* Sat May 08 2010 Lakshmi Narasimhan <lakshminaras202@gmail.com> - 1.0.1.3+- Initial version for Fedora 12+
@@ -0,0 +1,136 @@+%global pkg_name regex-base++%bcond_without doc+%bcond_without prof+%bcond_without shared++# ghc does not emit debug information+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 0.93.1+Release: 1%{?dist}+Summary: Haskell regex implementation++Group: System Environment/Libraries+License: BSD+URL: http://hackage.haskell.org/package/%{pkg_name}-%{version}+Source0: %{pkg_name}-%{version}.tar.gz+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros+%if %{with doc}+BuildRequires: ghc-doc+%endif+%if %{with prof}+BuildRequires: ghc-prof+%endif++%description+Haskell %{pkg_name} library for ghc-%{ghc_version}.++%package devel+Summary: Haskell regext-base implementation+Group: Development/Libraries+Requires: ghc = %{ghc_version}+Requires(post): ghc = %{ghc_version}+Requires(postun): ghc = %{ghc_version}++%description devel+ghc-regex-base library++This package contains the development files for %{name}+built for ghc-%{ghc_version}.+++%if %{with doc}+%package doc+Summary: Documentation for %{name}+Group: Development/Libraries+Requires: ghc-doc = %{ghc_version}+Requires(post): ghc-doc = %{ghc_version}+Requires(postun): ghc-doc = %{ghc_version}++%description doc+This package contains development documentation files+for the %{name} library.+%endif+++%if %{with prof}+%package prof+Summary: Profiling libraries for %{name}+Group: Development/Libraries+Requires: %{name}-devel = %{version}-%{release}+Requires: ghc-prof = %{ghc_version}++%description prof+This package contains profiling libraries for %{name}+built for ghc-%{ghc_version}.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc %{?with_prof:-p}+%cabal build+%ghc_gen_scripts+%if %{with doc}+%cabal haddock+%endif+++%install+%cabal_install+%ghc_install_scripts+%ghc_gen_filelists %{name}+++%clean+rm -rf $RPM_BUILD_ROOT+++%post devel+%ghc_register_pkg+++%if %{with doc}+%post doc+%ghc_reindex_haddock+%endif+++%if %{with doc}+%postun doc+if [ "$1" -eq 0 ] ; then+ %ghc_reindex_haddock+fi+%endif+++%preun devel+if [ "$1" -eq 0 ] ; then+ %ghc_unregister_pkg+fi++%files devel -f %{name}-devel.files+%defattr(-,root,root,-)+%{_docdir}/%{name}-%{version}++%if %{with doc}+%files doc -f %{name}-doc.files+%defattr(-,root,root,-)+%endif++%if %{with prof}+%files prof -f %{name}-prof.files+%defattr(-,root,root,-)+%endif+++%changelog+* Wed Dec 23 2009 Lakshmi Narasimhan <lakshminaras202@gmail.com> - 1.0.7+- Initial version for Fedora 12
@@ -0,0 +1,137 @@+%global pkg_name regex-tdfa++%bcond_without doc+%bcond_without prof+%bcond_without shared++# ghc does not emit debug information+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 1.1.2+Release: 1%{?dist}+Summary: Haskell regex-tdfa implementation++Group: System Environment/Libraries+License: BSD+URL: http://hackage.haskell.org/package/%{pkg_name}-%{version}+Source0: %{pkg_name}-%{version}.tar.gz+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros, ghc-regex-base-devel, ghc-regex-base-prof+%if %{with doc}+BuildRequires: ghc-doc+%endif+%if %{with prof}+BuildRequires: ghc-prof+%endif++%description+Haskell %{pkg_name} library for ghc-%{ghc_version}.++%package devel+Summary: Haskell regext-tdfa implementation+Group: Development/Libraries+Requires: ghc = %{ghc_version}+Requires(post): ghc = %{ghc_version}+Requires(postun): ghc = %{ghc_version}++%description devel+ghc-regex-tdfa library++This package contains the development files for %{name}+built for ghc-%{ghc_version}.+++%if %{with doc}+%package doc+Summary: Documentation for %{name}+Group: Development/Libraries+Requires: ghc-doc = %{ghc_version}+Requires(post): ghc-doc = %{ghc_version}+Requires(postun): ghc-doc = %{ghc_version}++%description doc+This package contains development documentation files+for the %{name} library.+%endif+++%if %{with prof}+%package prof+Summary: Profiling libraries for %{name}+Group: Development/Libraries+Requires: %{name}-devel = %{version}-%{release}+Requires: ghc-prof = %{ghc_version}++%description prof+This package contains profiling libraries for %{name}+built for ghc-%{ghc_version}.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc %{?with_prof:-p}+%cabal build+%ghc_gen_scripts+%if %{with doc}+%cabal haddock+%endif+++%install+%cabal_install+%ghc_install_scripts+%ghc_gen_filelists %{name}+++%clean+rm -rf $RPM_BUILD_ROOT+++%post devel+%ghc_register_pkg+++%if %{with doc}+%post doc+%ghc_reindex_haddock+%endif+++%if %{with doc}+%postun doc+if [ "$1" -eq 0 ] ; then+ %ghc_reindex_haddock+fi+%endif+++%preun devel+if [ "$1" -eq 0 ] ; then+ %ghc_unregister_pkg+fi++%files devel -f %{name}-devel.files+%defattr(-,root,root,-)+%{_docdir}/%{name}-%{version}++%if %{with doc}+%files doc -f %{name}-doc.files+%defattr(-,root,root,-)+%endif++%if %{with prof}+%files prof -f %{name}-prof.files+%defattr(-,root,root,-)+%endif+++%changelog+* Wed Dec 23 2009 Lakshmi Narasimhan <lakshminaras202@gmail.com> - 1.0.7+- Initial version for Fedora 12+
@@ -0,0 +1,118 @@+%global pkg_name leksah++%bcond_without doc+%bcond_without prof++# ghc does not emit debug information+%global debug_package %{nil}++Name: %{pkg_name}+Version: 0.8.0.6+Release: 1%{?dist}+Summary: Haskell IDE++Group: System Environment/Languages+License: GPL+URL: http://code.haskell.org/leksah/+Source0: %{pkg_name}-%{version}.tar.gz+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc >= 6.10.1, ghc-rpm-macros >= 0.2.5, ghc-gtk2hs-compat >= 0.10.1, ghc-utf8-string-devel >= 0.3.1.1, ghc-haskell-platform-devel,ghc-gtksourceview2-devel,ghc-gtk-devel,ghc-glib-devel, ghc-binary-shared-devel, haddock-leksah, leksah-server == 0.8.0.6, leksah-server-devel == 0.8.0.6, ghc-regex-tdfa-devel >= 1.1.0, ghc-regex-base-devel >= 0.93+%if %{with doc}+BuildRequires: ghc-doc+%endif+%if %{with prof}+BuildRequires: ghc-prof+%endif+Requires: atk, glibc, cairo, fontconfig, freetype, gtk2, glib2, gmp, gtksourceview2, pango, leksah-server == 0.8.0.6++%description+Haskell IDE++%if %{with doc}+%package doc+Summary: Documentation for %{name}+Group: Development/Libraries+Requires: ghc-doc = %{ghc_version}+Requires(post): ghc-doc = %{ghc_version}+Requires(postun): ghc-doc = %{ghc_version}++%description doc+This package contains development documentation files+for the %{name} library.+%endif+++%if %{with prof}+%package prof+Summary: Profiling libraries for %{name}+Group: Development/Libraries+Requires: %{name}-devel = %{version}-%{release}+Requires: ghc-prof = %{ghc_version}++%description prof+This package contains profiling libraries for %{name}+built for ghc-%{ghc_version}.+%endif++%prep+%setup -q+%cabal_configure+++%build+%cabal_configure --ghc %{?with_prof:-p}+%cabal build+%if %{with doc}+%cabal haddock+%endif++%install+%cabal_install+mkdir $RPM_BUILD_ROOT/usr/share/applications+cp linux/applications/leksah.desktop $RPM_BUILD_ROOT/usr/share/applications+mkdir -p $RPM_BUILD_ROOT/usr/share/icons/hicolor/48x48/apps+cp linux/icons/hicolor/48x48/apps/leksah_48x48.png $RPM_BUILD_ROOT/usr/share/icons/hicolor/48x48/apps++%clean+rm -rf $RPM_BUILD_ROOT++%post+gtk-update-icon-cache++%postun+gtk-update-icon-cache++%if %{with doc}+%post doc+%ghc_reindex_haddock+%endif+++%if %{with doc}+%postun doc+if [ "$1" -eq 0 ] ; then+ %ghc_reindex_haddock+fi+%endif++%files+%defattr(-,root,root,-)+%doc LICENSE+%attr(755,root,root) %{_bindir}/%{name}+%attr(755,root,root) %{_datadir}/%{pkg_name}-%{version}+%attr(644,root,root) /usr/share/applications/%{pkg_name}.desktop+%attr(644,root,root) /usr/share/icons/hicolor/48x48/apps/leksah_48x48.png++%changelog+* Fri May 28 2010 <lakshminaras2002@gmail.com>+- Upgrade to leksah 0.8.0.6++* Fri Apr 09 2010 <lakshminaras2002@gmail.com>+- Updated to 0.8.0.4+- Modified dependencies to accommodate split of leksah-server+- Added macros for prof and doc rpms+- Currently no prof or doc files are generated ++* Mon Feb 08 2010 <lakshminaras2002@gmail.com>+- Initial Version for Fedora 12
@@ -0,0 +1,145 @@+%global pkg_name leksah-server++%bcond_without doc+%bcond_without prof+%bcond_without shared++# ghc does not emit debug information+%global debug_package %{nil}++Name: %{pkg_name}+Version: 0.8.0.6+Release: 1%{?dist}+Summary: Haskell IDE++Group: System Development/IDE+License: GPL+URL: http://code.haskell.org/leksah/leksah-server+Source0: %{pkg_name}-%{version}.tar.gz+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc = %{ghc_version}, ghc-rpm-macros >= 0.2.5, ghc-gtk2hs-compat >= 0.10.1+%if %{with doc}+BuildRequires: ghc-doc+%endif+%if %{with prof}+BuildRequires: ghc-prof+%endif+Requires: atk, glibc, cairo, fontconfig, freetype, gtk2, glib2, gmp, gtksourceview2, pango, bash, ghc, cabal-install++%description+Haskell IDE++%package devel+Summary: Haskell IDE leksah-server development files+Group: Development/Libraries+BuildRequires: ghc = %{ghc_version}, ghc-rpm-macros >= 0.2.5, ghc-utf8-string-devel >= 0.3.1.1, ghc-haskell-platform-devel,ghc-gtksourceview2-devel,ghc-gtk-devel,ghc-glib-devel, ghc-deepseq-devel, ghc-deepseq-prof, ghc-hslogger-devel >= 1.0.10, ghc-ltk-devel >= 0.8, ghc-network-devel >= 2.2.1.4, ghc-binary-devel >= 0.5.0.2, ghc-binary-shared-devel >= 0.8, haddock-leksah >= 2.5.0, ghc-process-leksah-devel >= 1.0.1.3, ghc-hslogger-prof >= 1.0.10, ghc-process-leksah-prof >= 1.0.1.3, ghc-ltk-prof >= 0.8, ghc-binary-shared-prof >= 0.8, ghc-network-prof >= 2.2.1.4, ghc-binary-prof >= 0.5.0.2+Requires: ghc = %{ghc_version}, ghc-hslogger-devel >= 1.0.10, ghc-ltk-devel >= 0.8, ghc-network-devel >= 2.2.1.4, ghc-binary-devel >= 0.5.0.2, ghc-binary-shared-devel >= 0.8, ghc-deepseq-devel >= 1.1.0.0, haddock-leksah >= 2.5.0, cabal-install, ghc-process-leksah-devel >= 1.0.1.3+Requires(post): ghc = %{ghc_version}+Requires(postun): ghc = %{ghc_version}++%description devel+This package contains development files for leksah-server++%if %{with doc}+%package doc+Summary: Documentation for %{name}+Group: Development/Libraries+Requires: ghc-doc = %{ghc_version}+Requires(post): ghc-doc = %{ghc_version}+Requires(postun): ghc-doc = %{ghc_version}++%description doc+This package contains development documentation files+for the %{name} library.+%endif+++%if %{with prof}+%package prof+Summary: Profiling libraries for %{name}+Group: Development/Libraries+Requires: %{name}-devel = %{version}-%{release}+Requires: ghc-prof = %{ghc_version}++%description prof+This package contains profiling libraries for %{name}+built for ghc-%{ghc_version}.+%endif++%prep+%setup -q+%cabal_configure --ghc %{?with_prof:-p}+++%build+%cabal build+%ghc_gen_scripts+%if %{with doc}+%cabal haddock+%endif++%install+%cabal_install+%ghc_install_scripts+%ghc_gen_filelists %{name}++%clean+rm -rf $RPM_BUILD_ROOT++%post devel+%ghc_register_pkg ++%preun devel+if [ "$1" -eq 0 ] ; then+ %ghc_unregister_pkg+fi++%if %{with doc}+%post doc+%ghc_reindex_haddock+%endif+++%if %{with doc}+%postun doc+if [ "$1" -eq 0 ] ; then+ %ghc_reindex_haddock+fi+%endif++%files+%defattr(-,root,root,-)+%doc LICENSE+%attr(755,root,root) %{_bindir}/%{name}+%attr(755,root,root) %{_bindir}/leksahecho+%attr(755,root,root) %{_datadir}/%{pkg_name}-%{version}++%files devel -f %{name}-devel.files+%attr(755,root,root) %{_libdir}/ghc-%{ghc_version}/leksah-server-%{version}+%attr(755,root,root) %{_docdir}/ghc/libraries/leksah-server++%if %{with doc}+%files doc -f %{name}-doc.files+%defattr(-,root,root,-)+%endif++%if %{with prof}+%files prof -f %{name}-prof.files+%defattr(-,root,root,-)+%endif++%changelog+* Fri Apr 09 2010 <lakshminaras2002@gmail.com>+- Split leksah server into two rpms. The base rpm contains only+- the leskah-server, leksahecho binaries. The devel rpm contains+- the pa files. The installation of this rpm will require the +- other dependencies used in %ghc_register_pkg. This leads to +- smaller rpm size for users who only need leskah for their +- development work.+- Added ghc-process-leksah dependency.Fixed profiling requirements+- for building the rpm+- Added if macros for doc and prof rpms++* Mon Feb 08 2010 <lakshminaras2002@gmail.com>+- Initial Version for Fedora 12
@@ -0,0 +1,68 @@+%global pkg_name binary-shared++%global common_summary Haskell %{pkg_name} library++%global common_description A %{pkg_name} library for Haskell.++# add any Haskell library dependencies here:+%global ghc_pkg_deps ghc-binary-devel++%bcond_without shared++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 0.8+Release: 1%{?dist}+Summary: %{common_summary}++Group: System Environment/Libraries+License: GPL +URL: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/%{pkg_name}+Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros >= 0.5.1+BuildRequires: ghc-doc+BuildRequires: ghc-prof+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}+%{?ghc_pkg_c_deps:BuildRequires: %{ghc_pkg_c_deps}}++%description+%{common_description}+%if %{with shared}+#This package provides the shared library.+%endif+++%{?ghc_lib_package}+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc -p+%cabal build+%cabal haddock+++%install+%cabal_install+%cabal_pkg_conf++%ghc_gen_filelists++%files+%doc LICENSE++%clean+rm -rf $RPM_BUILD_ROOT+++%changelog+* Wed May 19 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 0.8-0+- initial packaging for Fedora automatically generated by cabal2spec-0.21.3
@@ -0,0 +1,62 @@+%global pkg_name hslogger++%global common_summary Haskell %{pkg_name} library++%global common_description A logging framework for Haskell++%global ghc_pkg_deps ghc-mtl-devel,ghc-network-devel++%bcond_without shared++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 1.0.10+Release: 1%{?dist}+Summary: %{common_summary}++Group: System Environment/Libraries+License: LGPL+URL: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/%{pkg_name}+Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros >= 0.5.1+BuildRequires: ghc-doc+BuildRequires: ghc-prof+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}++%description+%{common_description}+%if %{with shared}+This package provides the shared library.+%endif++%ghc_lib_package+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc -p+%cabal build+%cabal haddock+++%install+%cabal_install+%cabal_pkg_conf++%ghc_gen_filelists+++%clean+rm -rf $RPM_BUILD_ROOT+++%changelog+* Tue May 25 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 1.0.10-1+- initial packaging for Fedora automatically generated by cabal2spec-0.21.3
@@ -0,0 +1,70 @@+%global pkg_name ltk++%global common_summary Haskell %{pkg_name} library++%global common_description UI Framework used by leksah++# add any Haskell library dependencies here:+%global ghc_pkg_deps ghc-mtl-devel,ghc-parsec-devel,ghc-glib-devel,ghc-gtk-devel+++%bcond_without shared++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 0.8.0.6+Release: 1%{?dist}+Summary: %{common_summary}++Group: System Environment/Libraries+License: GPL+URL: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/%{pkg_name}+Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros >= 0.5.1+BuildRequires: ghc-doc+BuildRequires: ghc-prof+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}+%{?ghc_pkg_c_deps:BuildRequires: %{ghc_pkg_c_deps}}++%description+%{common_description}+%if %{with shared}+This package provides the shared library.+%endif+++%ghc_lib_package+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc -p+%cabal build+%cabal haddock+++%install+rm -rf $RPM_BUILD_ROOT+%cabal_install+%cabal_pkg_conf++%ghc_gen_filelists++%files+%doc LICENSE++%clean+rm -rf $RPM_BUILD_ROOT+++%changelog+* Wed May 26 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 0.8.0.6-0+- initial packaging for Fedora automatically generated by cabal2spec-0.21.3
@@ -0,0 +1,69 @@+%global pkg_name process-leksah++%global common_summary %{pkg_name} library++%global common_description A %{pkg_name} library for leksah+++%bcond_without shared++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 1.0.1.3+Release: 1%{?dist}+Summary: %{common_summary}++Group: System Environment/Libraries+License: BSD +URL: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/%{pkg_name}+Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros >= 0.5.1+BuildRequires: ghc-doc+BuildRequires: ghc-prof+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}+%{?ghc_pkg_c_deps:BuildRequires: %{ghc_pkg_c_deps}}++%description+This package contains libraries for dealing with system processes. Temporary version for use in leksah until main process library is updated+%if %{with shared}+This package provides the shared library.+%endif+++%ghc_lib_package+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc -p+%cabal build+%cabal haddock+++%install+rm -rf $RPM_BUILD_ROOT+%cabal_install+%cabal_pkg_conf++%ghc_gen_filelists+++%clean+rm -rf $RPM_BUILD_ROOT+++%changelog+* Sat May 29 2010 Lakshmi Narasimhan <lakshminaras2002@gmail.com> - 1.0.1.3-1+- Modified license text+- Added dependencies++* Fri May 28 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 1.0.1.3-0+- initial packaging for Fedora automatically generated by cabal2spec-0.21.3
@@ -0,0 +1,66 @@+%global pkg_name regex-tdfa++%global common_summary Haskell %{pkg_name} library++%global common_description A new all Haskell "tagged" DFA regex engine, inspired by libtre.++%global ghc_pkg_deps ghc-regex-base-devel,ghc-parsec-devel,ghc-mtl-devel++%bcond_without shared++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 1.1.2+Release: 1%{?dist}+Summary: %{common_summary}++Group: System Environment/Libraries+License: BSD+URL: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/%{pkg_name}+Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros >= 0.5.1+BuildRequires: ghc-doc+BuildRequires: ghc-prof+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}+%{?ghc_pkg_c_deps:BuildRequires: %{ghc_pkg_c_deps}}++%description+%{common_description}+%if %{with shared}+This package provides the shared library.+%endif+++%{?ghc_lib_package}+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%cabal_configure --ghc -p+%cabal build+%cabal haddock+++%install+rm -rf $RPM_BUILD_ROOT+%cabal_install+%cabal_pkg_conf++%ghc_gen_filelists+++%clean+rm -rf $RPM_BUILD_ROOT+++%changelog+* Tue May 25 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 1.1.2-1+- initial packaging for Fedora automatically generated by cabal2spec-0.21.3
@@ -0,0 +1,62 @@+%global pkg_name haddock++%global common_summary Haskell %{pkg_name} library++%global common_description A documentation-generation tool for Haskell libraries++%global ghc_pkg_deps ghc-ghc-paths-devel,ghc-ghc-devel++%bcond_with shared++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: %{pkg_name}+Version: 2.7.2+Release: 1%{?dist}+Summary: Haskell %{pkg_name}++Group: System Environment/Libraries+License: BSD3+URL: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/%{name}+Source0: http://hackage.haskell.org/packages/archive/%{name}/%{version}/%{name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros >= 0.5.1+BuildRequires: ghc-doc+BuildRequires: ghc-prof+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}++%description+%{common_description}++%ghc_lib_package++%prep+%setup -q++%build+%cabal_configure --ghc -p+%cabal build+%cabal haddock++%install+%cabal_install+%cabal_pkg_conf+mv $RPM_BUILD_ROOT/%{_bindir}/haddock $RPM_BUILD_ROOT/%{_bindir}/leksah-haddock++%ghc_gen_filelists++%clean+rm -rf $RPM_BUILD_ROOT++%files+%defattr(-,root,root,-)+%doc LICENSE+%attr(755,root,root) %{_bindir}/leksah-haddock+%attr(755,root,root) %{_datadir}/%{name}-%{version}/html++%changelog+* Fri May 28 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 2.7.2-0+- initial packaging for Fedora automatically generated by cabal2spec-0.21.3
@@ -0,0 +1,76 @@+%global pkg_name leksah-server++%global common_summary leksah-server for Leksah IDE++%global common_description %{common_summary}++# add any Haskell library dependencies here:+%global ghc_pkg_deps ghc-haddock-devel,ghc-process-leksah-devel,ghc-hslogger-devel,ghc-ltk-devel,ghc-binary-shared-devel++%bcond_with shared++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: %{pkg_name}+Version: 0.8.0.6+Release: 1%{?dist}+Summary: Haskell %{pkg_name}++Group: System Development/IDE+License: GPL+URL: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/%{name}+Source0: http://hackage.haskell.org/packages/archive/%{name}/%{version}/%{name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-rpm-macros >= 0.5.1+BuildRequires: ghc-doc+BuildRequires: ghc-prof+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}++Requires: atk, glibc, cairo, fontconfig, freetype, gtk2, glib2, gmp, gtksourceview2, pango, bash, ghc, cabal-install+++%description+%{common_description}+++%ghc_lib_package+++%prep+%setup -q+++%build+%cabal_configure --ghc -p+%cabal build+%cabal haddock+++%install+rm -rf $RPM_BUILD_ROOT+%cabal_install+%cabal_pkg_conf++%ghc_gen_filelists++%clean+rm -rf $RPM_BUILD_ROOT+++%files+%defattr(-,root,root,-)+%doc LICENSE+%attr(755,root,root) %{_bindir}/%{name}+%attr(755,root,root) %{_bindir}/leksahecho+%attr(644,root,root) %{_datadir}/%{pkg_name}-%{version}/data/prefscoll.lkshp+++%changelog+* Fri May 28 2010 Lakshmi Narasimhan <lakshminaras2002@gmail.com> - 0.8.0.6-1+- initial version for Fedora 13++* Wed May 26 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 0.8.0.6-0+- initial packaging for Fedora automatically generated by cabal2spec-0.21.3
@@ -0,0 +1,68 @@+%global pkg_name leksah++%bcond_with dynamic++# ghc does not emit debug information+%global debug_package %{nil}++%global ghc_pkg_deps ghc-utf8-string-devel,ghc-gtksourceview2-devel,ghc-gtk-devel,ghc-glib-devel,ghc-binary-shared-devel,ghc-leksah-server-devel,ghc-regex-base-devel,ghc-regex-tdfa-devel++Name: leksah+Version: 0.8.0.6+Release: 1%{?dist}+Summary: Haskell IDE++Group: System Environment/IDE+License: GPL+URL: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/%{name}+Source0: http://hackage.haskell.org/packages/archive/%{name}/%{version}/%{name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires : ghc >= 6.10.1, ghc-rpm-macros >= 0.2.5, ghc-gtk2hs-common >= 0.10.1,leksah-server == 0.8.0.6,haddock+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}++Requires: atk, glibc, cairo, fontconfig, freetype, gtk2, glib2, gmp, gtksourceview2, pango, leksah-server == 0.8.0.6++%description+Leksah is an IDE for Haskell++%prep+%setup -q+++%build+%cabal_configure --ghc+%cabal build+++%install+%cabal_install+mkdir $RPM_BUILD_ROOT/usr/share/applications+cp linux/applications/leksah.desktop $RPM_BUILD_ROOT/usr/share/applications+mkdir -p $RPM_BUILD_ROOT/usr/share/icons/hicolor/48x48/apps+cp linux/icons/hicolor/48x48/apps/leksah_48x48.png $RPM_BUILD_ROOT/usr/share/icons/hicolor/48x48/apps++%clean+rm -rf $RPM_BUILD_ROOT++%post+gtk-update-icon-cache++%postun+gtk-update-icon-cache++%files+%defattr(-,root,root,-)+%doc LICENSE+%attr(755,root,root) %{_bindir}/%{name}+%attr(755,root,root) %{_datadir}/%{pkg_name}-%{version}+%attr(644,root,root) /usr/share/applications/%{pkg_name}.desktop+%attr(644,root,root) /usr/share/icons/hicolor/48x48/apps/leksah_48x48.png+++%changelog+* Fri May 28 2010 Lakshmi Narasimhan <lakshminaras2002@gmail.com> - 0.8.0.6-1+- initial version for Fedora 13++* Wed May 26 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 0.8.0.6-0+- initial packaging for Fedora automatically generated by cabal2spec-0.21.3
@@ -0,0 +1,68 @@+%global pkg_name binary-shared++%global common_summary Haskell library for sharing binary elements++%global common_description This package adds the capability to share elements created by the binary package++%global ghc_pkg_deps ghc-binary-devel ghc-mtl-devel++%bcond_without shared+%bcond_without hscolour++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 0.8.1+Release: 1%{?dist}+Summary: %{common_summary}++Group: System Environment/Libraries+License: GPLv2+URL: http://hackage.haskell.org/package/%{pkg_name}+Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-doc, ghc-prof+BuildRequires: ghc-rpm-macros >= 0.8.1+%if %{with hscolour}+BuildRequires: hscolour+%endif+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}++%description+%{common_description}+%if %{with shared}+This package provides the shared library.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%ghc_lib_build+++%install+rm -rf $RPM_BUILD_ROOT+%ghc_lib_install+++%clean+rm -rf $RPM_BUILD_ROOT+++%{?ghc_lib_package}+++%changelog+* Sun Oct 10 2010 Lakshmi Narasimhan T V <lakshminaras2002@gmail.com> - 0.8.1-1+- Modified description+- Modified license+- Modified dependencies++* Sun Oct 10 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 0.8.1-0+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2
@@ -0,0 +1,68 @@+%global pkg_name haddock++%global common_summary Haskell %{pkg_name} library++%global common_description A documentation-generation tool for Haskell libraries++%global ghc_pkg_deps ghc-ghc-paths-devel,ghc-ghc-devel++%bcond_without shared+%bcond_without hscolour++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: %{pkg_name}+Version: 2.7.2+Release: 1%{?dist}+Summary: %{common_summary}++Group: System Environment/Libraries+License: BSD+URL: http://hackage.haskell.org/package/%{pkg_name}+Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-doc, ghc-prof+BuildRequires: ghc-rpm-macros >= 0.8.1+BuildRequires: alex,happy+%if %{with hscolour}+BuildRequires: hscolour+%endif+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}++%description+%{common_description}+%if %{with shared}+This package provides the shared library.+%endif++%prep+%setup -q -n %{pkg_name}-%{version}++%build+%ghc_lib_build+++%install+rm -rf $RPM_BUILD_ROOT+%ghc_lib_install+mv $RPM_BUILD_ROOT%{_bindir}/haddock $RPM_BUILD_ROOT%{_bindir}/haddock-%{version}+echo "%{_bindir}/haddock-%{version}" >> %{name}.files+echo "%{_datadir}/%{pkg_name}-%{version}/html" >> %{name}-devel.files++%clean+rm -rf $RPM_BUILD_ROOT+++%{ghc_lib_package}+++%changelog+* Sun Oct 10 2010 Lakshmi Narasimhan <lakshminaras2002@gmail.com> - 2.7.2-1+- Modified dependencies, license tag+- Changing binary executable name from haddock to haddock-version as ghc already ships with haddock binary++* Sun Oct 10 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 2.7.2-0+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2
@@ -0,0 +1,66 @@+%global pkg_name ltk++%global common_summary Leksah IDE's UI toolkit library++%global common_description This package provides UI toolkit library for Leksah IDE.++%global ghc_pkg_deps ghc-glib-devel, ghc-gtk-devel, ghc-mtl-devel, ghc-parsec-devel++%bcond_without shared+%bcond_without hscolour++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 0.8.0.8+Release: 1%{?dist}+Summary: %{common_summary}++Group: System Environment/Libraries+License: GPL+URL: http://hackage.haskell.org/package/%{pkg_name}+Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz+BuildRoot: %{tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-doc, ghc-prof+BuildRequires: ghc-rpm-macros >= 0.8.1+%if %{with hscolour}+BuildRequires: hscolour+%endif+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}++%description+%{common_description}+%if %{with shared}+This package provides the shared library.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%ghc_lib_build+++%install+rm -rf $RPM_BUILD_ROOT+%ghc_lib_install+++%clean+rm -rf $RPM_BUILD_ROOT+++%{?ghc_lib_package}+++%changelog+* Sun Oct 10 2010 Lakshmi Narasimhan <lakshminaras2002@gmail.com> - 0.8.0.8-1+- Modify license details, summary, description and added dependencies.++* Sun Oct 10 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 0.8.0.8-0+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2
@@ -0,0 +1,65 @@+%global pkg_name process-leksah++%global common_summary %{pkg_name} library++%global common_description A %{pkg_name} library for leksah++%bcond_without shared+%bcond_without hscolour++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 1.0.1.3+Release: 1%{?dist}+Summary: %{common_summary}++Group: System Environment/Libraries+License: BSD+URL: http://hackage.haskell.org/package/%{pkg_name}+Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-doc, ghc-prof+BuildRequires: ghc-rpm-macros >= 0.8.1+%if %{with hscolour}+BuildRequires: hscolour+%endif+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}++%description+%{common_description}+%if %{with shared}+This package provides the shared library.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%ghc_lib_build+++%install+rm -rf $RPM_BUILD_ROOT+%ghc_lib_install+++%clean+rm -rf $RPM_BUILD_ROOT+++%{?ghc_lib_package}+++%changelog+* Sun Oct 10 2010 Lakshmi Narasimhan <lakshminaras2002@gmail.com> - 1.0.1.3-1+- Modified license text+- Added dependencies++* Sun Oct 10 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 1.0.1.3-0+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2
@@ -0,0 +1,70 @@+%global pkg_name regex-tdfa++%global common_summary Haskell regular expression library++%global common_description A new all Haskell "tagged" DFA regex engine,inspired by libtre++%global ghc_pkg_deps ghc-regex-base-devel,ghc-parsec-devel,ghc-mtl-devel++%bcond_without shared+%bcond_without hscolour++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: ghc-%{pkg_name}+Version: 1.1.4+Release: 1%{?dist}+Summary: %{common_summary}++Group: System Environment/Libraries+License: BSD+URL: http://hackage.haskell.org/package/%{pkg_name}+Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-doc, ghc-prof+BuildRequires: ghc-rpm-macros >= 0.8.1+%if %{with hscolour}+BuildRequires: hscolour+%endif+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}++%description+%{common_description}+%if %{with shared}+This package provides the shared library.+%endif+++%prep+%setup -q -n %{pkg_name}-%{version}+++%build+%ghc_lib_build+++%install+rm -rf $RPM_BUILD_ROOT+%ghc_lib_install+++%clean+rm -rf $RPM_BUILD_ROOT+++%{?ghc_lib_package}+++%changelog+* Sat Sep 18 2010 Lakshmi Narasimhan T V <lakshminaras2002@gmail.com> - 1.1.4-1+- using ghc-rpm-macros 0.8.1 +- package updated to 1.1.4++* Sat Jul 3 2010 Lakshmi Narasimhan T V <lakshminaras2002@gmail.com> - 1.1.3-1+- initial packaging for Fedora automatically generated by cabal2spec-0.22.1+- Updated to use ghc_lib_package, ghc_lib_build, ghc_lib_install macros instead of cabal macros++* Tue May 25 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 1.1.2-1+- initial packaging for Fedora automatically generated by cabal2spec-0.21.3
@@ -0,0 +1,71 @@+%global pkg_name leksah-server++%global common_summary Haskell %{pkg_name} library++%global common_description %{common_summary}++%global ghc_pkg_deps ghc-hslogger-devel, ghc-network-devel, ghc-process-leksah-devel, ghc-deepseq-devel, ghc-mtl-devel, ghc-ltk-devel, ghc-binary-shared-devel, ghc-haddock-devel++%bcond_without shared+%bcond_without hscolour++# debuginfo is not useful for ghc+%global debug_package %{nil}++Name: %{pkg_name}+Version: 0.8.0.6+Release: 1%{?dist}+Summary: Haskell %{pkg_name}++Group: System Development/IDE+License: GPL+URL: http://hackage.haskell.org/package/%{name}+Source0: http://hackage.haskell.org/packages/archive/%{name}/%{version}/%{name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc, ghc-doc, ghc-prof+BuildRequires: ghc-rpm-macros >= 0.8.1+%if %{with hscolour}+BuildRequires: hscolour+%endif+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}++%description+%{common_description}+++%prep+%setup -q+++%build+%ghc_lib_build+++%install+rm -rf $RPM_BUILD_ROOT+%ghc_lib_install+++%clean+rm -rf $RPM_BUILD_ROOT+++%{?ghc_binlib_package}+++%files+%defattr(-,root,root,-)+%doc LICENSE+%attr(755,root,root) %{_bindir}/%{name}+%attr(755,root,root) %{_bindir}/leksahecho+%attr(644,root,root) %{_datadir}/%{pkg_name}-%{version}/data/prefscoll.lkshp+++%changelog+* Sun Oct 10 2010 Lakshmi Narasimhan <lakshminaras2002@gmail.com> - 0.8.0.6-1+- Modified license and depenedencies++* Sun Oct 10 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 0.8.0.6-0+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2
@@ -0,0 +1,89 @@+# link with shared libs+%bcond_without dynamic++%global ghc_pkg_deps ghc-utf8-string-devel,ghc-gtk-devel,ghc-glib-devel,ghc-binary-shared-devel,ghc-leksah-server-devel,ghc-regex-base-devel,ghc-regex-tdfa-devel++# ghc does not emit debug information+%global debug_package %{nil}++Name: leksah+Version: 0.8.0.6+Release: 1%{?dist}+Summary: Haskell IDE++Group: System Environment/IDE+License: GPL+URL: http://hackage.haskell.org/package/%{name}+Source0: http://hackage.haskell.org/packages/archive/%{name}/%{version}/%{name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc+BuildRequires: ghc-rpm-macros >= 0.7.0+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}+v v v v v v v+BuildRequires: ghc-gtksourceview2-devel <= 0.11.2+BuildRequires: ghc-gtksourceview2-doc,ghc-gtksourceview2-prof+*************+v v v v v v v+BuildRequires: ghc-gtksourceview2-devel <= 0.11.2+BuildRequires: ghc-gtksourceview2-doc,ghc-gtksourceview2-prof+*************+BuildRequires: ghc-gtksourceview2-devel <= 0.11.2+BuildRequires: ghc-gtksourceview2-doc,ghc-gtksourceview2-prof+^ ^ ^ ^ ^ ^ ^++Requires: leksah-server++^ ^ ^ ^ ^ ^ ^+%description+v v v v v v v+Haskell IDE+*************+v v v v v v v+@DESCRIPTION@++*************+Haskell IDE++^ ^ ^ ^ ^ ^ ^+^ ^ ^ ^ ^ ^ ^++%prep+%setup -q+++%build+%ghc_bin_build+++%install+rm -rf $RPM_BUILD_ROOT+%ghc_bin_install+mkdir -p $RPM_BUILD_ROOT/usr/share/applications+install -p -m 644 linux/applications/leksah.desktop $RPM_BUILD_ROOT/usr/share/applications+mkdir -p $RPM_BUILD_ROOT/usr/share/icons/hicolor/48x48/apps+install -p -m 644 linux/icons/hicolor/48x48/apps/leksah_48x48.png $RPM_BUILD_ROOT/usr/share/icons/hicolor/48x48/apps+mkdir -p $RPM_BUILD_ROOT/usr/share/mime/application/+install -p -m 644 linux/applications/leksah.xml $RPM_BUILD_ROOT/usr/share/mime/application/++%clean+rm -rf $RPM_BUILD_ROOT+++%files+%defattr(-,root,root,-)+%doc LICENSE+%attr(755,root,root) %{_bindir}/%{name}+%attr(755,root,root) %{_datadir}/%{name}-%{version}+%attr(644,root,root) /usr/share/applications/%{name}.desktop+%attr(644,root,root) /usr/share/mime/application/%{name}.xml+%attr(644,root,root) /usr/share/icons/hicolor/48x48/apps/leksah_48x48.png++%changelog+* Sun Oct 10 2010 Lakshmi Narasimhan T V <lakshminaras2002@gmail.com> - 0.8.0.6-1+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2+- Added desktop, mime and icon files++* Sun Oct 10 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 0.8.0.6-0+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2
@@ -0,0 +1,67 @@+# link with shared libs+%bcond_without dynamic++%global ghc_pkg_deps ghc-utf8-string-devel,ghc-gtk-devel,ghc-glib-devel,ghc-binary-shared-devel,ghc-leksah-server-devel,ghc-regex-base-devel,ghc-regex-tdfa-devel++# ghc does not emit debug information+%global debug_package %{nil}++Name: leksah+Version: 0.8.0.6+Release: 1%{?dist}+Summary: Haskell IDE++Group: System Environment/IDE+License: GPL+URL: http://hackage.haskell.org/package/%{name}+Source0: http://hackage.haskell.org/packages/archive/%{name}/%{version}/%{name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc+BuildRequires: ghc-rpm-macros >= 0.7.0+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}+BuildRequires: ghc-gtksourceview2-devel <= 0.11.2+BuildRequires: ghc-gtksourceview2-doc,ghc-gtksourceview2-prof+%description+@DESCRIPTION@+++%prep+%setup -q+++%build+%ghc_bin_build+++%install+rm -rf $RPM_BUILD_ROOT+%ghc_bin_install+mkdir -p $RPM_BUILD_ROOT/usr/share/applications+install -p -m 644 linux/applications/leksah.desktop $RPM_BUILD_ROOT/usr/share/applications+mkdir -p $RPM_BUILD_ROOT/usr/share/icons/hicolor/48x48/apps+install -p -m 644 linux/icons/hicolor/48x48/apps/leksah_48x48.png $RPM_BUILD_ROOT/usr/share/icons/hicolor/48x48/apps+mkdir -p $RPM_BUILD_ROOT/usr/share/mime/application/+install -p -m 644 linux/applications/leksah.xml $RPM_BUILD_ROOT/usr/share/mime/application/++%clean+rm -rf $RPM_BUILD_ROOT+++%files+%defattr(-,root,root,-)+%doc LICENSE+%attr(755,root,root) %{_bindir}/%{name}+%attr(755,root,root) %{_datadir}/%{name}-%{version}+%attr(644,root,root) /usr/share/applications/%{name}.desktop+%attr(644,root,root) /usr/share/mime/application/%{name}.xml+%attr(644,root,root) /usr/share/icons/hicolor/48x48/apps/leksah_48x48.png++%changelog+* Sun Oct 10 2010 Lakshmi Narasimhan T V <lakshminaras2002@gmail.com> - 0.8.0.6-1+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2+- Added desktop, mime and icon files++* Sun Oct 10 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 0.8.0.6-0+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2
@@ -0,0 +1,80 @@+# link with shared libs+%bcond_without dynamic++%global ghc_pkg_deps ghc-utf8-string-devel,ghc-gtk-devel,ghc-glib-devel,ghc-binary-shared-devel,ghc-leksah-server-devel,ghc-regex-base-devel,ghc-regex-tdfa-devel++# ghc does not emit debug information+%global debug_package %{nil}++Name: leksah+Version: 0.8.0.6+Release: 1%{?dist}+Summary: Haskell IDE++Group: System Environment/IDE+License: GPL+URL: http://hackage.haskell.org/package/%{name}+Source0: http://hackage.haskell.org/packages/archive/%{name}/%{version}/%{name}-%{version}.tar.gz+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)+# fedora ghc archs:+ExclusiveArch: %{ix86} x86_64 ppc alpha+BuildRequires: ghc+BuildRequires: ghc-rpm-macros >= 0.7.0+%{?ghc_pkg_deps:BuildRequires: %{ghc_pkg_deps}, %(echo %{ghc_pkg_deps} | sed -e "s/\(ghc-[^, ]\+\)-devel/\1-doc,\1-prof/g")}+v v v v v v v+BuildRequires: ghc-gtksourceview2-devel <= 0.11.2+BuildRequires: ghc-gtksourceview2-doc,ghc-gtksourceview2-prof+*************+BuildRequires: ghc-gtksourceview2-devel <= 0.11.2+BuildRequires: ghc-gtksourceview2-doc,ghc-gtksourceview2-prof++Requires: leksah-server++^ ^ ^ ^ ^ ^ ^+%description+v v v v v v v+@DESCRIPTION@++*************+Haskell IDE++^ ^ ^ ^ ^ ^ ^++%prep+%setup -q+++%build+%ghc_bin_build+++%install+rm -rf $RPM_BUILD_ROOT+%ghc_bin_install+mkdir -p $RPM_BUILD_ROOT/usr/share/applications+install -p -m 644 linux/applications/leksah.desktop $RPM_BUILD_ROOT/usr/share/applications+mkdir -p $RPM_BUILD_ROOT/usr/share/icons/hicolor/48x48/apps+install -p -m 644 linux/icons/hicolor/48x48/apps/leksah_48x48.png $RPM_BUILD_ROOT/usr/share/icons/hicolor/48x48/apps+mkdir -p $RPM_BUILD_ROOT/usr/share/mime/application/+install -p -m 644 linux/applications/leksah.xml $RPM_BUILD_ROOT/usr/share/mime/application/++%clean+rm -rf $RPM_BUILD_ROOT+++%files+%defattr(-,root,root,-)+%doc LICENSE+%attr(755,root,root) %{_bindir}/%{name}+%attr(755,root,root) %{_datadir}/%{name}-%{version}+%attr(644,root,root) /usr/share/applications/%{name}.desktop+%attr(644,root,root) /usr/share/mime/application/%{name}.xml+%attr(644,root,root) /usr/share/icons/hicolor/48x48/apps/leksah_48x48.png++%changelog+* Sun Oct 10 2010 Lakshmi Narasimhan T V <lakshminaras2002@gmail.com> - 0.8.0.6-1+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2+- Added desktop, mime and icon files++* Sun Oct 10 2010 Fedora Haskell SIG <haskell-devel@lists.fedoraproject.org> - 0.8.0.6-0+- initial packaging for Fedora automatically generated by cabal2spec-0.22.2
@@ -19,8 +19,27 @@ import IDE.Leksah (leksah) import IDE.YiConfig (defaultYiConfig) +#ifdef LOCALIZATION++import Text.I18N.GetText+import System.Locale.SetLocale++-- | Support for localization+initLocale = do+ setLocale LC_ALL (Just "")+ bindTextDomain __MESSAGE_CATALOG_DOMAIN__ (Just __MESSAGE_CATALOG_DIR__)+ textDomain (Just __MESSAGE_CATALOG_DOMAIN__)++#else++-- | no localization support+initLocale = return ()++#endif+ main :: IO () main = do putStrLn "Using default Yi configuration"+ initLocale leksah defaultYiConfig
@@ -0,0 +1,30 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">+<plist version="1.0">+<dict>+ <key>CFBundleDevelopmentRegion</key>+ <string>English</string>+ <key>CFBundleExecutable</key>+ <string>Leksah</string>+ <key>CFBundleGetInfoString</key>+ <string>0.13.0.0</string>+ <key>CFBundleIconFile</key>+ <string>leksah.icns</string>+ <key>CFBundleIdentifier</key>+ <string>org.leksah</string>+ <key>CFBundleInfoDictionaryVersion</key>+ <string>6.0</string>+ <key>CFBundlePackageType</key>+ <string>APPL</string>+ <key>CFBundleShortVersionString</key>+ <string>0.13.0.0</string>+ <key>CFBundleSignature</key>+ <string>????</string>+ <key>CFBundleVersion</key>+ <string>0.13.0.0</string>+ <key>NSHumanReadableCopyright</key>+ <string>2007-2011 Jürgen Nicklisch-Franken, GNU General Public License.</string>+ <key>LSMinimumSystemVersion</key>+ <string>10.6</string>+</dict>+</plist>
@@ -0,0 +1,3 @@+#!/bin/sh++PATH=$PREFIX/bin:$PATH gtk-mac-bundler leksah.bundle
@@ -0,0 +1,10 @@+#!/bin/sh -ex++jhbuild bootstrap --skip=libiconv+jhbuild build meta-gtk-osx-bootstrap+jhbuild build freetype++jhbuild build meta-gtk-osx-gtk3+jhbuild build gtksourceview3+jhbuild build librsvg+
@@ -0,0 +1,10 @@+#!/bin/sh -ex++jhbuild bootstrap --skip=libiconv+jhbuild build meta-gtk-osx-bootstrap+jhbuild build freetype++jhbuild build meta-gtk-osx-core+jhbuild build gtk-engines+jhbuild build gtksourceview+
@@ -0,0 +1,186 @@+#!/bin/sh++if test -e ~/.profile; then+ export PATH=`. ~/.profile;echo $PATH`+fi++if test "x$GTK_DEBUG_LAUNCHER" != x; then+ set -x+fi++if test "x$GTK_DEBUG_GDB" != x; then+ EXEC="gdb --args"+else+ EXEC=exec+fi++name=`basename "$0"`+tmp="$0"+tmp=`dirname "$tmp"`+tmp=`dirname "$tmp"`+bundle=`dirname "$tmp"`+bundle_contents="$bundle"/Contents+bundle_res="$bundle_contents"/Resources+bundle_lib="$bundle_res"/lib+bundle_bin="$bundle_res"/bin+bundle_data="$bundle_res"/share+bundle_etc="$bundle_res"/etc++export XDG_CONFIG_DIRS="$bundle_etc"+export XDG_DATA_DIRS="$bundle_data"+export GTK_DATA_PREFIX="$bundle_res"+export GTK_EXE_PREFIX="$bundle_res"+export GTK_PATH="$bundle_res"+export PATH="$bundle_bin":$PATH++export GTK2_RC_FILES="$bundle_etc/gtk-3.0/gtkrc"+export GTK_IM_MODULE_FILE="$bundle_etc/gtk-3.0/gtk.immodules"+export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-3.0/gdk-pixbuf.loaders"+export FONTCONFIG_PATH="$bundle_etc/fonts"+export PANGO_RC_FILE="$bundle_etc/pango/pangorc"+export PANGO_LIBDIR="$bundle_lib"+export PANGO_SYSCONFDIR="$bundle_etc"+export GST_PLUGIN_SCANNER="$bundle_res"/libexec/gst-plugin-scanner+export GST_PLUGIN_PATH="$bundle_res"/libexec/gstreamer-1.0+export GST_PLUGIN_SYSTEM_PATH=+export GIO_EXTRA_MODULES="$bundle_lib"/gio/modules++export leksah_bindir="$bundle_bin"+export leksah_libdir="$bundle_lib/leksah/ghc"+export leksah_datadir="$bundle_data/leksah"+export leksah_libexecdir="$bundle_res/libexec"++export hlint_datadir="$bundle_data/hlint"++APP=name+I18NDIR="$bundle_data/locale"+# Set the locale-related variables appropriately:+unset LANG LC_MESSAGES LC_MONETARY LC_COLLATE++# Has a language ordering been set?+# If so, set LC_MESSAGES and LANG accordingly; otherwise skip it.+# First step uses sed to clean off the quotes and commas, to change - to _, and change the names for the chinese scripts from "Hans" to CN and "Hant" to TW.+APPLELANGUAGES=`defaults read .GlobalPreferences AppleLanguages | sed -En -e 's/\-/_/' -e 's/Hant/TW/' -e 's/Hans/CN/' -e 's/[[:space:]]*\"?([[:alnum:]_]+)\"?,?/\1/p' `+if test "$APPLELANGUAGES"; then+ # A language ordering exists.+ # Test, item per item, to see whether there is an corresponding locale.+ for L in $APPLELANGUAGES; do+ #test for exact matches:+ if test -f "$I18NDIR/${L}/LC_MESSAGES/$APP.mo"; then+ export LANG=$L+ break+ fi+ #This is a special case, because often the original strings are in US+ #English and there is no translation file.+ if test "x$L" == "xen_US"; then+ export LANG=$L+ break+ fi+ #OK, now test for just the first two letters:+ if test -f "$I18NDIR/${L:0:2}/LC_MESSAGES/$APP.mo"; then+ export LANG=${L:0:2}+ break+ fi+ #Same thing, but checking for any english variant.+ if test "x${L:0:2}" == "xen"; then+ export LANG=$L+ break+ fi;+ done +fi+unset APPLELANGUAGES L++# If we didn't get a language from the language list, try the Collation preference, in case it's the only setting that exists.+APPLECOLLATION=`defaults read .GlobalPreferences AppleCollationOrder`+if test -z ${LANG} -a -n $APPLECOLLATION; then+ if test -f "$I18NDIR/${APPLECOLLATION:0:2}/LC_MESSAGES/$APP.mo"; then+ export LANG=${APPLECOLLATION:0:2}+ fi+fi+if test ! -z $APPLECOLLATION; then+ export LC_COLLATE=$APPLECOLLATION+fi+unset APPLECOLLATION++# Continue by attempting to find the Locale preference.+APPLELOCALE=`defaults read .GlobalPreferences AppleLocale`++if test -f "$I18NDIR/${APPLELOCALE:0:5}/LC_MESSAGES/$APP.mo"; then+ if test -z $LANG; then + export LANG="${APPLELOCALE:0:5}"+ fi++elif test -z $LANG -a -f "$I18NDIR/${APPLELOCALE:0:2}/LC_MESSAGES/$APP.mo"; then+ export LANG="${APPLELOCALE:0:2}"+fi++#Next we need to set LC_MESSAGES. If at all possilbe, we want a full+#5-character locale to avoid the "Locale not supported by C library"+#warning from Gtk -- even though Gtk will translate with a+#two-character code.+if test -n $LANG; then +#If the language code matches the applelocale, then that's the message+#locale; otherwise, if it's longer than two characters, then it's+#probably a good message locale and we'll go with it.+ if test $LANG == ${APPLELOCALE:0:5} -o $LANG != ${LANG:0:2}; then+ export LC_MESSAGES=$LANG+#Next try if the Applelocale is longer than 2 chars and the language+#bit matches $LANG+ elif test $LANG == ${APPLELOCALE:0:2} -a $APPLELOCALE > ${APPLELOCALE:0:2}; then+ export LC_MESSAGES=${APPLELOCALE:0:5}+#Fail. Get a list of the locales in $PREFIX/share/locale that match+#our two letter language code and pick the first one, special casing+#english to set en_US+ elif test $LANG == "en"; then+ export LC_MESSAGES="en_US"+ else+ LOC=`find $PREFIX/share/locale -name $LANG???`+ for L in $LOC; do + export LC_MESSAGES=$L+ done+ fi+else+#All efforts have failed, so default to US english+ export LANG="en_US"+ export LC_MESSAGES="en_US"+fi+CURRENCY=`echo $APPLELOCALE | sed -En 's/.*currency=([[:alpha:]]+).*/\1/p'`+if test "x$CURRENCY" != "x"; then +#The user has set a special currency. Gtk doesn't install LC_MONETARY files, but Apple does in /usr/share/locale, so we're going to look there for a locale to set LC_CURRENCY to.+ if test -f /usr/local/share/$LC_MESSAGES/LC_MONETARY; then+ if test -a `cat /usr/local/share/$LC_MESSAGES/LC_MONETARY` == $CURRENCY; then+ export LC_MONETARY=$LC_MESSAGES+ fi+ fi+ if test -z "$LC_MONETARY"; then + FILES=`find /usr/share/locale -name LC_MONETARY -exec grep -H $CURRENCY {} \;`+ if test -n "$FILES"; then + export LC_MONETARY=`echo $FILES | sed -En 's%/usr/share/locale/([[:alpha:]_]+)/LC_MONETARY.*%\1%p'`+ fi+ fi+fi+#No currency value means that the AppleLocale governs:+if test -z "$LC_MONETARY"; then+ LC_MONETARY=${APPLELOCALE:0:5}+fi+#For Gtk, which only looks at LC_ALL:+export LC_ALL=$LC_MESSAGES++unset APPLELOCALE FILES LOC++if test -f "$bundle_lib/charset.alias"; then+ export CHARSETALIASDIR="$bundle_lib"+fi++# Extra arguments can be added in environment.sh.+EXTRA_ARGS=+if test -f "$bundle_res/environment.sh"; then+ source "$bundle_res/environment.sh"+fi++# Strip out the argument added by the OS.+if /bin/expr "x$1" : '^x-psn_' > /dev/null; then+ shift 1+fi++$EXEC "$bundle_contents/Resources/bin/leksah" "$@" $EXTRA_ARGS
@@ -0,0 +1,196 @@+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->+<app-bundle>++ <meta>+ <!-- Where to pick up the GTK+ installation, icon themes,+ etc. Note that "${env:JHBUILD_PREFIX}" is evaluated to the+ value of the environment variable JHBUILD_PREFIX. You can+ define additional prefixes and refer to them in paths+ throughout this file on the form "${prefix:name}". This is+ useful for installing certain libraries or even the+ application itself separately. Note that JHBUILD_PREFIX is+ defined by jhbuild, so it you are not using jhbuild you can+ either define your own or just hardcode the path here.+ -->+ <prefix name="default">${env:JHBUILD_PREFIX}</prefix>+ <prefix name="leksah">${env:LEKSAH_PREFIX}</prefix>+ <prefix name="leksah-server">${env:LEKSAH_SERVER_PREFIX}</prefix>+ <prefix name="vcsgui">${env:VCSGUI_PREFIX}</prefix>+ <prefix name="hlint">${env:HLINT_PREFIX}</prefix>++ <!-- The project directory is the default location of the created+ app. If you leave out the path, the current directory is+ used. Note the usage of an environment variable here again.+ -->+ <destination overwrite="yes">Leksah</destination>++ <image>+ <!-- Not implemented yet (DMG image). -->+ </image>++ <!-- Comment this out to keep the install names in binaries -->+ <!-- <run-install-name-tool/> -->++ <!-- Optionally specify a launcher script to use. If the+ application sets up everything needed itself, like+ environment variable, linker paths, etc, a launcher script is+ not needed. If the source path is left out, the default+ script will be used.+ -->+ <launcher-script>${project}/launcher.sh</launcher-script>++ <!-- Not implemented: Optional runtime, could be python or mono+ for example.+ -->+ <!-- runtime copy="yes">/usr/bin/python</runtime -->+ <!-- Indicate the active gtk version to use. This is needed only+ for gtk+-3.0 projects. -->+ <gtk>gtk+-3.0</gtk>+ </meta>++ <!-- The special macro "${project}" refers to the directory where+ this bundle file is located. The application name and bundle+ identifier are taken from the plist file.+ -->+ <plist>${project}/Info.plist</plist>++ <main-binary>${prefix:leksah}/bin/leksah</main-binary>++ <binary>${prefix:leksah-server}/bin/leksahecho</binary>+ <binary>${prefix:leksah-server}/bin/leksah-server</binary>+ <binary>${prefix:vcsgui}/bin/vcsgui</binary>+ <binary>${prefix:vcsgui}/bin/vcsgui-askpass</binary>++ <!-- Copy in the input methods. Dunno if they actually work with+ OSX. Note the ${gtkdir} macro, which expands to the correct+ library subdirectory for the specified gtk version. -->+ <binary>+ ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so+ </binary>++ <!-- Copy in GTK+ theme engines. -->+ <binary>+ ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/theming-engines/*.so+ </binary>+++<!-- And the print backends -->+ <binary>+ ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so+ </binary>++<!-- Starting with 2.24, gdk-pixbuf installs into its own directory. -->+ <binary>+ ${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/loaders/*.so+ </binary>++ <binary>+ ${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/+ </binary>++ <binary>+ ${prefix}/lib/gio/modules/+ </binary>++ <binary>+ ${prefix}/lib/enchant/*.so+ </binary>++ <binary>+ ${prefix}/lib/gstreamer-1.0/*.so+ </binary>++ <binary dest="${bundle}/Contents/Resources/libexec">+ ${prefix}/libexec/gstreamer-1.0/+ </binary>++ <data>+ ${prefix}/etc/fonts/+ </data>++ <data>+ ${prefix}/etc/pango/+ </data>++ <!-- Translation filenames, one for each program or library that you+ want to copy in to the bundle. The "dest" attribute is+ optional, as usual. Bundler will find all translations of that+ library/program under the indicated directory and copy them.-->+ <translations name="gtk30">+ ${prefix}/share/locale+ </translations>+++ <!-- Data to copy in, usually Glade/UI files, images, sounds files+ etc. The destination inside the bundle can be specified if the+ files should end up at a different location, by using the+ "dest" property. The destination must then start with the macro+ "${bundle}", which refers to the bundle root directory.+ -->+ <data>+ ${prefix}/share/gtksourceview-3.0+ </data>++ <data dest="${bundle}/Contents/Resources/share/leksah">+ ${prefix:leksah}/share+ </data>++ <data dest="${bundle}/Contents/Resources/share/hlint">+ ${prefix:hlint}/share+ </data>++ <!-- Copy in the themes data. You may want to trim this to save space+ in your bundle. -->+ <data>+ ${prefix}/share/themes+ </data>+ <data>+ ${prefix}/share/glib-2.0+ </data>+ <data>+ ${prefix}/share/mime+ </data>++ <!-- Copy icons. Note that the .icns file is an Apple format which+ contains up to 4 sizes of icon. You can use+ /Developer/Applications/Utilities/Icon Composer.app to import+ artwork and create the file. -->+ <data dest="${bundle}/Contents/Resources">+ ${project}/leksah.icns+ </data>++ <!-- This is where theme commands go. You can copy them in from your+ theme of choice if they provide and example, or you can just+ change the source path. -->++ <data dest="${bundle}/Contents/Resources/etc/gtk-3.0/settings.ini">+ ${project}/settings.ini+ </data>++ <!--+ <data dest="${bundle}/Contents/Resources/etc/${gtk}/gtkrc">+ ${project}/gtkrc+ </data>+ -->++ <!-- Icon themes to copy. The "icons" property can be either of+ "auto", "all", or "none". All or none should be+ self-explanatory, while auto means that the script will try to+ figure out which icons are needed. This is done by getting all+ the strings from all copied binaries, and matching them against+ icon names. To be safe, you should use "all". "none" is useful+ if you want just the index.theme file but no icons, mostly+ needed for the "hicolor" base theme.+ -->+ <icon-theme icons="all">+ hicolor+ </icon-theme>++ <!-- Custom prefs for the Mac -->+ <data dest="${bundle}/Contents/Resources/share/leksah/data/prefs.lkshp">+ ${project}/prefs.lkshp+ </data>+ <data dest="${bundle}/Contents/Resources/share/leksah/data/keymap.lkshk">+ ${project}/keymap.lkshk+ </data>+</app-bundle>
binary file changed (absent → 291494 bytes)
@@ -0,0 +1,62 @@+#!/bin/sh -ex++cd ../leksah || exit++. scripts/stage.sh || exit++export GHC_USER_PREFIX=$HOME/Library/Haskell/ghc-`ghc$GHCVERSION --numeric-version`/lib+export LEKSAH_PREFIX=$GHC_USER_PREFIX/$LEKSAH_X_X_X_X+export LEKSAH_SERVER_PREFIX=$GHC_USER_PREFIX/$LEKSAH_SERVER_X_X_X_X+export VCSGUI_PREFIX=$GHC_USER_PREFIX/`ghc-pkg$GHCVERSION list |grep '^ *vcsgui-' | head -n1 | tr -d ' \n'`+export HLINT_PREFIX=$GHC_USER_PREFIX/`ghc-pkg$GHCVERSION list |grep '^ *hlint-' | head -n1 | tr -d ' \n'`++sed -e 's|TextView Font: *\"Monospace 10\"|TextView Font: "Monospace 14"|' -e 's|Browser: *\"firefox\"|Browser: \"open\"|' <data/prefs.lkshp >osx/prefs.lkshp++sed -e 's|\<ctrl\>|\<meta\>|' \+ -e 's|\<alt\>|\<control\>|' \+ -e 's|^--\<meta\>x |\<meta\>x |' \+ -e 's|^--\<meta\>c |\<meta\>c |' \+ -e 's|^--\<meta\>v |\<meta\>v |' \+ <data/keymap.lkshk >osx/keymap.lkshk+cat osx/osxkeymap.lkshk >>osx/keymap.lkshk++cd osx || exit++chmod +x bundle.sh launcher.sh || exit++echo Bundle Leksah+if test -e "Leksah"; then+ rm -rf "Leksah"+fi+JHBUILD_PREFIX=/opt/local ./bundle.sh || exit++echo Fixing library bindings+mv Leksah/Leksah.app/Contents/MacOS/Leksah-bin Leksah/Leksah.app/Contents/Resources/bin/leksah || exit+for f in `find Leksah/Leksah.app/Contents/Resources/lib -name '*.so' -o -name '*.dylib'` Leksah/Leksah.app/Contents/Resources/bin/* Leksah/Leksah.app/Contents/Resources/libexec/*; do+ chmod +w $f+ otool -L $f | grep "$GTK_PREFIX/.*(" | sed -e "s|.*$GTK_PREFIX/\([^ ]*\).*|\1|" | xargs -I {} install_name_tool -change $GTK_PREFIX/{} @executable_path/../{} $f || exit+ chmod -w $f+done++for f in Leksah/Leksah.app/Contents/Resources/libexec/gst-plugin-scanner; do+ chmod +w $f+ otool -L $f | grep "$GTK_PREFIX/.*(" | sed -e "s|.*$GTK_PREFIX/\([^ ]*\).*|\1|" | xargs -I {} install_name_tool -change $GTK_PREFIX/{} @executable_path/../../{} $f || exit+ chmod -w $f+done++echo Fixing immodules paths+sed -i "" -e "s|/opt/local/|@executable_path/../|" Leksah/Leksah.app/Contents/Resources/etc/gtk-3.0/gtk.immodules || exit+sed -i "" -e "s|@executable_path/../Resources/|@executable_path/../|" Leksah/Leksah.app/Contents/Resources/etc/gtk-3.0/gtk.immodules || exit++echo Fixing pixbuf loader paths+sed -i "" -e "s|@executable_path/../Resources/|@executable_path/../|" Leksah/Leksah.app/Contents/Resources/etc/gtk-3.0/gdk-pixbuf.loaders || exit++echo Fixing pango module paths+sed -i "" -e "s|@executable_path/../Resources/|@executable_path/../|" Leksah/Leksah.app/Contents/Resources/etc/pango/pango.modules || exit++LEKSAH_DMG="$LEKSAH_X_X_X_X_GHC_X_X_X.dmg"+if test -e "$LEKSAH_DMG"; then+ rm "$LEKSAH_DMG"+fi+hdiutil create -size 300m -srcfolder "Leksah" "$LEKSAH_DMG" || exit+
@@ -0,0 +1,24 @@+#!/bin/sh -ex++#export PATH=/Users/hamish/Library/Haskell/bin:/Library/Frameworks/GHC.framework/Versions/7.0.3-i386/usr/bin:$PATH+#scripts/clean.sh+#osx/makedmg.sh+#export PATH=/Users/hamish/Library/Haskell/bin:/Library/Frameworks/GHC.framework/Versions/7.0.4-i386/usr/bin:$PATH+#scripts/clean.sh+#osx/makedmg.sh+#export PATH=/Users/hamish/Library/Haskell/bin:/Library/Frameworks/GHC.framework/Versions/7.4.1-i386/usr/bin:$PATH+#scripts/clean.sh+#osx/makedmg.sh+#export PATH=/Users/hamish/Library/Haskell/bin:/Library/Frameworks/GHC.framework/Versions/7.4.2-i386/usr/bin:$PATH+#scripts/clean.sh+#osx/makedmg.sh+#export PATH=/Users/hamish/Library/Haskell/bin:/Library/Frameworks/GHC.framework/Versions/7.6.3-i386/usr/bin:$PATH+#scripts/clean.sh+#osx/makedmg.sh+export GHCVERSION=-7.6.3+scripts/clean.sh+osx/makedmg.sh+export GHCVERSION=+scripts/clean.sh+osx/makedmg.sh+-
@@ -0,0 +1,2 @@++
@@ -0,0 +1,5 @@+[Settings]+gtk-theme-name = Adwaita+gtk-icon-theme-name = Tango+gtk-icon-sizes = gtk-menu=11,11+
@@ -0,0 +1,2244 @@+# Translation file++msgid ""+msgstr ""++"Project-Id-Version: PACKAGE VERSION\n"+"Report-Msgid-Bugs-To: \n"+"POT-Creation-Date: 2009-01-13 06:05-0800\n"+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"+"Language-Team: LANGUAGE <LL@li.org>\n"+"MIME-Version: 1.0\n"+"Content-Type: text/plain; charset=UTF-8\n"+"Content-Transfer-Encoding: 8bit\n"+++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Breakpoints"+msgstr ""++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Location"+msgstr ""++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Remove breakpoint"+msgstr ""++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Debugger>> breakpointViewPopup: no selection2"+msgstr ""++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Remove all breakpoints"+msgstr ""++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Update"+msgstr ""++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Debugger>>deleteBreakpoint: Not a breakpoint"+msgstr ""++#: src/IDE/Pane/Errors.hs:0+msgid "Errors"+msgstr ""++#: src/IDE/Pane/Errors.hs:0+msgid "Description"+msgstr ""++#: src/IDE/Pane/Errors.hs:0+msgid "Resolve Errors"+msgstr ""++#: src/IDE/Pane/Files.hs:0+msgid "Files"+msgstr ""++#: src/IDE/Pane/Files.hs:0+msgid "File"+msgstr ""++#: src/IDE/Pane/Files.hs:0+msgid "Unexpected Expansion in Files Pane"+msgstr ""++#: src/IDE/Pane/Files.hs:0+msgid "Unexpected Activation in Files Pane"+msgstr ""++#: src/IDE/Pane/Files.hs:0+msgid "Unexpected Selection in Files Pane"+msgstr ""++#: src/IDE/Pane/Grep.hs:0+msgid "Grep"+msgstr ""++#: src/IDE/Pane/Grep.hs:0+msgid "Line"+msgstr ""++#: src/IDE/Pane/Grep.hs:0+msgid "Context"+msgstr ""++#: src/IDE/Pane/Grep.hs:0+msgid "(Stoped Searching)"+msgstr ""++#: src/IDE/Pane/Grep.hs:0+msgid "Search Complete"+msgstr ""++#: src/IDE/Pane/HLint.hs:0+msgid "Unexpected Expansion in HLint Pane"+msgstr ""++#: src/IDE/Pane/Info.hs:0+msgid "Info"+msgstr ""++#: src/IDE/Pane/Info.hs:0+msgid "Monospace"+msgstr ""++#: src/IDE/Pane/Info.hs:0+msgid "Goto Definition"+msgstr ""++#: src/IDE/Pane/Info.hs:0+msgid "Select Module"+msgstr ""++#: src/IDE/Pane/Info.hs:0+msgid "Open Documentation"+msgstr ""++#: src/IDE/Pane/Log.hs:0+msgid "Log"+msgstr ""++#: src/IDE/Pane/Log.hs:0+msgid "Terminate process"+msgstr ""++#: src/IDE/Pane/Log.hs:0+msgid "Remove launch"+msgstr ""++#: src/IDE/Pane/Log.hs:0+msgid "Can't init log"+msgstr ""++#: src/IDE/Pane/Log.hs:0+msgid "Run external called with args %s"+msgstr ""++#: src/IDE/Pane/Log.hs:0+msgid "Starting external tool: %s with args %s"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Modules"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Module"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Package"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Interface"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Workspace"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "System"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Imports"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Blacklist"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "no path found"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Modules>>insertNodesInTree: Should not happen2"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Impossible in makeNodes"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Edit source"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Expand here"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Collapse here"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Expand all"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Collapse all"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Add module"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Delete module"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Go to definition"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Modules>> descrViewPopup: no selection"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Insert in buffer"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid ">>>Info Changed!!! "+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "categories: %s"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "This should never be shown!"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Are you sure?"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "_Delete Module"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "No package description"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Not a valid module name : %s"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "File already exists! Importing existing file %s.hs"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Construct new module"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "New module "+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Root of the source path"+msgstr ""++#: src/IDE/Pane/Modules.hs:0+msgid "Is this an exposed library module"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select root folder for package"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select cabal package file (.cabal)"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Cabal file with configurations can't be edited with the current version of the editor"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Cabal file with tests of this type can't be edited with the current version of the editor"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "There is already file %s in this directory. Would you like to add this package to the workspace?"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "_Add Package"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "The path you have choosen %s is not an empty directory. Are you sure you want to make a new package here?"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "_Make Package Here"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Setup.(l)hs does not exist. Writing Standard"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Setup.(l)hs already exist"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Add Build Info"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Remove Build Info"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Unnamed"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Content doesn't validate"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Just one Build Info"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Unsaved changes. Close anyway?"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Synopsis"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A one-line summary of this package"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Package Identifier"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A more verbose description of this package"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Homepage"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Package URL"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Category"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Stability"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "License"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "License File"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select file"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Copyright"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Author"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Maintainer"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Bug Reports"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Dependencies "+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Build Dependencies"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Does this package depends on other packages?"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Meta Dep."+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Cabal version"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Does this package depends on a specific version of Cabal?"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Tested with compiler"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Data Files"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of files to be installed for run-time use by the package."+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select File"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Data directory"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Extra Files"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Extra Source Files"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of additional files to be included in source distributions."+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Extra Tmp Files"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of additional files or directories to be removed by setup clean."+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Other"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Build Type"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Describe executable programs contained in the package"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Specify?"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Custom Fields"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Name"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Value"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Executables"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Tests"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Describe tests contained in the package"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Library"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "If the package contains a library, specify the exported modules here"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Specify exported modules"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Does this package contain a library?"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Build Info"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Component is buildable here"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Where to look for the source hierarchy"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Root directories for the source hierarchy."+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select folder"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Non-exposed or non-main modules"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of modules used by the component but not exposed to users."+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Compiler "+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Options for haskell compilers"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Compiler Flavor"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Options"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Additional options for GHC when built with profiling"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Additional options for GHC when the package is built as shared library"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Extensions "+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Extensions"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of Haskell extensions used by every module."+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Build Tools "+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Tools needed for a build"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Pkg Config "+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of pkg-config packages, needed to build this package"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Opts C -1-"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Options for C compiler"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Options for linker"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of header files to use when compiling"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of header files to install"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Opts C -2-"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of directories to search for header files"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select Folder"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of C source files to be compiled,linked with the Haskell files."+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Opts Libs "+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of extra libraries to link with"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of directories to search for libraries."+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Other"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Options for C preprocessor"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Support frameworks for Mac OS X"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Custom fields build info"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Version"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Version Range"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select compiler"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Specify compiler"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Unknown"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Exposed"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Is the lib to be exposed by default?"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Exposed Modules"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Build Info"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Executable Name"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Module Path"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Build info index"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "File with main function"+msgstr ""++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Test Name"+msgstr ""++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Package Flags"+msgstr ""++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Config flags"+msgstr ""++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Build flags"+msgstr ""++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Test flags"+msgstr ""++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Haddock flags"+msgstr ""++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Executable flags"+msgstr ""++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Install flags"+msgstr ""++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Register flags"+msgstr ""++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Unregister flags"+msgstr ""++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Source Distribution flags"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Prefs"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Editor"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Version number of preferences file format"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Integer"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Time of last storage"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Show line numbers"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "(True/False)"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "TextView Font"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Right margin"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Size or 0 for no right margin"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Position"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Show it ?"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Tab width"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Wrap lines"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Use standard line ends even on windows"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Remove trailing blanks when saving a file"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Source candy"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Empty for do not use or the name of a candy file in a config dir"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Candy specification"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Use it ?"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Editor Style"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "classic"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Found Text Background"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Execution Context Text Background"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Breakpoint Text Background"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Automatically load modified files modified outside of Leksah"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Use Yi - Experimental feature (could wipe your files)"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "GUI Options"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "LogView Font"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Window default size"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Default size of the main ide window specified as pair (int,int)"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Use ctrl Tab for Notebook flipper"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Complete only on Hotkey"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Name of the keymap"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "The name of a keymap file in a config dir"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Initial Pane positions"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Categories for panes"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Pane Id"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Pane Category"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Pane path for category"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Pane category"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Pane path"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Default pane path"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Metadata"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Paths under which haskell sources for packages may be found"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Unpack source for cabal packages to"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "URL from which to download prebuilt metadata"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Strategy for downloading prebuilt metadata"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Try to download and then build locally if that fails"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Try to build locally and then download if that fails"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Never download (just try to build locally)"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Update metadata at startup"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Port number for leksah to comunicate with leksah-server"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "IP address for leksah to comunicate with leksah-server"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Stop the leksah-server process when leksah disconnects"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Packages which are excluded from the modules pane"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Build"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Automatically save all files before building"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Select first warning if built without errors"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Background build"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Run unit tests when building"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Make mode"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Single mode"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Single build without linking"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Don't install last package"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Debug"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Enable usage of Show instances in :print"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Break on any exception thrown"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Break on uncaught exceptions and errors"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Turn on printing of binding results in GHCi"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Help"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Browser"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "URL for searching documentation"+msgstr ""++#: src/IDE/Pane/Preferences.hs:0+msgid "Select a special style?"+msgstr ""++#: src/IDE/Pane/Search.hs:0+msgid "Search"+msgstr ""++#: src/IDE/Pane/Search.hs:0+msgid "Exact"+msgstr ""++#: src/IDE/Pane/Search.hs:0+msgid "Prefix"+msgstr ""++#: src/IDE/Pane/Search.hs:0+msgid "Regex"+msgstr ""++#: src/IDE/Pane/Search.hs:0+msgid "Case sensitive"+msgstr ""++#: src/IDE/Pane/Search.hs:0+msgid "Symbol"+msgstr ""++#: src/IDE/Pane/Search.hs:0+msgid "Type/Kind"+msgstr ""++#: src/IDE/Pane/Search.hs:0+msgid "Search >> listViewPopup: no selection"+msgstr ""++#: src/IDE/Pane/Search.hs:0+msgid "Search >> selectDescr: invalid path"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "File path not found "+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "File does not exist "+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Auto Loading "+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "\" has changed on disk."+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Load From Disk"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Always Load From Disk"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Don't Load"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "fileSave: Page not found"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Save File"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "File already exist."+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Overwrite"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Save changes to document: "+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Save"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Don't Save"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "notebook page not found: unexpected"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Open File"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Buffer already open."+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Make _Active"+msgstr ""++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Open Second"+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "Trace"+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "Index"+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "Function"+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "trace parse error %s\\ninput: %s"+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "Back"+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "Forward"+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "Empty history."+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "<end of history>"+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "Not stopped at a breakpoint"+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "traces parser"+msgstr ""++#: src/IDE/Pane/Trace.hs:0+msgid "trace parser"+msgstr ""++#: src/IDE/Pane/Variables.hs:0+msgid "Variables"+msgstr ""++#: src/IDE/Pane/Variables.hs:0+msgid "Type"+msgstr ""++#: src/IDE/Pane/Variables.hs:0+msgid "Force"+msgstr ""++#: src/IDE/Pane/Variables.hs:0+msgid "Print"+msgstr ""++#: src/IDE/Pane/Workspace.hs:0+msgid "Active"+msgstr ""++#: src/IDE/Pane/Workspace.hs:0+msgid "File path"+msgstr ""++#: src/IDE/Pane/Workspace.hs:0+msgid "Activate Package"+msgstr ""++#: src/IDE/Pane/Workspace.hs:0+msgid "Add Package"+msgstr ""++#: src/IDE/Pane/Workspace.hs:0+msgid "Remove Package"+msgstr ""++#: src/IDE/Pane/Workspace.hs:0+msgid "Workspace >> workspaceSelect: invalid path"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Version Con_trol"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Print File"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_File"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_New Module..."+msgstr ""++#: src/IDE/Command.hs:0+msgid "_New Text File"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Open..."+msgstr ""++#: src/IDE/Command.hs:0+msgid "Open _Recent"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Revert"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Save _As..."+msgstr ""++#: src/IDE/Command.hs:0+msgid "Save A_ll"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Close"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Close All"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Close All But Package"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Close All But Workspace"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Quit"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Edit"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Undo"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Redo"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Cu_t"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Copy"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Paste"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Delete"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Select_All"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Find"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Find _Next"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Find _Previous"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Goto Line"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Comment"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Uncomment"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Shift _Right"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Shift _Left"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Align _="+msgstr ""++#: src/IDE/Command.hs:0+msgid "Align -_>"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Align _<-"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Align _::"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Workspace"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_New..."+msgstr ""++#: src/IDE/Command.hs:0+msgid "Cl_ean"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Cleans all packages"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Make"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Makes all of this workspace"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Next Error"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Go to the next error"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Previous Error"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Go to the previous error"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Package"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Add..."+msgstr ""++#: src/IDE/Command.hs:0+msgid "Edit Flags"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Edit the package flags"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Cleans the package"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Configure"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Configures the package"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Build"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Builds the package"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Build Documentation"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Builds the documentation"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Copies the package"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Run"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Runs the package"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Resol_ve Errors"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Resolve 'Hidden package' and 'Not in scope' errors by adding the necessary dependancies or imports"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Install Dependencies"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Install the package's dependencies from the hackage server"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Register"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Test"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Source Dist"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Open Doc"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Debug"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Start Debugger"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Starts using the GHCi debugger for build and run"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Quit Debugger"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Quit the GHCi debugger if it is running"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Execute Selection"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Sends the selected text to the debugger"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Set Breakpoint"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Set a breakpoint on the selected name or current line"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show Next Breakpoint"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show the next breakpoint"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show Previous Breakpoint"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show the previous breakpoint"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Delete All Breakpoints"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Continue"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Resume after a breakpoint"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Abandon"+msgstr ""++#: src/IDE/Command.hs:0+msgid "At a breakpoint, abandon current computation"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Stop"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Interrupt the running operation."+msgstr ""++#: src/IDE/Command.hs:0+msgid "Step"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Single-step after stopping at a breakpoint"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Step Expression"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Single-step into selected expression"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Step Local"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Single-step within the current top-level binding"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Step Module"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Single-step restricted to the current module"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Trace after stopping at a breakpoint"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Trace Expression"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Evaluate the selected expression with tracing on"+msgstr ""++#: src/IDE/Command.hs:0+msgid "History"+msgstr ""++#: src/IDE/Command.hs:0+msgid "After 'Trace', show the execution history"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Go back in the history (after 'Trace')"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Go forward in the history (after 'Back')"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Print the selected expression, forcing unevaluated parts"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Prints a value without forcing its computation"+msgstr ""++#: src/IDE/Command.hs:0+msgid "SimplePrint"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Simplifed version of Print"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show Bin_dings"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show the current bindings"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show _Breakpoints"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show the active breakpoints"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show _Context"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show the breakpoint context"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show Loaded _Modules"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show the currently loaded modules"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show _Packages"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show the currently active packages"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show _Languages"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show the currently active language"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Information"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Display information about the selected name(s)"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Kind"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show the kind of the selected type"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Show the type of the selected expression"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Metadata"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Update workspace data"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Updates data for the current workspace"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Rebuild workspace data"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Rebuilds data for the current workspace"+msgstr ""++#: src/IDE/Command.hs:0+msgid "U_pdate system data"+msgstr ""++#: src/IDE/Command.hs:0+msgid "R_ebuild system data"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Session"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Save Session"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Load Session"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Forget Session"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Panes"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Debugger"+msgstr ""++#: src/IDE/Command.hs:0+msgid "HLint"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Documentation"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_View"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Move _Left"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Move _Right"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Move _Up"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Move _Down"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Split H_orizontal"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Split _Vertical"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Collapse"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Group"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Detach"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Full Screen"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Exit Full Screen"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Dark"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Light"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Tabs Left"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Tabs Right"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Tabs Up"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Tabs Down"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Tabs On/Off"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Close pane"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Flip down"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Flip up"+msgstr ""++#: src/IDE/Command.hs:0+msgid "StartComplete"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Clear Log"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Toggle Toolbar"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Configuration"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_To Candy"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Edit Prefs"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_Help"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Manual"+msgstr ""++#: src/IDE/Command.hs:0+msgid "About"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_BackgroundBuild"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Build in the background and report errors"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_RunUnitTests"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_MakeMode"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Make dependent packages"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Use GHCi debugger to build and run"+msgstr ""++#: src/IDE/Command.hs:0+msgid "_OpenDocu"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Opens a browser for a search of the selected data"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Menu>>makeMenu: failed to create menubar"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Menu>>makeMenu: failed to create toolbar"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Eval"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Eval & Insert"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Find (text)"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Search (metadata)"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Select a text first"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Copyright 2007-2011 Jürgen Nicklisch-Franken, Hamish Mackenzie"+msgstr ""++#: src/IDE/Command.hs:0+msgid "An integrated development environement (IDE) for the "+msgstr ""++#: src/IDE/Command.hs:0+msgid "programming language Haskell and the Glasgow Haskell Compiler"+msgstr ""++#: src/IDE/Command.hs:0+msgid "LICENSE"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Can't load icons from %s %s"+msgstr ""++#: src/IDE/Command.hs:0+msgid "Can't find UI Action %s"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Configuring"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Can't read package file"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Building"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Run the 'configure' command first"+msgstr ""++#: src/IDE/Package.hs:0+msgid "please re-configure"+msgstr ""++#: src/IDE/Package.hs:0+msgid "cannot satisfy -package-id"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Documenting"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Cleaning"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Select the target directory"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Copying"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Installing"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Running %s"+msgstr ""++#: src/IDE/Package.hs:0+msgid "no executable in selected package"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Registering"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Testing"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Opening Documentation"+msgstr ""++#: src/IDE/Package.hs:0+msgid "No active package"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Can't load package "+msgstr ""++#: src/IDE/Package.hs:0+msgid "Couldn't read template file: %s"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Can't update package "+msgstr ""++#: src/IDE/Package.hs:0+msgid "Cabal file with configurations can't be automatically updated with the current version of Leksah"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Can't upade package "+msgstr ""++#: src/IDE/Package.hs:0+msgid "Debugger already running"+msgstr ""++#: src/IDE/Package.hs:0+msgid "GHCi debugger is not running."+msgstr ""++#: src/IDE/Package.hs:0+msgid "_Start GHCi"+msgstr ""++#: src/IDE/Package.hs:0+msgid "Can't activate package "+msgstr ""++#: src/IDE/Session.hs:0+msgid "Version of session file format"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Time of storage"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Layout"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Population"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Window size"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Completion size"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Active pane"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Toolbar visible"+msgstr ""++#: src/IDE/Session.hs:0+msgid "FindbarState"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Recently opened files"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Recently opened workspaces"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Forget this session"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Now saving session"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Save Session as"+msgstr ""++#: src/IDE/Session.hs:0+msgid "Select session file"+msgstr ""++#: src/IDE/Session.hs:0+msgid "apply Layout can only be allied to empty Layout"+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "New file for workspace"+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "No workspace open"+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "You need to have a workspace open for this to work. "+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "Choose ~/leksah.lkshw to "+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "open workspace "+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "create a workspace "+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "_New Workspace"+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "_Open Workspace"+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "Select leksah workspace file (.lkshw)"+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "There are session settings stored with this workspace."+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "_Ignore Session"+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "Can't load workspace file %s\\n%s"+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "You need to have an active package for this to work."+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "_New Package"+msgstr ""++#: src/IDE/Workspaces.hs:0+msgid "No workspace for build."+msgstr ""+
@@ -0,0 +1,2258 @@+# Translation file+# Translators:+# Francisco Miranda Soares da Silva Neto <xfrancisco.soares@gmail.com>, 2013.+# thiago <tsilva.br@gmail.com>, 2013.+msgid ""+msgstr ""+"Project-Id-Version: leksah\n"+"Report-Msgid-Bugs-To: \n"+"POT-Creation-Date: 2009-01-13 06:05-0800\n"+"PO-Revision-Date: 2013-03-28 00:39+0000\n"+"Last-Translator: frsoares <xfrancisco.soares@gmail.com>\n"+"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/leksah/language/pt_BR/)\n"+"MIME-Version: 1.0\n"+"Content-Type: text/plain; charset=UTF-8\n"+"Content-Transfer-Encoding: 8bit\n"+"Language: pt_BR\n"+"Plural-Forms: nplurals=2; plural=(n > 1);\n"++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Breakpoints"+msgstr "Breakpoints"++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Location"+msgstr "Localização"++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Remove breakpoint"+msgstr "Remover breakpoint"++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Debugger>> breakpointViewPopup: no selection2"+msgstr "Depurador>> breakpointViewPopup: não há selection2"++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Remove all breakpoints"+msgstr "Remover todos os breakpoints"++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Update"+msgstr "Atualizar"++#: src/IDE/Pane/Breakpoints.hs:0+msgid "Debugger>>deleteBreakpoint: Not a breakpoint"+msgstr "Depurador>>deleteBreakpoint: Não é um breakpoint"++#: src/IDE/Pane/Errors.hs:0+msgid "Errors"+msgstr "Erros"++#: src/IDE/Pane/Errors.hs:0+msgid "Description"+msgstr "Descrição"++#: src/IDE/Pane/Errors.hs:0+msgid "Resolve Errors"+msgstr "Resolver Erros"++#: src/IDE/Pane/Files.hs:0+msgid "Files"+msgstr "Arquivos"++#: src/IDE/Pane/Files.hs:0+msgid "File"+msgstr "Arquivo"++#: src/IDE/Pane/Files.hs:0+msgid "Unexpected Expansion in Files Pane"+msgstr "Expansão inesperada no painel Arquivos"++#: src/IDE/Pane/Files.hs:0+msgid "Unexpected Activation in Files Pane"+msgstr "Ativação inesperada no painel Arquivos"++#: src/IDE/Pane/Files.hs:0+msgid "Unexpected Selection in Files Pane"+msgstr "Seleção inesperada no painel Arquivos"++#: src/IDE/Pane/Grep.hs:0+msgid "Grep"+msgstr "Grep"++#: src/IDE/Pane/Grep.hs:0+msgid "Line"+msgstr "Linha"++#: src/IDE/Pane/Grep.hs:0+msgid "Context"+msgstr "Contexto"++#: src/IDE/Pane/Grep.hs:0+msgid "(Stoped Searching)"+msgstr "(Busca parada)"++#: src/IDE/Pane/Grep.hs:0+msgid "Search Complete"+msgstr "Busca Completada"++#: src/IDE/Pane/HLint.hs:0+msgid "Unexpected Expansion in HLint Pane"+msgstr "Expansão inesperada no painel HLint"++#: src/IDE/Pane/Info.hs:0+msgid "Info"+msgstr "Info"++#: src/IDE/Pane/Info.hs:0+msgid "Monospace"+msgstr "Monospace"++#: src/IDE/Pane/Info.hs:0+msgid "Goto Definition"+msgstr "Ir para definição"++#: src/IDE/Pane/Info.hs:0+msgid "Select Module"+msgstr "Selecionar Módulo"++#: src/IDE/Pane/Info.hs:0+msgid "Open Documentation"+msgstr "Abrir Documentação"++#: src/IDE/Pane/Log.hs:0+msgid "Log"+msgstr "Log"++#: src/IDE/Pane/Log.hs:0+msgid "Terminate process"+msgstr "Terminar processo"++#: src/IDE/Pane/Log.hs:0+msgid "Remove launch"+msgstr "Remover lançamento"++#: src/IDE/Pane/Log.hs:0+msgid "Can't init log"+msgstr "Não foi possível iniciar log"++#: src/IDE/Pane/Log.hs:0+msgid "Run external called with args %s"+msgstr "Executar chamada externa com args %s"++#: src/IDE/Pane/Log.hs:0+msgid "Starting external tool: %s with args %s"+msgstr "Inicializando ferramenta externa: %s com args %s"++#: src/IDE/Pane/Modules.hs:0+msgid "Modules"+msgstr "Módulos"++#: src/IDE/Pane/Modules.hs:0+msgid "Module"+msgstr "Módulo"++#: src/IDE/Pane/Modules.hs:0+msgid "Package"+msgstr "Pacote"++#: src/IDE/Pane/Modules.hs:0+msgid "Interface"+msgstr "Interface"++#: src/IDE/Pane/Modules.hs:0+msgid "Workspace"+msgstr "Área de Trabalho"++#: src/IDE/Pane/Modules.hs:0+msgid "System"+msgstr "Sistema"++#: src/IDE/Pane/Modules.hs:0+msgid "Imports"+msgstr "Importa"++#: src/IDE/Pane/Modules.hs:0+msgid "Blacklist"+msgstr "Lista negra"++#: src/IDE/Pane/Modules.hs:0+msgid "no path found"+msgstr "caminho não encontrado"++#: src/IDE/Pane/Modules.hs:0+msgid "Modules>>insertNodesInTree: Should not happen2"+msgstr "Modules>>insertNodesInTree: Não deveria acontecer happen2"++#: src/IDE/Pane/Modules.hs:0+msgid "Impossible in makeNodes"+msgstr "Impossível em makeNodes"++#: src/IDE/Pane/Modules.hs:0+msgid "Edit source"+msgstr "Editar fonte"++#: src/IDE/Pane/Modules.hs:0+msgid "Expand here"+msgstr "Expandir aqui"++#: src/IDE/Pane/Modules.hs:0+msgid "Collapse here"+msgstr "Colapsar aqui"++#: src/IDE/Pane/Modules.hs:0+msgid "Expand all"+msgstr "Expandir todos"++#: src/IDE/Pane/Modules.hs:0+msgid "Collapse all"+msgstr "Colapsar tudo"++#: src/IDE/Pane/Modules.hs:0+msgid "Add module"+msgstr "Adicionar módulo"++#: src/IDE/Pane/Modules.hs:0+msgid "Delete module"+msgstr "Remover módulo"++#: src/IDE/Pane/Modules.hs:0+msgid "Go to definition"+msgstr "Ir para definição"++#: src/IDE/Pane/Modules.hs:0+msgid "Modules>> descrViewPopup: no selection"+msgstr "Modules>> descrViewPopup: não há seleção"++#: src/IDE/Pane/Modules.hs:0+msgid "Insert in buffer"+msgstr "Inserir no buffer"++#: src/IDE/Pane/Modules.hs:0+msgid ">>>Info Changed!!! "+msgstr ">>>Informação Alterada!!!"++#: src/IDE/Pane/Modules.hs:0+msgid "categories: %s"+msgstr "categorias: %s"++#: src/IDE/Pane/Modules.hs:0+msgid "This should never be shown!"+msgstr "Isto nunca deveria ser mostrado!"++#: src/IDE/Pane/Modules.hs:0+msgid "Are you sure?"+msgstr "Você tem certeza?"++#: src/IDE/Pane/Modules.hs:0+msgid "_Delete Module"+msgstr "_Deletar Módulo"++#: src/IDE/Pane/Modules.hs:0+msgid "No package description"+msgstr "Sem descrição de pacote"++#: src/IDE/Pane/Modules.hs:0+msgid "Not a valid module name : %s"+msgstr "Nome de módulo inválido: %s"++#: src/IDE/Pane/Modules.hs:0+msgid "File already exists! Importing existing file %s.hs"+msgstr "Arquivo já existe! Importando arquivo existente %s.hs"++#: src/IDE/Pane/Modules.hs:0+msgid "Construct new module"+msgstr "Construir novo modulo"++#: src/IDE/Pane/Modules.hs:0+msgid "New module "+msgstr "Novo módulo"++#: src/IDE/Pane/Modules.hs:0+msgid "Root of the source path"+msgstr "Raiz do caminho de fontes"++#: src/IDE/Pane/Modules.hs:0+msgid "Is this an exposed library module"+msgstr "Este módulo é uma biblioteca exposta?"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select root folder for package"+msgstr "Selecione o diretório raiz para pacote"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select cabal package file (.cabal)"+msgstr "Selecione o arquivo de pacote cabal (.cabal)"++#: src/IDE/Pane/PackageEditor.hs:0+msgid ""+"Cabal file with configurations can't be edited with the current version of "+"the editor"+msgstr "Arquivo cabal com configurações não pode ser editado com a versão atual do editor"++#: src/IDE/Pane/PackageEditor.hs:0+msgid ""+"Cabal file with tests of this type can't be edited with the current version "+"of the editor"+msgstr "Arquivos cabal com testes deste tipo não podem ser editados com a versão atual do editor"++#: src/IDE/Pane/PackageEditor.hs:0+msgid ""+"There is already file %s in this directory. Would you like to add this "+"package to the workspace?"+msgstr "O arquivo %s já existe neste diretório. Você gostaria de adicionar este pacote à área de trabalho?"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "_Add Package"+msgstr "_Adicionar Pacote"++#: src/IDE/Pane/PackageEditor.hs:0+msgid ""+"The path you have choosen %s is not an empty directory. Are you sure you "+"want to make a new package here?"+msgstr "O caminho escolhido %s não é um diretório vazio. Você tem certeza que deseja criar um novo pacote aqui?"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "_Make Package Here"+msgstr "_Criar Pacote Aqui"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Setup.(l)hs does not exist. Writing Standard"+msgstr "Setup.(l)hs não existe. Escrevendo o Padrão"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Setup.(l)hs already exist"+msgstr "Setup.(l)hs já existe!"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Add Build Info"+msgstr "Adicionar Informação de Build"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Remove Build Info"+msgstr "Remover Informação de Build"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Unnamed"+msgstr "Sem nome"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Content doesn't validate"+msgstr "Conteúdo não é válido"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Just one Build Info"+msgstr "Apenas uma Informação de Build"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Unsaved changes. Close anyway?"+msgstr "Há mudanças não salvas. Fechar assim mesmo?"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Synopsis"+msgstr "Sinopse"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A one-line summary of this package"+msgstr "Um resumo deste pacote em uma linha"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Package Identifier"+msgstr "Identificador do Pacote"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A more verbose description of this package"+msgstr "Uma descrição mais verbosa deste pacote"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Homepage"+msgstr "Homepage"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Package URL"+msgstr "URL do Pacote"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Category"+msgstr "Categoria"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Stability"+msgstr "Estabilidade"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "License"+msgstr "Licença"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "License File"+msgstr "Arquivo de Licença"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select file"+msgstr "Selecionar arquivo"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Copyright"+msgstr "Copyright"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Author"+msgstr "Autor"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Maintainer"+msgstr "Mantenedor"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Bug Reports"+msgstr "Relatórios de bugs"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Dependencies "+msgstr "Dependências"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Build Dependencies"+msgstr "Dependências de construção"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Does this package depends on other packages?"+msgstr "Este pacote depende de outros pacotes?"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Meta Dep."+msgstr "Meta dep."++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Cabal version"+msgstr "Versão do Cabal"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Does this package depends on a specific version of Cabal?"+msgstr "Este pacote depende de uma versão específica do Cabal?"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Tested with compiler"+msgstr "Testado com compilador"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Data Files"+msgstr "Arquivos de Dados"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of files to be installed for run-time use by the package."+msgstr "Uma lista de arquivos a serem instalados para uso pelo pacote em tempo de execução"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select File"+msgstr "Selecione Arquivo"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Data directory"+msgstr "Diretório de dados"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Extra Files"+msgstr "Arquivos Extras"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Extra Source Files"+msgstr "Arquivos-fonte Extras"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of additional files to be included in source distributions."+msgstr "Uma lista de arquivos adicionais a serem incluídos na distribuição de fontes"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Extra Tmp Files"+msgstr "Arquivos Temporários Extras"++#: src/IDE/Pane/PackageEditor.hs:0+msgid ""+"A list of additional files or directories to be removed by setup clean."+msgstr "Uma lista de arquivos ou diretórios adicionais a serem removidos pela limpeza de instalação."++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Other"+msgstr "Outro"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Build Type"+msgstr "Tipo de Construção"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Describe executable programs contained in the package"+msgstr "Descreva programas executáveis contidos no pacote"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Specify?"+msgstr "Especificar?"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Custom Fields"+msgstr "Campos Personalizados"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Name"+msgstr "Nome"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Value"+msgstr "Valor"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Executables"+msgstr "Executáveis"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Tests"+msgstr "Testes"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Describe tests contained in the package"+msgstr "Descreva testes contidos no pacote"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Library"+msgstr "Biblioteca"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "If the package contains a library, specify the exported modules here"+msgstr "Se o pacote contém uma biblioteca, especifique os módulos exportados aqui"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Specify exported modules"+msgstr "Especifique módulos exportados"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Does this package contain a library?"+msgstr "Este pacote contém uma biblioteca?"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Build Info"+msgstr "%s Informação de Construção"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Component is buildable here"+msgstr "Componente é construível aqui"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Where to look for the source hierarchy"+msgstr "Onde procurar a hierarquia de arquivos-fonte"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Root directories for the source hierarchy."+msgstr "Diretórios raiz para a hierarquia de fontes"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select folder"+msgstr "Selecione pasta"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Non-exposed or non-main modules"+msgstr "Módulos não-expostos ou sem main"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of modules used by the component but not exposed to users."+msgstr "Uma lista de módulos usados pelo componente mas não expostos para usuários"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Compiler "+msgstr "%s Compilador"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Options for haskell compilers"+msgstr "Opções para compiladores haskell"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Compiler Flavor"+msgstr "Tipo de Compilador"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Options"+msgstr "Opções"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Additional options for GHC when built with profiling"+msgstr "Opções adicionais para o GHC quando constrúido com profiling"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Additional options for GHC when the package is built as shared library"+msgstr "Opções adicionais para o GHC quando o pacote é construído como biblioteca compartilhada"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Extensions "+msgstr "%s Extensões"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Extensions"+msgstr "Extensões"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of Haskell extensions used by every module."+msgstr "Uma lista de extensões de Haskell usadas por cada módulo"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Build Tools "+msgstr "%s Ferramentas de construção"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Tools needed for a build"+msgstr "Ferramentas necessárias para construção"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Pkg Config "+msgstr "%s Pkg Config"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of pkg-config packages, needed to build this package"+msgstr "Uma lista de pacotes pkg-config, necessários para construir este pacote"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Opts C -1-"+msgstr "%s Opts C -1-"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Options for C compiler"+msgstr "Opções para compilador C"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Options for linker"+msgstr "Opções para ligador"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of header files to use when compiling"+msgstr "Uma lista de arquivos de header usados quando compilando"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of header files to install"+msgstr "Uma lista de arquivos de header para instalar"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Opts C -2-"+msgstr "%s Opts C -2-"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of directories to search for header files"+msgstr "Uma lista de diretórios para procurar por arquivos de header"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select Folder"+msgstr "Selecionar pasta"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of C source files to be compiled,linked with the Haskell files."+msgstr "Uma lista de arquivos-fonte C a serem compilados e ligados com arquivos Haskell."++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Opts Libs "+msgstr "%s Opts Libs "++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of extra libraries to link with"+msgstr "Uma lista de bibliotecas extras para linkar com"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "A list of directories to search for libraries."+msgstr "Uma lista de diretórios para procurar por bibliotecas"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "%s Other"+msgstr "%s Outro"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Options for C preprocessor"+msgstr "Opções para o pre-processador C"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Support frameworks for Mac OS X"+msgstr "Frameworks de suporte para Mac OS X"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Custom fields build info"+msgstr "Campos customizados"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Version"+msgstr "Versão"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Version Range"+msgstr "Conjunto de versões"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select compiler"+msgstr "Selecione compilador"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Specify compiler"+msgstr "Especificar compilador"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Select"+msgstr "Selecionar"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Unknown"+msgstr "Desconhecido"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Exposed"+msgstr "Exposto"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Is the lib to be exposed by default?"+msgstr "Essa biblioteca deve ser exposta por padrão?"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Exposed Modules"+msgstr "Módulos Expostos"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Build Info"+msgstr "Informação de Construção"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Executable Name"+msgstr "Nome do Executável"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Module Path"+msgstr "Caminho do Módulo"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Build info index"+msgstr "Índice de informação de construção"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "File with main function"+msgstr "Arquivo com função main"++#: src/IDE/Pane/PackageEditor.hs:0+msgid "Test Name"+msgstr "Nome do Teste"++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Package Flags"+msgstr "Flags do Pacote"++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Config flags"+msgstr "Flags de configuração"++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Build flags"+msgstr "Flags de construção"++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Test flags"+msgstr "Flags de teste"++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Haddock flags"+msgstr "Flags do Haddock"++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Executable flags"+msgstr "Flags do executável"++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Install flags"+msgstr "Flags de instalação"++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Register flags"+msgstr "Registrar flags"++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Unregister flags"+msgstr "Remover flags"++#: src/IDE/Pane/PackageFlags.hs:0+msgid "Source Distribution flags"+msgstr "Flags da distribuição do código fonte"++#: src/IDE/Pane/Preferences.hs:0+msgid "Prefs"+msgstr "Preferências"++#: src/IDE/Pane/Preferences.hs:0+msgid "Editor"+msgstr "Editor"++#: src/IDE/Pane/Preferences.hs:0+msgid "Version number of preferences file format"+msgstr "Número de versão do formato de arquivo de preferências"++#: src/IDE/Pane/Preferences.hs:0+msgid "Integer"+msgstr "Inteiro"++#: src/IDE/Pane/Preferences.hs:0+msgid "Time of last storage"+msgstr "Hora do último armazenamento"++#: src/IDE/Pane/Preferences.hs:0+msgid "Show line numbers"+msgstr "Mostrar números das linhas"++#: src/IDE/Pane/Preferences.hs:0+msgid "(True/False)"+msgstr "(Verdadeiro/Falso)"++#: src/IDE/Pane/Preferences.hs:0+msgid "TextView Font"+msgstr "Fonte do TextView"++#: src/IDE/Pane/Preferences.hs:0+msgid "Right margin"+msgstr "Margem à direita"++#: src/IDE/Pane/Preferences.hs:0+msgid "Size or 0 for no right margin"+msgstr "Tamanho ou 0 para nenhuma margem"++#: src/IDE/Pane/Preferences.hs:0+msgid "Position"+msgstr "Posição"++#: src/IDE/Pane/Preferences.hs:0+msgid "Show it ?"+msgstr "Mostrar?"++#: src/IDE/Pane/Preferences.hs:0+msgid "Tab width"+msgstr "Comprimento da tabulação"++#: src/IDE/Pane/Preferences.hs:0+msgid "Wrap lines"+msgstr "Quebrar linhas"++#: src/IDE/Pane/Preferences.hs:0+msgid "Use standard line ends even on windows"+msgstr "Usar quebras de linha padrão mesmo no Windows"++#: src/IDE/Pane/Preferences.hs:0+msgid "Remove trailing blanks when saving a file"+msgstr "Remover espaços em branco restantes quando salvar arquivo"++#: src/IDE/Pane/Preferences.hs:0+msgid "Source candy"+msgstr "Código açucarado (candy)"++#: src/IDE/Pane/Preferences.hs:0+msgid "Empty for do not use or the name of a candy file in a config dir"+msgstr "Vazio pois não utilize o nome de um arquivo candy em um diretório de configuração"++#: src/IDE/Pane/Preferences.hs:0+msgid "Candy specification"+msgstr "Especificação de Candy"++#: src/IDE/Pane/Preferences.hs:0+msgid "Use it ?"+msgstr "Usar?"++#: src/IDE/Pane/Preferences.hs:0+msgid "Editor Style"+msgstr "Estilo do Editor"++#: src/IDE/Pane/Preferences.hs:0+msgid "classic"+msgstr "clássico"++#: src/IDE/Pane/Preferences.hs:0+msgid "Found Text Background"+msgstr "Área de fundo para texto encontrado"++#: src/IDE/Pane/Preferences.hs:0+msgid "Execution Context Text Background"+msgstr "Área de fundo para contexto de execução"++#: src/IDE/Pane/Preferences.hs:0+msgid "Breakpoint Text Background"+msgstr "Área de fundo para breakpoint"++#: src/IDE/Pane/Preferences.hs:0+msgid "Automatically load modified files modified outside of Leksah"+msgstr "Carregar automaticamente arquivos modificados fora do Leksah"++#: src/IDE/Pane/Preferences.hs:0+msgid "Use Yi - Experimental feature (could wipe your files)"+msgstr "Usar Yi - Funcionalidade experimental (pode destruir seus arquivos)"++#: src/IDE/Pane/Preferences.hs:0+msgid "GUI Options"+msgstr "Opções de GUI"++#: src/IDE/Pane/Preferences.hs:0+msgid "LogView Font"+msgstr "Fonte do LogView"++#: src/IDE/Pane/Preferences.hs:0+msgid "Window default size"+msgstr "Tamanho padrão da janela"++#: src/IDE/Pane/Preferences.hs:0+msgid "Default size of the main ide window specified as pair (int,int)"+msgstr "Tamanho padrão da janela principal da IDE, especificado como um par (Int,Int)"++#: src/IDE/Pane/Preferences.hs:0+msgid "Use ctrl Tab for Notebook flipper"+msgstr "Use ctrl Tab para passar folhas."++#: src/IDE/Pane/Preferences.hs:0+msgid "Complete only on Hotkey"+msgstr "Completar apenas com hotkey"++#: src/IDE/Pane/Preferences.hs:0+msgid "Name of the keymap"+msgstr "Nome do mapa de teclado"++#: src/IDE/Pane/Preferences.hs:0+msgid "The name of a keymap file in a config dir"+msgstr "O nome do arquivo de mapa de teclado em um diretório de configuração"++#: src/IDE/Pane/Preferences.hs:0+msgid "Initial Pane positions"+msgstr "Posição inicial de painel"++#: src/IDE/Pane/Preferences.hs:0+msgid "Categories for panes"+msgstr "Categorias para painéis"++#: src/IDE/Pane/Preferences.hs:0+msgid "Pane Id"+msgstr "Id do Panel"++#: src/IDE/Pane/Preferences.hs:0+msgid "Pane Category"+msgstr "Categoria do Painel"++#: src/IDE/Pane/Preferences.hs:0+msgid "Pane path for category"+msgstr "Caminho do painel para categoria"++#: src/IDE/Pane/Preferences.hs:0+msgid "Pane category"+msgstr "Categoria do painel"++#: src/IDE/Pane/Preferences.hs:0+msgid "Pane path"+msgstr "Caminho do painel"++#: src/IDE/Pane/Preferences.hs:0+msgid "Default pane path"+msgstr "Caminho de painel padrão"++#: src/IDE/Pane/Preferences.hs:0+msgid "Metadata"+msgstr "Metadados"++#: src/IDE/Pane/Preferences.hs:0+msgid "Paths under which haskell sources for packages may be found"+msgstr "Caminhos onde fontes haskell para pacotes podem ser encontrados"++#: src/IDE/Pane/Preferences.hs:0+msgid "Unpack source for cabal packages to"+msgstr "Desempacotar arquivos-fonte de pacotes cabal para"++#: src/IDE/Pane/Preferences.hs:0+msgid "URL from which to download prebuilt metadata"+msgstr "URL de onde se obtem metadados pré-construídos"++#: src/IDE/Pane/Preferences.hs:0+msgid "Strategy for downloading prebuilt metadata"+msgstr "Estratégia para obter metadados pré-construídos"++#: src/IDE/Pane/Preferences.hs:0+msgid "Try to download and then build locally if that fails"+msgstr "Tentar baixar e, então, construir localmente se isso falhar"++#: src/IDE/Pane/Preferences.hs:0+msgid "Try to build locally and then download if that fails"+msgstr "Tentar construir localmente e, então, baixar se isso falhar"++#: src/IDE/Pane/Preferences.hs:0+msgid "Never download (just try to build locally)"+msgstr "Nunca baixar (apenas tentar construir localmente)"++#: src/IDE/Pane/Preferences.hs:0+msgid "Update metadata at startup"+msgstr "Atualizar metadados durante inicialização"++#: src/IDE/Pane/Preferences.hs:0+msgid "Port number for leksah to comunicate with leksah-server"+msgstr "Número da porta para leksah se comunicar com leksah-server"++#: src/IDE/Pane/Preferences.hs:0+msgid "IP address for leksah to comunicate with leksah-server"+msgstr "Enderço IP para leksah se comunicar com leksah-server"++#: src/IDE/Pane/Preferences.hs:0+msgid "Stop the leksah-server process when leksah disconnects"+msgstr "Parar o processo leksah-server quando leksah desconectar"++#: src/IDE/Pane/Preferences.hs:0+msgid "Packages which are excluded from the modules pane"+msgstr "Pacotes que estão excluídos do painel de módulos"++#: src/IDE/Pane/Preferences.hs:0+msgid "Build"+msgstr "Construir"++#: src/IDE/Pane/Preferences.hs:0+msgid "Automatically save all files before building"+msgstr "Salvar todos os arquivos automaticamente antes de construir"++#: src/IDE/Pane/Preferences.hs:0+msgid "Select first warning if built without errors"+msgstr "Selecionar o primeiro aviso se construir sem erros"++#: src/IDE/Pane/Preferences.hs:0+msgid "Background build"+msgstr "Construir em background"++#: src/IDE/Pane/Preferences.hs:0+msgid "Run unit tests when building"+msgstr "Executar testes unitários quando construir"++#: src/IDE/Pane/Preferences.hs:0+msgid "Make mode"+msgstr "Modo de Make"++#: src/IDE/Pane/Preferences.hs:0+msgid "Single mode"+msgstr "Modo individual"++#: src/IDE/Pane/Preferences.hs:0+msgid "Single build without linking"+msgstr "Construção individual sem linking"++#: src/IDE/Pane/Preferences.hs:0+msgid "Don't install last package"+msgstr "Não instalar último pacote"++#: src/IDE/Pane/Preferences.hs:0+msgid "Debug"+msgstr "Depurar"++#: src/IDE/Pane/Preferences.hs:0+msgid "Enable usage of Show instances in :print"+msgstr "Habilitar uso de instâncias de Show em :print"++#: src/IDE/Pane/Preferences.hs:0+msgid "Break on any exception thrown"+msgstr "Parar em qualquer excessão lançada"++#: src/IDE/Pane/Preferences.hs:0+msgid "Break on uncaught exceptions and errors"+msgstr "Parar em excessões não tratadas e erros"++#: src/IDE/Pane/Preferences.hs:0+msgid "Turn on printing of binding results in GHCi"+msgstr "Habilitar exibição de resultados de binding no GHCi"++#: src/IDE/Pane/Preferences.hs:0+msgid "Help"+msgstr "Ajuda"++#: src/IDE/Pane/Preferences.hs:0+msgid "Browser"+msgstr "Navegador"++#: src/IDE/Pane/Preferences.hs:0+msgid "URL for searching documentation"+msgstr "URL para procurar documentação"++#: src/IDE/Pane/Preferences.hs:0+msgid "Select a special style?"+msgstr "Selecionar um estilo especial?"++#: src/IDE/Pane/Search.hs:0+msgid "Search"+msgstr "Buscar"++#: src/IDE/Pane/Search.hs:0+msgid "Exact"+msgstr "Exato"++#: src/IDE/Pane/Search.hs:0+msgid "Prefix"+msgstr "Prefixo"++#: src/IDE/Pane/Search.hs:0+msgid "Regex"+msgstr "Regex"++#: src/IDE/Pane/Search.hs:0+msgid "Case sensitive"+msgstr "Sensível a maiúsculas"++#: src/IDE/Pane/Search.hs:0+msgid "Symbol"+msgstr "Símbolo"++#: src/IDE/Pane/Search.hs:0+msgid "Type/Kind"+msgstr "Tipo/Espécie"++#: src/IDE/Pane/Search.hs:0+msgid "Search >> listViewPopup: no selection"+msgstr "Busca>> listViewPopup: sem seleção"++#: src/IDE/Pane/Search.hs:0+msgid "Search >> selectDescr: invalid path"+msgstr "Busca>> selectDescr: caminho inválido"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "File path not found "+msgstr "Caminho de arquivo não encontrado"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "File does not exist "+msgstr "Arquivo não existe"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Auto Loading "+msgstr "Carregar automaticamente"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "\" has changed on disk."+msgstr "\" foi alterado no disco."++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Load From Disk"+msgstr "_Carregar do Disco"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Always Load From Disk"+msgstr "_Sempre Carregar do Disco"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Don't Load"+msgstr "_Não Carregar"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "fileSave: Page not found"+msgstr "fileSave: Página não encontrada"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Save File"+msgstr "Salvar Arquivo"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "File already exist."+msgstr "Arquivo já existe"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Overwrite"+msgstr "_Sobreescrever"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Save changes to document: "+msgstr "Salvar mudanças para documento:"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Save"+msgstr "_Salvar"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Don't Save"+msgstr "_Não Salvar"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "notebook page not found: unexpected"+msgstr "página de caderno não encontrada: inesperado"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Open File"+msgstr "Abrir Arquivo"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Buffer already open."+msgstr "Buffer já está aberto."++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "Make _Active"+msgstr "Tornar _Ativo"++#: src/IDE/Pane/SourceBuffer.hs:0+msgid "_Open Second"+msgstr "_Abrir Segundo"++#: src/IDE/Pane/Trace.hs:0+msgid "Trace"+msgstr "Trace"++#: src/IDE/Pane/Trace.hs:0+msgid "Index"+msgstr "Índice"++#: src/IDE/Pane/Trace.hs:0+msgid "Function"+msgstr "Função"++#: src/IDE/Pane/Trace.hs:0+msgid "trace parse error %s\\ninput: %s"+msgstr "trace erros de parsing %s\\ninput: %s"++#: src/IDE/Pane/Trace.hs:0+msgid "Back"+msgstr "Voltar"++#: src/IDE/Pane/Trace.hs:0+msgid "Forward"+msgstr "Avançar"++#: src/IDE/Pane/Trace.hs:0+msgid "Empty history."+msgstr "Histórico vazio."++#: src/IDE/Pane/Trace.hs:0+msgid "<end of history>"+msgstr "<fim do histórico>"++#: src/IDE/Pane/Trace.hs:0+msgid "Not stopped at a breakpoint"+msgstr "Não parou em um breakpoint"++#: src/IDE/Pane/Trace.hs:0+msgid "traces parser"+msgstr "trace em parser"++#: src/IDE/Pane/Trace.hs:0+msgid "trace parser"+msgstr "trace de parser"++#: src/IDE/Pane/Variables.hs:0+msgid "Variables"+msgstr "Variáveis"++#: src/IDE/Pane/Variables.hs:0+msgid "Type"+msgstr "Tipo"++#: src/IDE/Pane/Variables.hs:0+msgid "Force"+msgstr "Forçar"++#: src/IDE/Pane/Variables.hs:0+msgid "Print"+msgstr "Imprimir"++#: src/IDE/Pane/Workspace.hs:0+msgid "Active"+msgstr "Ativo"++#: src/IDE/Pane/Workspace.hs:0+msgid "File path"+msgstr "Caminho do arquivo"++#: src/IDE/Pane/Workspace.hs:0+msgid "Activate Package"+msgstr "Ativar Pacote"++#: src/IDE/Pane/Workspace.hs:0+msgid "Add Package"+msgstr "Adicionar Pacote"++#: src/IDE/Pane/Workspace.hs:0+msgid "Remove Package"+msgstr "Remover Pacote"++#: src/IDE/Pane/Workspace.hs:0+msgid "Workspace >> workspaceSelect: invalid path"+msgstr "Workspace >> workspaceSelect: caminho invaálido"++#: src/IDE/Command.hs:0+msgid "Version Con_trol"+msgstr "Con_trole de Versão"++#: src/IDE/Command.hs:0+msgid "_Print File"+msgstr "_Imprimir Arquivo"++#: src/IDE/Command.hs:0+msgid "_File"+msgstr "_Arquivo"++#: src/IDE/Command.hs:0+msgid "_New Module..."+msgstr "_Novo Módulo..."++#: src/IDE/Command.hs:0+msgid "_New Text File"+msgstr "_Novo Arquivo Texto"++#: src/IDE/Command.hs:0+msgid "_Open..."+msgstr "_Abrir..."++#: src/IDE/Command.hs:0+msgid "Open _Recent"+msgstr "Abrir _Recente"++#: src/IDE/Command.hs:0+msgid "_Revert"+msgstr "_Reverter"++#: src/IDE/Command.hs:0+msgid "Save _As..."+msgstr "Salvar _Como..."++#: src/IDE/Command.hs:0+msgid "Save A_ll"+msgstr "Salvar _Todos"++#: src/IDE/Command.hs:0+msgid "_Close"+msgstr "_Fechar"++#: src/IDE/Command.hs:0+msgid "Close All"+msgstr "Fechar Todos"++#: src/IDE/Command.hs:0+msgid "Close All But Package"+msgstr "Fechar Todos Exceto Pacote"++#: src/IDE/Command.hs:0+msgid "Close All But Workspace"+msgstr "Fechar Todos Menos a Área de Trabalho"++#: src/IDE/Command.hs:0+msgid "_Quit"+msgstr "_Sair"++#: src/IDE/Command.hs:0+msgid "_Edit"+msgstr "_Editar"++#: src/IDE/Command.hs:0+msgid "_Undo"+msgstr "_Desfazer"++#: src/IDE/Command.hs:0+msgid "_Redo"+msgstr "_Refazer"++#: src/IDE/Command.hs:0+msgid "Cu_t"+msgstr "Recor_tar"++#: src/IDE/Command.hs:0+msgid "_Copy"+msgstr "_Copiar"++#: src/IDE/Command.hs:0+msgid "_Paste"+msgstr "_Colar"++#: src/IDE/Command.hs:0+msgid "_Delete"+msgstr "_Deletar"++#: src/IDE/Command.hs:0+msgid "Select_All"+msgstr "Selecionar_Tudo"++#: src/IDE/Command.hs:0+msgid "Find"+msgstr "Buscar"++#: src/IDE/Command.hs:0+msgid "Find _Next"+msgstr "Buscar _Próximo"++#: src/IDE/Command.hs:0+msgid "Find _Previous"+msgstr "Buscar _Anterior"++#: src/IDE/Command.hs:0+msgid "_Goto Line"+msgstr "_Ir para a linha"++#: src/IDE/Command.hs:0+msgid "_Comment"+msgstr "_Comentar"++#: src/IDE/Command.hs:0+msgid "_Uncomment"+msgstr "_Descomentar"++#: src/IDE/Command.hs:0+msgid "Shift _Right"+msgstr "Shift à _Direita"++#: src/IDE/Command.hs:0+msgid "Shift _Left"+msgstr "Shift à _Esquerda"++#: src/IDE/Command.hs:0+msgid "Align _="+msgstr "Alinhar _="++#: src/IDE/Command.hs:0+msgid "Align -_>"+msgstr "Alinhar -_>"++#: src/IDE/Command.hs:0+msgid "Align _<-"+msgstr "Alinhar _<-"++#: src/IDE/Command.hs:0+msgid "Align _::"+msgstr "Alinhar _::"++#: src/IDE/Command.hs:0+msgid "_Workspace"+msgstr "_Área de Trabalho"++#: src/IDE/Command.hs:0+msgid "_New..."+msgstr "_Novo..."++#: src/IDE/Command.hs:0+msgid "Cl_ean"+msgstr "_Limpar"++#: src/IDE/Command.hs:0+msgid "Cleans all packages"+msgstr "Limpar todos os pacotes"++#: src/IDE/Command.hs:0+msgid "_Make"+msgstr "_Make"++#: src/IDE/Command.hs:0+msgid "Makes all of this workspace"+msgstr "Make em tudo nesta área de trabalho"++#: src/IDE/Command.hs:0+msgid "_Next Error"+msgstr "_Próximo Erro"++#: src/IDE/Command.hs:0+msgid "Go to the next error"+msgstr "Ir para o próximo erro"++#: src/IDE/Command.hs:0+msgid "_Previous Error"+msgstr "_Erro Anterior"++#: src/IDE/Command.hs:0+msgid "Go to the previous error"+msgstr "Ir para erro anterior"++#: src/IDE/Command.hs:0+msgid "_Package"+msgstr "_Pacote"++#: src/IDE/Command.hs:0+msgid "_Add..."+msgstr "_Adicionar..."++#: src/IDE/Command.hs:0+msgid "Edit Flags"+msgstr "Editar Flags"++#: src/IDE/Command.hs:0+msgid "Edit the package flags"+msgstr "Editar flags do pacote"++#: src/IDE/Command.hs:0+msgid "Cleans the package"+msgstr "Limpa o pacote"++#: src/IDE/Command.hs:0+msgid "_Configure"+msgstr "_Configurar"++#: src/IDE/Command.hs:0+msgid "Configures the package"+msgstr "Configura o pacote"++#: src/IDE/Command.hs:0+msgid "_Build"+msgstr "_Construir"++#: src/IDE/Command.hs:0+msgid "Builds the package"+msgstr "Constrói o pacote"++#: src/IDE/Command.hs:0+msgid "_Build Documentation"+msgstr "_Construir Documentação"++#: src/IDE/Command.hs:0+msgid "Builds the documentation"+msgstr "Constrói a documentação"++#: src/IDE/Command.hs:0+msgid "Copies the package"+msgstr "Copia o pacote"++#: src/IDE/Command.hs:0+msgid "_Run"+msgstr "_Executar"++#: src/IDE/Command.hs:0+msgid "Runs the package"+msgstr "Executa o pacote"++#: src/IDE/Command.hs:0+msgid "Resol_ve Errors"+msgstr "Resol_ver Erros"++#: src/IDE/Command.hs:0+msgid ""+"Resolve 'Hidden package' and 'Not in scope' errors by adding the necessary "+"dependancies or imports"+msgstr "Resolver erros de 'Pacote escondido' ou 'Fora de escopo' com adição das dependências ou importações necessárias"++#: src/IDE/Command.hs:0+msgid "_Install Dependencies"+msgstr "_Instalar Dependências"++#: src/IDE/Command.hs:0+msgid "Install the package's dependencies from the hackage server"+msgstr "Instalar dependências do pacote pelo servidor hackage"++#: src/IDE/Command.hs:0+msgid "_Register"+msgstr "_Registrar"++#: src/IDE/Command.hs:0+msgid "Test"+msgstr "Testar"++#: src/IDE/Command.hs:0+msgid "Source Dist"+msgstr "Distribuição de Fontes"++#: src/IDE/Command.hs:0+msgid "_Open Doc"+msgstr "_Abrir Documentação"++#: src/IDE/Command.hs:0+msgid "_Debug"+msgstr "_Depurar"++#: src/IDE/Command.hs:0+msgid "_Start Debugger"+msgstr "_Inicializar Depurador"++#: src/IDE/Command.hs:0+msgid "Starts using the GHCi debugger for build and run"+msgstr "Passa a usar o depurador GHCi para construção e execução"++#: src/IDE/Command.hs:0+msgid "_Quit Debugger"+msgstr "_Sair do Depurador"++#: src/IDE/Command.hs:0+msgid "Quit the GHCi debugger if it is running"+msgstr "Sair do depurador GHCi se estiver em execução"++#: src/IDE/Command.hs:0+msgid "_Execute Selection"+msgstr "_Executar Seleção"++#: src/IDE/Command.hs:0+msgid "Sends the selected text to the debugger"+msgstr "Envia o texto selecionado para o depurador"++#: src/IDE/Command.hs:0+msgid "Set Breakpoint"+msgstr "Criar breakpoint"++#: src/IDE/Command.hs:0+msgid "Set a breakpoint on the selected name or current line"+msgstr "Criar breakpoint no nome selecionado ou na linha atual"++#: src/IDE/Command.hs:0+msgid "Show Next Breakpoint"+msgstr "Mostrar Próximo Breakpoint"++#: src/IDE/Command.hs:0+msgid "Show the next breakpoint"+msgstr "Mostrar o próximo breakpoint"++#: src/IDE/Command.hs:0+msgid "Show Previous Breakpoint"+msgstr "Mostrar Breakpoint Anterior"++#: src/IDE/Command.hs:0+msgid "Show the previous breakpoint"+msgstr "Mostrar o breakpoint anterior"++#: src/IDE/Command.hs:0+msgid "Delete All Breakpoints"+msgstr "Deletar Todos os Breakpoints"++#: src/IDE/Command.hs:0+msgid "Continue"+msgstr "Continuar"++#: src/IDE/Command.hs:0+msgid "Resume after a breakpoint"+msgstr "Continuar após breakpoint"++#: src/IDE/Command.hs:0+msgid "Abandon"+msgstr "Abandonar"++#: src/IDE/Command.hs:0+msgid "At a breakpoint, abandon current computation"+msgstr "Em um breakpoint, abandonar a computação atual"++#: src/IDE/Command.hs:0+msgid "Stop"+msgstr "Parar"++#: src/IDE/Command.hs:0+msgid "Interrupt the running operation."+msgstr "Interromper a operação em execução"++#: src/IDE/Command.hs:0+msgid "Step"+msgstr "Passo"++#: src/IDE/Command.hs:0+msgid "Single-step after stopping at a breakpoint"+msgstr "Passo-simples após parar em breakpoint"++#: src/IDE/Command.hs:0+msgid "Step Expression"+msgstr "Expressão de Passo"++#: src/IDE/Command.hs:0+msgid "Single-step into selected expression"+msgstr "Passo-simples para a expressão selecionada"++#: src/IDE/Command.hs:0+msgid "Step Local"+msgstr "Passo Local"++#: src/IDE/Command.hs:0+msgid "Single-step within the current top-level binding"+msgstr "Passo-simples dentro dos bindings de maior nível atuais"++#: src/IDE/Command.hs:0+msgid "Step Module"+msgstr "Passo de Módulo"++#: src/IDE/Command.hs:0+msgid "Single-step restricted to the current module"+msgstr "Passo-simples restrito ao módulo atual"++#: src/IDE/Command.hs:0+msgid "Trace after stopping at a breakpoint"+msgstr "Trace após interromper em um breakpoint"++#: src/IDE/Command.hs:0+msgid "Trace Expression"+msgstr "Expressão de Trace"++#: src/IDE/Command.hs:0+msgid "Evaluate the selected expression with tracing on"+msgstr "Avaliar a expressão selecionada com trace ativado"++#: src/IDE/Command.hs:0+msgid "History"+msgstr "Histórico"++#: src/IDE/Command.hs:0+msgid "After 'Trace', show the execution history"+msgstr "Após 'Trace', exibir histórico de execução"++#: src/IDE/Command.hs:0+msgid "Go back in the history (after 'Trace')"+msgstr "Voltar no histórico (após 'Trace')"++#: src/IDE/Command.hs:0+msgid "Go forward in the history (after 'Back')"+msgstr "Avançar no histórico (após 'Voltar')"++#: src/IDE/Command.hs:0+msgid "Print the selected expression, forcing unevaluated parts"+msgstr "Imprime a expressão selecionada, forçando partes não ainda avaliadas"++#: src/IDE/Command.hs:0+msgid "Prints a value without forcing its computation"+msgstr "Imprime um valor sem forçar sua computação"++#: src/IDE/Command.hs:0+msgid "SimplePrint"+msgstr "Impressão Simples"++#: src/IDE/Command.hs:0+msgid "Simplifed version of Print"+msgstr "Versão simplificada de Imprimir"++#: src/IDE/Command.hs:0+msgid "Show Bin_dings"+msgstr "Exibir Bin_dings"++#: src/IDE/Command.hs:0+msgid "Show the current bindings"+msgstr "Mostrar os bindings atuais"++#: src/IDE/Command.hs:0+msgid "Show _Breakpoints"+msgstr "Exibir _Breakpoints"++#: src/IDE/Command.hs:0+msgid "Show the active breakpoints"+msgstr "Exibir os breakpoints ativos"++#: src/IDE/Command.hs:0+msgid "Show _Context"+msgstr "Exibir _Contexto"++#: src/IDE/Command.hs:0+msgid "Show the breakpoint context"+msgstr "Exibe o contexto do breakpoint"++#: src/IDE/Command.hs:0+msgid "Show Loaded _Modules"+msgstr "Exibir _Módulos Carregados"++#: src/IDE/Command.hs:0+msgid "Show the currently loaded modules"+msgstr "Exibe os módulos carregados no momento"++#: src/IDE/Command.hs:0+msgid "Show _Packages"+msgstr "Exibir _Pacotes"++#: src/IDE/Command.hs:0+msgid "Show the currently active packages"+msgstr "Exibe os pacotes ativos no momento"++#: src/IDE/Command.hs:0+msgid "Show _Languages"+msgstr "Exibir _Linguagens"++#: src/IDE/Command.hs:0+msgid "Show the currently active language"+msgstr "Exibe as flags de linguagem ativas no momento"++#: src/IDE/Command.hs:0+msgid "Information"+msgstr "Informação"++#: src/IDE/Command.hs:0+msgid "Display information about the selected name(s)"+msgstr "Apresentar informação sobre o(s) nome(s) selecionado(s)"++#: src/IDE/Command.hs:0+msgid "Kind"+msgstr "Espécie"++#: src/IDE/Command.hs:0+msgid "Show the kind of the selected type"+msgstr "Mostrar a espécie do tipo selecionado"++#: src/IDE/Command.hs:0+msgid "Show the type of the selected expression"+msgstr "Mostrar o tipo da expressão selecionada"++#: src/IDE/Command.hs:0+msgid "_Metadata"+msgstr "_Metadados"++#: src/IDE/Command.hs:0+msgid "_Update workspace data"+msgstr "_Atualizar dados da área de trabalho"++#: src/IDE/Command.hs:0+msgid "Updates data for the current workspace"+msgstr "Atualiza dados para a área de trabalho atual"++#: src/IDE/Command.hs:0+msgid "_Rebuild workspace data"+msgstr "_Reconstruir dados da área de trabalho"++#: src/IDE/Command.hs:0+msgid "Rebuilds data for the current workspace"+msgstr "Reconstroi os dados da área de trabalho atual"++#: src/IDE/Command.hs:0+msgid "U_pdate system data"+msgstr "A_tualizar dados do sistema"++#: src/IDE/Command.hs:0+msgid "R_ebuild system data"+msgstr "R_econstruir dados do sistema"++#: src/IDE/Command.hs:0+msgid "_Session"+msgstr "_Sessão"++#: src/IDE/Command.hs:0+msgid "_Save Session"+msgstr "_Salvar Sessão"++#: src/IDE/Command.hs:0+msgid "_Load Session"+msgstr "_Carregar Sessão"++#: src/IDE/Command.hs:0+msgid "_Forget Session"+msgstr "_Esquecer Sessão"++#: src/IDE/Command.hs:0+msgid "_Panes"+msgstr "_Painéis"++#: src/IDE/Command.hs:0+msgid "Debugger"+msgstr "Depurador"++#: src/IDE/Command.hs:0+msgid "HLint"+msgstr "HLint"++#: src/IDE/Command.hs:0+msgid "Documentation"+msgstr "Documentação"++#: src/IDE/Command.hs:0+msgid "_View"+msgstr "_Exibir"++#: src/IDE/Command.hs:0+msgid "Move _Left"+msgstr "Mover para a _Esquerda"++#: src/IDE/Command.hs:0+msgid "Move _Right"+msgstr "Mover para a _Direita"++#: src/IDE/Command.hs:0+msgid "Move _Up"+msgstr "Mover para _Cima"++#: src/IDE/Command.hs:0+msgid "Move _Down"+msgstr "Mover para _Baixo"++#: src/IDE/Command.hs:0+msgid "Split H_orizontal"+msgstr "Dividir H_orizontalmente"++#: src/IDE/Command.hs:0+msgid "Split _Vertical"+msgstr "Dividir _Verticalmente"++#: src/IDE/Command.hs:0+msgid "_Collapse"+msgstr "_Colapsar"++#: src/IDE/Command.hs:0+msgid "_Group"+msgstr "A_grupar"++#: src/IDE/Command.hs:0+msgid "_Detach"+msgstr "_Destacar"++#: src/IDE/Command.hs:0+msgid "_Full Screen"+msgstr "_Tela Cheia"++#: src/IDE/Command.hs:0+msgid "_Exit Full Screen"+msgstr "_Sair de Tela Cheia"++#: src/IDE/Command.hs:0+msgid "Dark"+msgstr "Escuro"++#: src/IDE/Command.hs:0+msgid "Light"+msgstr "Claro"++#: src/IDE/Command.hs:0+msgid "Tabs Left"+msgstr "Tabs à Esquerda"++#: src/IDE/Command.hs:0+msgid "Tabs Right"+msgstr "Tabs à Direita"++#: src/IDE/Command.hs:0+msgid "Tabs Up"+msgstr "Tabs acima"++#: src/IDE/Command.hs:0+msgid "Tabs Down"+msgstr "Tabs abaixo"++#: src/IDE/Command.hs:0+msgid "Tabs On/Off"+msgstr "Tabs ativado/desativado"++#: src/IDE/Command.hs:0+msgid "Close pane"+msgstr "Fechar painel"++#: src/IDE/Command.hs:0+msgid "Flip down"+msgstr "Flip abaixo"++#: src/IDE/Command.hs:0+msgid "Flip up"+msgstr "Flip acima"++#: src/IDE/Command.hs:0+msgid "StartComplete"+msgstr "Iniciar Preenchimento"++#: src/IDE/Command.hs:0+msgid "_Clear Log"+msgstr "_Limpar Log"++#: src/IDE/Command.hs:0+msgid "Toggle Toolbar"+msgstr "Acionar Toolbar"++#: src/IDE/Command.hs:0+msgid "_Configuration"+msgstr "_Configuração"++#: src/IDE/Command.hs:0+msgid "_To Candy"+msgstr "_Para Candy"++#: src/IDE/Command.hs:0+msgid "_Edit Prefs"+msgstr "_Editar Preferências"++#: src/IDE/Command.hs:0+msgid "_Help"+msgstr "_Ajuda"++#: src/IDE/Command.hs:0+msgid "Manual"+msgstr "Manual"++#: src/IDE/Command.hs:0+msgid "About"+msgstr "Sobre"++#: src/IDE/Command.hs:0+msgid "_BackgroundBuild"+msgstr "_Construção em segundo plano"++#: src/IDE/Command.hs:0+msgid "Build in the background and report errors"+msgstr "Construir em segundo plano e reportar erros"++#: src/IDE/Command.hs:0+msgid "_RunUnitTests"+msgstr "_Rodar testes unitários"++#: src/IDE/Command.hs:0+msgid "_MakeMode"+msgstr "_ModoMake"++#: src/IDE/Command.hs:0+msgid "Make dependent packages"+msgstr "Make dependências de pacote"++#: src/IDE/Command.hs:0+msgid "Use GHCi debugger to build and run"+msgstr "Usar depurador GHCi para construir e executar"++#: src/IDE/Command.hs:0+msgid "_OpenDocu"+msgstr "_AbrirDocu"++#: src/IDE/Command.hs:0+msgid "Opens a browser for a search of the selected data"+msgstr "Abre um navegador para uma busca dos dados selecionados."++#: src/IDE/Command.hs:0+msgid "Menu>>makeMenu: failed to create menubar"+msgstr "Menu>>makeMenu: falha ao criar barra de menu"++#: src/IDE/Command.hs:0+msgid "Menu>>makeMenu: failed to create toolbar"+msgstr "Menu>>makeMenu: falha ao criar barra de ferramentas"++#: src/IDE/Command.hs:0+msgid "Eval"+msgstr "Avaliar"++#: src/IDE/Command.hs:0+msgid "Eval & Insert"+msgstr "Avaliar & Inserir"++#: src/IDE/Command.hs:0+msgid "Find (text)"+msgstr "Pesquisar (texto)"++#: src/IDE/Command.hs:0+msgid "Search (metadata)"+msgstr "Buscar (metadados)"++#: src/IDE/Command.hs:0+msgid "Select a text first"+msgstr "Selecione texto primeiro"++#: src/IDE/Command.hs:0+msgid "Copyright 2007-2011 Jürgen Nicklisch-Franken, Hamish Mackenzie"+msgstr "Copyright 2007-2011 Jürgen Nicklisch-Franken, Hamish Mackenzie"++#: src/IDE/Command.hs:0+msgid "An integrated development environement (IDE) for the "+msgstr "Um ambiente de desenvolvimento integrado (IDE) para a"++#: src/IDE/Command.hs:0+msgid "programming language Haskell and the Glasgow Haskell Compiler"+msgstr "linguagem de programação Haskell e o compilador Glasgow"++#: src/IDE/Command.hs:0+msgid "LICENSE"+msgstr "LICENSE"++#: src/IDE/Command.hs:0+msgid "Can't load icons from %s %s"+msgstr "Não é possível carregar ícones de %s %s"++#: src/IDE/Command.hs:0+msgid "Can't find UI Action %s"+msgstr "UI Action %s não encontrada"++#: src/IDE/Package.hs:0+msgid "Configuring"+msgstr "Configurando"++#: src/IDE/Package.hs:0+msgid "Can't read package file"+msgstr "Não é possível ler arquivo de pacote"++#: src/IDE/Package.hs:0+msgid "Building"+msgstr "Construindo"++#: src/IDE/Package.hs:0+msgid "Run the 'configure' command first"+msgstr "Execute o comando 'configure' primeiro"++#: src/IDE/Package.hs:0+msgid "please re-configure"+msgstr "favor re-configurar"++#: src/IDE/Package.hs:0+msgid "cannot satisfy -package-id"+msgstr "Não foi possível satisfazer -pacote-id"++#: src/IDE/Package.hs:0+msgid "Documenting"+msgstr "Documentando"++#: src/IDE/Package.hs:0+msgid "Cleaning"+msgstr "Limpando"++#: src/IDE/Package.hs:0+msgid "Select the target directory"+msgstr "Selecione o diretório alvo"++#: src/IDE/Package.hs:0+msgid "Copying"+msgstr "Copiando"++#: src/IDE/Package.hs:0+msgid "Installing"+msgstr "Instalando"++#: src/IDE/Package.hs:0+msgid "Running %s"+msgstr "Executando %s"++#: src/IDE/Package.hs:0+msgid "no executable in selected package"+msgstr "nenhum executável no pacote selecionado"++#: src/IDE/Package.hs:0+msgid "Registering"+msgstr "Registrando"++#: src/IDE/Package.hs:0+msgid "Testing"+msgstr "Testando"++#: src/IDE/Package.hs:0+msgid "Opening Documentation"+msgstr "Abrindo Documentação"++#: src/IDE/Package.hs:0+msgid "No active package"+msgstr "Nenhum pacote ativo"++#: src/IDE/Package.hs:0+msgid "Can't load package "+msgstr "Não foi possível carregar pacote"++#: src/IDE/Package.hs:0+msgid "Couldn't read template file: %s"+msgstr "Não foi possível ler arquivo template: %s"++#: src/IDE/Package.hs:0+msgid "Can't update package "+msgstr "Não foi possível atualizar pacote"++#: src/IDE/Package.hs:0+msgid ""+"Cabal file with configurations can't be automatically updated with the "+"current version of Leksah"+msgstr "Arquivos cabal com configurações não podem ser atualizados automaticamente com a versão atual do Leksah"++#: src/IDE/Package.hs:0+msgid "Can't upade package "+msgstr "Não foi possível atualizar pacote"++#: src/IDE/Package.hs:0+msgid "Debugger already running"+msgstr "Depurador já está em execução"++#: src/IDE/Package.hs:0+msgid "GHCi debugger is not running."+msgstr "Depurador GHCi não está em execução."++#: src/IDE/Package.hs:0+msgid "_Start GHCi"+msgstr "_Iniciar GHCi"++#: src/IDE/Package.hs:0+msgid "Can't activate package "+msgstr "Não foi possível ativar pacote"++#: src/IDE/Session.hs:0+msgid "Version of session file format"+msgstr "Versão do formato de arquivo de sessão"++#: src/IDE/Session.hs:0+msgid "Time of storage"+msgstr "Horário do armazenamento"++#: src/IDE/Session.hs:0+msgid "Layout"+msgstr "Layout"++#: src/IDE/Session.hs:0+msgid "Population"+msgstr "População"++#: src/IDE/Session.hs:0+msgid "Window size"+msgstr "Tamanho da janela"++#: src/IDE/Session.hs:0+msgid "Completion size"+msgstr "Tamanho do preenchimento"++#: src/IDE/Session.hs:0+msgid "Active pane"+msgstr "Painel ativo"++#: src/IDE/Session.hs:0+msgid "Toolbar visible"+msgstr "Barra de ferramentas visível"++#: src/IDE/Session.hs:0+msgid "FindbarState"+msgstr "FindbarState"++#: src/IDE/Session.hs:0+msgid "Recently opened files"+msgstr "Arquivos recentes"++#: src/IDE/Session.hs:0+msgid "Recently opened workspaces"+msgstr "Áreas de trabalho recentes"++#: src/IDE/Session.hs:0+msgid "Forget this session"+msgstr "Esquecer desta sessão"++#: src/IDE/Session.hs:0+msgid "Now saving session"+msgstr "Salvando sessão agora"++#: src/IDE/Session.hs:0+msgid "Save Session as"+msgstr "Salvar Sessão como"++#: src/IDE/Session.hs:0+msgid "Select session file"+msgstr "Selecione arquivo de sessão"++#: src/IDE/Session.hs:0+msgid "apply Layout can only be allied to empty Layout"+msgstr "aplicar Layout só pode ser usado com Layout vazio"++#: src/IDE/Workspaces.hs:0+msgid "New file for workspace"+msgstr "Novo arquivo para área de trabalho"++#: src/IDE/Workspaces.hs:0+msgid "No workspace open"+msgstr "Nenhuma área de trabalho aberta"++#: src/IDE/Workspaces.hs:0+msgid "You need to have a workspace open for this to work. "+msgstr "É necessário uma área de trabalho aberta para isto funcionar. "++#: src/IDE/Workspaces.hs:0+msgid "Choose ~/leksah.lkshw to "+msgstr "Escolha ~/leksah.lkshw para "++#: src/IDE/Workspaces.hs:0+msgid "open workspace "+msgstr "abrir área de trabalho "++#: src/IDE/Workspaces.hs:0+msgid "create a workspace "+msgstr "criar área de trabalho "++#: src/IDE/Workspaces.hs:0+msgid "_New Workspace"+msgstr "_Nova Área de Trabalho"++#: src/IDE/Workspaces.hs:0+msgid "_Open Workspace"+msgstr "_Abrir Área de Trabalho"++#: src/IDE/Workspaces.hs:0+msgid "Select leksah workspace file (.lkshw)"+msgstr "Selecione arquivo de área de trabalho do leksah (.lkshw)"++#: src/IDE/Workspaces.hs:0+msgid "There are session settings stored with this workspace."+msgstr "Há configurações de sessão armazenadas nesta área de trabalho"++#: src/IDE/Workspaces.hs:0+msgid "_Ignore Session"+msgstr "_Ignorar Sessão"++#: src/IDE/Workspaces.hs:0+msgid "Can't load workspace file %s\\n%s"+msgstr "Não é possível carregar arquivo de área de trabalho %s\\n%s"++#: src/IDE/Workspaces.hs:0+msgid "You need to have an active package for this to work."+msgstr "Você precisa ter um pacote ativo para isto funcionar."++#: src/IDE/Workspaces.hs:0+msgid "_New Package"+msgstr "_Novo Pacote"++#: src/IDE/Workspaces.hs:0+msgid "No workspace for build."+msgstr "Não há área de trabalho para se construir."
@@ -0,0 +1,34 @@+#!/bin/sh -ex++ghc-pkg$GHCVERSION unregister --force leksah || true+ghc-pkg$GHCVERSION unregister --force leksah-server || true+ghc-pkg$GHCVERSION unregister --force ltk || true+ghc-pkg$GHCVERSION unregister --force vcsgui || true+ghc-pkg$GHCVERSION unregister --force vado || true+ghc-pkg$GHCVERSION unregister --force yi || true+ghc-pkg$GHCVERSION unregister --force ghcjs-dom || true+ghc-pkg$GHCVERSION unregister --force jsaddle || true+ghc-pkg$GHCVERSION unregister --force gtksourceview2 || true+ghc-pkg$GHCVERSION unregister --force gtksourceview3 || true+ghc-pkg$GHCVERSION unregister --force webkit-javascriptcore || true+ghc-pkg$GHCVERSION unregister --force webkitgtk3-javascriptcore || true+ghc-pkg$GHCVERSION unregister --force webkit || true+ghc-pkg$GHCVERSION unregister --force webkitgtk3 || true+ghc-pkg$GHCVERSION unregister --force gtk-mac-integration || true+ghc-pkg$GHCVERSION unregister --force gtk || true+ghc-pkg$GHCVERSION unregister --force gtk3 || true+ghc-pkg$GHCVERSION unregister --force pango || true+ghc-pkg$GHCVERSION unregister --force cairo || true+ghc-pkg$GHCVERSION unregister --force gio || true+ghc-pkg$GHCVERSION unregister --force glib || true+ghc-pkg$GHCVERSION unregister --force hlint || true++rm -rf vendor/*/dist \+ vendor/gtk2hs/*/dist \+ vendor/yi/*/dist \+ vendor/*/*/dist \+ vendor/*/vendor/*/dist \+ vendor/*/vendor/*/*/dist \+ vendor/*/vendor/gtk2hs/*/dist || true++cabal clean || exit
@@ -0,0 +1,54 @@+#!/bin/sh++ghc-pkg$GHCVERSION unregister leksah || true+ghc-pkg$GHCVERSION unregister leksah-server || true+ghc-pkg$GHCVERSION unregister ltk || true++export FULL_VERSION=`grep '^version: ' leksah.cabal | sed 's|version: ||' | tr -d '\r'`+export SHORT_VERSION=`echo $FULL_VERSION | sed 's|\.[0-9]*\.[0-9]*$||'`+export LEKSAH_X_X_X_X=leksah-$FULL_VERSION+export LEKSAH_X_X=leksah-$SHORT_VERSION++export GHC_VER=`ghc$GHCVERSION --numeric-version`+export LEKSAH_X_X_X_X_GHC_X_X_X=leksah-$FULL_VERSION-ghc-$GHC_VER++export GTK_PREFIX=`pkg-config --libs-only-L gtk+-3.0 | sed 's|^-L||' | sed 's|/lib *.*$||'`++echo Staging Leksah in $GTK_PREFIX++# These don't like all the extra options we pass (CPPFLAGS and --extra-lib-dirs)+# Gtk2Hs needs the latest Cabal to install properly+cabal install --with-ghc=ghc$GHCVERSION -j4 text parsec network uniplate Cabal --constraint='text>=0.11.3.1' --constraint='parsec>=3.1.3' || true++# Needed for installing curl package on windows+export CPPFLAGS=`pkg-config --cflags-only-I libcurl`++# Only used by OS X+# export DYLD_LIBRARY_PATH="/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources:$GTK_PREFIX/lib:$DYLD_LIBRARY_PATH"++echo https://github.com/leksah/ltk > sources.txt+echo https://github.com/leksah/leksah-server >> sources.txt+echo https://github.com/leksah/haskellVCSWrapper.git >> sources.txt+echo https://github.com/leksah/haskellVCSGUI.git >> sources.txt++# echo ./vendor/gtk2hs >> sources.txt+echo ./ >> sources.txt++if test "`uname`" = "Darwin"; then+ cabal install gtk3 ghcjs-dom jsaddle --with-ghc=ghc$GHCVERSION -j4 -fhave-quartz-gtk -fwebkit --with-gcc=gcc-mp-4.8 || exit+ cabal-meta install --with-ghc=ghc$GHCVERSION -j4 -flibcurl --with-gcc=gcc-mp-4.8 || exit+else+ HPDIR=`which ghc` || exit+ HPDIR=`dirname "$HPDIR"` || exit+ HPDIR=`dirname "$HPDIR"` || exit+ cabal install gtk3 ghcjs-dom jsaddle --with-ghc=ghc$GHCVERSION -j4 --extra-lib-dirs="$HPDIR"/mingw/lib --extra-lib-dirs=/c/MinGWRPM/lib -fwebkit --force-reinstalls || bash || exit+ cabal-meta install --with-ghc=ghc$GHCVERSION -j4 --extra-lib-dirs="$HPDIR"/mingw/lib --extra-lib-dirs=/c/MinGWRPM/lib -flibcurl --force-reinstalls || bash || exit+# if [ "$GHC_VER" != "7.0.3" ] && [ "$GHC_VER" != "7.0.4" ] && [ "$GHC_VER" != "7.6.1" ]; then+# echo https://github.com/yi-editor/yi.git >> sources.txt+# export LEKSAH_CONFIG_ARGS="$LEKSAH_CONFIG_ARGS -fyi -f-vty -f-dyre -fpango"+# fi+fi++export SERVER_VERSION=`grep '^version: ' vendor/leksah-server/leksah-server.cabal | sed 's|version: ||' | tr -d '\r'`+export LEKSAH_SERVER_X_X_X_X=leksah-server-$SERVER_VERSION+
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleInstances, DeriveDataTypeable, TypeSynonymInstances, MultiParamTypeClasses #-}+{-# LANGUAGE CPP, FlexibleInstances, DeriveDataTypeable, TypeSynonymInstances, MultiParamTypeClasses, Rank2Types, GADTs, FlexibleContexts, ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- -- Module : IDE.BufferMode@@ -19,10 +19,11 @@ import IDE.Core.State import Data.List (isPrefixOf, elemIndices, isInfixOf, isSuffixOf) import IDE.TextEditor- (EditorIter, getOffset, startsLine, getIterAtMark,- getSelectionBoundMark, getInsertMark, EditorBuffer, getBuffer,- EditorView, delete, getText, forwardCharsC, insert, getIterAtLine,- getLine)+ (getOffset, startsLine, getIterAtMark, EditorView(..),+ getSelectionBoundMark, getInsertMark, getBuffer,+ delete, getText, forwardCharsC, insert, getIterAtLine,+ getLine, TextEditor(..), EditorBuffer(..),+ EditorIter(..)) import Data.IORef (IORef) import System.Time (ClockTime) import Data.Typeable (cast, Typeable)@@ -36,6 +37,9 @@ import Graphics.UI.Gtk (Notebook, castToWidget, notebookPageNum, ScrolledWindow) import Control.Monad.IO.Class (MonadIO(..))+#if MIN_VERSION_directory(1,2,0)+import Data.Time (UTCTime)+#endif -- * Buffer Basics@@ -43,13 +47,17 @@ -- -- | A text editor pane description ---data IDEBuffer = IDEBuffer {+data IDEBuffer = forall editor. TextEditor editor => IDEBuffer { fileName :: Maybe FilePath , bufferName :: String , addedIndex :: Int-, sourceView :: EditorView+, sourceView :: EditorView editor , scrolledWindow :: ScrolledWindow+#if MIN_VERSION_directory(1,2,0)+, modTime :: IORef (Maybe (UTCTime))+#else , modTime :: IORef (Maybe (ClockTime))+#endif , mode :: Mode } deriving (Typeable) @@ -88,7 +96,7 @@ mbBufs <- mapM mbPaneFromName recentPanes' return $ map paneName ((catMaybes $ map (\ (PaneC p) -> cast p) $ catMaybes mbBufs) :: [IDEBuffer]) -getStartAndEndLineOfSelection :: EditorBuffer -> IDEM (Int,Int)+getStartAndEndLineOfSelection :: TextEditor editor => EditorBuffer editor -> IDEM (Int,Int) getStartAndEndLineOfSelection ebuf = do startMark <- getInsertMark ebuf endMark <- getSelectionBoundMark ebuf@@ -103,8 +111,8 @@ let endLineReal = if b && endLine /= startLine then endLine' - 1 else endLine' return (startLine',endLineReal) -inBufContext :: alpha -> IDEBuffer -> (Notebook -> EditorBuffer -> IDEBuffer -> Int -> IDEM alpha) -> IDEM alpha-inBufContext def ideBuf f = do+inBufContext :: alpha -> IDEBuffer -> (forall editor. TextEditor editor => Notebook -> EditorView editor -> EditorBuffer editor -> IDEBuffer -> Int -> IDEM alpha) -> IDEM alpha+inBufContext def (ideBuf@IDEBuffer{sourceView = v}) f = do (pane,_) <- guiPropertiesFromName (paneName ideBuf) nb <- getNotebook pane mbI <- liftIO $notebookPageNum nb (scrolledWindow ideBuf)@@ -113,20 +121,19 @@ sysMessage Normal $ bufferName ideBuf ++ " notebook page not found: unexpected" return def Just i -> do- ebuf <- getBuffer (sourceView ideBuf)- f nb ebuf ideBuf i+ ebuf <- getBuffer v+ f nb v ebuf ideBuf i -inActiveBufContext :: alpha -> (Notebook -> EditorBuffer -> IDEBuffer -> Int -> IDEM alpha) -> IDEM alpha+inActiveBufContext :: alpha -> (forall editor. TextEditor editor => Notebook -> EditorView editor -> EditorBuffer editor -> IDEBuffer -> Int -> IDEM alpha) -> IDEM alpha inActiveBufContext def f = do- mbBuf <- maybeActiveBuf+ mbBuf <- maybeActiveBuf case mbBuf of Nothing -> return def Just ideBuf -> do inBufContext def ideBuf f --doForSelectedLines :: [a] -> (EditorBuffer -> Int -> IDEM a) -> IDEM [a]-doForSelectedLines d f = inActiveBufContext d $ \_ ebuf currentBuffer _ -> do+doForSelectedLines :: [a] -> (forall editor. TextEditor editor => EditorBuffer editor -> Int -> IDEM a) -> IDEM [a]+doForSelectedLines d f = inActiveBufContext d $ \_ _ ebuf currentBuffer _ -> do (start,end) <- getStartAndEndLineOfSelection ebuf mapM (f ebuf) [start .. end] @@ -138,10 +145,10 @@ modeEditUncomment :: IDEAction, modeSelectedModuleName :: IDEM (Maybe String), modeEditToCandy :: (String -> Bool) -> IDEAction,- modeTransformToCandy :: (String -> Bool) -> EditorBuffer -> IDEAction,+ modeTransformToCandy :: TextEditor editor => (String -> Bool) -> EditorBuffer editor -> IDEAction, modeEditFromCandy :: IDEAction, modeEditKeystrokeCandy :: Maybe Char -> (String -> Bool) -> IDEAction,- modeEditInsertCode :: String -> EditorIter -> EditorBuffer -> IDEAction,+ modeEditInsertCode :: TextEditor editor => String -> EditorIter editor -> EditorBuffer editor -> IDEAction, modeEditInCommentOrString :: String -> Bool } @@ -171,7 +178,7 @@ else return () return (), modeSelectedModuleName = do- inActiveBufContext Nothing $ \_ ebuf currentBuffer _ -> do+ inActiveBufContext Nothing $ \_ _ ebuf currentBuffer _ -> do case fileName currentBuffer of Just filePath -> liftIO $ moduleNameFromFilePath filePath Nothing -> return Nothing,@@ -180,15 +187,15 @@ transformToCandy ct ebuf inCommentOrString, modeEditToCandy = \ inCommentOrString -> do ct <- readIDE candy- inActiveBufContext () $ \_ ebuf _ _ -> do+ inActiveBufContext () $ \_ _ ebuf _ _ -> do transformToCandy ct ebuf inCommentOrString, modeEditFromCandy = do ct <- readIDE candy- inActiveBufContext () $ \_ ebuf _ _ -> do+ inActiveBufContext () $ \_ _ ebuf _ _ -> do transformFromCandy ct ebuf, modeEditKeystrokeCandy = \c inCommentOrString -> do ct <- readIDE candy- inActiveBufContext () $ \_ ebuf _ _ -> do+ inActiveBufContext () $ \_ _ ebuf _ _ -> do keystrokeCandy ct c ebuf inCommentOrString, modeEditInsertCode = \ str iter buf -> insert buf iter str,@@ -223,7 +230,7 @@ (insert ebuf sol ">") return (), modeSelectedModuleName = do- inActiveBufContext Nothing $ \_ ebuf currentBuffer _ -> do+ inActiveBufContext Nothing $ \_ _ ebuf currentBuffer _ -> do case fileName currentBuffer of Just filePath -> liftIO $ moduleNameFromFilePath filePath Nothing -> return Nothing,@@ -232,15 +239,15 @@ transformToCandy ct ebuf inCommentOrString, modeEditToCandy = \ inCommentOrString -> do ct <- readIDE candy- inActiveBufContext () $ \_ ebuf _ _ -> do+ inActiveBufContext () $ \_ _ ebuf _ _ -> do transformToCandy ct ebuf inCommentOrString, modeEditFromCandy = do ct <- readIDE candy- inActiveBufContext () $ \_ ebuf _ _ -> do+ inActiveBufContext () $ \_ _ ebuf _ _ -> do transformFromCandy ct ebuf, modeEditKeystrokeCandy = \c inCommentOrString -> do ct <- readIDE candy- inActiveBufContext () $ \_ ebuf _ _ -> do+ inActiveBufContext () $ \_ _ ebuf _ _ -> do keystrokeCandy ct c ebuf inCommentOrString, modeEditInsertCode = \ str iter buf -> insert buf iter (unlines $ map (\ s -> "> " ++ s) $ lines str),@@ -297,7 +304,7 @@ withCurrentMode :: alpha -> (Mode -> IDEM alpha) -> IDEM alpha withCurrentMode def act = do- mbBuf <- maybeActiveBuf+ mbBuf <- maybeActiveBuf case mbBuf of Nothing -> return def Just ideBuf -> act (mode ideBuf)@@ -321,7 +328,7 @@ editKeystrokeCandy c = withCurrentMode () (\m -> modeEditKeystrokeCandy m c (modeEditInCommentOrString m)) -editInsertCode :: EditorBuffer -> EditorIter -> String -> IDEAction+editInsertCode :: TextEditor editor => EditorBuffer editor -> EditorIter editor -> String -> IDEAction editInsertCode buffer iter str = withCurrentMode () (\ m -> modeEditInsertCode m str iter buffer)
@@ -24,8 +24,8 @@ import Data.Map (Map) import IDE.Core.State- (triggerEventIDE, readIDE, IDEAction, Workspace(..), ipdPackageId,- ipdDepends, IDEPackage)+ (postSyncIDE, triggerEventIDE, readIDE, IDEAction, Workspace(..),+ ipdPackageId, ipdDepends, IDEPackage) import qualified Data.Map as Map (insert, empty, lookup, toList, fromList) import Data.Graph@@ -36,7 +36,8 @@ import Distribution.Version (withinRange) import Data.Maybe (mapMaybe) import IDE.Package- (packageClean', packageCopy', packageRegister', buildPackage, packageConfig', packageTest')+ (packageClean', packageCopy', packageRegister', buildPackage, packageConfig',+ packageTest', packageDoc') import IDE.Core.Types (IDEEvent(..), Prefs(..), IDE(..), WorkspaceAction) import Distribution.Text (Text(..))@@ -196,6 +197,8 @@ doBuildChain ms chain@Chain{mcAction = MoBuild} = buildPackage (msBackgroundBuild ms) (msJumpToWarnings ms) (not (msMakeMode ms) && msSingleBuildWithoutLinking ms) (mcEle chain) (constrCont ms (mcPos chain) (mcNeg chain))+doBuildChain ms chain@Chain{mcAction = MoDocu} =+ packageDoc' (msBackgroundBuild ms) (msJumpToWarnings ms) (mcEle chain) (constrCont ms (mcPos chain) (mcNeg chain)) doBuildChain ms chain@Chain{mcAction = MoTest} = packageTest' (mcEle chain) (constrCont ms (mcPos chain) (mcNeg chain)) doBuildChain ms chain@Chain{mcAction = MoCopy} =@@ -205,7 +208,7 @@ doBuildChain ms chain@Chain{mcAction = MoClean} = packageClean' (mcEle chain) (constrCont ms (mcPos chain) (mcNeg chain)) doBuildChain ms chain@Chain{mcAction = MoMetaInfo} =- triggerEventIDE UpdateWorkspaceInfo >> return ()+ postSyncIDE (triggerEventIDE UpdateWorkspaceInfo) >> return () doBuildChain ms chain = doBuildChain ms (mcPos chain) constrCont ms pos (Just neg) False = doBuildChain ms neg
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -XTypeSynonymInstances -XScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables, ForeignFunctionInterface #-} {-# OPTIONS_GHC -fno-warn-incomplete-patterns #-} ----------------------------------------------------------------------------- --@@ -34,33 +34,32 @@ ) where import Graphics.UI.Gtk- (containerAdd, windowAddAccelGroup, onKeyPress, boxPackEnd,- boxPackStart, widgetSetName, vBoxNew, windowSetIconFromFile,- Widget, Window, actionGroupGetAction, uiManagerGetActionGroups,- Action, actionSetSensitive, iconFactoryAdd, iconSetNewFromPixbuf,+ (toToolbar, ToolbarClass, Toolbar(..), keyToChar, eventKeyVal,+ eventModifier, eventKeyName, EKey, containerAdd,+ windowAddAccelGroup, keyPressEvent, boxPackEnd, boxPackStart,+ widgetSetName, vBoxNew, windowSetIconFromFile, Widget, Window,+ actionGroupGetAction, uiManagerGetActionGroups, Action,+ actionSetSensitive, iconFactoryAdd, iconSetNewFromPixbuf, pixbufNewFromFile, iconFactoryAddDefault, iconFactoryNew,- dialogRun, aboutDialogSetAuthors, aboutDialogSetWebsite,- aboutDialogSetLicense, aboutDialogSetComments,- aboutDialogSetCopyright, aboutDialogSetVersion, aboutDialogSetName,- aboutDialogNew, mainQuit, widgetHide, widgetShow,- castToWidget, separatorMenuItemNew,+ dialogRun, aboutDialogAuthors, aboutDialogWebsite,+ aboutDialogLicense, aboutDialogComments, aboutDialogCopyright,+ aboutDialogVersion, aboutDialogName, aboutDialogNew, mainQuit,+ widgetHide, widgetShow, castToWidget, separatorMenuItemNew, containerGetChildren, Menu, widgetSetSizeRequest, toolbarSetStyle,- toolbarSetIconSize, castToToolbar, castToMenuBar,- uiManagerGetWidget, uiManagerGetAccelGroup, onActionActivate,- actionNew, actionGroupAddActionWithAccel, actionToggled,- toggleActionNew, uiManagerAddUiFromString,- uiManagerInsertActionGroup, actionGroupNew, UIManager,- widgetShowAll, menuItemSetSubmenu, widgetDestroy, widgetHideAll,- menuItemGetSubmenu, menuShellAppend, onActivateLeaf,- menuItemNewWithLabel, menuNew, Packing(..), ToolbarStyle(..),- PositionType(..), on, IconSize(..))+ set, AttrOp(..), castToToolbar, castToMenuBar, uiManagerGetWidget,+ uiManagerGetAccelGroup, actionActivated, actionNew,+ actionGroupAddActionWithAccel, actionToggled, toggleActionNew,+ uiManagerAddUiFromString, uiManagerInsertActionGroup,+ actionGroupNew, UIManager, widgetShowAll, menuItemSetSubmenu,+ widgetDestroy, menuItemGetSubmenu, menuShellAppend,+ menuItemActivate, menuItemNewWithLabel, menuNew, Packing(..),+ ToolbarStyle(..), PositionType(..), on, IconSize(..), Modifier(..)) import System.FilePath import Data.Version import Prelude hiding (catch) import Control.Exception import Data.Maybe - import IDE.Core.State import IDE.Pane.SourceBuffer import IDE.Pane.Preferences@@ -68,6 +67,10 @@ import IDE.Pane.PackageEditor import IDE.Pane.Errors import IDE.Pane.Search+import IDE.Pane.Info+import IDE.Pane.Breakpoints+import IDE.Pane.Trace+import IDE.Pane.Variables import IDE.Package import IDE.Pane.Log import IDE.Session@@ -76,7 +79,6 @@ import IDE.Pane.Info import IDE.Utils.FileUtils import IDE.Utils.GUIUtils-import Paths_leksah import IDE.GUIHistory import IDE.Metainfo.Provider (getWorkspaceInfo, getIdentifierDescr, updateWorkspaceInfo,@@ -86,10 +88,7 @@ import IDE.LogRef import IDE.Debug import System.Directory (doesFileExist)-import qualified Graphics.UI.Gtk.Gdk.Events as GdkEvents-import Graphics.UI.Gtk.Gdk.Events- (Modifier(..),- Event(..))+import Graphics.UI.Gtk.Gdk.EventM (EventM) import qualified Data.Map as Map (lookup) import Data.List (sort) import Control.Event (registerEvent)@@ -103,326 +102,373 @@ import IDE.PaneGroups import IDE.Pane.Search (getSearch, IDESearch(..)) import IDE.Pane.Grep (getGrep)-import IDE.Pane.Files (getFiles)+import IDE.Pane.HLint (refreshHLint, getHLint)+import IDE.Pane.WebKit.Documentation (getDocumentation)+import IDE.Pane.WebKit.Output (getOutputPane)+import IDE.Pane.Files (refreshFiles, getFiles) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad (unless, when) import Control.Monad.Trans.Reader (ask)+import Text.Printf (printf)+import System.Log.Logger (debugM)+import Foreign.C.Types (CInt(..))+import Foreign.Ptr (Ptr(..))+import Foreign.ForeignPtr (withForeignPtr)+import Graphics.UI.GtkInternals (unToolbar)+import IDE.Session (viewFullScreen, viewDark)+import qualified Data.Text as T (pack) +foreign import ccall safe "gtk_toolbar_set_icon_size"+ gtk_toolbar_set_icon_size :: Ptr Toolbar -> CInt -> IO ()++toolbarSetIconSize :: ToolbarClass self => self -> IconSize -> IO ()+toolbarSetIconSize self iconSize =+ withForeignPtr (unToolbar $ toToolbar self) $+ \selfPtr ->gtk_toolbar_set_icon_size selfPtr (fromIntegral $ fromEnum iconSize)+ -- -- | The Actions known to the system (they can be activated by keystrokes or menus) -- mkActions :: [ActionDescr IDERef] mkActions =- [AD "File" "_File" Nothing Nothing (return ()) [] False- ,AD "FileNew" "_New Module..." Nothing (Just "gtk-new")+ [+ AD "vcs" (__ "Version Con_trol") Nothing Nothing (return ()) [] False+ ,AD "FilePrint" (__ "_Print File") Nothing Nothing (filePrint) [] False+ ,AD "File" (__ "_File") Nothing Nothing (return ()) [] False+ ,AD "FileNew" (__ "_New Module...") Nothing (Just "gtk-new") (packageTry $ addModule []) [] False- ,AD "FileNewTextFile" "_New Text File" Nothing Nothing+ ,AD "FileNewTextFile" (__ "_New Text File") Nothing Nothing fileNew [] False- ,AD "FileOpen" "_Open..." Nothing (Just "gtk-open")+ ,AD "FileOpen" (__ "_Open...") Nothing (Just "gtk-open") fileOpen [] False- ,AD "RecentFiles" "Open _Recent" Nothing Nothing (return ()) [] False- ,AD "FileRevert" "_Revert" Nothing Nothing+ ,AD "RecentFiles" (__ "Open _Recent") Nothing Nothing (return ()) [] False+ ,AD "FileRevert" (__ "_Revert") Nothing Nothing fileRevert [] False- ,AD "FileSave" "_Save" Nothing (Just "gtk-save")+ ,AD "FileSave" (__ "_Save") Nothing (Just "gtk-save") (do fileSave False; return ()) [] False- ,AD "FileSaveAs" "Save _As..." Nothing (Just "gtk-save-as")+ ,AD "FileSaveAs" (__ "Save _As...") Nothing (Just "gtk-save-as") (do fileSave True; return ()) [] False- ,AD "FileSaveAll" "Save A_ll" Nothing Nothing+ ,AD "FileSaveAll" (__ "Save A_ll") Nothing Nothing (do fileSaveAll (\ b -> return (bufferName b /= "_Eval.hs")); return ()) [] False- ,AD "FileClose" "_Close" Nothing (Just "gtk-close")+ ,AD "FileClose" (__ "_Close") Nothing (Just "gtk-close") (do fileClose; return ()) [] False- ,AD "FileCloseAll" "Close All" Nothing Nothing+ ,AD "FileCloseAll" (__ "Close All") Nothing Nothing (do fileCloseAll (\ b -> return (bufferName b /= "_Eval.hs")); return ()) [] False- ,AD "FileCloseAllButPackage" "Close All But Package" Nothing Nothing+ ,AD "FileCloseAllButPackage" (__ "Close All But Package") Nothing Nothing (do fileCloseAllButPackage; return ()) [] False- ,AD "FileCloseAllButWorkspace" "Close All But Workspace" Nothing Nothing+ ,AD "FileCloseAllButWorkspace" (__ "Close All But Workspace") Nothing Nothing (do fileCloseAllButWorkspace; return ()) [] False- ,AD "Quit" "_Quit" Nothing (Just "gtk-quit")+ ,AD "Quit" (__ "_Quit") Nothing (Just "gtk-quit") quit [] False - ,AD "Edit" "_Edit" Nothing Nothing (return ()) [] False- ,AD "EditUndo" "_Undo" Nothing (Just "gtk-undo")+ ,AD "Edit" (__ "_Edit") Nothing Nothing (return ()) [] False+ ,AD "EditUndo" (__ "_Undo") Nothing (Just "gtk-undo") editUndo [] False- ,AD "EditRedo" "_Redo" Nothing (Just "gtk-redo")+ ,AD "EditRedo" (__ "_Redo") Nothing (Just "gtk-redo") editRedo [] False- ,AD "EditCut" "Cu_t" Nothing (Just "gtk-cut")+ ,AD "EditCut" (__ "Cu_t") Nothing (Just "gtk-cut") editCut [] {--Just "<control>X"--} False- ,AD "EditCopy" "_Copy" Nothing (Just "gtk-copy")+ ,AD "EditCopy" (__ "_Copy") Nothing (Just "gtk-copy") editCopy [] {--Just "<control>C"--} False- ,AD "EditPaste" "_Paste" Nothing (Just "gtk-paste")+ ,AD "EditPaste" (__ "_Paste") Nothing (Just "gtk-paste") editPaste [] {--Just "<control>V"--} False- ,AD "EditDelete" "_Delete" Nothing (Just "gtk-delete")+ ,AD "EditDelete" (__ "_Delete") Nothing (Just "gtk-delete") editDelete [] False- ,AD "EditSelectAll" "Select_All" Nothing (Just "gtk-select-all")+ ,AD "EditSelectAll" (__ "Select_All") Nothing (Just "gtk-select-all") editSelectAll [] False- ,AD "EditFind" "Find" Nothing (Just "gtk-find")+ ,AD "EditFind" (__ "Find") Nothing (Just "gtk-find") (editFindInc Initial) [] False- ,AD "EditFindNext" "Find _Next" Nothing (Just "gtk-find-next")+ ,AD "EditFindNext" (__ "Find _Next") Nothing (Just "gtk-find-next") (editFindInc Forward) [] False- ,AD "EditFindPrevious" "Find _Previous" Nothing (Just "gtk-find-previous")+ ,AD "EditFindPrevious" (__ "Find _Previous") Nothing (Just "gtk-find-previous") (editFindInc Backward) [] False- ,AD "EditGotoLine" "_Goto Line" Nothing (Just "gtk-jump")+ ,AD "EditGotoLine" (__ "_Goto Line") Nothing (Just "gtk-jump") editGotoLine [] False - ,AD "EditComment" "_Comment" Nothing Nothing+ ,AD "EditComment" (__ "_Comment") Nothing Nothing editComment [] False- ,AD "EditUncomment" "_Uncomment" Nothing Nothing+ ,AD "EditUncomment" (__ "_Uncomment") Nothing Nothing editUncomment [] False- ,AD "EditShiftRight" "Shift _Right" Nothing Nothing+ ,AD "EditShiftRight" (__ "Shift _Right") Nothing Nothing editShiftRight [] False- ,AD "EditShiftLeft" "Shift _Left" Nothing Nothing+ ,AD "EditShiftLeft" (__ "Shift _Left") Nothing Nothing editShiftLeft [] False --,AD "Align" "_Align" Nothing Nothing (return ()) [] False- ,AD "EditAlignEqual" "Align _=" Nothing Nothing+ ,AD "EditAlignEqual" (__ "Align _=") Nothing Nothing (align '=') [] False- ,AD "EditAlignRightArrow" "Align -_>" Nothing Nothing+ ,AD "EditAlignRightArrow" (__ "Align -_>") Nothing Nothing (align '>') [] False- ,AD "EditAlignLeftArrow" "Align _<-" Nothing Nothing+ ,AD "EditAlignLeftArrow" (__ "Align _<-") Nothing Nothing (align '<') [] False- ,AD "EditAlignTypeSig" "Align _::" Nothing Nothing+ ,AD "EditAlignTypeSig" (__ "Align _::") Nothing Nothing (align ':') [] False - ,AD "Workspace" "_Workspace" Nothing Nothing (return ()) [] False- ,AD "NewWorkspace" "_New..." Nothing Nothing+ ,AD "Workspace" (__ "_Workspace") Nothing Nothing (return ()) [] False+ ,AD "NewWorkspace" (__ "_New...") Nothing Nothing (workspaceNew >> showWorkspace) [] False- ,AD "OpenWorkspace" "_Open..." Nothing Nothing+ ,AD "OpenWorkspace" (__ "_Open...") Nothing Nothing (workspaceOpen >> showWorkspace) [] False- ,AD "RecentWorkspaces" "Open _Recent" Nothing Nothing (return ()) [] False- ,AD "CloseWorkspace" "_Close" Nothing Nothing+ ,AD "RecentWorkspaces" (__ "Open _Recent") Nothing Nothing (return ()) [] False+ ,AD "CloseWorkspace" (__ "_Close") Nothing Nothing workspaceClose [] False - ,AD "CleanWorkspace" "Cl_ean" (Just "Cleans all packages") (Just "ide_clean")+ ,AD "CleanWorkspace" (__ "Cl_ean") (Just (__ "Cleans all packages")) (Just "ide_clean") (workspaceTry workspaceClean) [] False- ,AD "MakeWorkspace" "_Make" (Just "Makes all of this workspace") (Just "ide_configure")+ ,AD "MakeWorkspace" (__ "_Make") (Just (__ "Makes all of this workspace")) (Just "ide_configure") (workspaceTry workspaceMake) [] False- ,AD "NextError" "_Next Error" (Just "Go to the next error") (Just "ide_error_next")+ ,AD "NextError" (__ "_Next Error") (Just (__ "Go to the next error")) (Just "ide_error_next") nextError [] False- ,AD "PreviousError" "_Previous Error" (Just "Go to the previous error") (Just "ide_error_prev")+ ,AD "PreviousError" (__ "_Previous Error") (Just (__ "Go to the previous error")) (Just "ide_error_prev") previousError [] False - ,AD "Package" "_Package" Nothing Nothing (return ()) [] False- ,AD "NewPackage" "_New..." Nothing Nothing+ ,AD "Package" (__ "_Package") Nothing Nothing (return ()) [] False+ ,AD "NewPackage" (__ "_New...") Nothing Nothing (showWorkspace >> workspaceTry workspacePackageNew) [] False- ,AD "AddPackage" "_Add..." Nothing Nothing+ ,AD "AddPackage" (__ "_Add...") Nothing Nothing (showWorkspace >> workspaceTry workspaceAddPackage) [] False+ ,AD "ClonePackage" (__ "Add From Source _Repository...") Nothing Nothing+ (showWorkspace >> workspaceTry workspacePackageClone) [] False -- ,AD "RecentPackages" "_Recent Packages" Nothing Nothing (return ()) [] False- ,AD "EditPackage" "_Edit" Nothing Nothing+ ,AD "PackageEdit" (__ "_Edit") Nothing Nothing (return ()) [] False+ ,AD "EditPackage" (__ "With _Package Editor") Nothing Nothing (packageTry packageEdit) [] False+ ,AD "EditPackageText" (__ "With _Text Editor") Nothing Nothing+ (packageTry packageEditText) [] False -- ,AD "RemovePackage" "_Close Package" Nothing Nothing -- removePackage [] False - ,AD "PackageFlags" "Edit Flags" (Just "Edit the package flags") Nothing+ ,AD "PackageFlags" (__ "Package Flags") (Just (__ "Edit the package flags used")) Nothing (getFlags Nothing >>= \ p -> displayPane p False) [] False- ,AD "CleanPackage" "Cl_ean" (Just "Cleans the package") (Just "ide_clean")+ ,AD "CleanPackage" (__ "Cl_ean") (Just (__ "Cleans the package")) (Just "ide_clean") (packageTry packageClean) [] False- ,AD "ConfigPackage" "_Configure" (Just "Configures the package") (Just "ide_configure")+ ,AD "ConfigPackage" (__ "_Configure") (Just (__ "Configures the package")) (Just "ide_configure") (packageTry packageConfig) [] False- ,AD "BuildPackage" "_Build" (Just "Builds the package") (Just "ide_make")+ ,AD "BuildPackage" (__ "_Build") (Just (__ "Builds the package")) (Just "ide_make") (packageTry makePackage) [] False- ,AD "DocPackage" "_Build Documentation" (Just "Builds the documentation") Nothing+ ,AD "DocPackage" (__ "_Build Documentation") (Just (__ "Builds the documentation")) Nothing (packageTry packageDoc) [] False- ,AD "CopyPackage" "_Copy" (Just "Copies the package") Nothing+ ,AD "CopyPackage" (__ "_Copy") (Just (__ "Copies the package")) Nothing (packageTry packageCopy) [] False- ,AD "RunPackage" "_Run" (Just "Runs the package") (Just "ide_run")+ ,AD "RunPackage" (__ "_Run") (Just (__ "Runs the package")) (Just "ide_run") (packageTry packageRun) [] False- ,AD "ResolveErrors" "Resol_ve Errors" (Just "Resolve 'Hidden package' and 'Not in scope' errors by adding the necessary dependancies or imports") Nothing+ ,AD "ResolveErrors" (__ "Resol_ve Errors") (Just (__ "Resolve 'Hidden package' and 'Not in scope' errors by adding the necessary dependancies or imports")) Nothing resolveErrors [] False - ,AD "InstallDependenciesPackage" "_Install Dependencies" (Just "Install the package's dependencies from the hackage server") Nothing+ ,AD "InstallDependenciesPackage" (__ "_Install Dependencies") (Just (__ "Install the package's dependencies from the hackage server")) Nothing (packageTry packageInstallDependencies) [] False- ,AD "RegisterPackage" "_Register" Nothing Nothing+ ,AD "RegisterPackage" (__ "_Register") Nothing Nothing (packageTry packageRegister) [] False- ,AD "TestPackage" "Test" Nothing Nothing+ ,AD "TestPackage" (__ "Test") Nothing Nothing (packageTry packageTest) [] False- ,AD "SdistPackage" "Source Dist" Nothing Nothing+ ,AD "SdistPackage" (__ "Source Dist") Nothing Nothing (packageTry packageSdist) [] False- ,AD "OpenDocPackage" "_Open Doc" Nothing Nothing+ ,AD "OpenDocPackage" (__ "_Open Doc") Nothing Nothing (packageTry packageOpenDoc) [] False - ,AD "Debug" "_Debug" Nothing Nothing (return ()) [] False- ,AD "StartDebugger" "_Start Debugger" (Just "Starts using the GHCi debugger for build and run") Nothing+ ,AD "Debug" (__ "_Debug") Nothing Nothing (return ()) [] False+ ,AD "StartDebugger" (__ "_Start Debugger") (Just (__ "Starts using the GHCi debugger for build and run")) Nothing (packageTry debugStart) [] False- ,AD "QuitDebugger" "_Quit Debugger" (Just "Quit the GHCi debugger if it is running") Nothing+ ,AD "QuitDebugger" (__ "_Quit Debugger") (Just (__ "Quit the GHCi debugger if it is running")) Nothing debugQuit [] False- ,AD "ExecuteSelection" "_Execute Selection" (Just "Sends the selected text to the debugger") Nothing+ ,AD "ExecuteSelection" (__ "_Execute Selection") (Just (__ "Sends the selected text to the debugger")) Nothing debugExecuteSelection [] False - ,AD "DebugSetBreakpoint" "Set Breakpoint" (Just "Set a breakpoint on the selected name or current line") Nothing+ ,AD "DebugSetBreakpoint" (__ "Set Breakpoint") (Just (__ "Set a breakpoint on the selected name or current line")) Nothing debugSetBreakpoint [] False- ,AD "ShowNextBreakpoint" "Show Next Breakpoint" (Just "Show the next breakpoint") Nothing+ ,AD "ShowNextBreakpoint" (__ "Show Next Breakpoint") (Just (__ "Show the next breakpoint")) Nothing nextBreakpoint [] False- ,AD "ShowPreviousBreakpoint" "Show Previous Breakpoint" (Just "Show the previous breakpoint") Nothing+ ,AD "ShowPreviousBreakpoint" (__ "Show Previous Breakpoint") (Just (__ "Show the previous breakpoint")) Nothing previousBreakpoint [] False- ,AD "DebugDeleteAllBreakpoints" "Delete All Breakpoints" (Just "") Nothing+ ,AD "DebugDeleteAllBreakpoints" (__ "Delete All Breakpoints") (Just "") Nothing debugDeleteAllBreakpoints [] False - ,AD "DebugContinue" "Continue" (Just "Resume after a breakpoint") (Just "ide_continue")+ ,AD "DebugContinue" (__ "Continue") (Just (__ "Resume after a breakpoint")) (Just "ide_continue") debugContinue [] False- ,AD "DebugAbandon" "Abandon" (Just "At a breakpoint, abandon current computation") Nothing+ ,AD "DebugAbandon" (__ "Abandon") (Just (__ "At a breakpoint, abandon current computation")) Nothing debugAbandon [] False- ,AD "DebugStop" "Stop" (Just "Interrupt the running operation.") Nothing+ ,AD "DebugStop" (__ "Stop") (Just (__ "Interrupt the running operation.")) Nothing debugStop [] False - ,AD "DebugStep" "Step" (Just "Single-step after stopping at a breakpoint") (Just "ide_step")+ ,AD "DebugStep" (__ "Step") (Just (__ "Single-step after stopping at a breakpoint")) (Just "ide_step") debugStep [] False- ,AD "DebugStepExpression" "Step Expression" (Just "Single-step into selected expression") Nothing+ ,AD "DebugStepExpression" (__ "Step Expression") (Just (__ "Single-step into selected expression")) Nothing debugStepExpression [] False- ,AD "DebugStepLocal" "Step Local" (Just "Single-step within the current top-level binding") (Just "ide_local")+ ,AD "DebugStepLocal" (__ "Step Local") (Just (__ "Single-step within the current top-level binding")) (Just "ide_local") debugStepLocal [] False- ,AD "DebugStepModule" "Step Module" (Just "Single-step restricted to the current module") (Just "ide_module")+ ,AD "DebugStepModule" (__ "Step Module") (Just (__ "Single-step restricted to the current module")) (Just "ide_module") debugStepModule [] False - ,AD "DebugTrace" "Trace" (Just "Trace after stopping at a breakpoint") Nothing+ ,AD "DebugTrace" (__ "Trace") (Just (__ "Trace after stopping at a breakpoint")) Nothing debugTrace [] False- ,AD "DebugTraceExpression" "Trace Expression" (Just "Evaluate the selected expression with tracing on") Nothing+ ,AD "DebugTraceExpression" (__ "Trace Expression") (Just (__ "Evaluate the selected expression with tracing on")) Nothing debugTraceExpression [] False- ,AD "DebugHistory" "History" (Just "After 'Trace', show the execution history") Nothing+ ,AD "DebugHistory" (__ "History") (Just (__ "After 'Trace', show the execution history")) Nothing debugHistory [] False- ,AD "DebugBack" "Back" (Just "Go back in the history (after 'Trace')") Nothing+ ,AD "DebugBack" (__ "Back") (Just (__ "Go back in the history (after 'Trace')")) Nothing debugBack [] False- ,AD "DebugForward" "Forward" (Just "Go forward in the history (after 'Back')") Nothing+ ,AD "DebugForward" (__ "Forward") (Just (__ "Go forward in the history (after 'Back')")) Nothing debugForward [] False - ,AD "DebugForce" "Force" (Just "Print the selected expression, forcing unevaluated parts") Nothing+ ,AD "DebugForce" (__ "Force") (Just (__ "Print the selected expression, forcing unevaluated parts")) Nothing debugForce [] False- ,AD "DebugPrint" "Print" (Just "Prints a value without forcing its computation") Nothing+ ,AD "DebugPrint" (__ "Print") (Just (__ "Prints a value without forcing its computation")) Nothing debugPrint [] False- ,AD "DebugSimplePrint" "SimplePrint" (Just "Simplifed version of Print") Nothing+ ,AD "DebugSimplePrint" (__ "SimplePrint") (Just (__ "Simplifed version of Print")) Nothing debugSimplePrint [] False - ,AD "ShowBindings" "Show Bin_dings" (Just "Show the current bindings") Nothing+ ,AD "ShowBindings" (__ "Show Bin_dings") (Just (__ "Show the current bindings")) Nothing debugShowBindings [] False- ,AD "ShowBreakpoints" "Show _Breakpoints" (Just "Show the active breakpoints") Nothing+ ,AD "ShowBreakpoints" (__ "Show _Breakpoints") (Just (__ "Show the active breakpoints")) Nothing debugShowBreakpoints [] False- ,AD "ShowContext" "Show _Context" (Just "Show the breakpoint context") Nothing+ ,AD "ShowContext" (__ "Show _Context") (Just (__ "Show the breakpoint context")) Nothing debugShowContext [] False- ,AD "ShowLoadedModules" "Show Loaded _Modules" (Just "Show the currently loaded modules") Nothing+ ,AD "ShowLoadedModules" (__ "Show Loaded _Modules") (Just (__ "Show the currently loaded modules")) Nothing debugShowModules [] False- ,AD "ShowPackages" "Show _Packages" (Just "Show the currently active packages") Nothing+ ,AD "ShowPackages" (__ "Show _Packages") (Just (__ "Show the currently active packages")) Nothing debugShowPackages [] False- ,AD "ShowLanguages" "Show _Languages" (Just "Show the currently active language") Nothing+ ,AD "ShowLanguages" (__ "Show _Languages") (Just (__ "Show the currently active language")) Nothing debugShowLanguages [] False - ,AD "DebugInformation" "Information" (Just "Display information about the selected name(s)") Nothing+ ,AD "DebugInformation" (__ "Information") (Just (__ "Display information about the selected name(s)")) Nothing debugInformation [] False- ,AD "DebugKind" "Kind" (Just "Show the kind of the selected type") Nothing+ ,AD "DebugKind" (__ "Kind") (Just (__ "Show the kind of the selected type")) Nothing debugKind [] False- ,AD "DebugType" "Type" (Just "Show the type of the selected expression") Nothing+ ,AD "DebugType" (__ "Type") (Just (__ "Show the type of the selected expression")) Nothing debugType [] False - ,AD "Metadata" "_Metadata" Nothing Nothing (return ()) [] False- ,AD "UpdateMetadataCurrent" "_Update workspace data" (Just "Updates data for the current workspace")+ ,AD "Metadata" (__ "_Metadata") Nothing Nothing (return ()) [] False+ ,AD "UpdateMetadataCurrent" (__ "_Update workspace data") (Just (__ "Updates data for the current workspace")) (Just "ide_rebuild_meta") updateWorkspaceInfo [] False- ,AD "RebuildMetadataCurrent" "_Rebuild workspace data" (Just "Rebuilds data for the current workspace")+ ,AD "RebuildMetadataCurrent" (__ "_Rebuild workspace data") (Just (__ "Rebuilds data for the current workspace")) Nothing rebuildWorkspaceInfo [] False- ,AD "UpdateMetadataLib" "U_pdate system data" Nothing Nothing+ ,AD "UpdateMetadataLib" (__ "U_pdate system data") Nothing Nothing updateSystemInfo [] False- ,AD "RebuildMetadataLib" "R_ebuild system data" Nothing Nothing+ ,AD "RebuildMetadataLib" (__ "R_ebuild system data") Nothing Nothing rebuildSystemInfo [] False - ,AD "Session" "_Session" Nothing Nothing (return ()) [] False- ,AD "SaveSession" "_Save Session" Nothing Nothing+ ,AD "Session" (__ "_Session") Nothing Nothing (return ()) [] False+ ,AD "SaveSession" (__ "_Save Session") Nothing Nothing saveSessionAsPrompt [] False- ,AD "LoadSession" "_Load Session" Nothing Nothing+ ,AD "LoadSession" (__ "_Load Session") Nothing Nothing loadSessionPrompt [] False- ,AD "ForgetSession" "_Forget Session" Nothing Nothing+ ,AD "ForgetSession" (__ "_Forget Session") Nothing Nothing (return ()) [] True - ,AD "Panes" "_Panes" Nothing Nothing (return ()) [] False- ,AD "ShowBrowser" "Browser" Nothing Nothing+ ,AD "Panes" (__ "_Panes") Nothing Nothing (return ()) [] False+ ,AD "ShowBrowser" (__ "Browser") Nothing Nothing showBrowser [] False- ,AD "ShowDebugger" "Debugger" Nothing Nothing+ ,AD "ShowModules" (__ "Modules") Nothing Nothing+ showModules [] False+ ,AD "ShowInfo" (__ "Info") Nothing Nothing+ showInfo [] False+ ,AD "ShowDebugger" (__ "Debugger") Nothing Nothing showDebugger [] False- ,AD "ShowSearch" "Search" Nothing Nothing+ ,AD "ShowBreakpointsPane" (__ "Breakpoints") Nothing Nothing+ showBreakpoints [] False+ ,AD "ShowTrace" (__ "Trace") Nothing Nothing+ showTrace [] False+ ,AD "ShowVariables" (__ "Variables") Nothing Nothing+ showVariables [] False+ ,AD "ShowSearch" (__ "Search") Nothing Nothing (getSearch Nothing >>= \ p -> displayPane p False) [] False- ,AD "ShowFiles" "Files" Nothing Nothing- (getFiles Nothing >>= \ p -> displayPane p False) [] False- ,AD "ShowGrep" "Grep" Nothing Nothing+ ,AD "ShowFiles" (__ "Files") Nothing Nothing+ (getFiles Nothing >>= \ p -> displayPane p False >> refreshFiles) [] False+ ,AD "ShowGrep" (__ "Grep") Nothing Nothing (getGrep Nothing >>= \ p -> displayPane p False) [] False- ,AD "ShowErrors" "Errors" Nothing Nothing+ ,AD "ShowHLint" (__ "HLint") Nothing Nothing+ (getHLint Nothing >>= \ p -> displayPane p False >> workspaceTry refreshHLint) [] False+ ,AD "ShowDocumentation" (__ "Documentation") Nothing Nothing+ (getDocumentation Nothing >>= \ p -> displayPane p False) [] False+ ,AD "ShowOutput" (__ "Output") Nothing Nothing+ (getOutputPane Nothing >>= \ p -> displayPane p False) [] False+ ,AD "ShowErrors" (__ "Errors") Nothing Nothing (getErrors Nothing >>= \ p -> displayPane p False) [] False- ,AD "ShowLog" "Log" Nothing Nothing+ ,AD "ShowLog" (__ "Log") Nothing Nothing showLog [] False- ,AD "ShowWorkspace" "Workspace" Nothing Nothing+ ,AD "ShowWorkspace" (__ "Workspace") Nothing Nothing showWorkspace [] False - ,AD "View" "_View" Nothing Nothing (return ()) [] False- ,AD "ViewMoveLeft" "Move _Left" Nothing Nothing+ ,AD "View" (__ "_View") Nothing Nothing (return ()) [] False+ ,AD "ViewMoveLeft" (__ "Move _Left") Nothing Nothing (viewMove LeftP) [] False- ,AD "ViewMoveRight" "Move _Right" Nothing Nothing+ ,AD "ViewMoveRight" (__ "Move _Right") Nothing Nothing (viewMove RightP) [] False- ,AD "ViewMoveUp" "Move _Up" Nothing Nothing+ ,AD "ViewMoveUp" (__ "Move _Up") Nothing Nothing (viewMove TopP) [] False- ,AD "ViewMoveDown" "Move _Down" Nothing Nothing+ ,AD "ViewMoveDown" (__ "Move _Down") Nothing Nothing (viewMove BottomP) [] False- ,AD "ViewSplitHorizontal" "Split H_orizontal" Nothing Nothing+ ,AD "ViewSplitHorizontal" (__ "Split H_orizontal") Nothing Nothing viewSplitHorizontal [] False- ,AD "ViewSplitVertical" "Split _Vertical" Nothing Nothing+ ,AD "ViewSplitVertical" (__ "Split _Vertical") Nothing Nothing viewSplitVertical [] False- ,AD "ViewCollapse" "_Collapse" Nothing Nothing+ ,AD "ViewCollapse" (__ "_Collapse") Nothing Nothing viewCollapse [] False- ,AD "ViewNest" "_Group" Nothing Nothing+ ,AD "ViewNest" (__ "_Group") Nothing Nothing (viewNewGroup) [] False- ,AD "ViewDetach" "_Detach" Nothing Nothing+ ,AD "ViewDetach" (__ "_Detach") Nothing Nothing viewDetachInstrumented [] False+ ,AD "ViewFullScreen" (__ "_Full Screen") Nothing Nothing+ viewFullScreen [] True+ ,AD "ViewDark" (__ "Dark") Nothing Nothing+ viewDark [] True - ,AD "ViewTabsLeft" "Tabs Left" Nothing Nothing+ ,AD "ViewTabsLeft" (__ "Tabs Left") Nothing Nothing (viewTabsPos PosLeft) [] False- ,AD "ViewTabsRight" "Tabs Right" Nothing Nothing+ ,AD "ViewTabsRight" (__ "Tabs Right") Nothing Nothing (viewTabsPos PosRight) [] False- ,AD "ViewTabsUp" "Tabs Up" Nothing Nothing+ ,AD "ViewTabsUp" (__ "Tabs Up") Nothing Nothing (viewTabsPos PosTop) [] False- ,AD "ViewTabsDown" "Tabs Down" Nothing Nothing+ ,AD "ViewTabsDown" (__ "Tabs Down") Nothing Nothing (viewTabsPos PosBottom) [] False- ,AD "ViewSwitchTabs" "Tabs On/Off" Nothing Nothing+ ,AD "ViewSwitchTabs" (__ "Tabs On/Off") Nothing Nothing viewSwitchTabs [] False - ,AD "ViewClosePane" "Close pane" Nothing (Just "gtk-close")+ ,AD "ViewClosePane" (__ "Close pane") Nothing (Just "gtk-close") sessionClosePane [] False - ,AD "FlipDown" "Flip down" Nothing Nothing+ ,AD "FlipDown" (__ "Flip down") Nothing Nothing flipDown [] False- ,AD "FlipUp" "Flip up" Nothing Nothing+ ,AD "FlipUp" (__ "Flip up") Nothing Nothing flipUp [] False- ,AD "StartComplete" "StartComplete" Nothing Nothing+ ,AD "StartComplete" (__ "StartComplete") Nothing Nothing startComplete [] False - ,AD "ViewHistoryBack" "Back" Nothing (Just "gtk-go-back")+ ,AD "ViewHistoryBack" (__ "Back") Nothing (Just "gtk-go-back") historyBack [] False- ,AD "ViewHistoryForth" "Forward" Nothing (Just "gtk-go-forward")+ ,AD "ViewHistoryForth" (__ "Forward") Nothing (Just "gtk-go-forward") historyForward [] False - ,AD "ClearLog" "_Clear Log" Nothing Nothing+ ,AD "ClearLog" (__ "_Clear Log") Nothing Nothing clearLog [] False- ,AD "ToggleToolbar" "Toggle Toolbar" Nothing Nothing+ ,AD "ToggleToolbar" (__ "Toggle Toolbar") Nothing Nothing toggleToolbar [] False - ,AD "Configuration" "_Configuration" Nothing Nothing (return ()) [] False- ,AD "EditCandy" "_To Candy" Nothing Nothing+ ,AD "Configuration" (__ "_Configuration") Nothing Nothing (return ()) [] False+ ,AD "EditCandy" (__ "_To Candy") Nothing Nothing editCandy [] True- ,AD "PrefsEdit" "_Edit Prefs" Nothing Nothing+ ,AD "PrefsEdit" (__ "_Edit Prefs") Nothing Nothing (getPrefs Nothing >>= \ p -> displayPane p False) [] False - ,AD "Help" "_Help" Nothing Nothing (return ()) [] False- ,AD "HelpDebug" "Debug" Nothing Nothing (do+ ,AD "Help" (__ "_Help") Nothing Nothing (return ()) [] False+ ,AD "HelpDebug" (__ "Debug") Nothing Nothing (do pack <- readIDE activePack ideMessage Normal (show pack)) [] False -- ,AD "HelpDebug2" "Debug2" (Just "<Ctrl>d") Nothing dbgInstalledPackageInfo [] False- ,AD "HelpManual" "Manual" Nothing Nothing (openBrowser "http://leksah.org/leksah_manual.pdf") [] False- ,AD "HelpHomepage" "Homepage" Nothing Nothing (openBrowser "http://leksah.org") [] False- ,AD "HelpAbout" "About" Nothing (Just "gtk-about") (liftIO aboutDialog) [] False+ ,AD "HelpManual" (__ "Manual") Nothing Nothing (openBrowser "http://leksah.org/leksah_manual.pdf") [] False+ ,AD "HelpHomepage" (__ "Homepage") Nothing Nothing (openBrowser "http://leksah.org") [] False+ ,AD "HelpAbout" (__ "About") Nothing (Just "gtk-about") (liftIO aboutDialog) [] False - ,AD "BackgroundBuildToggled" "_BackgroundBuild" (Just "Build in the background and report errors") (Just "ide_build")+ ,AD "BackgroundBuildToggled" (__ "_BackgroundBuild") (Just (__ "Build in the background and report errors")) (Just "ide_build") backgroundBuildToggled [] True- ,AD "RunUnitTestsToggled" "_RunUnitTests" (Just "Run unit tests when building") (Just "gtk-apply")+ ,AD "RunUnitTestsToggled" (__ "_RunUnitTests") (Just (__ "Run unit tests when building")) (Just "gtk-apply") runUnitTestsToggled [] True- ,AD "MakeModeToggled" "_MakeMode" (Just "Make dependent packages") (Just "ide_make")+ ,AD "MakeModeToggled" (__ "_MakeMode") (Just (__ "Make dependent packages")) (Just "ide_make") makeModeToggled [] True- ,AD "DebugToggled" "_Debug" (Just "Use GHCi debugger to build and run") (Just "ide_debug")+ ,AD "DebugToggled" (__ "_Debug") (Just (__ "Use GHCi debugger to build and run")) (Just "ide_debug") debugToggled [] True- ,AD "OpenDocu" "_OpenDocu" (Just "Opens a browser for a search of the selected data") Nothing+ ,AD "OpenDocu" (__ "_OpenDocu") (Just (__ "Opens a browser for a search of the selected data")) Nothing openDocu [] True ] @@ -436,6 +482,8 @@ res <- readFile prefsPath return res ++ updateRecentEntries :: IDEAction updateRecentEntries = do recentFiles' <- readIDE recentFiles@@ -448,11 +496,11 @@ fe <- doesFileExist s when fe $ do mi <- menuItemNewWithLabel s- mi `onActivateLeaf` (reflectIDE (fileOpenThis s) ideR)+ mi `on` menuItemActivate $ reflectIDE (fileOpenThis s) ideR menuShellAppend recentFilesMenu mi) recentFiles' oldSubmenu <- menuItemGetSubmenu recentFilesItem when (isJust oldSubmenu) $ do- widgetHideAll (fromJust oldSubmenu)+ widgetHide (fromJust oldSubmenu) widgetDestroy (fromJust oldSubmenu) menuItemSetSubmenu recentFilesItem recentFilesMenu widgetShowAll recentFilesMenu@@ -461,11 +509,11 @@ fe <- doesFileExist s when fe $ do mi <- menuItemNewWithLabel s- mi `onActivateLeaf` (reflectIDE (workspaceOpenThis True (Just s) >> showWorkspace) ideR)+ mi `on` menuItemActivate $ reflectIDE (workspaceOpenThis True (Just s) >> showWorkspace) ideR menuShellAppend recentWorkspacesMenu mi) recentWorkspaces' oldSubmenu <- menuItemGetSubmenu recentWorkspacesItem when (isJust oldSubmenu) $ do- widgetHideAll (fromJust oldSubmenu)+ widgetHide (fromJust oldSubmenu) widgetDestroy (fromJust oldSubmenu) menuItemSetSubmenu recentWorkspacesItem recentWorkspacesMenu widgetShowAll recentWorkspacesMenu)@@ -489,11 +537,11 @@ if isToggle then do act <- toggleActionNew name label tooltip stockId- on act actionToggled (doAction ideAction ideR accString)+ on act actionToggled $ doAction ideAction ideR accString actionGroupAddActionWithAccel ag act acc else do act <- actionNew name label tooltip stockId- onActionActivate act (doAction ideAction ideR accString)+ on act actionActivated $ doAction ideAction ideR accString actionGroupAddActionWithAccel ag act acc doAction ideAction ideR accStr = (reflectIDE (do@@ -507,13 +555,13 @@ mbMenu <- uiManagerGetWidget uiManager "/ui/menubar" let menu = case mbMenu of Just it -> castToMenuBar it- Nothing -> throwIDE "Menu>>makeMenu: failed to create menubar"+ Nothing -> throwIDE (__ "Menu>>makeMenu: failed to create menubar") mbToolbar <- uiManagerGetWidget uiManager "/ui/toolbar" let toolbar = case mbToolbar of Just it -> castToToolbar it- Nothing -> throwIDE "Menu>>makeMenu: failed to create toolbar"- toolbarSetIconSize toolbar IconSizeSmallToolbar+ Nothing -> throwIDE (__ "Menu>>makeMenu: failed to create toolbar") toolbarSetStyle toolbar ToolbarIcons+ toolbarSetIconSize toolbar IconSizeSmallToolbar widgetSetSizeRequest toolbar 700 (-1) return (accGroup,menu,toolbar) @@ -521,44 +569,44 @@ textPopupMenu ideR menu = do let reflectIDE_ x = reflectIDE x ideR items <- containerGetChildren menu- mi1 <- menuItemNewWithLabel "Eval"- mi1 `onActivateLeaf` reflectIDE_ debugExecuteSelection+ mi1 <- menuItemNewWithLabel (__ "Eval")+ mi1 `on` menuItemActivate $ reflectIDE_ debugExecuteSelection menuShellAppend menu mi1- mi11 <- menuItemNewWithLabel "Eval & Insert"- mi11 `onActivateLeaf` reflectIDE_ debugExecuteAndShowSelection+ mi11 <- menuItemNewWithLabel (__ "Eval & Insert")+ mi11 `on` menuItemActivate $ reflectIDE_ debugExecuteAndShowSelection menuShellAppend menu mi11- mi12 <- menuItemNewWithLabel "Step"- mi12 `onActivateLeaf` reflectIDE_ debugStepExpression+ mi12 <- menuItemNewWithLabel (__ "Step")+ mi12 `on` menuItemActivate $ reflectIDE_ debugStepExpression menuShellAppend menu mi12- mi13 <- menuItemNewWithLabel "Trace"- mi13 `onActivateLeaf` reflectIDE_ debugTraceExpression+ mi13 <- menuItemNewWithLabel (__ "Trace")+ mi13 `on` menuItemActivate $ reflectIDE_ debugTraceExpression menuShellAppend menu mi13- mi16 <- menuItemNewWithLabel "Set Breakpoint"- mi16 `onActivateLeaf` reflectIDE_ debugSetBreakpoint+ mi16 <- menuItemNewWithLabel (__ "Set Breakpoint")+ mi16 `on` menuItemActivate $ reflectIDE_ debugSetBreakpoint menuShellAppend menu mi16 sep1 <- separatorMenuItemNew menuShellAppend menu sep1- mi14 <- menuItemNewWithLabel "Type"- mi14 `onActivateLeaf` reflectIDE_ debugType+ mi14 <- menuItemNewWithLabel (__ "Type")+ mi14 `on` menuItemActivate $ reflectIDE_ debugType menuShellAppend menu mi14- mi141 <- menuItemNewWithLabel "Info"- mi141 `onActivateLeaf` reflectIDE_ debugInformation+ mi141 <- menuItemNewWithLabel (__ "Info")+ mi141 `on` menuItemActivate $ reflectIDE_ debugInformation menuShellAppend menu mi141- mi15 <- menuItemNewWithLabel "Kind"- mi15 `onActivateLeaf` reflectIDE_ debugKind+ mi15 <- menuItemNewWithLabel (__ "Kind")+ mi15 `on` menuItemActivate $ reflectIDE_ debugKind menuShellAppend menu mi15 sep2 <- separatorMenuItemNew menuShellAppend menu sep2- mi2 <- menuItemNewWithLabel "Find (text)"- mi2 `onActivateLeaf` reflectIDE_ (editFindInc Initial)+ mi2 <- menuItemNewWithLabel (__ "Find (text)")+ mi2 `on` menuItemActivate $ reflectIDE_ (editFindInc Initial) menuShellAppend menu mi2- mi3 <- menuItemNewWithLabel "Search (metadata)"- mi3 `onActivateLeaf` (reflectIDE_ $+ mi3 <- menuItemNewWithLabel (__ "Search (metadata)")+ mi3 `on` menuItemActivate $ (reflectIDE_ $ getSearch Nothing >>= (\search -> do mbtext <- selectedText case mbtext of Just t -> searchMetaGUI search t- Nothing -> ideMessage Normal "Select a text first"))+ Nothing -> ideMessage Normal (__ "Select a text first"))) menuShellAppend menu mi3 let interpretingEntries = [castToWidget mi16] let interpretingSelEntries = [castToWidget mi1, castToWidget mi11, castToWidget mi12,@@ -596,16 +644,16 @@ aboutDialog :: IO () aboutDialog = do d <- aboutDialogNew- aboutDialogSetName d "Leksah"- aboutDialogSetVersion d (showVersion version)- aboutDialogSetCopyright d "Copyright 2007-2011 Jürgen Nicklisch-Franken, Hamish Mackenzie"- aboutDialogSetComments d $ "An integrated development environement (IDE) for the " ++- "programming language Haskell and the Glasgow Haskell Compiler" dd <- getDataDir- license <- catch (readFile $ dd </> "LICENSE") (\ (_ :: SomeException) -> return "")- aboutDialogSetLicense d $ Just license- aboutDialogSetWebsite d "http://leksah.org/"- aboutDialogSetAuthors d ["Jürgen Nicklisch-Franken","Hamish Mackenzie"]+ license <- catch (readFile $ dd </> (__ "LICENSE")) (\ (_ :: SomeException) -> return "")+ set d [ aboutDialogName := "Leksah"+ , aboutDialogVersion := showVersion version+ , aboutDialogCopyright := (__ "Copyright 2007-2011 Jürgen Nicklisch-Franken, Hamish Mackenzie")+ , aboutDialogComments := (__ "An integrated development environement (IDE) for the ") +++ (__ "programming language Haskell and the Glasgow Haskell Compiler")+ , aboutDialogLicense := Just license+ , aboutDialogWebsite := "http://leksah.org/"+ , aboutDialogAuthors := ["Jürgen Nicklisch-Franken","Hamish Mackenzie"] ] dialogRun d widgetDestroy d return ()@@ -622,7 +670,7 @@ "ide_debug", "ide_step", "ide_local", "ide_module", "ide_continue", "ide_rebuild_meta", "ide_empty","ide_source_local"] iconFactoryAddDefault iconFactory)- (\(e :: SomeException) -> getDataDir >>= \dataDir -> throwIDE ("Can't load icons from " ++ dataDir ++ " " ++ show e))+ (\(e :: SomeException) -> getDataDir >>= \dataDir -> throwIDE (printf (__ "Can't load icons from %s %s") dataDir (show e))) where loadIcon dataDir iconFactory name = do pb <- pixbufNewFromFile $ dataDir </> "pics" </> (name ++ ".png")@@ -663,7 +711,7 @@ uiManager' <- getUiManager actionGroups <- liftIO $ uiManagerGetActionGroups uiManager' res <- liftIO $ actionGroupGetAction (head actionGroups) string- when (isNothing res) $ ideMessage Normal $ "Can't find UI Action " ++ string+ when (isNothing res) $ ideMessage Normal $ (printf (__ "Can't find UI Action %s") string) return res getAdditionalActionsFor :: SensitivityMask -> [Bool -> IDEAction]@@ -702,7 +750,7 @@ boxPackStart vb findbar PackNatural 0 statusBar <- buildStatusbar boxPackEnd vb statusBar PackNatural 0- win `onKeyPress` (\ e -> reflectIDE (handleSpecialKeystrokes e) ideR)+ win `on` keyPressEvent $ handleSpecialKeystrokes ideR windowAddAccelGroup win acc containerAdd win vb reflectIDE (do@@ -713,6 +761,7 @@ instrumentSecWindow :: Window -> IDEAction instrumentSecWindow win = do+ liftIO $ debugM "leksah" "instrumentSecWindow" ideR <- ask uiManager' <- getUiManager liftIO $ do@@ -724,15 +773,19 @@ (acc,_,_) <- getMenuAndToolbars uiManager' windowAddAccelGroup win acc- win `onKeyPress` (\ e -> reflectIDE (handleSpecialKeystrokes e) ideR)+ win `on` keyPressEvent $ handleSpecialKeystrokes ideR return () -- -- | Callback function for onKeyPress of the main window, so 'preprocess' any key ---handleSpecialKeystrokes :: GdkEvents.Event -> IDEM Bool-handleSpecialKeystrokes (Key { eventKeyName = name, eventModifier = mods,- eventKeyVal = keyVal, eventKeyChar = mbChar}) = do+handleSpecialKeystrokes :: IDERef -> EventM EKey Bool+handleSpecialKeystrokes ideR = do+ name <- eventKeyName+ mods <- eventModifier+ keyVal <- eventKeyVal+ let mbChar = keyToChar keyVal+ liftIO $ (`reflectIDE` ideR) $ do prefs' <- readIDE prefs case (name, mods) of (tab, [Control]) | (tab == "Tab" || tab == "ISO_Left_Tab")@@ -775,7 +828,6 @@ printMods :: [Modifier] -> String printMods [] = "" printMods (m:r) = show m ++ printMods r-handleSpecialKeystrokes _ = return True setSymbol :: String -> Bool -> IDEAction setSymbol symbol openSource = do@@ -802,9 +854,16 @@ registerLeksahEvents :: IDEAction registerLeksahEvents = do stRef <- ask+ liftIO $ debugM "leksah" "registerLeksahEvents"+ defaultLogLaunch <- getDefaultLogLaunch registerEvent stRef "LogMessage"- (\e@(LogMessage s t) -> getLog >>= \(log :: IDELog) -> liftIO $ appendLog log s t- >> return e)+ (\e@(LogMessage s t) -> do+ postAsyncIDE $ do+ log <- getLog+ defaultLogLaunch <- getDefaultLogLaunch+ liftIO $ appendLog log defaultLogLaunch (T.pack s) t+ return ()+ return e) registerEvent stRef "SelectInfo" (\ e@(SelectInfo str gotoSource) -> setSymbol str gotoSource >> return e) registerEvent stRef "SelectIdent"
@@ -0,0 +1,46 @@+{-# LANGUAGE CPP #-}+-----------------------------------------------------------------------------+--+-- Module : IDE.Command.Print+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- | TODO this module should be moved to some other place, maybe utils+--+-----------------------------------------------------------------------------++module IDE.Command.Print (+ print+ , PrintError (..)+) where++import System.Exit+import Prelude hiding (print)+import IDE.Core.Types+import IDE.Core.State+import IDE.Utils.Tool (readProcessWithExitCode)++data PrintError = PrintError {+ exitCode :: Int+ , stderr :: String+ , printCmd :: FilePath+ } deriving (Read,Show)+++#if defined (windows_HOST_OS)+printCommand = "print"+#else+printCommand = "lpr"+#endif++print :: FilePath -> IO (Either PrintError String)+print fileName = do+ (ec, out, err) <- readProcessWithExitCode printCommand [fileName] ""+ case ec of+ ExitSuccess -> return $ Right out+ ExitFailure i -> return $ Left $ PrintError i err printCommand+
@@ -0,0 +1,20 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Command.VCS+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability : +--+-- |+--+-----------------------------------------------------------------------------++module IDE.Command.VCS (++) where+++
@@ -0,0 +1,176 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Command.VCS.Common+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------+module IDE.Command.VCS.Common (+ setMenuForPackage++ --getter+ ,getVCSConf'+) where++import IDE.Core.Types+import IDE.Core.State+import qualified IDE.Utils.GUIUtils as GUIUtils+import qualified IDE.Workspaces.Writer as Writer+import qualified IDE.Command.VCS.Types as Types+import qualified IDE.Command.VCS.GIT as GIT+import qualified IDE.Command.VCS.SVN as SVN+import qualified IDE.Command.VCS.Mercurial as Mercurial+++import qualified VCSWrapper.Common as VCS+import qualified VCSGui.Common as VCSGUI++import qualified Graphics.UI.Gtk as Gtk+import Control.Monad.Reader+import Control.Monad.Trans(liftIO)+import qualified Control.Exception as Exc+import Data.Maybe+import qualified Data.Map as Map++++setMenuForPackage :: Gtk.Menu -> FilePath -> Maybe VCSConf -> IDEAction+setMenuForPackage vcsMenu cabalFp mbVCSConf = do+ ideR <- ask++ -- create or get packageItem and set it to ide to be able to get it later again+ (oldMenuItems,pw) <- readIDE vcsData+ packageItem <- do+ case (Map.lookup cabalFp oldMenuItems) of+ Nothing -> liftIO $ Gtk.menuItemNewWithLabel cabalFp+ Just menuItem -> return menuItem+ let newMenuItems = Map.insert cabalFp packageItem oldMenuItems+ modifyIDE_ (\ide -> ide {vcsData = (newMenuItems,pw)})++ packageMenu <- liftIO $ Gtk.menuNew++ -- build and set set-up repo action+ setupActionItem <- liftIO $ Gtk.menuItemNewWithMnemonic "_Setup Repo"+ liftIO $ setupActionItem `Gtk.on` Gtk.menuItemActivate $+ reflectIDE (+ runSetupRepoActionWithContext cabalFp+ ) ideR+ liftIO $ Gtk.menuShellAppend packageMenu setupActionItem++ -- build and set other actions+ let packageMenuOperations = case mbVCSConf of+ Nothing -> []+ Just (vcsType,_,_) -> mkVCSActions vcsType+ liftIO $ addActions cabalFp packageMenu ideR packageMenuOperations++ -- set menus+ liftIO $ Gtk.menuItemRemoveSubmenu packageItem+ liftIO $ Gtk.menuItemSetSubmenu packageItem packageMenu+ liftIO $ Gtk.menuShellAppend vcsMenu packageItem+ liftIO $ Gtk.widgetShowAll vcsMenu+ return ()+ where+ addActions cabalFp packageMenu ideR actions = mapM_ (\(name,action) -> do+ -- for each operation add it to menu and connect action+ actionItem <- Gtk.menuItemNewWithMnemonic name+ actionItem `Gtk.on` Gtk.menuItemActivate $+ reflectIDE (runActionWithContext action cabalFp) ideR+ Gtk.menuShellAppend packageMenu actionItem+ ) actions+ mkVCSActions :: VCS.VCSType -> [(String, Types.VCSAction ())]+ mkVCSActions VCS.SVN = SVN.mkSVNActions+ mkVCSActions VCS.GIT = GIT.mkGITActions+ mkVCSActions VCS.Mercurial = Mercurial.mkMercurialActions+++++{- |+ Retrieves VCS configuration for given package from current workspace and runs given+ VCS action using it. VCS Configuration must be set before.+-}+runActionWithContext :: Types.VCSAction () -- ^ computation to execute, i.e. showCommit+ -> FilePath -- ^ filepath to package+ -> IDEAction+runActionWithContext vcsAction packageFp = do+ config <- getVCSConf'' packageFp+ runVcs config packageFp $ vcsAction+ where+ runVcs :: VCSConf -> FilePath -> Types.VCSAction t -> IDEM t+ runVcs config cabalFp (Types.VCSAction a) = runReaderT a (config,cabalFp)++{- |+ Shows a GUI to set up a VCS. If a vcs-config is set for given package it will be used.+-}+runSetupRepoActionWithContext :: FilePath+ -> IDEAction+runSetupRepoActionWithContext packageFp = do+ eConfigErr <- getVCSConf packageFp+ case eConfigErr of+ Left error -> liftIO $ GUIUtils.showErrorDialog error+ Right mbConfig -> do+ ide <- ask+ liftIO $ VCSGUI.showSetupConfigGUI mbConfig (callback ide packageFp)+ where+ callback :: IDERef -> FilePath -> Maybe (VCS.VCSType, VCS.Config, Maybe VCSGUI.MergeTool) -> IO()+ callback ideRef packageFp mbConfig = do+ -- set config in workspace+ runReaderT (workspaceSetVCSConfig packageFp mbConfig) ideRef+++++++--+-- Basic setters and getters+--++workspaceSetVCSConfig :: FilePath -> Maybe VCSConf -> IDEAction+workspaceSetVCSConfig pathToPackage mbVCSConf = do+ vcsItem <- GUIUtils.getVCS+ mbVcsMenu <- liftIO $ Gtk.menuItemGetSubmenu vcsItem+ let vcsMenu = Gtk.castToMenu $ fromJust mbVcsMenu+ setMenuForPackage vcsMenu pathToPackage mbVCSConf+ modifyIDE_ (\ide -> do+ let oldWs = fromJust (workspace ide)+ let oldMap = packageVcsConf oldWs+ let newMap = case mbVCSConf of+ Nothing -> Map.delete pathToPackage oldMap+ Just vcsConf -> Map.insert pathToPackage vcsConf oldMap+ let newWs = (fromJust (workspace ide)) { packageVcsConf = newMap }+ ide {workspace = Just newWs })+ newWs <- readIDE workspace+ Writer.writeWorkspace $ fromJust newWs++++-- | vcs conf for given package in current workspace.+getVCSConf :: FilePath -> IDEM (Either String (Maybe VCSConf))+getVCSConf pathToPackage = do+ mbWorkspace <- readIDE workspace+ case mbWorkspace of+ Nothing -> return $ Left $ "No open workspace. Open Workspace first."+ Just workspace -> getVCSConf' workspace pathToPackage++-- | vcs conf for given package in given workspace.+getVCSConf' :: Workspace -> FilePath -> IDEM (Either String (Maybe VCSConf))+getVCSConf' workspace pathToPackage = do+ let mbConfig = Map.lookup pathToPackage $ packageVcsConf workspace+ case mbConfig of+ --Left $ "Could not find version-control-system configuration for package "++pathToPackage+ Nothing -> return $ Right $ Nothing+ Just conf -> return $ Right $ Just conf++-- | vcs conf for given package in current workspace. Workspae and VCS conf must be set before.+getVCSConf'' :: FilePath -> IDEM VCSConf+getVCSConf'' pathToPackage = do+ (Just workspace) <- readIDE workspace+ return $ fromJust $ Map.lookup pathToPackage $ packageVcsConf workspace+
@@ -0,0 +1,59 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Command.VCS.Common.GUI+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.Command.VCS.Common.GUI (+-- addMenuForPackage+) where++--import IDE.Core.Types+--import IDE.Core.State+--+--import Graphics.UI.Gtk (+-- menuNew, menuItemNewWithLabel, onActivateLeaf, menuShellAppend, menuItemSetSubmenu+-- ,widgetShowAll, menuItemNewWithMnemonic, menuItemGetSubmenu, widgetHideAll, widgetDestroy)+--import Control.Monad.Reader(liftIO,ask,when)++--vcsMenu from+-- vcsItem <- GUIUtils.getVCS+-- vcsMenu <- liftIO $ menuNew+-- ideR from ask+-- setupRepoAction actionContext packageMenuOperations from common+--addMenuForPackage cabalFp = do+-- packageItem <- liftIO $ menuItemNewWithLabel cabalFp+-- packageMenu <- liftIO $ menuNew+--+-- -- set-up repo action+-- actionItem <- liftIO $ menuItemNewWithMnemonic "_Setup Repo"+-- liftIO $ actionItem `onActivateLeaf` (+-- reflectIDE (+-- setupRepoAction cabalFp+-- ) ideR)+-- liftIO $ menuShellAppend packageMenu actionItem+--+-- -- other actions if repo set+-- liftIO $ addActions cabalFp packageMenu ideR packageMenuOperations actionContext+--+-- liftIO $ menuItemSetSubmenu packageItem packageMenu+-- liftIO $ menuShellAppend vcsMenu packageItem+-- where+-- addActions cabalFp packageMenu ideR actions runner = mapM_ (\(name,action) -> do+-- -- for each operation add it to menu and connect action+-- actionItem <- menuItemNewWithMnemonic name+-- actionItem `onActivateLeaf` (reflectIDE (runner action cabalFp) ideR)+-- menuShellAppend packageMenu actionItem+-- ) actions++++
@@ -0,0 +1,80 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Command.VCS.Common.Helper+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.Command.VCS.Common.Helper (+ --helper for vcs actions+ eMergeToolSetter+ ,createActionFromContext+) where+++import IDE.Core.Types+import IDE.Core.State+import qualified IDE.Workspaces.Writer as Writer+import qualified IDE.Command.VCS.Types as Types++import qualified VCSWrapper.Common as VCS+import qualified VCSGui.Common as VCSGUI++import Control.Monad.Reader+import Control.Monad.Trans(liftIO)+import Data.Maybe+import qualified Data.Map as Map++{- |+ Runs given vcs-action using the vcs-conf set in the ReaderT.+ Provides a basic exception handler for any errors occuring.+-}+createActionFromContext :: VCS.Ctx() -- ^ computation to execute, i.e. showCommit+ -> Types.VCSAction ()+createActionFromContext vcsAction = do+ ((_,conf,_),_) <- ask+ liftIO $ VCSGUI.defaultVCSExceptionHandler $ VCS.runVcs conf $ vcsAction++{- |+ Creates an 'eMergeToolSetter' (Either MergeTool or MT-Setter) from given parameters.+-}+eMergeToolSetter :: IDERef+ -> FilePath+ -> Maybe VCSGUI.MergeTool+ -> Either VCSGUI.MergeTool (VCSGUI.MergeTool -> IO())+eMergeToolSetter ideRef cabalFp mbMergeTool = do+ case mbMergeTool of+ Nothing -> Right $ mergeToolSetter ideRef cabalFp+ Just mergeTool -> Left $ mergeTool++{- |+ Facility to set a mergetool for a given package.+-}+mergeToolSetter :: IDERef -> FilePath -> VCSGUI.MergeTool -> IO()+mergeToolSetter ideRef cabalFp mergeTool = do+ runReaderT (workspaceSetMergeTool cabalFp mergeTool) ideRef++{- |+ Sets the given mergetool for given package in current workspace. Workspace must be set.+-}+workspaceSetMergeTool :: FilePath -> VCSGUI.MergeTool -> IDEAction+workspaceSetMergeTool pathToPackage mergeTool = do+ modifyIDE_ (\ide -> do+ let oldWs = fromJust (workspace ide)+ let oldMap = packageVcsConf oldWs+ case (Map.lookup pathToPackage oldMap) of+ Nothing -> ide --TODO error+ Just (vcsType,config,_) -> do+ let vcsConf = (vcsType,config,Just mergeTool)+ let newMap = Map.insert pathToPackage vcsConf oldMap+ let newWs = oldWs { packageVcsConf = newMap }+ ide {workspace = Just newWs })+ newWs <- readIDE workspace+ Writer.writeWorkspace $ fromJust newWs
@@ -0,0 +1,85 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Command.VCS.Common.Workspaces+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.Command.VCS.Common.Workspaces (+ onWorkspaceOpen+ , onWorkspaceClose+) where++-- VCS imports+import IDE.Utils.FileUtils(getConfigFilePathForLoad)+import qualified IDE.Utils.GUIUtils as GUIUtils+import IDE.Core.Types+import IDE.Core.State+import qualified IDE.Command.VCS.Common as Common+import qualified IDE.Command.VCS.SVN as SVN (mkSVNActions)+import qualified IDE.Command.VCS.GIT as GIT (mkGITActions)+import qualified IDE.Command.VCS.Common.GUI as GUI++import qualified VCSWrapper.Common as VCS+import qualified VCSGui.Common as VCSGUI++import Data.IORef(writeIORef, readIORef, IORef(..))+import Control.Monad.Reader(liftIO,ask,when)++import Graphics.UI.Frame.Panes+import Graphics.UI.Gtk (+ menuNew, menuItemNewWithLabel, menuItemActivate, menuShellAppend, menuItemSetSubmenu+ ,widgetShowAll, menuItemNewWithMnemonic, menuItemGetSubmenu, widgetHide, widgetDestroy, menuItemRemoveSubmenu)++import Data.Maybe+import Data.List+import System.Log.Logger (debugM)++onWorkspaceClose :: IDEAction+onWorkspaceClose = do+ vcsItem <- GUIUtils.getVCS+ liftIO $ menuItemRemoveSubmenu vcsItem++onWorkspaceOpen :: Workspace -> IDEAction+onWorkspaceOpen ws = do+ liftIO $ debugM "leksah" "onWorkspaceOpen"+ let mbPackages = wsPackages ws+ packages <- mapM (mapper ws)+ mbPackages+ vcsItem <- GUIUtils.getVCS+ vcsMenu <- liftIO $ menuNew++ ideR <- ask++ --for each package add an extra menu containing vcs specific menuitems+ mapM_ (\(p,mbVcsConf) -> do+ Common.setMenuForPackage vcsMenu (ipdCabalFile p) mbVcsConf+ liftIO $ menuItemSetSubmenu vcsItem vcsMenu+ )+ packages++ liftIO $ widgetShowAll vcsItem+ return ()+ where+ mapper :: Workspace -> IDEPackage -> IDEM (IDEPackage, Maybe VCSConf)+ mapper workspace p = do+ let fp = ipdCabalFile p+ eErrConf <- Common.getVCSConf' workspace fp+ case eErrConf of+ Left error -> do+ liftIO $ putStrLn $ "Could not retrieve vcs-conf due to '"++error++"'."+ return (p, Nothing)+ Right mbConf -> case mbConf of+ Nothing -> do+ liftIO $ putStrLn $ "Could not retrieve vcs-conf for active package. No vcs-conf set up."+ return (p, Nothing)+ Just vcsConf -> return $ (p, Just vcsConf)++
@@ -0,0 +1,50 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Command.VCS.GIT+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.Command.VCS.GIT (+ commitAction+ ,viewLogAction+ ,pushAction+ ,pullAction+ ,mkGITActions+) where++import IDE.Core.Types+import IDE.Core.State++import qualified IDE.Command.VCS.Common.Helper as Helper+import qualified IDE.Command.VCS.Types as Types++import qualified VCSGui.Git as GitGUI+import qualified VCSWrapper.Git as Git++commitAction :: Types.VCSAction ()+commitAction = Helper.createActionFromContext GitGUI.showCommitGUI++viewLogAction :: Types.VCSAction ()+viewLogAction = Helper.createActionFromContext GitGUI.showLogGUI++pushAction :: Types.VCSAction ()+pushAction = Helper.createActionFromContext $ GitGUI.askPassWrapper Git.push++pullAction :: Types.VCSAction ()+pullAction = Helper.createActionFromContext $ GitGUI.askPassWrapper GitGUI.pull++mkGITActions :: [(String, Types.VCSAction ())]+mkGITActions = [+ ("_Commit", commitAction)+ ,("_View Log", viewLogAction)+ ,("_Push", pushAction)+ ,("_Pull", pullAction)+ ]
@@ -0,0 +1,46 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Command.VCS.Mercurial+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.Command.VCS.Mercurial (+ mkMercurialActions+) where++import IDE.Core.Types+import IDE.Core.State++import qualified IDE.Command.VCS.Common.Helper as Helper+import qualified IDE.Command.VCS.Types as Types++import qualified VCSGui.Mercurial as MercurialGUI+import qualified VCSWrapper.Mercurial as Mercurial++commitAction :: Types.VCSAction ()+commitAction = Helper.createActionFromContext MercurialGUI.showCommitGUI++viewLogAction :: Types.VCSAction ()+viewLogAction = Helper.createActionFromContext MercurialGUI.showLogGUI++pushAction :: Types.VCSAction ()+pushAction = Helper.createActionFromContext $ Mercurial.push++pullAction :: Types.VCSAction ()+pullAction = Helper.createActionFromContext $ Mercurial.pull++mkMercurialActions :: [(String, Types.VCSAction ())]+mkMercurialActions = [+ ("_Commit", commitAction)+ ,("_View Log", viewLogAction)+ ,("_Push", pushAction)+ ,("_Pull", pullAction)+ ]
@@ -0,0 +1,84 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Command.VCS.SVN+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- | TODO use new runActionWithContext+--+-----------------------------------------------------------------------------++module IDE.Command.VCS.SVN (+ commitAction+ ,updateAction+ ,viewLogAction+ ,mkSVNActions+) where+++import IDE.Core.Types+import IDE.Core.State++import qualified IDE.Command.VCS.Common.Helper as Helper+import qualified IDE.Command.VCS.Types as Types++import qualified VCSGui.Common as VCSGUI+import qualified VCSGui.Svn as GUISvn+import qualified VCSWrapper.Svn as Wrapper.Svn+import qualified VCSWrapper.Common as Wrapper++import Graphics.UI.Gtk.ActionMenuToolbar.UIManager(MergeId)++import Control.Monad.Reader(liftIO,ask,lift)+import Data.IORef(atomicModifyIORef, IORef)+import Data.Either++commitAction :: Types.VCSAction ()+commitAction = do+ ((_,_,mbMergeTool),package) <- ask+ ide <- Types.askIDERef+ createSVNActionFromContext $ GUISvn.showCommitGUI $ Helper.eMergeToolSetter ide package mbMergeTool++updateAction :: Types.VCSAction ()+updateAction = do+ ((_,_,mbMergeTool),package) <- ask+ ideRef <- Types.askIDERef+ createSVNActionFromContext $ GUISvn.showUpdateGUI $ Helper.eMergeToolSetter ideRef package mbMergeTool++viewLogAction :: Types.VCSAction ()+viewLogAction = createSVNActionFromContext GUISvn.showLogGUI++mkSVNActions :: [(String, Types.VCSAction ())]+mkSVNActions = [+ ("_Commit", commitAction)+ ,("_View Log", viewLogAction)+ ,("_Update", updateAction)+ ]++--HELPERS++createSVNActionFromContext :: (Either GUISvn.Handler (Maybe String)+ -> Wrapper.Ctx())+ -> Types.VCSAction ()+createSVNActionFromContext action = do+ (mergeInfo, mbPw) <- Types.readIDE' vcsData+ ide <- Types.askIDERef+ case mbPw of+ Nothing -> Helper.createActionFromContext $ action $ Left $ passwordHandler ide mergeInfo+ Just mb -> Helper.createActionFromContext $ action $ Right mb+ where+-- passwordHandler :: IORef IDE-> Maybe MergeId -> ((Maybe (Bool, Maybe String)) -> Wrapper.Ctx ())+ passwordHandler ide mbMergeInfo result = liftIO $ do+ case result of+ Just (True, pw) -> modifyIDE_' ide (\ide -> ide {vcsData = (mbMergeInfo, Just pw) })+ _ -> return ()+ modifyIDE_' ide f = do+ liftIO (atomicModifyIORef ide f')+ where+ f' a = (f a,())++
@@ -0,0 +1,39 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Command.VCS.Types+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------+{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving #-}+module IDE.Command.VCS.Types (+ --types+ VCSAction(..)+ ,askIDERef+ ,readIDE'+ ,reflectIDE'+) where+import Control.Monad.Reader+import IDE.Core.Types+import IDE.Core.State++newtype VCSAction a = VCSAction (ReaderT (VCSConf,FilePath) IDEM a)+ deriving (Monad, MonadIO, MonadReader (VCSConf,FilePath))++askIDERef :: VCSAction IDERef+askIDERef = VCSAction $ lift $ ask++--liftIDE :: ReaderT (VCSConf,FilePath) IDEM a+--liftIDE = VCSAction $ lift++readIDE' :: (IDE -> a) -> VCSAction a+readIDE' f = VCSAction $ lift $ readIDE f++reflectIDE' :: IDEM a -> IDERef -> IO a+reflectIDE' c ideR = reflectIDE c ideR
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE CPP, ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Completion@@ -21,16 +21,19 @@ import Data.Char import Data.IORef import Control.Monad-import Graphics.UI.Gtk as Gtk hiding(onKeyPress, onKeyRelease)+import Graphics.UI.Gtk as Gtk import Graphics.UI.Gtk.Gdk.EventM as Gtk import IDE.Core.State import IDE.Metainfo.Provider(getDescription,getCompletionOptions)-import IDE.TextEditor+import IDE.TextEditor as TE import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Trans.Reader (ask) import qualified Control.Monad.Reader as Gtk (liftIO)+import Control.Monad.Trans.Class (MonadTrans(..))+import Control.Applicative ((<$>))+import IDE.Utils.GUIUtils (getDarkState) -complete :: EditorView -> Bool -> IDEAction+complete :: TextEditor editor => EditorView editor -> Bool -> IDEAction complete sourceView always = do currentState' <- readIDE currentState prefs' <- readIDE prefs@@ -61,7 +64,7 @@ modifyIDE_ $ \ide -> ide{completion = ((x, y), completion)} setCompletionSize _ = return () -getIsWordChar :: EditorView -> IDEM (Char -> Bool)+getIsWordChar :: forall editor. TextEditor editor => EditorView editor -> IDEM (Char -> Bool) getIsWordChar sourceView = do ideR <- ask buffer <- getBuffer sourceView@@ -81,7 +84,7 @@ Just prevChar | isOp prevChar -> return isOp _ -> return $ const False -initCompletion :: EditorView -> Bool -> IDEAction+initCompletion :: forall editor. TextEditor editor => EditorView editor -> Bool -> IDEAction initCompletion sourceView always = do ideR <- ask ((width, height), completion') <- readIDE completion@@ -95,13 +98,13 @@ windows <- getWindows prefs <- readIDE prefs window <- liftIO windowNewPopup- liftIO $ windowSetTransientFor window (head windows) liftIO $ set window [ windowTypeHint := WindowTypeHintUtility, windowDecorated := False, windowResizable := True, windowDefaultWidth := width,- windowDefaultHeight := height]+ windowDefaultHeight := height,+ windowTransientFor := head windows] liftIO $ containerSetBorderWidth window 3 paned <- liftIO $ hPanedNew liftIO $ containerAdd window paned@@ -132,9 +135,10 @@ liftIO $ set tree [treeViewHeadersVisible := False] - descriptionBuffer <- newGtkBuffer Nothing ""+ descriptionBuffer <- newDefaultBuffer Nothing "" descriptionView <- newView descriptionBuffer (textviewFont prefs)- setStyle descriptionBuffer $ case sourceStyle prefs of+ preferDark <- getDarkState+ setStyle preferDark descriptionBuffer $ case sourceStyle prefs of (False,_) -> Nothing (True,v) -> Just v descriptionScrolledWindow <- getScrolledWindow descriptionView@@ -144,8 +148,8 @@ treeSelection <- liftIO $ treeViewGetSelection tree - liftIO $ treeSelection `onSelectionChanged` (do- treeSelectionSelectedForeach treeSelection (\treePath -> (do+ liftIO $ on treeSelection treeSelectionSelectionChanged $ do+ treeSelectionSelectedForeach treeSelection $ \treePath -> do rows <- treeSelectionGetSelectedRows treeSelection case rows of [treePath] -> reflectIDE (withWord store treePath (\name -> do@@ -153,8 +157,6 @@ setText descriptionBuffer description )) ideR _ -> return ()- ))- ) liftIO $ panedAdd1 paned nameScrolledWindow liftIO $ panedAdd2 paned descriptionScrolledWindow@@ -165,11 +167,14 @@ completion = ((width, height), Just (CompletionWindow window tree store))}) updateOptions window tree store sourceView cids isWordChar always -addEventHandling :: Window -> EditorView -> TreeView -> ListStore String+addEventHandling :: TextEditor editor => Window -> EditorView editor -> TreeView -> ListStore String -> (Char -> Bool) -> Bool -> IDEM Connections addEventHandling window sourceView tree store isWordChar always = do ideR <- ask- cidsPress <- sourceView `onKeyPress` \name modifier keyVal -> do+ cidsPress <- TE.onKeyPress sourceView $ do+ keyVal <- lift eventKeyVal+ name <- lift eventKeyName+ modifier <- lift eventModifier char <- liftIO $ keyvalToChar keyVal Just model <- liftIO $ treeViewGetModel tree selection <- liftIO $ treeViewGetSelection tree@@ -179,7 +184,7 @@ ("Tab", _, _) -> (do visible <- liftIO $ get tree widgetVisible if visible then (do- tryToUpdateOptions window tree store sourceView True isWordChar always+ liftIDE $ tryToUpdateOptions window tree store sourceView True isWordChar always return True ) else return False@@ -194,7 +199,7 @@ return True ) Nothing -> (do- cancel+ liftIDE cancel return False ) )@@ -238,14 +243,16 @@ return False ) _ -> (do- cancel+ liftIDE cancel return False ) - cidsRelease <- sourceView `onKeyRelease` \name modifier keyVal -> do+ cidsRelease <- TE.onKeyRelease sourceView $ do+ name <- lift eventKeyName+ modifier <- lift eventModifier case (name, modifier) of ("BackSpace", _) -> do- complete sourceView False+ liftIDE $ complete sourceView False return False _ -> return False @@ -256,19 +263,26 @@ (x, y) <- eventCoordinates time <- eventTime - drawWindow <- Gtk.liftIO $ widgetGetDrawWindow window- status <- Gtk.liftIO $ pointerGrab- drawWindow- False- [PointerMotionMask, ButtonReleaseMask]- (Nothing:: Maybe DrawWindow)- Nothing- time- when (status == GrabSuccess) $ Gtk.liftIO $ do- (width, height) <- windowGetSize window- writeIORef resizeHandler $ Just $ \(newX, newY) -> do- reflectIDE (- setCompletionSize ((width + (floor (newX - x))), (height + (floor (newY - y))))) ideR+#ifdef MIN_VERSION_gtk3+ mbDrawWindow <- Gtk.liftIO $ widgetGetWindow window+#else+ mbDrawWindow <- Gtk.liftIO $ Just <$> widgetGetDrawWindow window+#endif+ case mbDrawWindow of+ Just drawWindow -> do+ status <- Gtk.liftIO $ pointerGrab+ drawWindow+ False+ [PointerMotionMask, ButtonReleaseMask]+ (Nothing:: Maybe DrawWindow)+ Nothing+ time+ when (status == GrabSuccess) $ Gtk.liftIO $ do+ (width, height) <- windowGetSize window+ writeIORef resizeHandler $ Just $ \(newX, newY) -> do+ reflectIDE (+ setCompletionSize ((width + (floor (newX - x))), (height + (floor (newY - y))))) ideR+ Nothing -> return () return True @@ -288,9 +302,9 @@ return True Nothing -> return False - idSelected <- liftIO $ tree `onRowActivated` (\treePath column -> (do+ idSelected <- liftIO $ on tree rowActivated $ \treePath column -> do reflectIDE (withWord store treePath (replaceWordStart sourceView isWordChar)) ideR- liftIO $ postGUIAsync $ reflectIDE cancel ideR))+ liftIO $ postGUIAsync $ reflectIDE cancel ideR return $ concat [cidsPress, cidsRelease, [ConnectC idButtonPress, ConnectC idMotion, ConnectC idButtonRelease, ConnectC idSelected]] @@ -304,7 +318,7 @@ _ -> return () ) -replaceWordStart :: EditorView -> (Char -> Bool) -> String -> IDEM ()+replaceWordStart :: TextEditor editor => EditorView editor -> (Char -> Bool) -> String -> IDEM () replaceWordStart sourceView isWordChar name = do buffer <- getBuffer sourceView (selStart, selEnd) <- getSelectionBounds buffer@@ -326,16 +340,16 @@ liftIO (do listStoreClear (store :: ListStore String) signalDisconnectAll connections- widgetHideAll window+ widgetHide window ) modifyIDE_ (\ide -> ide{currentState = IsRunning}) -updateOptions :: Window -> TreeView -> ListStore String -> EditorView -> Connections -> (Char -> Bool) -> Bool -> IDEAction+updateOptions :: forall editor. TextEditor editor => Window -> TreeView -> ListStore String -> EditorView editor -> Connections -> (Char -> Bool) -> Bool -> IDEAction updateOptions window tree store sourceView connections isWordChar always = do result <- tryToUpdateOptions window tree store sourceView False isWordChar always when (not result) $ cancelCompletion window tree store connections -tryToUpdateOptions :: Window -> TreeView -> ListStore String -> EditorView -> Bool -> (Char -> Bool) -> Bool -> IDEM Bool+tryToUpdateOptions :: TextEditor editor => Window -> TreeView -> ListStore String -> EditorView editor -> Bool -> (Char -> Bool) -> Bool -> IDEM Bool tryToUpdateOptions window tree store sourceView selectLCP isWordChar always = do ideR <- ask liftIO $ listStoreClear (store :: ListStore String)@@ -354,14 +368,14 @@ return () return True -findWordStart :: EditorIter -> (Char -> Bool) -> IDEM EditorIter+findWordStart :: TextEditor editor => EditorIter editor -> (Char -> Bool) -> IDEM (EditorIter editor) findWordStart iter isWordChar = do maybeWS <- backwardFindCharC iter (not . isWordChar) Nothing case maybeWS of Nothing -> atOffset iter 0 Just ws -> forwardCharC ws -findWordEnd :: EditorIter -> (Char -> Bool) -> IDEM EditorIter+findWordEnd :: TextEditor editor => EditorIter editor -> (Char -> Bool) -> IDEM (EditorIter editor) findWordEnd iter isWordChar = do maybeWE <- forwardFindCharC iter (not . isWordChar) Nothing case maybeWE of@@ -371,7 +385,7 @@ longestCommonPrefix (x:xs) (y:ys) | x == y = x : longestCommonPrefix xs ys longestCommonPrefix _ _ = [] -processResults :: Window -> TreeView -> ListStore String -> EditorView -> String -> [String]+processResults :: TextEditor editor => Window -> TreeView -> ListStore String -> EditorView editor -> String -> [String] -> Bool -> (Char -> Bool) -> Bool -> IDEAction processResults window tree store sourceView wordStart options selectLCP isWordChar always = do case options of@@ -397,44 +411,47 @@ Rectangle startx starty width height <- getIterLocation sourceView start (wWindow, hWindow) <- liftIO $ windowGetSize window (x, y) <- bufferToWindowCoords sourceView (startx, starty+height)- drawWindow <- getDrawWindow sourceView- (ox, oy) <- liftIO $ drawWindowGetOrigin drawWindow- Just namesSW <- liftIO $ widgetGetParent tree- (wNames, hNames) <- liftIO $ widgetGetSize namesSW- Just paned <- liftIO $ widgetGetParent namesSW- Just first <- liftIO $ panedGetChild1 (castToPaned paned)- Just second <- liftIO $ panedGetChild2 (castToPaned paned)- screen <- liftIO $ windowGetScreen window- monitor <- liftIO $ screenGetMonitorAtPoint screen (ox+x) (oy+y)- monitorLeft <- liftIO $ screenGetMonitorAtPoint screen (ox+x-wWindow+wNames) (oy+y)- monitorRight <- liftIO $ screenGetMonitorAtPoint screen (ox+x+wWindow) (oy+y)- monitorBelow <- liftIO $ screenGetMonitorAtPoint screen (ox+x) (oy+y+hWindow)- wScreen <- liftIO $ screenGetWidth screen- hScreen <- liftIO $ screenGetHeight screen- top <- if monitorBelow /= monitor || (oy+y+hWindow) > hScreen- then do- sourceSW <- getScrolledWindow sourceView- (_, hSource) <- liftIO $ widgetGetSize sourceSW- scrollToIter sourceView end 0.1 (Just (1.0, 1.0 - (fromIntegral hWindow / fromIntegral hSource)))- (_, newy) <- bufferToWindowCoords sourceView (startx, starty+height)- return (oy+newy)- else return (oy+y)- swap <- if (monitorRight /= monitor || (ox+x+wWindow) > wScreen) && monitorLeft == monitor && (ox+x-wWindow+wNames) > 0- then do- liftIO $ windowMove window (ox+x-wWindow+wNames) top- return $ first == namesSW- else do- liftIO $ windowMove window (ox+x) top- return $ first /= namesSW- when swap $ liftIO $ do- pos <- panedGetPosition (castToPaned paned)- containerRemove (castToPaned paned) first- containerRemove (castToPaned paned) second- panedAdd1 (castToPaned paned) second- panedAdd2 (castToPaned paned) first- panedSetPosition (castToPaned paned) (wWindow-pos)- when (not $ null newOptions) $ liftIO $ treeViewSetCursor tree [0] Nothing- liftIO $ widgetShowAll window+ mbDrawWindow <- getWindow sourceView+ case mbDrawWindow of+ Nothing -> return ()+ Just drawWindow -> do+ (ox, oy) <- liftIO $ drawWindowGetOrigin drawWindow+ Just namesSW <- liftIO $ widgetGetParent tree+ (Rectangle _ _ wNames hNames) <- liftIO $ widgetGetAllocation namesSW+ Just paned <- liftIO $ widgetGetParent namesSW+ Just first <- liftIO $ panedGetChild1 (castToPaned paned)+ Just second <- liftIO $ panedGetChild2 (castToPaned paned)+ screen <- liftIO $ windowGetScreen window+ monitor <- liftIO $ screenGetMonitorAtPoint screen (ox+x) (oy+y)+ monitorLeft <- liftIO $ screenGetMonitorAtPoint screen (ox+x-wWindow+wNames) (oy+y)+ monitorRight <- liftIO $ screenGetMonitorAtPoint screen (ox+x+wWindow) (oy+y)+ monitorBelow <- liftIO $ screenGetMonitorAtPoint screen (ox+x) (oy+y+hWindow)+ wScreen <- liftIO $ screenGetWidth screen+ hScreen <- liftIO $ screenGetHeight screen+ top <- if monitorBelow /= monitor || (oy+y+hWindow) > hScreen+ then do+ sourceSW <- getScrolledWindow sourceView+ (Rectangle _ _ _ hSource) <- liftIO $ widgetGetAllocation sourceSW+ scrollToIter sourceView end 0.1 (Just (1.0, 1.0 - (fromIntegral hWindow / fromIntegral hSource)))+ (_, newy) <- bufferToWindowCoords sourceView (startx, starty+height)+ return (oy+newy)+ else return (oy+y)+ swap <- if (monitorRight /= monitor || (ox+x+wWindow) > wScreen) && monitorLeft == monitor && (ox+x-wWindow+wNames) > 0+ then do+ liftIO $ windowMove window (ox+x-wWindow+wNames) top+ return $ first == namesSW+ else do+ liftIO $ windowMove window (ox+x) top+ return $ first /= namesSW+ when swap $ liftIO $ do+ pos <- panedGetPosition (castToPaned paned)+ containerRemove (castToPaned paned) first+ containerRemove (castToPaned paned) second+ panedAdd1 (castToPaned paned) second+ panedAdd2 (castToPaned paned) first+ panedSetPosition (castToPaned paned) (wWindow-pos)+ when (not $ null newOptions) $ liftIO $ treeViewSetCursor tree [0] Nothing+ liftIO $ widgetShowAll window when (newWordStart /= currentWordStart) $ replaceWordStart sourceView isWordChar newWordStart
@@ -50,6 +50,7 @@ , catchIDE , postSyncIDE , postAsyncIDE+, onIDE , forkIDE , sysMessage@@ -67,6 +68,11 @@ , liftYiControl , liftYi +, leksahSubDir+, leksahOrPackageDir+, getDataDir+, P.version+ , module IDE.Core.Types , module IDE.Core.CTypes , module IDE.Utils.Utils@@ -88,18 +94,24 @@ import Control.Event import System.IO import Data.Maybe (isJust)-import System.FilePath (dropFileName)+import System.FilePath+ (dropFileName, takeDirectory, (</>), takeFileName) import IDE.Core.CTypes import Control.Concurrent (forkIO) import IDE.Utils.Utils import qualified Data.Map as Map (empty, lookup) import Data.Typeable(Typeable) import qualified IDE.YiConfig as Yi-import Data.Enumerator (runIteratee, Iteratee(..))-import qualified Data.Enumerator as E- (returnI, Step(..), yield, continue)+import Data.Conduit (($$))+import qualified Data.Conduit as C+ (transPipe, Sink, awaitForever, yield, leftover, ($$))+import qualified Data.Conduit.List as CL+ (sourceList) import Control.Monad (liftM, when) import Control.Monad.Trans.Reader (ask, ReaderT(..))+import qualified Paths_leksah as P+import System.Environment.Executable (getExecutablePath)+import System.Directory (doesDirectoryExist) instance PaneMonad IDEM where getFrameState = readIDE frameState@@ -215,8 +227,9 @@ ideMessage :: MessageLevel -> String -> IDEAction ideMessage level str = do- triggerEventIDE (LogMessage (str ++ "\n") LogTag) liftIO $ sysMessage level str+ triggerEventIDE (LogMessage (str ++ "\n") LogTag)+ return () logMessage :: String -> LogTag -> IDEAction logMessage str tag = do@@ -292,14 +305,8 @@ reflectIDE :: IDEM a -> IDERef -> IO a reflectIDE c ideR = runReaderT c ideR -reflectIDEI :: Iteratee a IDEM b -> IDERef -> Iteratee a IO b-reflectIDEI c ideR = loop c where- loop x = do- s <- liftIO $ reflectIDE (runIteratee x) ideR- case s of- E.Continue f -> E.continue $ loop . f- E.Yield a b -> E.yield a b- E.Error e -> E.returnI $ E.Error e+reflectIDEI :: C.Sink a IDEM () -> IDERef -> C.Sink a IO ()+reflectIDEI c ideR = C.transPipe (`reflectIDE` ideR) c liftYiControl :: Yi.ControlM a -> IDEM a liftYiControl f = do@@ -321,6 +328,10 @@ postAsyncIDE :: IDEM () -> IDEM () postAsyncIDE f = reifyIDE (\ideR -> postGUIAsync (reflectIDE f ideR)) +onIDE obj signal callback = do+ ideRef <- ask+ liftIO $ obj `on` signal $ runReaderT callback ideRef+ -- --------------------------------------------------------------------- -- Convenience methods for accesing the IDE State --@@ -419,5 +430,32 @@ exchange p | ipdCabalFile p == file = ideP | otherwise = p +-- | Find a directory relative to the leksah install directory+leksahSubDir :: FilePath -- ^ Sub directory to look for+ -> IO (Maybe FilePath)+leksahSubDir subDir = do+ exePath <- getExecutablePath+ if takeFileName exePath == "leksah.exe"+ then do+ let dataDir = (takeDirectory $ takeDirectory exePath) </> subDir+ exists <- doesDirectoryExist dataDir+ if exists then return (Just dataDir) else return Nothing+ else return Nothing +-- | Get the leksah data dir based on the executable name or if that fails+-- use the directroy for the package. This is allows us to make binary packages+-- where the data directory id relative to the leksah executable.+-- This is important for Wind32 where setting environment variables for the+-- locations in a launch script causes problems (you can't pin the exe).+leksahOrPackageDir :: FilePath -- ^ Sub directory to look for+ -> IO FilePath -- ^ Used to get the package dir if we can't find the leksah one+ -> IO FilePath+leksahOrPackageDir subDir getPackageDir = do+ mbResult <- leksahSubDir subDir+ case mbResult of+ Just result -> return result+ Nothing -> getPackageDir++getDataDir :: IO FilePath+getDataDir = leksahOrPackageDir "leksah" P.getDataDir
@@ -31,6 +31,7 @@ , IDEState(..) , IDERef , IDEM+, IDEEventM , IDEAction , IDEEvent(..) , liftIDE@@ -50,12 +51,14 @@ , IDEPackage(..) , Workspace(..)+, VCSConf , ActionDescr(..) , ActionString , KeyString , Prefs(..)+, cabalCommand , LogRefType(..) , LogRef(..)@@ -78,6 +81,8 @@ , ModuleDescrCache , CompletionWindow(..)+, LogLaunch(..)+, LogLaunchData(..) , LogTag(..) , GUIHistory , GUIHistory'(..)@@ -88,8 +93,8 @@ import qualified IDE.YiConfig as Yi import Graphics.UI.Gtk- (Window(..), KeyVal(..), Color(..), Menu(..), TreeView(..),- ListStore(..), Toolbar(..))+ (TextBuffer, MenuItem, Window(..), KeyVal(..), Color(..), Menu(..),+ TreeView(..), ListStore(..), Toolbar(..)) import Data.Unique (newUnique, Unique(..)) import Graphics.UI.Frame.Panes import Distribution.Package@@ -98,11 +103,8 @@ import Data.Map (Map(..)) import Data.Set (Set(..)) import Distribution.ModuleName (ModuleName(..))-#if MIN_VERSION_gtk(0,10,5) import Graphics.UI.Gtk.Gdk.EventM (Modifier(..))-#else-import Graphics.UI.Gtk.Gdk.Enums (Modifier(..))-#endif+import Graphics.UI.Gtk.ActionMenuToolbar.UIManager(MergeId) import System.Time (ClockTime(..)) import Distribution.Simple (Extension(..)) import IDE.Utils.Tool (ToolState(..), ProcessHandle)@@ -119,7 +121,19 @@ import Control.Monad.Trans.Class (lift) import Control.Monad.IO.Class (liftIO) import Control.Monad.Trans.Reader (ReaderT(..))+#if MIN_VERSION_directory(1,2,0)+import Data.Time (UTCTime(..))+#endif +import qualified VCSWrapper.Common as VCS+import qualified VCSGui.Common as VCSGUI+import qualified Data.Map as Map (Map)+import Data.Typeable (Typeable)+import Foreign (Ptr)+import Control.Monad.Reader.Class (MonadReader(..))+import Data.Text (Text)+import qualified Data.Text as T (unpack)+ -- --------------------------------------------------------------------- -- IDE State --@@ -136,6 +150,7 @@ , prefs :: Prefs -- ^ configuration preferences , workspace :: Maybe Workspace -- ^ may be a workspace (set of packages) , activePack :: Maybe IDEPackage+, activeExe :: Maybe String , bufferProjCache :: Map FilePath (Maybe IDEPackage) , allLogRefs :: [LogRef] , currentEBC :: (Maybe LogRef, Maybe LogRef, Maybe LogRef)@@ -156,6 +171,9 @@ , completion :: ((Int, Int), Maybe CompletionWindow) , yiControl :: Yi.Control , server :: Maybe Handle+, vcsData :: (Map FilePath MenuItem, Maybe (Maybe String)) -- menus for packages, password+, logLaunches :: Map.Map String LogLaunchData+, autoCommand :: IDEAction } --deriving Show --@@ -188,9 +206,12 @@ | IsCompleting Connections -liftIDE :: IDEM a -> WorkspaceM a-liftIDE = lift+class MonadIDE m where+ liftIDE :: IDEM a -> m a +instance MonadIDE WorkspaceM where+ liftIDE = lift+ (?>>=) :: Monad m => (m (Maybe a)) -> (a -> m ()) -> m () a ?>>= b = do mA <- a@@ -199,6 +220,16 @@ Nothing -> return () -- ---------------------------------------------------------------------+-- Monad for Gtk events (use onIDE instead of on)+--+type IDEEventM t = ReaderT IDERef (ReaderT (Ptr t) IO)++instance MonadIDE (IDEEventM t) where+ liftIDE f = do+ ideR <- ask+ liftIO $ runReaderT f ideR++-- --------------------------------------------------------------------- -- Monad for functions that need an open workspace -- type WorkspaceM = ReaderT Workspace IDEM@@ -323,6 +354,7 @@ , ipdDepends :: [Dependency] , ipdModules :: Map ModuleName BuildInfo , ipdHasLibs :: Bool+, ipdExes :: [String] , ipdTests :: [String] , ipdMain :: [(FilePath, BuildInfo, Bool)] , ipdExtraSrcs :: Set FilePath@@ -357,7 +389,9 @@ , wsPackages :: [IDEPackage] , wsPackagesFiles :: [FilePath] , wsActivePackFile:: Maybe FilePath+, wsActiveExe :: Maybe String , wsNobuildPack :: [IDEPackage]+, packageVcsConf :: Map FilePath VCSConf -- ^ (FilePath to package, Version-Control-System Configuration) } deriving Show -- ---------------------------------------------------------------------@@ -398,10 +432,11 @@ , textviewFont :: Maybe String , sourceStyle :: (Bool, String) , foundBackground :: Color+ , matchBackground :: Color , contextBackground :: Color , breakpointBackground :: Color , autoLoad :: Bool- , useYi :: Bool+ , textEditor :: String , logviewFont :: Maybe String , defaultSize :: (Int,Int) , browser :: String@@ -415,6 +450,8 @@ , completeRestricted :: Bool , saveAllBeforeBuild :: Bool , jumpToWarnings :: Bool+ , useVado :: Bool+ , useCabalDev :: Bool , backgroundBuild :: Bool , runUnitTests :: Bool , makeMode :: Bool@@ -434,6 +471,9 @@ , endWithLastConn :: Bool } deriving(Eq,Show) +cabalCommand :: Prefs -> String+cabalCommand p = if useCabalDev p then "cabal-dev" else "cabal"+ data SearchHint = Forward | Backward | Insert | Delete | Initial deriving (Eq) @@ -442,21 +482,34 @@ where compare a b = compare (fromEnum a) (fromEnum b) #endif +-- Version-Control-System Configuration+type VCSConf = (VCS.VCSType, VCS.Config, Maybe VCSGUI.MergeTool)+ -- -- | Other types --++data LogLaunchData = LogLaunchData {+ logLaunch :: LogLaunch+, mbPid :: Maybe ProcessHandle+}++data LogLaunch = LogLaunch {+ logBuffer :: TextBuffer+} deriving Typeable+ data LogRefType = WarningRef | ErrorRef | BreakpointRef | ContextRef deriving (Eq, Show) data LogRef = LogRef { logRefSrcSpan :: SrcSpan , logRefPackage :: IDEPackage-, refDescription :: String+, refDescription :: Text , logLines :: (Int,Int) , logRefType :: LogRefType } deriving (Eq) instance Show LogRef where- show lr = refDescription lr ++ displaySrcSpan (logRefSrcSpan lr)+ show lr = (T.unpack $ refDescription lr) ++ displaySrcSpan (logRefSrcSpan lr) displaySrcSpan s = srcSpanFilename s ++ ":" ++ if srcSpanStartLine s == srcSpanEndLine s@@ -555,5 +608,8 @@ | CompartmentCollect Bool type PackageDescrCache = Map PackageIdentifier ModuleDescrCache+#if MIN_VERSION_directory(1,2,0)+type ModuleDescrCache = Map ModuleName (UTCTime, Maybe FilePath, ModuleDescr)+#else type ModuleDescrCache = Map ModuleName (ClockTime, Maybe FilePath, ModuleDescr)-+#endif
@@ -1,5 +1,4 @@-{-# LANGUAGE CPP, ForeignFunctionInterface #-}-{-# OPTIONS_GHC -XScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Debug@@ -74,27 +73,32 @@ insertTextAfterSelection, selectedTextOrCurrentLine) import IDE.Metainfo.Provider (getActivePackageDescr) import Distribution.Text (display)-import IDE.Pane.Log (appendLog)-import Data.List (isSuffixOf)+import IDE.Pane.Log+import Data.List (stripPrefix, isSuffixOf) import IDE.Utils.GUIUtils (getDebugToggled) import IDE.Package (debugStart, executeDebugCommand, tryDebug, printBindResultFlag, breakOnErrorFlag, breakOnExceptionFlag, printEvldWithShowFlag) import IDE.Utils.Tool (ToolOutput(..), toolProcess, interruptProcessGroupOf) import IDE.Workspaces (packageTry)-import qualified Data.Enumerator as E-import qualified Data.Enumerator.List as EL+import qualified Data.Conduit as C+import qualified Data.Conduit.List as CL+import qualified Data.Conduit.Util as CU import Control.Monad.Trans.Class (MonadTrans(..)) import Control.Monad.Trans.Reader (ask) import Control.Monad.IO.Class (MonadIO(..))+import Control.Applicative (Alternative(..))+import Data.IORef (newIORef)+import Data.Monoid ((<>), Monoid(..))+import Data.Text (Text)+import qualified Data.Text as T (isSuffixOf, unpack) -debugCommand :: String -> E.Iteratee ToolOutput IDEM () -> DebugAction+debugCommand :: String -> C.Sink ToolOutput IDEM () -> DebugAction debugCommand command handler = do- debugCommand' command $ do- handler- lift $ triggerEventIDE VariablesChanged- return ()+ debugCommand' command handler+ lift $ triggerEventIDE VariablesChanged+ return () -debugCommand' :: String -> E.Iteratee ToolOutput IDEM () -> DebugAction+debugCommand' :: String -> C.Sink ToolOutput IDEM () -> DebugAction debugCommand' command handler = do ghci <- ask lift $ catchIDE (runDebug (executeDebugCommand command handler) ghci)@@ -113,16 +117,35 @@ debugQuit = do maybeDebug <- readIDE debugState case maybeDebug of- Just debug -> runDebug (debugCommand ":quit" logOutput) debug+ Just debug -> runDebug (debugCommand ":quit" logOutputDefault) debug _ -> return () +-- | Remove haddock code prefix from selected text so it can be run+-- in ghci+--+-- Press Ctrl + Enter on these to try it out...+--+-- > stripComments "-- > Wow this is meta"+--+-- > stripComments "-- This is still a comment"+stripComments :: String -> String+stripComments t = maybe t unlines $+ sequence (map (stripPrefix "-- >>>") lines')+ <|> sequence (map (stripPrefix "-- >") lines')+ where+ lines' = lines t+ debugExecuteSelection :: IDEAction debugExecuteSelection = do maybeText <- selectedTextOrCurrentLine case maybeText of- Just text -> packageTry $ tryDebug $ do- debugSetLiberalScope- debugCommand text logOutput+ Just text -> do+ let command = packageTry $ tryDebug $ do+ debugSetLiberalScope+ buffer <- liftIO $ newIORef mempty+ debugCommand (stripComments text) $ logOutputPane buffer+ modifyIDE_ $ \ide -> ide {autoCommand = command}+ command Nothing -> ideMessage Normal "Please select some text in the editor to execute" debugExecuteAndShowSelection :: IDEAction@@ -131,14 +154,14 @@ case maybeText of Just text -> packageTry $ tryDebug $ do debugSetLiberalScope- debugCommand text $ do- (out, _) <- EL.zip (EL.fold buildOutputString "") logOutput- lift $ insertTextAfterSelection $ " " ++ out+ debugCommand (stripComments text) $ do+ (out, _) <- CU.zipSinks (CL.fold buildOutputString "") logOutputDefault+ lift . insertTextAfterSelection . T.unpack $ " " <> out Nothing -> ideMessage Normal "Please select some text in the editor to execute" where- buildOutputString :: String -> ToolOutput -> String+ buildOutputString :: Text -> ToolOutput -> Text buildOutputString "" (ToolOutput str) = str- buildOutputString s (ToolOutput str) = s ++ "\n" ++ str+ buildOutputString s (ToolOutput str) = s <> "\n" <> str buildOutputString s _ = s debugSetLiberalScope :: DebugAction@@ -146,18 +169,20 @@ maybeModuleName <- lift selectedModuleName case maybeModuleName of Just moduleName -> do- debugCommand' (":module *" ++ moduleName) logOutput+ debugCommand (":module *" ++ moduleName) CL.sinkNull Nothing -> do mbPackage <- lift getActivePackageDescr case mbPackage of Nothing -> return () Just p -> let packageNames = map (display . modu . mdModuleId) (pdModules p)- in debugCommand' (foldl (\a b -> a ++ " *" ++ b) ":module " packageNames)- logOutput+ in debugCommand' (foldl (\a b -> a ++ " *" ++ b) ":module + " packageNames)+ CL.sinkNull debugAbandon :: IDEAction-debugAbandon = packageTry $ tryDebug $ debugCommand ":abandon" logOutput+debugAbandon = do + packageTry $ tryDebug $ debugCommand ":abandon" logOutputDefault+ debugBack :: IDEAction debugBack = packageTry $ do currentHist' <- lift $ readIDE currentHist@@ -165,7 +190,7 @@ lift $ modifyIDE_ (\ide -> ide{currentHist = min (currentHist' - 1) 0}) tryDebug $ do (debugPackage, _) <- ask- debugCommand ":back" (logOutputForHistoricContext debugPackage)+ debugCommand ":back" (logOutputForHistoricContextDefault debugPackage) debugForward :: IDEAction debugForward = packageTry $ do@@ -174,7 +199,7 @@ lift $ modifyIDE_ (\ide -> ide{currentHist = currentHist' + 1}) tryDebug $ do (debugPackage, _) <- ask- debugCommand ":forward" (logOutputForHistoricContext debugPackage)+ debugCommand ":forward" (logOutputForHistoricContextDefault debugPackage) debugStop :: IDEAction debugStop = do@@ -188,16 +213,16 @@ rootPath <- lift $ activeProjectDir tryDebug $ do (debugPackage, _) <- ask- debugCommand ":continue" (logOutputForLiveContext debugPackage)+ debugCommand ":continue" (logOutputForHistoricContextDefault debugPackage) debugDeleteAllBreakpoints :: IDEAction debugDeleteAllBreakpoints = do- packageTry $ tryDebug $ debugCommand ":delete *" logOutput+ packageTry $ tryDebug $ debugCommand ":delete *" logOutputDefault setBreakpointList [] debugDeleteBreakpoint :: String -> LogRef -> IDEAction debugDeleteBreakpoint indexString lr = do- packageTry $ tryDebug $ debugCommand (":delete " ++ indexString) logOutput+ packageTry $ tryDebug $ debugCommand (":delete " ++ indexString) logOutputDefault bl <- readIDE breakpointRefs setBreakpointList $ filter (/= lr) bl ideR <- ask@@ -207,24 +232,24 @@ debugForce = do maybeText <- selectedTextOrCurrentLine case maybeText of- Just text -> packageTry $ tryDebug $ debugCommand (":force " ++ text) logOutput+ Just text -> packageTry $ tryDebug $ debugCommand (":force " ++ stripComments text) logOutputDefault Nothing -> ideMessage Normal "Please select an expression in the editor" debugHistory :: IDEAction-debugHistory = packageTry $ tryDebug $ debugCommand ":history" logOutput+debugHistory = packageTry $ tryDebug $ debugCommand ":history" logOutputDefault debugPrint :: IDEAction debugPrint = do maybeText <- selectedTextOrCurrentLine case maybeText of- Just text -> packageTry $ tryDebug $ debugCommand (":print " ++ text) logOutput+ Just text -> packageTry $ tryDebug $ debugCommand (":print " ++ stripComments text) logOutputDefault Nothing -> ideMessage Normal "Please select an name in the editor" debugSimplePrint :: IDEAction debugSimplePrint = do maybeText <- selectedTextOrCurrentLine case maybeText of- Just text -> packageTry $ tryDebug $ debugCommand (":force " ++ text) logOutput+ Just text -> packageTry $ tryDebug $ debugCommand (":force " ++ stripComments text) logOutputDefault Nothing -> ideMessage Normal "Please select an name in the editor" debugStep :: IDEAction@@ -233,7 +258,7 @@ tryDebug $ do (debugPackage, _) <- ask debugSetLiberalScope- debugCommand ":step" (logOutputForLiveContext debugPackage)+ debugCommand ":step" (logOutputForHistoricContextDefault debugPackage) debugStepExpression :: IDEAction debugStepExpression = do@@ -247,7 +272,7 @@ (debugPackage, _) <- ask rootPath <- lift $ activeProjectDir case maybeText of- Just text -> debugCommand (":step " ++ text) (logOutputForLiveContext debugPackage)+ Just text -> debugCommand (":step " ++ stripComments text) (logOutputForHistoricContextDefault debugPackage) Nothing -> lift $ ideMessage Normal "Please select an expression in the editor" debugStepLocal :: IDEAction@@ -255,24 +280,27 @@ rootPath <- lift $ activeProjectDir tryDebug $ do (debugPackage, _) <- ask- debugCommand ":steplocal" (logOutputForLiveContext debugPackage)+ debugCommand ":steplocal" (logOutputForHistoricContextDefault debugPackage) debugStepModule :: IDEAction debugStepModule = packageTry $ do rootPath <- lift $ activeProjectDir tryDebug $ do (debugPackage, _) <- ask- debugCommand ":stepmodule" (logOutputForLiveContext debugPackage)+ debugCommand ":stepmodule" (logOutputForHistoricContextDefault debugPackage) ++logTraceOutput debugPackage = do+ logOutputForLiveContextDefault debugPackage+ lift $ triggerEventIDE TraceChanged+ return ()+ debugTrace :: IDEAction debugTrace = packageTry $ do rootPath <- lift $ activeProjectDir tryDebug $ do (debugPackage, _) <- ask- debugCommand ":trace" $ do- logOutputForLiveContext debugPackage- lift $ triggerEventIDE TraceChanged- return ()+ debugCommand ":trace" $ logTraceOutput debugPackage debugTraceExpression :: IDEAction debugTraceExpression = do@@ -285,49 +313,45 @@ debugTraceExpr maybeText = do (debugPackage, _) <- ask case maybeText of- Just text -> debugCommand (":trace " ++ text) $ do--- rootPath <- activeProjectDir- logOutputForLiveContext debugPackage- lift $ triggerEventIDE TraceChanged- return ()+ Just text -> debugCommand (":trace " ++ stripComments text) $ logTraceOutput debugPackage Nothing -> lift $ ideMessage Normal "Please select an expression in the editor" debugShowBindings :: IDEAction-debugShowBindings = packageTry $ tryDebug $ debugCommand ":show bindings" logOutput+debugShowBindings = packageTry $ tryDebug $ debugCommand ":show bindings" logOutputDefault debugShowBreakpoints :: IDEAction debugShowBreakpoints = packageTry $ do rootPath <- lift activeProjectDir tryDebug $ do (debugPackage, _) <- ask- debugCommand ":show breaks" (logOutputForBreakpoints debugPackage)+ debugCommand ":show breaks" (logOutputForSetBreakpointDefault debugPackage) debugShowContext :: IDEAction debugShowContext = packageTry $ do rootPath <- lift activeProjectDir tryDebug $ do (debugPackage, _) <- ask- debugCommand ":show context" (logOutputForLiveContext debugPackage)+ debugCommand ":show context" (logOutputForHistoricContextDefault debugPackage) debugShowModules :: IDEAction debugShowModules = packageTry $ tryDebug $ debugCommand ":show modules" $- logOutputLines_ $ \log output -> liftIO $ do+ logOutputLines_Default $ \log logLaunch output -> liftIO $ do case output of- ToolInput line -> appendLog log (line ++ "\n") InputTag- ToolOutput line | ", interpreted )" `isSuffixOf` line- -> appendLog log (line ++ "\n") LogTag- ToolOutput line -> appendLog log (line ++ "\n") InfoTag- ToolError line -> appendLog log (line ++ "\n") ErrorTag- ToolPrompt _ -> defaultLineLogger' log output- ToolExit _ -> appendLog log "X--X--X ghci process exited unexpectedly X--X--X" FrameTag+ ToolInput line -> appendLog log logLaunch (line <> "\n") InputTag+ ToolOutput line | ", interpreted )" `T.isSuffixOf` line+ -> appendLog log logLaunch (line <> "\n") LogTag+ ToolOutput line -> appendLog log logLaunch (line <> "\n") InfoTag+ ToolError line -> appendLog log logLaunch (line <> "\n") ErrorTag+ ToolPrompt _ -> defaultLineLogger' log logLaunch output+ ToolExit _ -> appendLog log logLaunch "X--X--X ghci process exited unexpectedly X--X--X" FrameTag return () debugShowPackages :: IDEAction-debugShowPackages = packageTry $ tryDebug $ debugCommand ":show packages" logOutput+debugShowPackages = packageTry $ tryDebug $ debugCommand ":show packages" logOutputDefault debugShowLanguages :: IDEAction-debugShowLanguages = packageTry $ tryDebug $ debugCommand ":show languages" logOutput+debugShowLanguages = packageTry $ tryDebug $ debugCommand ":show languages" logOutputDefault debugInformation :: IDEAction debugInformation = do@@ -335,7 +359,7 @@ case maybeText of Just text -> packageTry $ tryDebug $ do debugSetLiberalScope- debugCommand (":info "++text) logOutput+ debugCommand (":info "++stripComments text) logOutputDefault Nothing -> ideMessage Normal "Please select a name in the editor" debugKind :: IDEAction@@ -344,7 +368,7 @@ case maybeText of Just text -> packageTry $ tryDebug $ do debugSetLiberalScope- debugCommand (":kind "++text) logOutput+ debugCommand (":kind "++stripComments text) logOutputDefault Nothing -> ideMessage Normal "Please select a type in the editor" debugType :: IDEAction@@ -353,7 +377,7 @@ case maybeText of Just text -> packageTry $ tryDebug $ do debugSetLiberalScope- debugCommand (":type "++text) logOutput+ debugCommand (":type "++stripComments text) logOutputDefault Nothing -> ideMessage Normal "Please select an expression in the editor" debugSetBreakpoint :: IDEAction@@ -367,15 +391,15 @@ case maybeText of Just text -> packageTry $ tryDebug $ do (debugPackage, _) <- ask- debugCommand' (":module *" ++ moduleName) logOutput- debugCommand (":break " ++ text) (logOutputForSetBreakpoint debugPackage)+ debugCommand (":module *" ++ moduleName) logOutputDefault+ debugCommand (":break " ++ text) (logOutputForSetBreakpointDefault debugPackage) Nothing -> do maybeLocation <- selectedLocation case maybeLocation of Just (line, lineOffset) -> packageTry $ tryDebug $ do (debugPackage, _) <- ask debugCommand (":break " ++ moduleName ++ " " ++ (show (line+1)) ++ " " ++- (show lineOffset)) (logOutputForSetBreakpoint debugPackage)+ (show lineOffset)) (logOutputForSetBreakpointDefault debugPackage) Nothing -> ideMessage Normal "Unknown error setting breakpoint" ref <- ask return ()@@ -383,7 +407,7 @@ debugSet :: (Bool -> String) -> Bool -> IDEAction debugSet flag value = do- packageTry $ tryDebug $ debugCommand (":set "++(flag value)) logOutput+ packageTry $ tryDebug $ debugCommand (":set "++(flag value)) logOutputDefault debugSetPrintEvldWithShow :: Bool -> IDEAction debugSetPrintEvldWithShow = debugSet printEvldWithShowFlag
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -XScopedTypeVariables -XDeriveDataTypeable -XMultiParamTypeClasses- -XTypeSynonymInstances #-}+{-# LANGUAGE ForeignFunctionInterface #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Find@@ -35,28 +34,28 @@ ) where import Graphics.UI.Gtk- (toggleToolButtonSetActive, castToToggleToolButton,- toggleToolButtonGetActive, castToBin, binGetChild, widgetGetName,- containerGetChildren, listStoreGetValue, treeModelGetPath,- TreeIter, ListStore, widgetModifyText, widgetModifyBase,- toolbarChildHomogeneous, afterEntryActivate, spinButtonSetRange,- afterFocusIn, onEntryActivate, afterKeyPress, afterDeleteText,- afterInsertText, treeModelGetValue, matchSelected,+ (toToolbar, ToolbarClass, toggleToolButtonSetActive,+ castToToggleToolButton, toggleToolButtonGetActive, castToBin,+ binGetChild, widgetGetName, containerGetChildren,+ listStoreGetValue, treeModelGetPath, TreeIter, ListStore,+ widgetModifyText, widgetModifyBase, toolbarChildHomogeneous, after,+ entryActivate, spinButtonSetRange, focusInEvent, keyPressEvent,+ deleteText, insertText, treeModelGetValue, matchSelected, entryCompletionSetMatchFunc, cellText, cellLayoutSetAttributes, cellLayoutPackStart, cellRendererTextNew, entryCompletionModel, entrySetCompletion, entryCompletionNew, makeColumnIdString, customStoreSetColumn, listStoreNew, toolItemSetExpand,- toolButtonSetLabel, toggleToolButtonNew, entryNew, tooltipsSetTip,+ toolButtonSetLabel, toggleToolButtonNew, entryNew, onToolButtonClicked, Widget, toolButtonNew, separatorToolItemNew, labelNew, containerAdd, widgetSetName, spinButtonNewWithRange, toolItemNew, toolbarInsert, toolButtonNewFromStock,- toolbarSetIconSize, toolbarSetStyle, tooltipsNew, toolbarNew,- Toolbar, widgetGrabFocus, widgetShowAll, widgetHideAll,- listStoreAppend, listStoreClear, entrySetText, spinButtonSetValue,- listStoreToList, castToEntry, entryGetText, castToSpinButton,- spinButtonGetValueAsInt, StateType(..), ToolbarStyle(..),- IconSize(..), AttrOp(..), set, on, Color(..))-import Graphics.UI.Gtk.Gdk.Events+ toolbarSetStyle, toolbarNew, Toolbar, widgetGrabFocus,+ widgetShowAll, widgetHide, listStoreAppend, listStoreClear,+ entrySetText, spinButtonSetValue, listStoreToList, castToEntry,+ entryGetText, castToSpinButton, spinButtonGetValueAsInt,+ StateType(..), ToolbarStyle(..), IconSize(..), AttrOp(..), set, on,+ Color(..), widgetTooltipText)+import Graphics.UI.Gtk.Gdk.EventM import qualified Graphics.UI.Gtk as Gtk import Graphics.UI.Gtk.Buttons.ToggleButton import Graphics.UI.Gtk.Buttons.CheckButton@@ -66,7 +65,7 @@ import IDE.TextEditor hiding(afterFocusIn) import IDE.Pane.SourceBuffer import Data.Char (digitToInt, isDigit, toLower, isAlphaNum)-import Text.Regex.TDFA hiding (caseSensitive)+import Text.Regex.TDFA hiding (caseSensitive, after) import qualified Text.Regex.TDFA as Regex import Text.Regex.TDFA.String (compile) import Data.List (find, isPrefixOf)@@ -77,7 +76,19 @@ import Control.Monad.Trans.Reader (ask) import Control.Monad.Trans.Class (MonadTrans(..)) import Control.Monad (liftM, filterM, when)+import Foreign.C.Types (CInt(..))+import Foreign.Ptr (Ptr(..))+import Foreign.ForeignPtr (withForeignPtr)+import Graphics.UI.GtkInternals (unToolbar) +foreign import ccall safe "gtk_toolbar_set_icon_size"+ gtk_toolbar_set_icon_size :: Ptr Toolbar -> CInt -> IO ()++toolbarSetIconSize :: ToolbarClass self => self -> IconSize -> IO ()+toolbarSetIconSize self iconSize =+ withForeignPtr (unToolbar $ toToolbar self) $+ \selfPtr ->gtk_toolbar_set_icon_size selfPtr (fromIntegral $ fromEnum iconSize)+ data FindState = FindState { entryStr :: String , entryHist :: [String]@@ -134,7 +145,7 @@ Nothing -> return () Just tb -> do modifyIDE_ (\ide -> ide{toolbar = (False,snd (toolbar ide))})- liftIO $ widgetHideAll tb+ liftIO $ widgetHide tb showToolbar :: IDEAction showToolbar = do@@ -158,7 +169,7 @@ modifyIDE_ (\ide -> ide{findbar = (False,mbfb)}) case mbfb of Nothing -> return ()- Just (fb,_) -> liftIO $ widgetHideAll fb+ Just (fb,_) -> liftIO $ widgetHide fb showFindbar :: IDEAction showFindbar = do@@ -185,7 +196,6 @@ constructFindReplace :: IDEM Toolbar constructFindReplace = reifyIDE $ \ ideR -> do toolbar <- toolbarNew- tooltips <- tooltipsNew toolbarSetStyle toolbar ToolbarIcons toolbarSetIconSize toolbar IconSizeSmallToolbar closeButton <- toolButtonNewFromStock "gtk-close"@@ -210,7 +220,7 @@ grepButton <- toolButtonNew (Nothing :: Maybe Widget) (Just "Grep") toolbarInsert toolbar grepButton 0 grepButton `onToolButtonClicked` performGrep- tooltipsSetTip tooltips grepButton "Search in multiple files" ""+ set grepButton [widgetTooltipText := Just "Search in multiple files"] sep1 <- separatorToolItemNew toolbarInsert toolbar sep1 0@@ -238,18 +248,18 @@ nextButton <- toolButtonNewFromStock "gtk-go-forward" toolbarInsert toolbar nextButton 0- tooltipsSetTip tooltips nextButton "Search for the next match in the current file" ""+ set nextButton [widgetTooltipText := Just "Search for the next match in the current file"] nextButton `onToolButtonClicked` (doSearch toolbar Forward ideR ) wrapAroundButton <- toggleToolButtonNew toolButtonSetLabel wrapAroundButton (Just "Wrap") widgetSetName wrapAroundButton "wrapAroundButton" toolbarInsert toolbar wrapAroundButton 0- tooltipsSetTip tooltips wrapAroundButton "When selected searching will continue from the top when no more matches are found" ""+ set wrapAroundButton [widgetTooltipText := Just "When selected searching will continue from the top when no more matches are found"] previousButton <- toolButtonNewFromStock "gtk-go-back" toolbarInsert toolbar previousButton 0- tooltipsSetTip tooltips previousButton "Search for the previous match in the current file" ""+ set previousButton [widgetTooltipText := Just "Search for the previous match in the current file"] previousButton `onToolButtonClicked` (doSearch toolbar Backward ideR ) entryTool <- toolItemNew@@ -283,37 +293,38 @@ widgetSetName regexButton "regexButton" toolbarInsert toolbar regexButton 0 regexButton `onToolButtonClicked` (doSearch toolbar Insert ideR)- tooltipsSetTip tooltips regexButton "When selected the search string is used as a regular expression" ""+ set regexButton [widgetTooltipText := Just "When selected the search string is used as a regular expression"] entireWordButton <- toggleToolButtonNew toolButtonSetLabel entireWordButton (Just "Words") widgetSetName entireWordButton "entireWordButton" toolbarInsert toolbar entireWordButton 0 entireWordButton `onToolButtonClicked` (doSearch toolbar Insert ideR)- tooltipsSetTip tooltips entireWordButton "When selected only entire words are matched" ""+ set entireWordButton [widgetTooltipText := Just "When selected only entire words are matched"] caseSensitiveButton <- toggleToolButtonNew toolButtonSetLabel caseSensitiveButton (Just "Case") widgetSetName caseSensitiveButton "caseSensitiveButton" toolbarInsert toolbar caseSensitiveButton 0 caseSensitiveButton `onToolButtonClicked` (doSearch toolbar Insert ideR)- tooltipsSetTip tooltips caseSensitiveButton "When selected the search is case sensitive" ""+ set caseSensitiveButton [widgetTooltipText := Just "When selected the search is case sensitive"] labelTool <- toolItemNew label <- labelNew (Just "Find: ") containerAdd labelTool label toolbarInsert toolbar labelTool 0 - entry `afterInsertText` (\t i -> do+ after entry insertText (\t i -> do doSearch toolbar Insert ideR return i)- entry `afterDeleteText` (\ _ _ -> doSearch toolbar Delete ideR )+ after entry deleteText (\ _ _ -> doSearch toolbar Delete ideR ) - entry `onEntryActivate` doSearch toolbar Forward ideR- entry `Gtk.onFocusIn` \_ -> reflectIDE (triggerEventIDE (Sensitivity [(SensitivityEditor, False)]) >> return False) ideR-+ on entry entryActivate $ doSearch toolbar Forward ideR+ on entry focusInEvent $ do+ liftIO $ reflectIDE (triggerEventIDE (Sensitivity [(SensitivityEditor, False)])) ideR+ return False replaceButton `onToolButtonClicked` replace toolbar Forward ideR let performReplaceAll = replaceAll toolbar Forward ideR@@ -331,71 +342,60 @@ old <- toggleToolButtonGetActive btn toggleToolButtonSetActive btn $ not old - entry `Gtk.onKeyPress` (\ e -> do- case e of- k@(Key _ _ _ _ _ _ _ _ _ _)- | eventKeyName k == "Down" -> do- doSearch toolbar Forward ideR- return True- | eventKeyName k == "Up" -> do- doSearch toolbar Backward ideR- return True- | eventKeyName k == "Escape" -> do- getOut ideR- return True- | eventKeyName k == "Tab" -> do- re <- getReplaceEntry toolbar- widgetGrabFocus re- --- widgetAc- return True- | (mapControlCommand Control) `elem` (eventModifier k) ->- ctrl $ map toLower $ eventKeyName k- | otherwise -> return False- _ -> return False)+ entry `on` keyPressEvent $ do+ name <- eventKeyName+ mods <- eventModifier+ case name of+ "Down" -> liftIO $ doSearch toolbar Forward ideR >> return True+ "Up" -> liftIO $ doSearch toolbar Backward ideR >> return True+ "Escape" -> liftIO $ getOut ideR >> return True+ "Tab" -> liftIO $ do+ re <- getReplaceEntry toolbar+ widgetGrabFocus re+ --- widgetAc+ return True+ _ | (mapControlCommand Control) `elem` mods -> liftIO . ctrl $ map toLower name+ _ -> return False - rentry `Gtk.onKeyPress` (\ e -> do- case e of- k@(Key _ _ _ _ _ _ _ _ _ _)- | eventKeyName k == "Tab" || eventKeyName k == "ISO_Left_Tab" -> do+ rentry `on` keyPressEvent $ do+ name <- eventKeyName+ mods <- eventModifier+ case () of+ _+ | name == "Tab" || name == "ISO_Left_Tab" -> liftIO $ do fe <- getFindEntry toolbar widgetGrabFocus fe return True- | (mapControlCommand Control) `elem` (eventModifier k) ->- ctrl $ map toLower $ eventKeyName k+ | (mapControlCommand Control) `elem` mods ->+ liftIO . ctrl $ map toLower name | otherwise -> return False- _ -> return False) --- spinL `afterFocusIn` (\ _ -> (reflectIDE (inActiveBufContext True $ \_ gtkbuf currentBuffer _ -> do- max <- getLineCount gtkbuf+ after spinL focusInEvent . liftIO $ reflectIDE (inActiveBufContext True $ \_ _ ebuf _ _ -> do+ max <- getLineCount ebuf liftIO $ spinButtonSetRange spinL 1.0 (fromIntegral max)- return True) ideR))+ return True) ideR - spinL `Gtk.onKeyPress` (\ e -> do- case e of- k@(Key _ _ _ _ _ _ _ _ _ _)- | eventKeyName k == "Escape" -> do- getOut ideR- return True- | eventKeyName k == "Tab" -> do- re <- getFindEntry toolbar- widgetGrabFocus re- return True- | (mapControlCommand Control) `elem` (eventModifier k) ->- ctrl $ map toLower $ eventKeyName k- | otherwise -> return False- _ -> return False)+ spinL `on` keyPressEvent $ do+ name <- eventKeyName+ mods <- eventModifier+ case name of+ "Escape" -> liftIO $ getOut ideR >> return True+ "Tab" -> liftIO $ do+ re <- getFindEntry toolbar+ widgetGrabFocus re+ return True+ _ | (mapControlCommand Control) `elem` mods -> liftIO . ctrl $ map toLower name+ _ -> return False - spinL `afterEntryActivate` (reflectIDE (inActiveBufContext () $ \_ gtkbuf currentBuffer _ -> do+ after spinL entryActivate $ reflectIDE (inActiveBufContext () $ \_ sv ebuf _ _ -> do line <- liftIO $ spinButtonGetValueAsInt spinL- iter <- getIterAtLine gtkbuf (line - 1)- placeCursor gtkbuf iter- scrollToIter (sourceView currentBuffer) iter 0.2 Nothing+ iter <- getIterAtLine ebuf (line - 1)+ placeCursor ebuf iter+ scrollToIter sv iter 0.2 Nothing liftIO $ getOut ideR- return ()) ideR )+ return ()) ideR closeButton `onToolButtonClicked` do reflectIDE hideFindbar ideR@@ -521,52 +521,52 @@ editFind' :: Regex -> Int -> Bool -> String -> SearchHint -> IDEM Bool editFind' exp matchIndex wrapAround dummy hint =- inActiveBufContext False $ \_ gtkbuf currentBuffer _ -> do- i1 <- getStartIter gtkbuf- i2 <- getEndIter gtkbuf- text <- getText gtkbuf i1 i2 True- removeTagByName gtkbuf "found" i1 i2- startMark <- getInsertMark gtkbuf- st1 <- getIterAtMark gtkbuf startMark+ inActiveBufContext False $ \_ sv ebuf _ _ -> do+ i1 <- getStartIter ebuf+ i2 <- getEndIter ebuf+ text <- getText ebuf i1 i2 True+ removeTagByName ebuf "found"+ startMark <- getInsertMark ebuf+ st1 <- getIterAtMark ebuf startMark mbsr2 <- do if hint == Backward then do st2 <- backwardCharC st1 st3 <- backwardCharC st2- mbsr <- backSearch exp matchIndex gtkbuf text st3+ mbsr <- backSearch exp matchIndex ebuf text st3 case mbsr of Nothing -> if wrapAround- then do backSearch exp matchIndex gtkbuf text i2+ then do backSearch exp matchIndex ebuf text i2 else return Nothing m -> return m else do st2 <- if hint == Forward then forwardCharC st1 else return st1- mbsr <- forwardSearch exp matchIndex gtkbuf text st2+ mbsr <- forwardSearch exp matchIndex ebuf text st2 case mbsr of Nothing -> if wrapAround- then do forwardSearch exp matchIndex gtkbuf text i1+ then do forwardSearch exp matchIndex ebuf text i1 else return Nothing m -> return m case mbsr2 of Just (start,end,_) -> do --found --widgetGrabFocus sourceView- scrollToIter (sourceView currentBuffer) start 0.2 Nothing- applyTagByName gtkbuf "found" start end- placeCursor gtkbuf start+ scrollToIter sv start 0.2 Nothing+ applyTagByName ebuf "found" start end+ placeCursor ebuf start return True Nothing -> return False where- backSearch exp matchIndex gtkbuf text iter = do+ backSearch exp matchIndex ebuf text iter = do offset <- getOffset iter- findMatch exp matchIndex gtkbuf text (<= offset) True+ findMatch exp matchIndex ebuf text (<= offset) True - forwardSearch exp matchIndex gtkbuf text iter = do+ forwardSearch exp matchIndex ebuf text iter = do offset <- getOffset iter- findMatch exp matchIndex gtkbuf text (>= offset) False+ findMatch exp matchIndex ebuf text (>= offset) False regexAndMatchIndex :: Bool -> Bool -> Bool -> String -> IO (Maybe (Regex, Int)) regexAndMatchIndex caseSensitive entireWord regex string = do@@ -591,7 +591,7 @@ then ("(^|[^a-zA-Z0-9])(" ++ regexString ++ ")($|[^a-zA-Z0-9])", 2) else (regexString, 0) -findMatch :: Regex -> Int -> EditorBuffer -> String -> (Int -> Bool) -> Bool -> IDEM (Maybe (EditorIter, EditorIter, MatchArray))+findMatch :: TextEditor editor => Regex -> Int -> EditorBuffer editor -> String -> (Int -> Bool) -> Bool -> IDEM (Maybe (EditorIter editor, EditorIter editor, MatchArray)) findMatch exp matchIndex gtkbuf text offsetPred findLast = do let matches = (if findLast then reverse else id) (matchAll exp text) case find (offsetPred . fst . (!matchIndex)) matches of@@ -608,24 +608,24 @@ editReplace' :: Bool -> Bool -> Bool -> Bool -> String -> String -> SearchHint -> Bool -> IDEM Bool editReplace' entireWord caseSensitive wrapAround regex search replace hint mayRepeat =- inActiveBufContext False $ \_ gtkbuf currentBuffer _ -> do- insertMark <- getInsertMark gtkbuf- iter <- getIterAtMark gtkbuf insertMark+ inActiveBufContext False $ \_ _ ebuf _ _ -> do+ insertMark <- getInsertMark ebuf+ iter <- getIterAtMark ebuf insertMark offset <- getOffset iter mbExpAndMatchIndex <- liftIO $ regexAndMatchIndex caseSensitive entireWord regex search case mbExpAndMatchIndex of Just (exp, matchIndex) -> do- iStart <- getStartIter gtkbuf- iEnd <- getEndIter gtkbuf- text <- getText gtkbuf iStart iEnd True- match <- findMatch exp matchIndex gtkbuf text (== offset) False+ iStart <- getStartIter ebuf+ iEnd <- getEndIter ebuf+ text <- getText ebuf iStart iEnd True+ match <- findMatch exp matchIndex ebuf text (== offset) False case match of Just (iterStart, iterEnd, matches) -> do mbText <- liftIO $ replacementText regex text matchIndex matches replace case mbText of Just text -> do- delete gtkbuf iterStart iterEnd- insert gtkbuf iterStart text+ delete ebuf iterStart iterEnd+ insert ebuf iterStart text Nothing -> do sysMessage Normal "Should never happen. findMatch worked but repleacementText failed"@@ -692,11 +692,11 @@ ideR <- ask (fb,_) <- needFindbar case hint of- Initial -> inActiveBufContext () $ \_ gtkbuf currentBuffer _ -> do- hasSelection <- hasSelection gtkbuf+ Initial -> inActiveBufContext () $ \_ _ ebuf _ _ -> do+ hasSelection <- hasSelection ebuf when hasSelection $ do- (i1,i2) <- getSelectionBounds gtkbuf- text <- getText gtkbuf i1 i2 False+ (i1,i2) <- getSelectionBounds ebuf+ text <- getText ebuf i1 i2 False findEntry <- liftIO $ getFindEntry fb liftIO $ entrySetText (castToEntry findEntry) text return ()
@@ -1,432 +1,543 @@ {-# LANGUAGE CPP #-}------------------------------------------------------------------------------ --- --- Module : IDE.ImportTool --- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie --- License : GPL --- --- Maintainer : Jutaro <jutaro@leksah.org> --- Stability : provisional --- Portability : --- --- | Help for constructing import statements --- ------------------------------------------------------------------------------ - -module IDE.ImportTool ( - resolveErrors -, addOneImport -, addImport -, addPackage -, parseNotInScope +-----------------------------------------------------------------------------+--+-- Module : IDE.ImportTool+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL+--+-- Maintainer : Jutaro <jutaro@leksah.org>+-- Stability : provisional+-- Portability :+--+-- | Help for constructing import statements+--+-----------------------------------------------------------------------------++module IDE.ImportTool (+ resolveErrors+, addOneImport+, addResolveMenuItems , parseHiddenModule-, HiddenModuleResult(..) -) where - -import IDE.Core.State -import Data.Maybe (isNothing,isJust) -import IDE.Metainfo.Provider - (getPackageImportInfo, getIdentifierDescr) -import Text.PrettyPrint (render) -import Distribution.Text (simpleParse, display, disp) -import IDE.Pane.SourceBuffer -import Graphics.UI.Gtk -import Text.ParserCombinators.Parsec.Language (haskellStyle) -import Graphics.UI.Editor.MakeEditor - (getRealWidget, FieldDescription(..), buildEditor, mkField) -import Graphics.UI.Editor.Parameters - ((<<<-), paraMinSize, emptyParams, Parameter(..), paraMultiSel, - paraName) -import Data.Maybe (fromJust) -import Text.ParserCombinators.Parsec hiding (parse) -import qualified Text.ParserCombinators.Parsec as Parsec (parse) -import Graphics.UI.Editor.Simple (staticListEditor) -import Control.Monad (forM, when) -import Data.List (sort, nub, nubBy) -import IDE.Utils.ServerConnection -import Text.PrinterParser (prettyPrint) -import IDE.TextEditor (delete, setModified, insert, getIterAtLine) -import qualified Distribution.ModuleName as D (ModuleName(..)) -import qualified Text.ParserCombinators.Parsec.Token as P - (operator, dot, identifier, symbol, lexeme, whiteSpace, - makeTokenParser) -import Distribution.PackageDescription.Parse - (readPackageDescription) -import Distribution.Verbosity (normal) -import IDE.Pane.PackageEditor (hasConfigs) -import Distribution.Package +, HiddenModuleResult(..)+) where++import IDE.Core.State+import Data.Maybe (isNothing,isJust)+import IDE.Metainfo.Provider+ (getWorkspaceInfo, getPackageImportInfo, getIdentifierDescr)+import Text.PrettyPrint (render)+import Distribution.Text (simpleParse, display, disp)+import IDE.Pane.SourceBuffer+import Graphics.UI.Gtk+import Text.ParserCombinators.Parsec.Language (haskellStyle)+import Graphics.UI.Editor.MakeEditor+ (getRealWidget, FieldDescription(..), buildEditor, mkField)+import Graphics.UI.Editor.Parameters+ ((<<<-), paraMinSize, emptyParams, Parameter(..), paraMultiSel,+ paraName)+import Data.Maybe (catMaybes, fromJust)+import Text.ParserCombinators.Parsec hiding (parse)+import qualified Text.ParserCombinators.Parsec as Parsec (parse)+import Graphics.UI.Editor.Simple (staticListEditor)+import Control.Monad (forM, when)+import Control.Applicative ((<$>))+import Data.List (stripPrefix, sort, nub, nubBy)+import IDE.Utils.ServerConnection+import Text.PrinterParser (prettyPrint)+import IDE.TextEditor (delete, setModified, insert, getIterAtLine)+import qualified Distribution.ModuleName as D (ModuleName(..))+import qualified Text.ParserCombinators.Parsec.Token as P+ (operator, dot, identifier, symbol, lexeme, whiteSpace,+ makeTokenParser)+import Distribution.PackageDescription.Parse+ (readPackageDescription)+import Distribution.Verbosity (normal)+import IDE.Pane.PackageEditor (hasConfigs)+import Distribution.Package import Distribution.Version (anyVersion, orLaterVersion, intersectVersionRanges,- earlierVersion, Version(..)) -import Distribution.PackageDescription - (CondTree(..), condExecutables, condLibrary, packageDescription, - buildDepends) -import Distribution.PackageDescription.Configuration - (flattenPackageDescription) -import IDE.BufferMode (editInsertCode) -import Control.Monad.IO.Class (MonadIO(..)) -#if MIN_VERSION_Cabal(1,10,0) -import Distribution.PackageDescription.PrettyPrintCopied - (writeGenericPackageDescription) -#else -import Distribution.PackageDescription.Parse - (writePackageDescription) -import Distribution.PackageDescription - (CondTree(..)) -#endif - --- | Add all imports which gave error messages ... -resolveErrors :: IDEAction -resolveErrors = do - prefs' <- readIDE prefs - let buildInBackground = backgroundBuild prefs' - when buildInBackground $ - modifyIDE_ (\ide -> ide{prefs = prefs'{backgroundBuild = False}}) - errors <- readIDE errorRefs - addPackageResults <- forM errors addPackage - let notInScopes = [ y | (x,y) <- - nubBy (\ (p1,_) (p2,_) -> p1 == p2) - $ [(x,y) | (x,y) <- [((parseNotInScope . refDescription) e, e) | e <- errors]], - isJust x] - when (not (or addPackageResults) && null notInScopes) $ ideMessage Normal $ "No errors that can be auto resolved" - addAll buildInBackground notInScopes (True,[]) - where - addAll :: Bool -> [LogRef] -> (Bool,[Descr]) -> IDEM () - addAll bib (errorSpec:rest) (True,descrList) = addImport errorSpec descrList (addAll bib rest) - addAll bib _ _ = finally bib - - finally buildInBackground = when buildInBackground $ do - prefs' <- readIDE prefs - modifyIDE_ (\ide -> ide{prefs = prefs'{backgroundBuild = True}}) - --- | Add import for current error ... -addOneImport :: IDEAction -addOneImport = do - errors' <- readIDE errorRefs - currentErr' <- readIDE currentError - case currentErr' of - Nothing -> do - ideMessage Normal $ "No error selected" - return () - Just ref -> addImport ref [] (\ _ -> return ()) - --- | Add one missing import --- Returns a boolean, if the process should be stopped in case of multiple addition --- Returns a list of already added descrs, so that it will not be added two times and can --- be used for default selection -addImport :: LogRef -> [Descr] -> ((Bool,[Descr]) -> IDEAction) -> IDEAction -addImport error descrList continuation = - case parseNotInScope (refDescription error) of - Nothing -> continuation (True,descrList) - Just nis -> do - currentInfo' <- getScopeForActiveBuffer - case currentInfo' of - Nothing -> continuation (True,descrList) - Just (GenScopeC(PackScope _ symbolTable1),GenScopeC(PackScope _ symbolTable2)) -> - let list = getIdentifierDescr (id' nis) symbolTable1 symbolTable2 - in case list of - [] -> do - ideMessage Normal $ "Identifier " ++ (id' nis) ++ - " not found in imported packages" - continuation (True, descrList) - descr : [] -> addImport' nis (logRefFullFilePath error) descr descrList continuation - list -> do - window' <- getMainWindow - mbDescr <- liftIO $ selectModuleDialog window' list (id' nis) (mbQual' nis) - (if null descrList - then Nothing - else Just (head descrList)) - case mbDescr of - Nothing -> continuation (False, []) - Just descr -> if elem descr descrList - then continuation (True,descrList) - else addImport' nis (logRefFullFilePath error) - descr descrList continuation - -addPackage :: LogRef -> IDEM Bool -addPackage error = do - case parseHiddenModule (refDescription error) of - Nothing -> return False - Just (HiddenModuleResult mod pack) -> do - let idePackage = logRefPackage error - gpd <- liftIO $ readPackageDescription normal (ipdCabalFile $ idePackage) - ideMessage Normal $ "addPackage " ++ (display $ pkgName pack) -#if MIN_VERSION_Cabal(1,10,0) - liftIO $ writeGenericPackageDescription (ipdCabalFile $ idePackage) - gpd { condLibrary = addDepToLib pack (condLibrary gpd), - condExecutables = map (addDepToExe pack) - (condExecutables gpd)} - return True -#else - if hasConfigs gpd - then return False - else do - let flat = flattenPackageDescription gpd - liftIO $ writePackageDescription (ipdCabalFile $ idePackage) - flat { buildDepends = dep pack : buildDepends flat} - return True -#endif - where - addDepToLib _ Nothing = Nothing - addDepToLib p (Just cn@CondNode{condTreeConstraints = deps}) = - Just (cn{condTreeConstraints = dep p : deps}) - addDepToExe p (str,cn@CondNode{condTreeConstraints = deps}) = + earlierVersion, Version(..))+import Distribution.PackageDescription+ (CondTree(..), condExecutables, condLibrary, packageDescription,+ buildDepends)+import Distribution.PackageDescription.Configuration+ (flattenPackageDescription)+import IDE.BufferMode (editInsertCode)+import Control.Monad.IO.Class (MonadIO(..))+#if MIN_VERSION_Cabal(1,10,0)+import Distribution.PackageDescription.PrettyPrintCopied+ (writeGenericPackageDescription)+#else+import Distribution.PackageDescription.Parse+ (writePackageDescription)+import Distribution.PackageDescription+ (CondTree(..))+#endif+import qualified Data.Text as T (unpack)+import Language.Haskell.Exts (KnownExtension)+import Text.Read (readMaybe)++-- | Add all imports which gave error messages ...+resolveErrors :: IDEAction+resolveErrors = do+ prefs' <- readIDE prefs+ let buildInBackground = backgroundBuild prefs'+ when buildInBackground $+ modifyIDE_ (\ide -> ide{prefs = prefs'{backgroundBuild = False}})+ errors <- readIDE errorRefs+ addPackageResults <- forM errors addPackage+ let notInScopes = [ y | (x,y) <-+ nubBy (\ (p1,_) (p2,_) -> p1 == p2)+ $ [(x,y) | (x,y) <- [((parseNotInScope . T.unpack . refDescription) e, e) | e <- errors]],+ isJust x]+ let extensions = [ y | (x,y) <-+ nubBy (\ (p1,_) (p2,_) -> p1 == p2)+ $ [(x,y) | (x,y) <- [((parsePerhapsYouIntendedToUse . T.unpack . refDescription) e, e) | e <- errors]],+ length x == 1]+ when (not (or addPackageResults) && null notInScopes && null extensions) $ ideMessage Normal $ "No errors that can be auto resolved"+ addAll buildInBackground notInScopes extensions+ where+ addAll buildInBackground notInScopes extensions = addAllImports notInScopes (True,[])+ where+ addAllImports :: [LogRef] -> (Bool,[Descr]) -> IDEM ()+ addAllImports (errorSpec:rest) (True,descrList) = addImport errorSpec descrList (addAllImports rest)+ addAllImports _ (cont, _) = addAllExtensions extensions cont++ addAllExtensions :: [LogRef] -> Bool -> IDEM ()+ addAllExtensions (errorSpec:rest) True = addExtension errorSpec (addAllExtensions rest)+ addAllExtensions _ _ = finally++ finally = when buildInBackground $ do+ prefs' <- readIDE prefs+ modifyIDE_ (\ide -> ide{prefs = prefs'{backgroundBuild = True}})++-- | Add import for current error ...+addOneImport :: IDEAction+addOneImport = do+ errors' <- readIDE errorRefs+ currentErr' <- readIDE currentError+ case currentErr' of+ Nothing -> do+ ideMessage Normal $ "No error selected"+ return ()+ Just ref -> addImport ref [] (\ _ -> return ())++-- | Add one missing import+-- Returns a boolean, if the process should be stopped in case of multiple addition+-- Returns a list of already added descrs, so that it will not be added two times and can+-- be used for default selection+addImport :: LogRef -> [Descr] -> ((Bool,[Descr]) -> IDEAction) -> IDEAction+addImport error descrList continuation =+ case parseNotInScope . T.unpack $ refDescription error of+ Nothing -> continuation (True,descrList)+ Just nis -> do+ currentInfo' <- getScopeForActiveBuffer+ wsInfo' <- getWorkspaceInfo+ case (currentInfo', wsInfo') of+ (Nothing, _) -> continuation (True,descrList)+ (_, Nothing) -> continuation (True,descrList)+ (Just (GenScopeC(PackScope _ symbolTable1),GenScopeC(PackScope _ symbolTable2)),+ Just (GenScopeC(PackScope _ symbolTable3),GenScopeC(PackScope _ symbolTable4))) ->+ let list = getIdentifierDescr (id' nis) symbolTable1 symbolTable2+ wslist = getIdentifierDescr (id' nis) symbolTable3 symbolTable4+ in case (list, wslist) of+ ([], []) -> do+ ideMessage Normal $ "Identifier " ++ (id' nis) ++ " not found"+ continuation (True, descrList)+ ([], list) -> do+ window' <- getMainWindow+ mbDescr <- liftIO $ selectModuleDialog window' list (id' nis) (mbQual' nis)+ (if null descrList+ then Nothing+ else Just (head descrList))+ case mbDescr of+ Nothing -> continuation (False, [])+ Just descr -> if elem descr descrList+ then continuation (True,descrList)+ else addImport' nis (logRefFullFilePath error)+ descr descrList continuation+ (descr : [], _) -> addImport' nis (logRefFullFilePath error) descr descrList continuation+ _ -> do+ let fullList = list ++ wslist+ window' <- getMainWindow+ mbDescr <- liftIO $ selectModuleDialog window' fullList (id' nis) (mbQual' nis)+ (if null descrList+ then Nothing+ else Just (head descrList))+ case mbDescr of+ Nothing -> continuation (False, [])+ Just descr -> if elem descr descrList+ then continuation (True,descrList)+ else addImport' nis (logRefFullFilePath error)+ descr descrList continuation++addPackage :: LogRef -> IDEM Bool+addPackage error = do+ case parseHiddenModule . T.unpack $ refDescription error of+ Nothing -> return False+ Just (HiddenModuleResult mod pack) -> do+ let idePackage = logRefPackage error+ gpd <- liftIO $ readPackageDescription normal (ipdCabalFile $ idePackage)+ ideMessage Normal $ "addPackage " ++ (display $ pkgName pack)+#if MIN_VERSION_Cabal(1,10,0)+ liftIO $ writeGenericPackageDescription (ipdCabalFile $ idePackage)+ gpd { condLibrary = addDepToLib pack (condLibrary gpd),+ condExecutables = map (addDepToExe pack)+ (condExecutables gpd)}+ return True+#else+ if hasConfigs gpd+ then return False+ else do+ let flat = flattenPackageDescription gpd+ liftIO $ writePackageDescription (ipdCabalFile $ idePackage)+ flat { buildDepends = dep pack : buildDepends flat}+ return True+#endif+ where+ addDepToLib _ Nothing = Nothing+ addDepToLib p (Just cn@CondNode{condTreeConstraints = deps}) =+ Just (cn{condTreeConstraints = dep p : deps})+ addDepToExe p (str,cn@CondNode{condTreeConstraints = deps}) = (str,cn{condTreeConstraints = dep p : deps})- -- Empty version is probably only going to happen for ghc-prim + -- Empty version is probably only going to happen for ghc-prim dep p | null . versionBranch $ packageVersion p = Dependency (packageName p) (anyVersion) dep p = Dependency (packageName p) ( intersectVersionRanges (orLaterVersion (packageVersion p))- (earlierVersion (majorAndMinor (packageVersion p)))) + (earlierVersion (majorAndMinor (packageVersion p)))) majorAndMinor v@Version{versionBranch = b} = v{versionBranch = nextMinor b} nextMinor = nextMinor' . (++[0,0]) nextMinor' (major:minor:_) = [major, minor+1] nextMinor' _ = undefined -getScopeForActiveBuffer :: IDEM (Maybe (GenScope, GenScope)) -getScopeForActiveBuffer = do - mbActiveBuf <- maybeActiveBuf - case mbActiveBuf of - Nothing -> return Nothing - Just buf -> do - mbPackage <- belongsToPackage buf - case mbPackage of - Nothing -> return Nothing - Just pack -> getPackageImportInfo pack - -addImport' :: NotInScopeParseResult -> FilePath -> Descr -> [Descr] -> ((Bool,[Descr]) -> IDEAction) -> IDEAction -addImport' nis filePath descr descrList continuation = do - mbBuf <- selectSourceBuf filePath - let mbMod = case dsMbModu descr of - Nothing -> Nothing - Just pm -> Just (modu pm) - case (mbBuf,mbMod) of - (Just buf,Just mod) -> do - inActiveBufContext () $ \ nb gtkbuf idebuf n -> do - ideMessage Normal $ "addImport " ++ show (dscName descr) ++ " from " - ++ (render $ disp $ mod) - doServerCommand (ParseHeaderCommand filePath) $ \ res -> - case res of - ServerHeader (Left imports) -> - case filter (qualifyAsImportStatement mod) imports of - [] -> let newLine = prettyPrint (newImpDecl mod) ++ "\n" - lastLine = foldr max 0 (map (locationELine . importLoc) imports) - in do - i1 <- getIterAtLine gtkbuf lastLine - editInsertCode gtkbuf i1 newLine - fileSave False - setModified gtkbuf True - continuation (True,(descr : descrList)) - l@(impDecl:_) -> - let newDecl = addToDecl impDecl - newLine = prettyPrint newDecl ++ "\n" - myLoc = importLoc impDecl - lineStart = locationSLine myLoc - lineEnd = locationELine myLoc - in do - i1 <- getIterAtLine gtkbuf (lineStart - 1) - i2 <- getIterAtLine gtkbuf (lineEnd) - delete gtkbuf i1 i2 - editInsertCode gtkbuf i1 newLine - fileSave False - setModified gtkbuf True - continuation (True,(descr : descrList)) - ServerHeader (Right lastLine) -> - let newLine = prettyPrint (newImpDecl mod) ++ "\n" - in do - i1 <- getIterAtLine gtkbuf lastLine - editInsertCode gtkbuf i1 newLine - fileSave False - setModified gtkbuf True - continuation (True,(descr : descrList)) - ServerFailed string -> do - ideMessage Normal ("Can't parse module header " ++ filePath ++ - " failed with: " ++ string) - continuation (False,[]) - _ -> do - ideMessage Normal ("ImportTool>>addImport: Impossible server answer") - continuation (False,[]) - _ -> return () - where - qualifyAsImportStatement :: D.ModuleName -> ImportDecl -> Bool - qualifyAsImportStatement moduleName impDecl = - let importName = importModule impDecl - getHiding (ImportSpecList isHiding _) = isHiding - in importName == display moduleName - && ((isNothing (mbQual' nis) && not (importQualified impDecl)) || - (isJust (mbQual' nis) && importQualified impDecl - && fromJust (mbQual' nis) == qualString impDecl)) - && (isNothing (importSpecs impDecl) || not (getHiding (fromJust (importSpecs impDecl)))) - newImpDecl :: D.ModuleName -> ImportDecl - newImpDecl mod = ImportDecl { - importLoc = noLocation, - importModule = display mod, - importQualified = isJust (mbQual' nis), - importSrc = False, - importPkg = Nothing, - importAs = if isJust (mbQual' nis) - then Just (fromJust (mbQual' nis)) - else Nothing, - importSpecs = (Just (ImportSpecList False [newImportSpec]))} - newImportSpec :: ImportSpec - newImportSpec = getRealId descr (id' nis) - addToDecl :: ImportDecl -> ImportDecl - addToDecl impDecl = case importSpecs impDecl of - Just (ImportSpecList True listIE) -> throwIDE "ImportTool>>addToDecl: ImpList is hiding" - Just (ImportSpecList False listIE) -> - impDecl{importSpecs = Just (ImportSpecList False (nub (newImportSpec : listIE)))} - Nothing -> - impDecl{importSpecs = Just (ImportSpecList False [newImportSpec])} - noLocation = Location 0 0 0 0 - -getRealId descr id = case descr of - Reexported rdescr -> getRealId (dsrDescr rdescr) id - Real edescr -> getReal (dscTypeHint' edescr) - where - getReal (FieldDescr d) = IThingAll (dscName d) - getReal (ConstructorDescr d) = IThingAll (dscName d) - getReal (MethodDescr d) = IThingAll (dscName d) - getReal _ = IVar id - -qualString :: ImportDecl -> String -qualString impDecl = case importAs impDecl of - Nothing -> "" - Just modName -> modName - --- | The import data - -data NotInScopeParseResult = NotInScopeParseResult { - mbQual' :: Maybe String - , id' :: String - , isSub' :: Bool - , isOp' :: Bool} - deriving Eq - --- |* The error line parser - -lexer = P.makeTokenParser haskellStyle -whiteSpace = P.whiteSpace lexer -lexeme = P.lexeme lexer -symbol = P.symbol lexer -identifier = P.identifier lexer -dot = P.dot lexer -operator = P.operator lexer - -parseNotInScope :: String -> (Maybe NotInScopeParseResult) -parseNotInScope str = - case Parsec.parse scopeParser "" str of - Left e -> Nothing - Right r -> Just r - -scopeParser :: CharParser () NotInScopeParseResult -scopeParser = do - whiteSpace - symbol "Not in scope:" - isSub <- optionMaybe (try (choice [symbol "type constructor or class" - , symbol "data constructor"])) - symbol "`" - mbQual <- optionMaybe (try (do - q <- lexeme conid - dot - return q)) - id <- optionMaybe (try identifier) - case id of - Just id -> return (NotInScopeParseResult mbQual - (take (length id - 1) id) (isJust isSub) False) - Nothing -> do - op <- operator - symbol "'" - return (NotInScopeParseResult mbQual op (isJust isSub) True) - <?> "scopeParser" - -conid = do - c <- upper - cs <- many (alphaNum <|> oneOf "_'") - return (c:cs) - <?> "conid" - - --- |* The little dialog to choose between possible modules - -moduleFields :: [String] -> String -> FieldDescription String -moduleFields list ident = - mkField - (paraName <<<- ParaName ("From which module is " ++ ident) - $ paraMultiSel <<<- ParaMultiSel False - $ paraMinSize <<<- ParaMinSize (300,400) - $ emptyParams) - (\ a -> a) - (\ a b -> a) - (staticListEditor ( list) id) - -selectModuleDialog :: Window -> [Descr] -> String -> Maybe String -> Maybe Descr -> IO (Maybe Descr) -selectModuleDialog parentWindow list id mbQual mbDescr = - let selectionList = (nub . sort) $ map (render . disp . modu . fromJust . dsMbModu) list - in if length selectionList == 1 - then return (Just (head list)) - else do - let mbSelectedString = case mbDescr of - Nothing -> Nothing - Just descr -> case dsMbModu descr of - Nothing -> Nothing - Just pm -> Just ((render . disp . modu) pm) - let realSelectionString = case mbSelectedString of - Nothing -> head selectionList - Just str -> if elem str selectionList - then str - else head selectionList - let qualId = case mbQual of - Nothing -> id - Just str -> str ++ "." ++ id - dia <- dialogNew - windowSetTransientFor dia parentWindow - upper <- dialogGetUpper dia - okButton <- dialogAddButton dia "Ok" ResponseOk - dialogAddButton dia "Cancel" ResponseCancel - (widget,inj,ext,_) <- buildEditor (moduleFields selectionList qualId) realSelectionString - boxPackStart upper widget PackGrow 7 - dialogSetDefaultResponse dia ResponseOk --does not work for the tree view - widgetShowAll dia - rw <- getRealWidget widget - set okButton [widgetCanDefault := True] - widgetGrabDefault okButton - resp <- dialogRun dia - value <- ext ([]) - widgetHide dia - widgetDestroy dia - --find - case (resp,value) of - (ResponseOk,Just v) -> return (Just (head - (filter (\e -> case dsMbModu e of - Nothing -> False - Just pm -> (render . disp . modu) pm == v) list))) - _ -> return Nothing - -data HiddenModuleResult = HiddenModuleResult { - hiddenModule :: String - , missingPackage :: PackageId} - deriving (Eq, Show) - -parseHiddenModule :: String -> (Maybe HiddenModuleResult) -parseHiddenModule str = - case Parsec.parse hiddenModuleParser "" str of - Left e -> Nothing - Right (mod, pack) -> - case simpleParse pack of - Just p -> Just $ HiddenModuleResult mod p - Nothing -> Nothing - -hiddenModuleParser :: CharParser () (String, String) -hiddenModuleParser = do - whiteSpace - symbol "Could not find module `" - mod <- many (noneOf "'")- many (noneOf "\n") +getScopeForActiveBuffer :: IDEM (Maybe (GenScope, GenScope))+getScopeForActiveBuffer = do+ mbActiveBuf <- maybeActiveBuf+ case mbActiveBuf of+ Nothing -> return Nothing+ Just buf -> do+ mbPackage <- belongsToPackage buf+ case mbPackage of+ Nothing -> return Nothing+ Just pack -> getPackageImportInfo pack++addImport' :: NotInScopeParseResult -> FilePath -> Descr -> [Descr] -> ((Bool,[Descr]) -> IDEAction) -> IDEAction+addImport' nis filePath descr descrList continuation = do+ mbBuf <- selectSourceBuf filePath+ let mbMod = case dsMbModu descr of+ Nothing -> Nothing+ Just pm -> Just (modu pm)+ case (mbBuf,mbMod) of+ (Just buf,Just mod) -> do+ inActiveBufContext () $ \ nb _ gtkbuf idebuf n -> do+ ideMessage Normal $ "addImport " ++ show (dscName descr) ++ " from "+ ++ (render $ disp $ mod)+ doServerCommand (ParseHeaderCommand filePath) $ \ res ->+ case res of+ ServerHeader (Left imports) ->+ case filter (qualifyAsImportStatement mod) imports of+ [] -> let newLine = prettyPrint (newImpDecl mod) ++ "\n"+ lastLine = foldr max 0 (map (locationELine . importLoc) imports)+ in do+ i1 <- getIterAtLine gtkbuf lastLine+ editInsertCode gtkbuf i1 newLine+ fileSave False+ setModified gtkbuf True+ continuation (True,(descr : descrList))+ l@(impDecl:_) ->+ let newDecl = addToDecl impDecl+ newLine = prettyPrint newDecl ++ "\n"+ myLoc = importLoc impDecl+ lineStart = locationSLine myLoc+ lineEnd = locationELine myLoc+ in do+ i1 <- getIterAtLine gtkbuf (lineStart - 1)+ i2 <- getIterAtLine gtkbuf (lineEnd)+ delete gtkbuf i1 i2+ editInsertCode gtkbuf i1 newLine+ fileSave False+ setModified gtkbuf True+ continuation (True,(descr : descrList))+ ServerHeader (Right lastLine) ->+ let newLine = prettyPrint (newImpDecl mod) ++ "\n"+ in do+ i1 <- getIterAtLine gtkbuf lastLine+ editInsertCode gtkbuf i1 newLine+ fileSave False+ setModified gtkbuf True+ continuation (True,(descr : descrList))+ ServerFailed string -> do+ ideMessage Normal ("Can't parse module header " ++ filePath +++ " failed with: " ++ string)+ continuation (False,[])+ _ -> do+ ideMessage Normal ("ImportTool>>addImport: Impossible server answer")+ continuation (False,[])+ _ -> return ()+ where+ qualifyAsImportStatement :: D.ModuleName -> ImportDecl -> Bool+ qualifyAsImportStatement moduleName impDecl =+ let importName = importModule impDecl+ getHiding (ImportSpecList isHiding _) = isHiding+ in importName == display moduleName+ && ((isNothing (mbQual' nis) && not (importQualified impDecl)) ||+ (isJust (mbQual' nis) && importQualified impDecl+ && fromJust (mbQual' nis) == qualString impDecl))+ && (isNothing (importSpecs impDecl) || not (getHiding (fromJust (importSpecs impDecl))))+ newImpDecl :: D.ModuleName -> ImportDecl+ newImpDecl mod = ImportDecl {+ importLoc = noLocation,+ importModule = display mod,+ importQualified = isJust (mbQual' nis),+ importSrc = False,+ importPkg = Nothing,+ importAs = if isJust (mbQual' nis)+ then Just (fromJust (mbQual' nis))+ else Nothing,+ importSpecs = (Just (ImportSpecList False [newImportSpec]))}+ newImportSpec :: ImportSpec+ newImportSpec = getRealId descr (id' nis)+ addToDecl :: ImportDecl -> ImportDecl+ addToDecl impDecl = case importSpecs impDecl of+ Just (ImportSpecList True listIE) -> throwIDE "ImportTool>>addToDecl: ImpList is hiding"+ Just (ImportSpecList False listIE) ->+ impDecl{importSpecs = Just (ImportSpecList False (nub (newImportSpec : listIE)))}+ Nothing ->+ impDecl{importSpecs = Just (ImportSpecList False [newImportSpec])}+ noLocation = Location 0 0 0 0++getRealId descr id = case descr of+ Reexported rdescr -> getRealId (dsrDescr rdescr) id+ Real edescr -> getReal (dscTypeHint' edescr)+ where+ getReal (FieldDescr d) = IThingAll (dscName d)+ getReal (ConstructorDescr d) = IThingAll (dscName d)+ getReal (MethodDescr d) = IThingAll (dscName d)+ getReal _ = IVar id++qualString :: ImportDecl -> String+qualString impDecl = case importAs impDecl of+ Nothing -> ""+ Just modName -> modName++-- | The import data++data NotInScopeParseResult = NotInScopeParseResult {+ mbQual' :: Maybe String+ , id' :: String+ , isSub' :: Bool+ , isOp' :: Bool}+ deriving Eq++-- |* The error line parser++lexer = P.makeTokenParser haskellStyle+whiteSpace = P.whiteSpace lexer+lexeme = P.lexeme lexer+symbol = P.symbol lexer+identifier = P.identifier lexer+dot = P.dot lexer+operator = P.operator lexer++parseNotInScope :: String -> (Maybe NotInScopeParseResult)+parseNotInScope str =+ case Parsec.parse scopeParser "" str of+ Left e -> Nothing+ Right r -> Just r++scopeParser :: CharParser () NotInScopeParseResult+scopeParser = do+ whiteSpace+ symbol "Not in scope:"+ isSub <- optionMaybe (try (choice [symbol "type constructor or class"+ , symbol "data constructor"]))+ ( (do+ char '`'+ mbQual <- optionMaybe (try (do+ q <- lexeme conid+ dot+ return q))+ id <- optionMaybe (try identifier)+ case id of+ Just id -> return (NotInScopeParseResult mbQual+ (take (length id - 1) id) (isJust isSub) False)+ Nothing -> do+ op <- operator+ char '\''+ return (NotInScopeParseResult mbQual op (isJust isSub) True))+ <|> (do+ char '‛'+ mbQual <- optionMaybe (try (do+ q <- lexeme conid+ dot+ return q))+ id <- optionMaybe (try identifier)+ result <- case id of+ Just id -> return (NotInScopeParseResult mbQual+ (take (length id) id) (isJust isSub) False)+ Nothing -> do+ op <- operator+ return (NotInScopeParseResult mbQual op (isJust isSub) True)+ char '’'+ return result))+ <?> "scopeParser"++conid = do+ c <- upper+ cs <- many (alphaNum <|> oneOf "_'")+ return (c:cs)+ <?> "conid"+++-- |* The little dialog to choose between possible modules++moduleFields :: [String] -> String -> FieldDescription String+moduleFields list ident =+ mkField+ (paraName <<<- ParaName ("From which module is " ++ ident)+ $ paraMultiSel <<<- ParaMultiSel False+ $ paraMinSize <<<- ParaMinSize (300,400)+ $ emptyParams)+ (\ a -> a)+ (\ a b -> a)+ (staticListEditor ( list) id)++selectModuleDialog :: Window -> [Descr] -> String -> Maybe String -> Maybe Descr -> IO (Maybe Descr)+selectModuleDialog parentWindow list id mbQual mbDescr =+ let selectionList = (nub . sort) $ map (render . disp . modu . fromJust . dsMbModu) list+ in if length selectionList == 1+ then return (Just (head list))+ else do+ let mbSelectedString = case mbDescr of+ Nothing -> Nothing+ Just descr -> case dsMbModu descr of+ Nothing -> Nothing+ Just pm -> Just ((render . disp . modu) pm)+ let realSelectionString = case mbSelectedString of+ Nothing -> head selectionList+ Just str -> if elem str selectionList+ then str+ else head selectionList+ let qualId = case mbQual of+ Nothing -> id+ Just str -> str ++ "." ++ id+ dia <- dialogNew+ set dia [ windowTransientFor := parentWindow ]+#ifdef MIN_VERSION_gtk3+ upper <- dialogGetContentArea dia+#else+ upper <- dialogGetUpper dia+#endif+ okButton <- dialogAddButton dia "Ok" ResponseOk+ dialogAddButton dia "Cancel" ResponseCancel+ (widget,inj,ext,_) <- buildEditor (moduleFields selectionList qualId) realSelectionString+ boxPackStart (castToBox upper) widget PackGrow 7+ dialogSetDefaultResponse dia ResponseOk --does not work for the tree view+ widgetShowAll dia+ rw <- getRealWidget widget+ set okButton [widgetCanDefault := True]+ widgetGrabDefault okButton+ resp <- dialogRun dia+ value <- ext ([])+ widgetHide dia+ widgetDestroy dia+ --find+ case (resp,value) of+ (ResponseOk,Just v) -> return (Just (head+ (filter (\e -> case dsMbModu e of+ Nothing -> False+ Just pm -> (render . disp . modu) pm == v) list)))+ _ -> return Nothing++data HiddenModuleResult = HiddenModuleResult {+ hiddenModule :: String+ , missingPackage :: PackageId}+ deriving (Eq, Show)++parseHiddenModule :: String -> (Maybe HiddenModuleResult)+parseHiddenModule str =+ case Parsec.parse hiddenModuleParser "" str of+ Left e -> Nothing+ Right (mod, pack) ->+ case simpleParse pack of+ Just p -> Just $ HiddenModuleResult mod p+ Nothing -> Nothing++hiddenModuleParser :: CharParser () (String, String)+hiddenModuleParser = do+ whiteSpace+ symbol "Could not find module "+ (char '`' <|> char '‛')+ mod <- many (noneOf "'’")+ many (noneOf "\n") symbol "\n"- whiteSpace - symbol "It is a member of the hidden package `" - pack <- many (noneOf "'") - symbol "'.\n" - many anyChar - return (mod, pack) - <?> "hiddenModuleParser" + whiteSpace+ symbol "It is a member of the hidden package "+ (char '`' <|> char '‛')+ pack <- many (noneOf "'’")+ (char '\'' <|> char '’')+ symbol ".\n"+ many anyChar+ return (mod, pack)+ <?> "hiddenModuleParser"++-- | Given an error message this returns the list of extensions that were+-- suggested in the message.+--+-- > parsePerhapsExt "Error blah blah\n Perhaps you intended to use -XNoBugsExt\n\n"+--+-- > parsePerhapsExt "Error blah blah\n Perhaps you intended to use ScopedTypeVariables\n\n"+--+-- > parsePerhapsExt "Error blah blah\n Use -XNoBugsExt\n\n"+parsePerhapsYouIntendedToUse :: String -> [KnownExtension]+parsePerhapsYouIntendedToUse =+ concatMap (parseLine . dropWhile (==' ')) . lines+ where+ parseLine :: String -> [KnownExtension]+ parseLine line = take 1 . catMaybes . map readMaybe $ catMaybes [+ stripPrefix "Perhaps you intended to use -X" line+ , stripPrefix "Perhaps you intended to use " line+ , takeWhile (/=' ') <$> stripPrefix "Use -X" line+ , takeWhile (/=' ') <$> stripPrefix "Use " line+ , takeWhile (/=' ') <$> stripPrefix "(Use -X" line+ , takeWhile (/=' ') <$> stripPrefix "(Use " line+ , takeWhile (/=' ') <$> stripPrefix "You need -X" line+ , takeWhile (/=' ') <$> stripPrefix "You need " line]++addExtension :: LogRef -> (Bool -> IDEAction) -> IDEAction+addExtension error continuation =+ case parsePerhapsYouIntendedToUse . T.unpack $ refDescription error of+ [] -> continuation True+ [ext] -> addExtension' (show ext) (logRefFullFilePath error) continuation+ list -> continuation True++addExtension' :: String -> FilePath -> (Bool -> IDEAction) -> IDEAction+addExtension' ext filePath continuation = do+ mbBuf <- selectSourceBuf filePath+ case mbBuf of+ Just buf ->+ inActiveBufContext () $ \ nb _ gtkbuf idebuf n -> do+ ideMessage Normal $ "addExtension " ++ ext+ i1 <- getIterAtLine gtkbuf 0+ editInsertCode gtkbuf i1 $ "{-# LANGUAGE " ++ ext ++ " #-}\n"+ fileSave False+ setModified gtkbuf True+ continuation True+ _ -> return ()++addResolveMenuItems ideR theMenu logRef = do+ let msg = T.unpack $ refDescription logRef+ when (isJust $ parseNotInScope msg) $+ addFixMenuItem "Add Import" $ addImport logRef [] (\ _ -> return ())+ when (isJust $ parseHiddenModule msg) $+ addFixMenuItem "Add Package" $ addPackage logRef+ when ((length $ parsePerhapsYouIntendedToUse msg) == 1) $+ addFixMenuItem "Add Extension" $ addExtension logRef (\ _ -> return ())+ where+ addFixMenuItem name fix = do+ item <- menuItemNewWithLabel name+ item `on` menuItemActivate $ do+ reflectIDE (fix >> return ()) ideR+ menuShellAppend theMenu item+
@@ -18,6 +18,7 @@ import IDE.Core.State import Control.Monad (foldM)+import System.Log.Logger (infoM) class Keymap alpha where parseKeymap :: FilePath -> IO alpha@@ -36,6 +37,7 @@ parseKeymap' :: FilePath -> IO KeymapI parseKeymap' fn = do+ infoM "leksah" $ "Reading keymap from " ++ fn res <- parseFromFile keymapParser fn case res of Left pe -> throwIDE $"Error reading keymap file " ++ show fn ++ " " ++ show pe
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, ScopedTypeVariables #-}+{-# LANGUAGE CPP, ScopedTypeVariables, OverloadedStrings #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Leksah@@ -38,7 +38,6 @@ import qualified Config.Dyre as Dyre #endif -import Paths_leksah import IDE.Session import IDE.Core.State import Control.Event@@ -73,12 +72,13 @@ (doesDirectoryExist, copyFile, createDirectoryIfMissing, getHomeDirectory, doesFileExist) import System.FilePath (dropExtension, splitExtension, (</>))-import qualified Data.Enumerator as E-import qualified Data.Enumerator.List as EL-import Data.Enumerator (($$))+import qualified Data.Conduit as C+import qualified Data.Conduit.List as CL+import Data.Conduit (($$)) import Control.Monad (when, unless, liftM) import Control.Monad.IO.Class (MonadIO(..)) import Control.Applicative ((<$>))+import qualified Data.Text as T (unpack, stripPrefix) -- -------------------------------------------------------------------- -- Command line options@@ -212,28 +212,60 @@ st <- unsafeInitGUIForThreadedRTS when rtsSupportsBoundThreads (sysMessage Normal "Linked with -threaded")- timeoutAddFull (yield >> return True) priorityHigh 10- mapM_ (sysMessage Normal) st- initGtkRc- dataDir <- getDataDir- mbStartupPrefs <- if not isFirstStart- then return $ Just iprefs- else do- firstStartOK <- firstStart iprefs- if not firstStartOK- then return Nothing- else do- prefsPath <- getConfigFilePathForLoad standardPreferencesFilename Nothing dataDir- prefs <- readPrefs prefsPath- return $ Just prefs- case mbStartupPrefs of- Nothing -> return ()- Just startupPrefs -> startMainWindow yiControl sessionFP mbWorkspaceFP sourceFPs- startupPrefs isFirstStart+ postGUIAsync $ do+ mapM_ (sysMessage Normal) st+ initGtkRc+ dataDir <- getDataDir+ mbStartupPrefs <- if not isFirstStart+ then return $ Just iprefs+ else do+ firstStartOK <- firstStart iprefs+ if not firstStartOK+ then return Nothing+ else do+ prefsPath <- getConfigFilePathForLoad standardPreferencesFilename Nothing dataDir+ prefs <- readPrefs prefsPath+ return $ Just prefs+ case mbStartupPrefs of+ Nothing -> return ()+ Just startupPrefs -> startMainWindow yiControl sessionFP mbWorkspaceFP sourceFPs+ startupPrefs isFirstStart+ unless rtsSupportsBoundThreads $ postGUIAsync mainLoop+ debugM "leksah" "starting mainGUI"+ mainGUI+ debugM "leksah" "finished mainGUI" +mainLoop :: IO ()+mainLoop = eventsPending >>= loop 50+ where+ loop :: Int -> Int -> IO ()+ loop delay n = do+ quit <- loopn (n+2)+ if quit+ then return ()+ else do+ yield+ pending <- eventsPending+ if pending > 0+ then do+ loop 50 pending+ else do+ threadDelay delay+ eventsPending >>= loop (if n > 0+ then 50+ else min (delay+delay) 5000)+ loopn :: Int -> IO Bool+ loopn 0 = return False+ loopn n = do+ quit <- mainIterationDo False+ if quit+ then return True+ else loopn (n - 1)+ startMainWindow :: Yi.Control -> FilePath -> Maybe FilePath -> [FilePath] -> Prefs -> Bool -> IO () startMainWindow yiControl sessionFP mbWorkspaceFP sourceFPs startupPrefs isFirstStart = do+ debugM "leksah" "startMainWindow" osxApp <- OSX.applicationNew uiManager <- uiManagerNew newIcons@@ -269,6 +301,7 @@ , prefs = startupPrefs , workspace = Nothing , activePack = Nothing+ , activeExe = Nothing , bufferProjCache = Map.empty , allLogRefs = [] , currentHist = 0@@ -289,14 +322,17 @@ , completion = ((750,400),Nothing) , yiControl = yiControl , server = Nothing+ , vcsData = (Map.empty, Nothing)+ , logLaunches = Map.empty+ , autoCommand = return () } ideR <- newIORef ide menuDescription' <- menuDescription reflectIDE (makeMenu uiManager accelActions menuDescription') ideR nb <- reflectIDE (newNotebook []) ideR- afterSwitchPage nb (\i -> reflectIDE (handleNotebookSwitch nb i) ideR)+ after nb switchPage (\i -> reflectIDE (handleNotebookSwitch nb i) ideR) widgetSetName nb $"root"- win `onDelete` (\ _ -> do reflectIDE quit ideR; return True)+ on win deleteEvent . liftIO $ reflectIDE quit ideR >> return True reflectIDE (instrumentWindow win startupPrefs (castToWidget nb)) ideR reflectIDE (do setCandyState (fst (sourceCandy startupPrefs))@@ -314,6 +350,8 @@ mapM_ instrumentSecWindow (tail wins) return pair ) ideR++ debugM "leksah" "Show main window" widgetShowAll win reflectIDE (do@@ -354,14 +392,16 @@ when (backgroundBuild currentPrefs) $ backgroundMake) ideR return True) priorityDefaultIdle 1000 reflectIDE (triggerEvent ideR (Sensitivity [(SensitivityInterpreting, False)])) ideR- mainGUI+ return ()+-- mainGUI fDescription :: FilePath -> FieldDescription Prefs fDescription configPath = VFD emptyParams [ mkField (paraName <<<- ParaName "Paths under which haskell sources for packages may be found" $ paraDirection <<<- ParaDirection Vertical- $ emptyParams)+ $ paraMinSize <<<- ParaMinSize (-1, 150)+ $ emptyParams) sourceDirectories (\b a -> a{sourceDirectories = b}) (filesEditor Nothing FileChooserActionSelectFolder "Select folders")@@ -397,16 +437,20 @@ windowWindowPosition := WinPosCenter] dialogAddButton dialog "gtk-ok" ResponseOk dialogAddButton dialog "gtk-cancel" ResponseCancel+#ifdef MIN_VERSION_gtk3+ vb <- dialogGetContentArea dialog+#else vb <- dialogGetUpper dialog+#endif label <- labelNew (Just ( "Before you start using Leksah it will collect and download metadata about your installed Haskell packages.\n" ++ "You can add folders under which you have sources for Haskell packages not available from Hackage.")) (widget, setInj, getExt,notifier) <- buildEditor (fDescription configDir) prefs- boxPackStart vb label PackNatural 7+ boxPackStart (castToBox vb) label PackNatural 7 sw <- scrolledWindowNew Nothing Nothing scrolledWindowAddWithViewport sw widget scrolledWindowSetPolicy sw PolicyNever PolicyAutomatic- boxPackStart vb sw PackGrow 7+ boxPackStart (castToBox vb) sw PackGrow 7 windowSetDefaultSize dialog 800 630 widgetShowAll dialog response <- dialogRun dialog@@ -451,18 +495,22 @@ windowTitle := "Leksah: Updating Metadata", windowWindowPosition := WinPosCenter, windowDeletable := False]+#ifdef MIN_VERSION_gtk3+ vb <- dialogGetContentArea dialog+#else vb <- dialogGetUpper dialog+#endif progressBar <- progressBarNew progressBarSetText progressBar "Please wait while Leksah collects information about Haskell packages on your system" progressBarSetFraction progressBar 0.0- boxPackStart vb progressBar PackGrow 7+ boxPackStart (castToBox vb) progressBar PackGrow 7 forkIO $ do logger <- getRootLogger let verbosity = case getLevel logger of Just level -> ["--verbosity=" ++ show level] Nothing -> [] (output, pid) <- runTool "leksah-server" (["-sbo", "+RTS", "-N2", "-RTS"] ++ verbosity) Nothing- E.run_ $ output $$ EL.mapM_ (update progressBar)+ output $$ CL.mapM_ (update progressBar) waitForProcess pid postGUIAsync (dialogResponse dialog ResponseOk) widgetShowAll dialog@@ -473,9 +521,9 @@ where update pb to = do let str = toolline to- case stripPrefix "update_toolbar " str of- Just rest -> postGUIAsync $ progressBarSetFraction pb (read rest)- Nothing -> liftIO $ debugM "leksah" str+ case T.stripPrefix "update_toolbar " str of+ Just rest -> postGUIAsync $ progressBarSetFraction pb (read $ T.unpack rest)+ Nothing -> liftIO $ debugM "leksah" $ T.unpack str
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, ScopedTypeVariables #-}+{-# LANGUAGE CPP, ScopedTypeVariables, OverloadedStrings #-} ----------------------------------------------------------------------------- -- -- Module : IDE.LogRef@@ -26,12 +26,18 @@ , defaultLineLogger' , logOutputLines , logOutputLines_+, logOutputLines_Default , logOutput+, logOutputDefault+, logOutputPane , logOutputForBuild , logOutputForBreakpoints , logOutputForSetBreakpoint+, logOutputForSetBreakpointDefault , logOutputForLiveContext+, logOutputForLiveContextDefault , logOutputForHistoricContext+, logOutputForHistoricContextDefault , selectRef , setBreakpointList , showSourceSpan@@ -39,6 +45,7 @@ ) where import Graphics.UI.Gtk+import Control.Monad.Reader import Text.ParserCombinators.Parsec.Language import Text.ParserCombinators.Parsec hiding(Parser) import qualified Text.ParserCombinators.Parsec.Token as P@@ -46,21 +53,24 @@ import IDE.Core.State import IDE.TextEditor import IDE.Pane.SourceBuffer-import IDE.Pane.Log+import qualified IDE.Pane.Log as Log import IDE.Utils.Tool import System.FilePath (equalFilePath) import Data.List (stripPrefix, elemIndex, isPrefixOf)-import Data.Maybe (catMaybes)+import Data.Maybe (catMaybes, isJust) import System.Exit (ExitCode(..)) import System.Log.Logger (debugM) import IDE.Utils.FileUtils(myCanonicalizePath)-import qualified Data.Enumerator as E-import qualified Data.Enumerator.List as EL-import Data.Enumerator ((=$))-import Control.Monad.IO.Class (MonadIO(..))-import Control.Monad (forM_, unless)-import Control.Monad.Trans.Reader (ask)-import Control.Monad.Trans.Class (lift)+import IDE.Pane.Log (getDefaultLogLaunch, IDELog(..), getLog)+import qualified Data.Conduit as C+import qualified Data.Conduit.List as CL+import Data.Conduit ((=$))+import IDE.Pane.WebKit.Output(setOutput)+import Data.IORef (atomicModifyIORef, IORef, readIORef)+import Data.Text (Text)+import Control.Applicative ((<$>))+import qualified Data.Text as T (unpack, unlines, pack, null)+import Data.Monoid ((<>)) showSourceSpan :: LogRef -> String showSourceSpan = displaySrcSpan . logRefSrcSpan@@ -75,8 +85,8 @@ case mbBuf of Just buf -> markRefInSourceBuf index buf ref True Nothing -> liftIO $ debugM "leksah" "no buf" >> return ()- log :: IDELog <- getLog- liftIO $ markErrorInLog log (logLines ref)+ log :: Log.IDELog <- Log.getLog+ Log.markErrorInLog log (logLines ref) selectRef Nothing = return () forOpenLogRefs :: (Int -> LogRef -> IDEBuffer -> IDEAction) -> IDEAction@@ -97,11 +107,9 @@ unmarkLogRefs :: IDEAction unmarkLogRefs = do- forOpenLogRefs $ \index logRef buf -> do- gtkbuf <- getBuffer (sourceView buf)- i1 <- getStartIter gtkbuf- i2 <- getEndIter gtkbuf- removeTagByName gtkbuf (show (logRefType logRef) ++ show index) i1 i2+ forOpenLogRefs $ \index logRef (IDEBuffer {sourceView = sv}) -> do+ buf <- getBuffer sv+ removeTagByName buf (show (logRefType logRef) ++ show index) setErrorList :: [LogRef] -> IDEAction setErrorList errs = do@@ -257,9 +265,17 @@ fixColumn = id #endif +srcPathParser :: CharParser () FilePath+srcPathParser = try (do+ symbol "dist/build/tmp-" -- Support for cabal haddock+ many digit+ char '/'+ many (noneOf ":"))+ <|> many (noneOf ":")+ srcSpanParser :: CharParser () SrcSpan srcSpanParser = try (do- filePath <- many (noneOf ":")+ filePath <- srcPathParser char ':' char '(' beginLine <- int@@ -274,7 +290,7 @@ char ')' return $ SrcSpan filePath beginLine (fixColumn beginCol) endLine (fixColumn endCol)) <|> try (do- filePath <- many (noneOf ":")+ filePath <- srcPathParser char ':' line <- int char ':'@@ -283,7 +299,7 @@ endCol <- int return $ SrcSpan filePath line (fixColumn beginCol) line (fixColumn endCol)) <|> try (do- filePath <- many (noneOf ":")+ filePath <- srcPathParser char ':' line <- int char ':'@@ -369,48 +385,92 @@ colon = P.colon lexer int = fmap fromInteger $ P.integer lexer -defaultLineLogger :: IDELog -> ToolOutput -> IDEM Int-defaultLineLogger log out = liftIO $ defaultLineLogger' log out+defaultLineLogger :: IDELog -> LogLaunch -> ToolOutput -> IDEM Int+defaultLineLogger log logLaunch out = liftIO $ defaultLineLogger' log logLaunch out -defaultLineLogger' :: IDELog -> ToolOutput -> IO Int-defaultLineLogger' log out = do+defaultLineLogger' :: IDELog -> LogLaunch -> ToolOutput -> IO Int+defaultLineLogger' log logLaunch out = do case out of- ToolInput line -> appendLog log (line ++ "\n") InputTag- ToolOutput line -> appendLog log (line ++ "\n") LogTag- ToolError line -> appendLog log (line ++ "\n") ErrorTag+ ToolInput line -> appendLog' (line <> "\n") InputTag+ ToolOutput line -> appendLog' (line <> "\n") LogTag+ ToolError line -> appendLog' (line <> "\n") ErrorTag ToolPrompt line -> do- unless (null line) $ appendLog log (line ++ "\n") LogTag >> return ()- appendLog log (concat (take 20 (repeat "- ")) ++ "-\n") FrameTag- ToolExit ExitSuccess -> appendLog log (take 41 (repeat '-') ++ "\n") FrameTag- ToolExit (ExitFailure 1) -> appendLog log (take 41 (repeat '=') ++ "\n") FrameTag- ToolExit (ExitFailure n) -> appendLog log (take 41 ("========== " ++ show n ++ " " ++ repeat '=') ++ "\n") FrameTag+ unless (T.null line) $ appendLog' (line <> "\n") LogTag >> return ()+ appendLog' (T.pack (concat (take 20 (repeat "- "))) <> "-\n") FrameTag+ ToolExit ExitSuccess -> appendLog' (T.pack (take 41 (repeat '-')) <> "\n") FrameTag+ ToolExit (ExitFailure 1) -> appendLog' (T.pack (take 41 (repeat '=')) <> "\n") FrameTag+ ToolExit (ExitFailure n) -> appendLog' (T.pack (take 41 ("========== " ++ show n <> " " ++ repeat '=')) <> "\n") FrameTag+ where+ appendLog' = Log.appendLog log logLaunch -logOutputLines :: (IDELog -> ToolOutput -> IDEM a) -> E.Iteratee ToolOutput IDEM [a]-logOutputLines lineLogger = do- ideR <- lift ask- log <- lift getLog- liftIO $ postGUISync $ bringPaneToFront log- results <- (EL.mapM $ liftIO . postGUISync . flip reflectIDE ideR . lineLogger log) =$ EL.consume- liftIO $ postGUISync $ reflectIDE (do- triggerEventIDE (StatusbarChanged [CompartmentState "", CompartmentBuild False])- ) ideR+paneLineLogger :: IDELog -> LogLaunch -> ToolOutput -> IDEM (Maybe Text)+paneLineLogger log logLaunch out = liftIO $ paneLineLogger' log logLaunch out++paneLineLogger' :: IDELog -> LogLaunch -> ToolOutput -> IO (Maybe Text)+paneLineLogger' log logLaunch out = do+ case out of+ ToolInput line -> appendLog' (line <> "\n") InputTag >> return Nothing+ ToolOutput line -> appendLog' (line <> "\n") LogTag >> return (Just line)+ ToolError line -> appendLog' (line <> "\n") ErrorTag >> return Nothing+ ToolPrompt line -> do+ unless (T.null line) $ appendLog' (line <> "\n") LogTag >> return ()+ appendLog' (T.pack (concat (take 20 (repeat "- "))) <> "-\n") FrameTag+ return Nothing+ ToolExit ExitSuccess -> appendLog' (T.pack (take 41 (repeat '-')) <> "\n") FrameTag >> return Nothing+ ToolExit (ExitFailure 1) -> appendLog' (T.pack (take 41 (repeat '=')) <> "\n") FrameTag >> return Nothing+ ToolExit (ExitFailure n) -> appendLog' (T.pack (take 41 ("========== " ++ show n ++ " " ++ repeat '=')) <> "\n") FrameTag >> return Nothing+ where+ appendLog' = Log.appendLog log logLaunch++logOutputLines :: LogLaunch -- ^ logLaunch+ -> (IDELog -> LogLaunch -> ToolOutput -> IDEM a)+ -> C.Sink ToolOutput IDEM [a]+logOutputLines logLaunch lineLogger = do+ log :: Log.IDELog <- lift $ postSyncIDE Log.getLog+ results <- (CL.mapM $ postSyncIDE . lineLogger log logLaunch) =$ CL.consume+ lift $ triggerEventIDE (StatusbarChanged [CompartmentState "", CompartmentBuild False]) return results -logOutputLines_ :: (IDELog -> ToolOutput -> IDEM a) -> E.Iteratee ToolOutput IDEM ()-logOutputLines_ lineLogger = do- logOutputLines lineLogger+logOutputLines_ :: LogLaunch+ -> (IDELog -> LogLaunch -> ToolOutput -> IDEM a)+ -> C.Sink ToolOutput IDEM ()+logOutputLines_ logLaunch lineLogger = do+ logOutputLines logLaunch lineLogger return () -logOutput :: E.Iteratee ToolOutput IDEM ()-logOutput = do- logOutputLines defaultLineLogger+logOutputLines_Default :: (IDELog -> LogLaunch -> ToolOutput -> IDEM a)+ -> C.Sink ToolOutput IDEM ()+logOutputLines_Default lineLogger = do+ defaultLogLaunch <- lift $ getDefaultLogLaunch+ logOutputLines_ defaultLogLaunch lineLogger++logOutput :: LogLaunch+ -> C.Sink ToolOutput IDEM ()+logOutput logLaunch = do+ logOutputLines logLaunch defaultLineLogger return () -logOutputForBuild :: IDEPackage -> Bool -> Bool -> E.Iteratee ToolOutput IDEM ()+logOutputDefault :: C.Sink ToolOutput IDEM ()+logOutputDefault = do+ defaultLogLaunch <- lift $ getDefaultLogLaunch+ logOutput defaultLogLaunch++logOutputPane :: IORef [Text] -> C.Sink ToolOutput IDEM ()+logOutputPane buffer = do+ defaultLogLaunch <- lift $ getDefaultLogLaunch+ result <- catMaybes <$> logOutputLines defaultLogLaunch paneLineLogger+ when (not $ null result) $ do+ new <- liftIO . atomicModifyIORef buffer $ \x -> let new = x ++ result in (new, new)+ lift . postSyncIDE . setOutput $ T.unpack $ T.unlines new++logOutputForBuild :: IDEPackage+ -> Bool+ -> Bool+ -> C.Sink ToolOutput IDEM [LogRef] logOutputForBuild package backgroundBuild jumpToWarnings = do log <- lift getLog- unless backgroundBuild $ liftIO $ postGUISync $ bringPaneToFront log- (_, _, errs) <- EL.foldM readAndShow (log, False, [])+ logLaunch <- lift $ Log.getDefaultLogLaunch+ (_, _, errs) <- CL.foldM (readAndShow logLaunch) (log, False, []) ideR <- lift ask liftIO $ postGUISync $ reflectIDE (do setErrorList $ reverse errs@@ -420,14 +480,14 @@ triggerEventIDE (StatusbarChanged [CompartmentState (show errorNum ++ " Errors, " ++ show warnNum ++ " Warnings"), CompartmentBuild False]) unless (backgroundBuild || (not jumpToWarnings && errorNum == 0)) nextError- return ()) ideR+ return errs) ideR where- readAndShow :: (IDELog, Bool, [LogRef]) -> ToolOutput -> IDEM (IDELog, Bool, [LogRef])- readAndShow (log, inError, errs) output = do+ readAndShow :: LogLaunch -> (IDELog, Bool, [LogRef]) -> ToolOutput -> IDEM (IDELog, Bool, [LogRef])+ readAndShow logLaunch (log, inError, errs) output = do ideR <- ask liftIO $ postGUISync $ case output of ToolError line -> do- let parsed = parse buildLineParser "" line+ let parsed = parse buildLineParser "" $ T.unpack line let nonErrorPrefixes = ["Linking ", "ar:", "ld:", "ld warning:"] tag <- case parsed of Right BuildLine -> return InfoTag@@ -440,105 +500,126 @@ Right (OtherLine text) | any (`isPrefixOf` text) nonErrorPrefixes -> do return InfoTag _ -> return ErrorTag- lineNr <- appendLog log (line ++ "\n") tag+ lineNr <- Log.appendLog log logLaunch (line <> "\n") tag case (parsed, errs) of (Left e,_) -> do sysMessage Normal (show e) return (log, False, errs) (Right ne@(ErrorLine span refType str),_) ->- return (log, True, ((LogRef span package str (lineNr,lineNr) refType):errs))+ return (log, True, ((LogRef span package (T.pack str) (lineNr,lineNr) refType):errs)) (Right (OtherLine str1),(LogRef span rootPath str (l1,l2) refType):tl) -> if inError then return (log, True, ((LogRef span rootPath- (if null str+ (if T.null str then line- else str ++ "\n" ++ line)+ else str <> "\n" <> line) (l1,lineNr) refType) : tl)) else return (log, False, errs) (Right (WarningLine str1),(LogRef span rootPath str (l1,l2) isError):tl) -> if inError then return (log, True, ((LogRef span rootPath- (if null str+ (if T.null str then line- else str ++ "\n" ++ line)+ else str <> "\n" <> line) (l1,lineNr) WarningRef) : tl)) else return (log, False, errs) otherwise -> return (log, False, errs) ToolOutput line -> do- appendLog log (line ++ "\n") LogTag+ Log.appendLog log logLaunch (line <> "\n") LogTag return (log, inError, errs) ToolInput line -> do- appendLog log (line ++ "\n") InputTag+ Log.appendLog log logLaunch (line <> "\n") InputTag return (log, inError, errs) ToolPrompt line -> do- unless (null line) $ appendLog log (line ++ "\n") LogTag >> return ()+ unless (T.null line) $ Log.appendLog log logLaunch (line <> "\n") LogTag >> return () let errorNum = length (filter isError errs) let warnNum = length errs - errorNum case errs of- [] -> defaultLineLogger' log output- _ -> appendLog log ("- - - " ++ show errorNum ++ " errors - "+ [] -> defaultLineLogger' log logLaunch output+ _ -> Log.appendLog log logLaunch (T.pack $ "- - - " ++ show errorNum ++ " errors - " ++ show warnNum ++ " warnings - - -\n") FrameTag return (log, inError, errs) ToolExit _ -> do let errorNum = length (filter isError errs) let warnNum = length errs - errorNum case errs of- [] -> defaultLineLogger' log output- _ -> appendLog log ("----- " ++ show errorNum ++ " errors -- "+ [] -> defaultLineLogger' log logLaunch output+ _ -> Log.appendLog log logLaunch (T.pack $ "----- " ++ show errorNum ++ " errors -- " ++ show warnNum ++ " warnings -----\n") FrameTag return (log, inError, errs) -logOutputForBreakpoints :: IDEPackage -> E.Iteratee ToolOutput IDEM ()-logOutputForBreakpoints package = do- breaks <- logOutputLines (\log out -> do++--logOutputLines :: String -- ^ logLaunch+-- -> (LogLaunch -> ToolOutput -> IDEM a)+-- -> [ToolOutput]+-- -> IDEM [a]++logOutputForBreakpoints :: IDEPackage+ -> LogLaunch -- ^ loglaunch+ -> C.Sink ToolOutput IDEM ()+logOutputForBreakpoints package logLaunch = do+ breaks <- logOutputLines logLaunch (\log logLaunch out -> do case out of ToolOutput line -> do- logLineNumber <- liftIO $ appendLog log (line ++ "\n") LogTag- case parse breaksLineParser "" line of+ logLineNumber <- liftIO $ Log.appendLog log logLaunch (line <> "\n") LogTag+ case parse breaksLineParser "" $ T.unpack line of Right (BreakpointDescription n span) -> return $ Just $ LogRef span package line (logLineNumber, logLineNumber) BreakpointRef _ -> return Nothing _ -> do- liftIO $ defaultLineLogger' log out+ defaultLineLogger log logLaunch out return Nothing) lift $ setBreakpointList $ catMaybes breaks -logOutputForSetBreakpoint :: IDEPackage -> E.Iteratee ToolOutput IDEM ()-logOutputForSetBreakpoint package = do- breaks <- logOutputLines (\log out -> do+logOutputForSetBreakpoint :: IDEPackage+ -> LogLaunch -- ^ loglaunch+ -> C.Sink ToolOutput IDEM ()+logOutputForSetBreakpoint package logLaunch = do+ breaks <- logOutputLines logLaunch (\log logLaunch out -> do case out of ToolOutput line -> do- logLineNumber <- liftIO $ appendLog log (line ++ "\n") LogTag- case parse setBreakpointLineParser "" line of+ logLineNumber <- liftIO $ Log.appendLog log logLaunch (line <> "\n") LogTag+ case parse setBreakpointLineParser "" $ T.unpack line of Right (BreakpointDescription n span) -> return $ Just $ LogRef span package line (logLineNumber, logLineNumber) BreakpointRef _ -> return Nothing _ -> do- defaultLineLogger log out+ defaultLineLogger log logLaunch out return Nothing) lift $ addLogRefs $ catMaybes breaks -logOutputForContext :: IDEPackage -> (String -> [SrcSpan]) -> E.Iteratee ToolOutput IDEM ()-logOutputForContext package getContexts = do- refs <- fmap catMaybes $ logOutputLines (\log out -> do+logOutputForSetBreakpointDefault :: IDEPackage+ -> C.Sink ToolOutput IDEM ()+logOutputForSetBreakpointDefault package = do+ defaultLogLaunch <- lift $ getDefaultLogLaunch+ logOutputForSetBreakpoint package defaultLogLaunch++logOutputForContext :: IDEPackage+ -> LogLaunch -- ^ loglaunch+ -> (String -> [SrcSpan])+ -> C.Sink ToolOutput IDEM ()+logOutputForContext package loglaunch getContexts = do+ refs <- fmap catMaybes $ logOutputLines loglaunch (\log logLaunch out -> do case out of ToolOutput line -> do- logLineNumber <- liftIO $ appendLog log (line ++ "\n") LogTag- let contexts = getContexts line+ logLineNumber <- liftIO $ Log.appendLog log logLaunch (line <> "\n") LogTag+ let contexts = getContexts $ T.unpack line if null contexts then return Nothing else return $ Just $ LogRef (last contexts) package line (logLineNumber, logLineNumber) ContextRef _ -> do- defaultLineLogger log out+ defaultLineLogger log logLaunch out return Nothing) lift $ unless (null refs) $ do addLogRefs [last refs] lastContext -logOutputForLiveContext :: IDEPackage -> E.Iteratee ToolOutput IDEM ()-logOutputForLiveContext package = logOutputForContext package getContexts+logOutputForLiveContext :: IDEPackage+ -> LogLaunch -- ^ loglaunch+ -> C.Sink ToolOutput IDEM ()+logOutputForLiveContext package logLaunch = logOutputForContext package logLaunch getContexts where getContexts [] = [] getContexts line@(x:xs) = case stripPrefix "Stopped at " line of@@ -547,8 +628,17 @@ _ -> getContexts xs _ -> getContexts xs -logOutputForHistoricContext :: IDEPackage -> E.Iteratee ToolOutput IDEM ()-logOutputForHistoricContext package = logOutputForContext package getContexts+logOutputForLiveContextDefault :: IDEPackage+ -> C.Sink ToolOutput IDEM ()+logOutputForLiveContextDefault package = do+ defaultLogLaunch <- lift $ getDefaultLogLaunch+ logOutputForLiveContext package defaultLogLaunch+++logOutputForHistoricContext :: IDEPackage+ -> LogLaunch -- ^ loglaunch+ -> C.Sink ToolOutput IDEM ()+logOutputForHistoricContext package logLaunch = logOutputForContext package logLaunch getContexts where getContexts line = case stripPrefix "Logged breakpoint at " line of Just rest -> case parse srcSpanParser "" rest of@@ -556,3 +646,8 @@ _ -> [] _ -> [] +logOutputForHistoricContextDefault :: IDEPackage+ -> C.Sink ToolOutput IDEM ()+logOutputForHistoricContextDefault package = do+ defaultLogLaunch <- lift $ getDefaultLogLaunch+ logOutputForHistoricContext package defaultLogLaunch
@@ -1,5 +1,4 @@-{-# OPTIONS_GHC -XTypeSynonymInstances -XScopedTypeVariables -XNoMonomorphismRestriction- -XFlexibleContexts -XBangPatterns #-}+{-# LANGUAGE CPP, ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Metainfo.Provider@@ -59,7 +58,11 @@ import System.IO.Unsafe (unsafePerformIO) import Text.Regex.TDFA.String (execute,compile) import Data.Binary.Shared (decodeSer)+#if MIN_VERSION_Cabal(1,16,0)+import Language.Haskell.Extension (KnownExtension)+#else import Language.Haskell.Extension (knownExtensions)+#endif import Distribution.Text (display) import IDE.Core.Serializable () import Data.Map (Map(..))@@ -88,16 +91,13 @@ callCollector False True True $ \ _ -> do ideMessage Normal "Now loading metadata ..." loadSystemInfo- ideMessage Normal "Now updating workspace metadata ..." updateWorkspaceInfo' False $ \ _ -> do- ideMessage Normal "Finished" triggerEventIDE (InfoChanged True) >> return () trace "blah" $ continuation else do ideMessage Normal "Now loading metadata ..." loadSystemInfo- ideMessage Normal "Now updating workspace metadata ..." updateWorkspaceInfo' False $ \ _ -> do ideMessage Normal "Finished" triggerEventIDE (InfoChanged True) >> return ()@@ -151,6 +151,7 @@ -- updateSystemInfo' :: Bool -> (Bool -> IDEAction) -> IDEAction updateSystemInfo' rebuild continuation = do+ ideMessage Normal "Now updating system metadata ..." wi <- getSystemInfo case wi of Nothing -> loadSystemInfo@@ -175,6 +176,7 @@ (Map.elems psmap3) modifyIDE_ (\ide -> ide{systemInfo = Just (GenScopeC (addOtherToScope scope False))}) continuation True+ ideMessage Normal "Finished updating system metadata" getEmptyDefaultScope :: Map String [Descr] getEmptyDefaultScope = symEmpty@@ -194,6 +196,7 @@ updateWorkspaceInfo' :: Bool -> (Bool -> IDEAction) -> IDEAction updateWorkspaceInfo' rebuild continuation = do+ postAsyncIDE $ ideMessage Normal "Now updating workspace metadata ..." mbWorkspace <- readIDE workspace systemInfo' <- getSystemInfo case mbWorkspace of@@ -245,6 +248,7 @@ GenScopeC(addOtherToScope scope2 False))}) _ -> modifyIDE_ (\ide -> ide{packageInfo = Nothing}) continuation True+ postAsyncIDE $ ideMessage Normal "Finished updating workspace metadata" updatePackageInfos :: Bool -> [IDEPackage] -> (Bool -> [PackageDescr] -> IDEAction) -> IDEAction updatePackageInfos rebuild packs conts = updatePackageInfos' [] rebuild packs conts@@ -809,7 +813,12 @@ Nothing (Just (BS.pack " Haskell language extension")) ExtensionDescr- True) knownExtensions+ True)+#if MIN_VERSION_Cabal(1,16,0)+ ([minBound..maxBound]::[KnownExtension])+#else+ knownExtensions+#endif moduleNameDescrs :: PackageDescr -> [Descr] moduleNameDescrs pd = map (\md -> Real $ RealDescr
@@ -22,12 +22,12 @@ treeSelectionSelectionChanged, treeViewGetSelection, rowActivated, treeViewSetCursor, treeViewGetCursor, treeModelIterNChildren, treeViewGetModel, treeViewRowActivated, treeViewGetColumn,- widgetShowAll, windowWindowPosition, widgetDestroy, widgetHideAll,+ widgetShowAll, windowWindowPosition, widgetDestroy, widgetHide, listStoreGetValue, keyReleaseEvent, treeViewHeadersVisible, cellText, cellLayoutSetAttributes, treeViewColumnPackStart, cellRendererTextNew, treeViewAppendColumn, treeViewColumnNew, treeViewSetModel, listStoreNew, treeViewNew,- containerAdd, windowResizable, windowSetTransientFor,+ containerAdd, windowResizable, windowTransientFor, windowNewPopup, TreeViewClass, WindowPosition(..), signalDisconnect, AttrOp(..), set, EventM, EKey, eventKeyName, windowGetSize, windowTypeHint, WindowTypeHint(..), windowDecorated,@@ -96,14 +96,14 @@ recentPanes' <- recentSourceBuffers (tree', store') <- reifyIDE $ \ideR -> do window <- windowNewPopup- windowSetTransientFor window mainWindow (_, height) <- windowGetSize mainWindow set window [ windowTypeHint := WindowTypeHintUtility, windowDecorated := False, windowResizable := True, windowDefaultWidth := 200,- windowDefaultHeight := height]+ windowDefaultHeight := height,+ windowTransientFor := mainWindow] scrolledWindow <- scrolledWindowNew Nothing Nothing containerAdd window scrolledWindow@@ -136,7 +136,7 @@ modifyIDE_ $ \ide -> ide{ recentPanes = paneName pane : filter (/= paneName pane) (recentPanes ide)} Nothing -> return ()) ideR- widgetHideAll window+ widgetHide window widgetDestroy window reflectIDE (modifyIDE_ (\ide -> ide{currentState = IsRunning})) ideR
@@ -1,5 +1,5 @@-{-# LANGUAGE CPP, ForeignFunctionInterface #-}-{-# OPTIONS_GHC -XScopedTypeVariables #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Package@@ -21,6 +21,7 @@ , buildPackage , packageDoc+, packageDoc' , packageClean , packageClean' , packageCopy@@ -75,10 +76,10 @@ import Prelude hiding (catch) import Data.Maybe (isNothing, isJust, fromJust) import Control.Exception (SomeException(..), catch)-import Paths_leksah import IDE.Core.State import IDE.Utils.GUIUtils+import IDE.Pane.Log import IDE.Pane.PackageEditor import IDE.Pane.SourceBuffer import IDE.Pane.PackageFlags (readFlags)@@ -94,10 +95,12 @@ import qualified Data.Map as Map (empty, fromList) import System.Exit (ExitCode(..)) import Control.Applicative ((<$>))-import IDE.Utils.Tool (executeGhciCommand, getProcessExitCode, interruptProcessGroupOf)-import qualified Data.Enumerator as E (run_, Iteratee(..), last)-import qualified Data.Enumerator.List as EL (foldM, zip3, zip)-import Data.Enumerator (($$))+import IDE.Utils.Tool (executeGhciCommand, getProcessExitCode, interruptProcessGroupOf,+ ProcessHandle)+import qualified Data.Conduit as C (Sink)+import qualified Data.Conduit.List as CL (foldM, fold)+import qualified Data.Conduit.Util as CU (zipSinks)+import Data.Conduit (($$)) import Control.Monad.Trans.Reader (ask) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Trans.Class (lift)@@ -107,7 +110,17 @@ (writeGenericPackageDescription) #endif import Debug.Trace (trace)+import IDE.Pane.WebKit.Documentation+ (getDocumentation, loadDoc, reloadDoc)+import Text.Printf (printf)+import System.Log.Logger (debugM)+import System.Process.Vado (getMountPoint, vado, readSettings)+import qualified Data.Text as T (pack, isInfixOf)+import IDE.Utils.ExternalTool (runExternalTool', runExternalTool, isRunning, interruptBuild) +-- | Get the last item+sinkLast = CL.fold (\_ a -> Just a) Nothing+ moduleInfo :: (a -> BuildInfo) -> (a -> [ModuleName]) -> a -> [(ModuleName, BuildInfo)] moduleInfo bi mods a = map (\m -> (m, buildInfo)) $ mods a where buildInfo = bi a@@ -121,33 +134,14 @@ myLibModules pd = moduleInfo libModules libBuildInfo pd myExeModules pd = moduleInfo exeModules buildInfo pd #endif---packageOpen :: IDEAction-packageOpen = packageOpenThis Nothing--packageOpenThis :: Maybe FilePath -> IDEAction-packageOpenThis mbFilePath = do- active <- readIDE activePack- case active of- Just p -> deactivatePackage- Nothing -> return ()- selectActivePackage mbFilePath- return ()--selectActivePackage :: Maybe FilePath -> IDEM (Maybe IDEPackage)-selectActivePackage mbFilePath' = do- window <- getMainWindow- mbFilePath <- case mbFilePath' of- Nothing -> liftIO $ choosePackageFile window Nothing- Just fp -> return (Just fp)- case mbFilePath of- Nothing -> return Nothing- Just filePath -> idePackageFromPath filePath >>= (\ p -> activatePackage p >> return p)+#if MIN_VERSION_Cabal(1,10,0)+myTestModules pd = concatMap (moduleInfo testBuildInfo (otherModules . testBuildInfo)) (testSuites pd)+#endif -activatePackage :: Maybe IDEPackage -> IDEM ()-activatePackage mbPack@(Just pack) = do- modifyIDE_ (\ide -> ide{activePack = mbPack})+activatePackage :: Maybe (IDEPackage, Maybe String) -> IDEM ()+activatePackage (Just (pack, mbExe)) = do+ liftIO $ debugM "leksah" "activatePackage"+ modifyIDE_ (\ide -> ide{activePack = Just pack, activeExe = mbExe}) liftIO $ setCurrentDirectory (dropFileName (ipdCabalFile pack)) triggerEventIDE (Sensitivity [(SensitivityProjectActive,True)]) mbWs <- readIDE workspace@@ -161,8 +155,9 @@ deactivatePackage :: IDEAction deactivatePackage = do+ liftIO $ debugM "leksah" "deactivatePackage" oldActivePack <- readIDE activePack- modifyIDE_ (\ide -> ide{activePack = Nothing})+ modifyIDE_ (\ide -> ide{activePack = Nothing, activeExe = Nothing}) when (isJust oldActivePack) $ do triggerEventIDE (Sensitivity [(SensitivityProjectActive,False)]) return ()@@ -181,20 +176,26 @@ packageConfig' :: IDEPackage -> (Bool -> IDEAction) -> IDEAction packageConfig' package continuation = do+ prefs <- readIDE prefs let dir = dropFileName (ipdCabalFile package)- runExternalTool "Configuring" "cabal" (["configure"]- ++ (ipdConfigFlags package)) (Just dir) $ do- (mbLastOutput, _) <- EL.zip E.last logOutput+ logLaunch <- getDefaultLogLaunch+ showDefaultLogLaunch'++ runExternalTool' (__ "Configuring")+ (cabalCommand prefs)+ (["configure"] ++ (ipdConfigFlags package))+ dir $ do+ (mbLastOutput, _) <- CU.zipSinks sinkLast (logOutput logLaunch) lift $ do mbPack <- idePackageFromPath (ipdCabalFile package) case mbPack of Just pack -> do changePackage pack- triggerEventIDE (WorkspaceChanged False True)+ triggerEventIDE $ WorkspaceChanged False True continuation (mbLastOutput == Just (ToolExit ExitSuccess)) return () Nothing -> do- ideMessage Normal "Can't read package file"+ postAsyncIDE $ ideMessage Normal (__ "Can't read package file") continuation False return() @@ -207,8 +208,8 @@ then ["--with-ld=false"] else [] ++ ipdBuildFlags package)- runExternalTool "Building" "cabal" args (Just dir) $ do- (mbLastOutput, isConfigErr, _) <- EL.zip3 E.last isConfigError $+ runExternalTool' (__ "Building") (cabalCommand prefs) args dir $ do+ (mbLastOutput, (isConfigErr, _)) <- CU.zipSinks sinkLast $ CU.zipSinks isConfigError $ logOutputForBuild package backgroundBuild jumpToWarnings lift $ do errs <- readIDE errorRefs@@ -220,14 +221,14 @@ continuation (mbLastOutput == Just (ToolExit ExitSuccess)) return () -isConfigError :: Monad m => E.Iteratee ToolOutput m Bool-isConfigError = EL.foldM (\a b -> return $ a || isCErr b) False+isConfigError :: Monad m => C.Sink ToolOutput m Bool+isConfigError = CL.foldM (\a b -> return $ a || isCErr b) False where- isCErr (ToolError str) = str1 `isInfixOf` str || str2 `isInfixOf` str || str3 `isInfixOf` str+ isCErr (ToolError str) = str1 `T.isInfixOf` str || str2 `T.isInfixOf` str || str3 `T.isInfixOf` str isCErr _ = False- str1 = "Run the 'configure' command first"- str2 = "please re-configure"- str3 = "cannot satisfy -package-id"+ str1 = T.pack (__ "Run the 'configure' command first")+ str2 = T.pack (__ "please re-configure")+ str3 = T.pack (__ "cannot satisfy -package-id") buildPackage :: Bool -> Bool -> Bool -> IDEPackage -> (Bool -> IDEAction) -> IDEAction buildPackage backgroundBuild jumpToWarnings withoutLinking package continuation = catchIDE (do@@ -255,17 +256,31 @@ when ready $ do let dir = dropFileName (ipdCabalFile package) when (saveAllBeforeBuild prefs) (do fileSaveAll belongsToWorkspace; return ())- runDebug (executeDebugCommand ":reload" (logOutputForBuild package backgroundBuild jumpToWarnings)) debug+ (`runDebug` debug) . executeDebugCommand ":reload" $ do+ errs <- logOutputForBuild package backgroundBuild jumpToWarnings+ unless (any isError $ errs) $ do+ cmd <- lift $ readIDE autoCommand+ liftIO . postGUISync $ reflectIDE cmd ideR+ lift $ continuation True ) (\(e :: SomeException) -> sysMessage Normal (show e)) packageDoc :: PackageAction packageDoc = do package <- ask- lift $ catchIDE (do+ lift $ packageDoc' False True package (\ _ -> return ())++packageDoc' :: Bool -> Bool -> IDEPackage -> (Bool -> IDEAction) -> IDEAction+packageDoc' backgroundBuild jumpToWarnings package continuation = do+ prefs <- readIDE prefs+ catchIDE (do let dir = dropFileName (ipdCabalFile package)- runExternalTool "Documenting" "cabal" (["haddock"]- ++ (ipdHaddockFlags package)) (Just dir) logOutput)+ runExternalTool' (__ "Documenting") (cabalCommand prefs) (["haddock"]+ ++ (ipdHaddockFlags package)) dir $ do+ (mbLastOutput, _) <- CU.zipSinks sinkLast $+ logOutputForBuild package backgroundBuild jumpToWarnings+ lift $ reloadDoc+ lift $ continuation (mbLastOutput == Just (ToolExit ExitSuccess))) (\(e :: SomeException) -> putStrLn (show e)) packageClean :: PackageAction@@ -275,42 +290,67 @@ packageClean' :: IDEPackage -> (Bool -> IDEAction) -> IDEAction packageClean' package continuation = do+ prefs <- readIDE prefs+ logLaunch <- getDefaultLogLaunch+ showDefaultLogLaunch'+ let dir = dropFileName (ipdCabalFile package)- runExternalTool "Cleaning" "cabal" ["clean"] (Just dir) $ do- (mbLastOutput, _) <- EL.zip E.last logOutput+ runExternalTool' (__ "Cleaning")+ (cabalCommand prefs)+ ["clean"]+ dir $ do+ (mbLastOutput, _) <- CU.zipSinks sinkLast (logOutput logLaunch) lift $ continuation (mbLastOutput == Just (ToolExit ExitSuccess)) packageCopy :: PackageAction packageCopy = do package <- ask+ logLaunch <- lift $ getDefaultLogLaunch+ lift $ showDefaultLogLaunch'+ lift $ catchIDE (do+ prefs <- readIDE prefs window <- getMainWindow- mbDir <- liftIO $ chooseDir window "Select the target directory" Nothing+ mbDir <- liftIO $ chooseDir window (__ "Select the target directory") Nothing case mbDir of Nothing -> return () Just fp -> do let dir = dropFileName (ipdCabalFile package)- runExternalTool "Copying" "cabal" (["copy"]- ++ ["--destdir=" ++ fp]) (Just dir) logOutput)+ runExternalTool' (__ "Copying")+ (cabalCommand prefs)+ (["copy"] ++ ["--destdir=" ++ fp])+ dir+ (logOutput logLaunch)) (\(e :: SomeException) -> putStrLn (show e)) packageInstallDependencies :: PackageAction packageInstallDependencies = do package <- ask+ logLaunch <- lift $ getDefaultLogLaunch+ lift $ showDefaultLogLaunch'+ lift $ catchIDE (do+ prefs <- readIDE prefs let dir = dropFileName (ipdCabalFile package)- runExternalTool "Installing" "cabal" (["install","--only-dependencies"]+ runExternalTool' (__ "Installing") (cabalCommand prefs) (+ (if useCabalDev prefs+ then ["install-deps"]+ else ["install","--only-dependencies"]) ++ (ipdConfigFlags package)- ++ (ipdInstallFlags package)) (Just dir) logOutput)+ ++ (ipdInstallFlags package)) dir (logOutput logLaunch)) (\(e :: SomeException) -> putStrLn (show e)) packageCopy' :: IDEPackage -> (Bool -> IDEAction) -> IDEAction packageCopy' package continuation = do+ prefs <- readIDE prefs+ logLaunch <- getDefaultLogLaunch+ showDefaultLogLaunch'+ catchIDE (do let dir = dropFileName (ipdCabalFile package)- runExternalTool "Copying" "cabal" (["copy"]- ++ (ipdInstallFlags package)) (Just dir) $ do- (mbLastOutput, _) <- EL.zip E.last logOutput+ runExternalTool' (__ "Copying") (cabalCommand prefs) (["copy"]+ ++ (ipdInstallFlags package)) dir $ do+ (mbLastOutput, _) <- CU.zipSinks sinkLast (logOutput logLaunch) lift $ continuation (mbLastOutput == Just (ToolExit ExitSuccess))) (\(e :: SomeException) -> putStrLn (show e)) @@ -321,27 +361,43 @@ ideR <- ask maybeDebug <- readIDE debugState pd <- liftIO $ readPackageDescription normal (ipdCabalFile package) >>= return . flattenPackageDescription+ mbExe <- readIDE activeExe+ let exes = filter (isActiveExe mbExe) $ executables pd case maybeDebug of Nothing -> do- case executables pd of+ case exes of (Executable name _ _):_ -> do+ (logLaunch,logName) <- buildLogLaunchByName name let path = "dist/build" </> name </> name let dir = dropFileName (ipdCabalFile package)- runExternalTool ("Running " ++ name) path (ipdExeFlags package) (Just dir) logOutput+ IDE.Package.runPackage (addLogLaunchData logName logLaunch)+ (printf (__ "Running %s") name)+ path+ (ipdExeFlags package)+ dir+ (logOutput logLaunch)++ otherwise -> do- sysMessage Normal "no executable in selected package"+ sysMessage Normal (__ "no executable in selected package") return () Just debug -> do -- TODO check debug package matches active package- case executables pd of- (Executable _ mainFilePath _):_ -> do+ case exes of+ (Executable name mainFilePath _):_ -> do+ (logLaunch,logName) <- buildLogLaunchByName name runDebug (do- executeDebugCommand (":module *" ++ (map (\c -> if c == '/' then '.' else c) (takeWhile (/= '.') mainFilePath))) logOutput- executeDebugCommand (":main " ++ (unwords (ipdExeFlags package))) logOutput) debug+ executeDebugCommand (":module *" ++ (map (\c -> if c == '/' then '.' else c) (takeWhile (/= '.') mainFilePath))) (logOutput logLaunch)+ executeDebugCommand (":main " ++ (unwords (ipdExeFlags package))) (logOutput logLaunch))+ debug otherwise -> do- sysMessage Normal "no executable in selected package"+ sysMessage Normal (__ "no executable in selected package") return ()) (\(e :: SomeException) -> putStrLn (show e))+ where+ isActiveExe Nothing _ = True+ isActiveExe (Just selected) (Executable name _ _) = selected == name+ isActiveExe _ _ = False packageRegister :: PackageAction packageRegister = do@@ -351,11 +407,15 @@ packageRegister' :: IDEPackage -> (Bool -> IDEAction) -> IDEAction packageRegister' package continuation = if ipdHasLibs package- then catchIDE (do+ then do+ logLaunch <- getDefaultLogLaunch+ showDefaultLogLaunch'+ catchIDE (do+ prefs <- readIDE prefs let dir = dropFileName (ipdCabalFile package)- runExternalTool "Registering" "cabal" (["register"]- ++ (ipdRegisterFlags package)) (Just dir) $ do- (mbLastOutput, _) <- EL.zip E.last logOutput+ runExternalTool' (__ "Registering") (cabalCommand prefs) (["register"]+ ++ (ipdRegisterFlags package)) dir $ do+ (mbLastOutput, _) <- CU.zipSinks sinkLast (logOutput logLaunch) lift $ continuation (mbLastOutput == Just (ToolExit ExitSuccess))) (\(e :: SomeException) -> putStrLn (show e)) else continuation True@@ -368,11 +428,15 @@ packageTest' :: IDEPackage -> (Bool -> IDEAction) -> IDEAction packageTest' package continuation = if "--enable-tests" `elem` ipdConfigFlags package- then catchIDE (do+ then do+ logLaunch <- getDefaultLogLaunch+ showDefaultLogLaunch'+ catchIDE (do+ prefs <- readIDE prefs let dir = dropFileName (ipdCabalFile package)- runExternalTool "Testing" "cabal" (["test"]- ++ (ipdTestFlags package)) (Just dir) $ do- (mbLastOutput, _) <- EL.zip E.last logOutput+ runExternalTool' (__ "Testing") (cabalCommand prefs) (["test"]+ ++ (ipdTestFlags package)) dir $ do+ (mbLastOutput, _) <- CU.zipSinks sinkLast (logOutput logLaunch) lift $ continuation (mbLastOutput == Just (ToolExit ExitSuccess))) (\(e :: SomeException) -> putStrLn (show e)) else continuation True@@ -380,59 +444,50 @@ packageSdist :: PackageAction packageSdist = do package <- ask+ logLaunch <- lift $ getDefaultLogLaunch+ lift $ showDefaultLogLaunch'+ lift $ catchIDE (do+ prefs <- readIDE prefs let dir = dropFileName (ipdCabalFile package)- runExternalTool "Source Dist" "cabal" (["sdist"]- ++ (ipdSdistFlags package)) (Just dir) logOutput)+ runExternalTool' (__ "Source Dist") (cabalCommand prefs) (["sdist"]+ ++ (ipdSdistFlags package)) dir (logOutput logLaunch)) (\(e :: SomeException) -> putStrLn (show e)) packageOpenDoc :: PackageAction packageOpenDoc = do package <- ask- lift $ catchIDE (do+ logLaunch <- lift $ getDefaultLogLaunch+ lift $ showDefaultLogLaunch'++ lift $ do prefs <- readIDE prefs let path = dropFileName (ipdCabalFile package) </> "dist/doc/html" </> display (pkgName (ipdPackageId package)) </> "index.html" dir = dropFileName (ipdCabalFile package)- runExternalTool "Opening Documentation" (browser prefs) [path] (Just dir) logOutput)+#ifdef WEBKITGTK+ loadDoc ("file:///" ++ dir </> path)+ getDocumentation Nothing >>= \ p -> displayPane p False+#else+ openBrowser path+#endif+ `catchIDE` (\(e :: SomeException) -> putStrLn (show e)) -runExternalTool :: String -> FilePath -> [String] -> Maybe FilePath -> E.Iteratee ToolOutput IDEM () -> IDEAction-runExternalTool description executable args mbDir handleOutput = do- prefs <- readIDE prefs- alreadyRunning <- isRunning- unless alreadyRunning $ do- when (saveAllBeforeBuild prefs) (do fileSaveAll belongsToWorkspace; return ())- triggerEventIDE (StatusbarChanged [CompartmentState description, CompartmentBuild True])- reifyIDE $ \ideR -> forkIO $ do- (output, pid) <- runTool executable args mbDir- reflectIDE (modifyIDE_ (\ide -> ide{runningTool = Just pid})) ideR- E.run_ $ output $$ (reflectIDEI handleOutput ideR)- return () +runPackage :: (ProcessHandle -> IDEAction)+ -> String+ -> FilePath+ -> [String]+ -> FilePath+ -> C.Sink ToolOutput IDEM ()+ -> IDEAction+runPackage = runExternalTool (return True) -- TODO here one could check if package to be run is building/configuring/etc atm --- ------------------------------------------------------------------------ | Handling of Compiler errors----isRunning :: IDEM Bool-isRunning = do- maybeProcess <- readIDE runningTool- liftIO $ do- case maybeProcess of- Just process -> do- isNothing <$> getProcessExitCode process- Nothing -> return False -interruptBuild :: IDEAction-interruptBuild = do- maybeProcess <- readIDE runningTool- liftIO $ case maybeProcess of- Just h -> interruptProcessGroupOf h- _ -> return ()- -- --------------------------------------------------------------------- -- | * Utility functions/procedures, that have to do with packages --@@ -442,7 +497,7 @@ active <- readIDE activePack case active of Nothing -> do- ideMessage Normal "No active package"+ ideMessage Normal (__ "No active package") return Nothing Just p -> do ideR <- ask@@ -450,7 +505,7 @@ pd <- readPackageDescription normal (ipdCabalFile p) return (Just (flattenPackageDescription pd,ipdCabalFile p))) (\(e :: SomeException) -> do- reflectIDE (ideMessage Normal ("Can't load package " ++(show e))) ideR+ reflectIDE (ideMessage Normal ((__ "Can't load package ") ++(show e))) ideR return Nothing)) getEmptyModuleTemplate :: PackageDescription -> String -> IO String@@ -470,7 +525,7 @@ , ("@ModuleName@" , modName) , ("@ModuleExports@", exports) , ("@ModuleBody@" , body)]))- (\ (e :: SomeException) -> sysMessage Normal ("Couldn't read template file: " ++ show e) >> return "")+ (\ (e :: SomeException) -> sysMessage Normal (printf (__ "Couldn't read template file: %s") (show e)) >> return "") #if MIN_VERSION_Cabal(1,10,0) addModuleToPackageDescr :: ModuleName -> Bool -> PackageAction@@ -493,7 +548,7 @@ (condExecutables gpd)} writeGenericPackageDescription (ipdCabalFile p) npd) (\(e :: SomeException) -> do- reflectIDE (ideMessage Normal ("Can't update package " ++ show e)) ideR+ reflectIDE (ideMessage Normal ((__ "Can't update package ") ++ show e)) ideR return ())) addModToLib :: ModuleName -> CondTree ConfVar [Dependency] Library ->@@ -535,7 +590,7 @@ (condExecutables gpd)} writeGenericPackageDescription (ipdCabalFile p) npd) (\(e :: SomeException) -> do- reflectIDE (ideMessage Normal ("Can't update package " ++ show e)) ideR+ reflectIDE (ideMessage Normal ((__ "Can't update package ") ++ show e)) ideR return ())) delModFromLib :: ModuleName -> CondTree ConfVar [Dependency] Library ->@@ -569,7 +624,7 @@ if hasConfigs gpd then do reflectIDE (ideMessage High- "Cabal file with configurations can't be automatically updated with the current version of Leksah") ideR+ (__ "Cabal file with configurations can't be automatically updated with the current version of Leksah")) ideR else let pd = flattenPackageDescription gpd npd = if isExposed && isJust (library pd)@@ -584,7 +639,7 @@ (executables npd1)} in writePackageDescription (ipdCabalFile p) npd) (\(e :: SomeException) -> do- reflectIDE (ideMessage Normal ("Can't upade package " ++ show e)) ideR+ reflectIDE (ideMessage Normal ((__ "Can't upade package ") ++ show e)) ideR return ())) where addModToBuildInfo :: BuildInfo -> ModuleName -> BuildInfo@@ -599,7 +654,7 @@ if hasConfigs gpd then do reflectIDE (ideMessage High- "Cabal file with configurations can't be automatically updated with the current version of Leksah") ideR+ (__ "Cabal file with configurations can't be automatically updated with the current version of Leksah")) ideR else let pd = flattenPackageDescription gpd isExposedAndJust = isExposedModule pd moduleName@@ -615,7 +670,7 @@ (executables npd1)} in writePackageDescription (ipdCabalFile p) npd) (\(e :: SomeException) -> do- reflectIDE (ideMessage Normal ("Can't update package " ++ show e)) ideR+ reflectIDE (ideMessage Normal ((__ "Can't update package ") ++ show e)) ideR return ())) where delModFromBuildInfo :: BuildInfo -> ModuleName -> BuildInfo@@ -679,17 +734,19 @@ maybeDebug <- readIDE debugState case maybeDebug of Nothing -> do- ghci <- reifyIDE $ \ideR -> newGhci (ipdBuildFlags package) (interactiveFlags prefs')- $ reflectIDEI (logOutputForBuild package True False) ideR+ let dir = dropFileName (ipdCabalFile package)+ mbExe <- readIDE activeExe+ ghci <- reifyIDE $ \ideR -> newGhci dir mbExe (interactiveFlags prefs')+ $ reflectIDEI (logOutputForBuild package True False >> return ()) ideR modifyIDE_ (\ide -> ide {debugState = Just (package, ghci)}) triggerEventIDE (Sensitivity [(SensitivityInterpreting, True)]) setDebugToggled True -- Fork a thread to wait for the output from the process to close liftIO $ forkIO $ do readMVar (outputClosed ghci)- postGUISync $ reflectIDE (do+ postGUISync . (`reflectIDE` ideRef) $ do setDebugToggled False- modifyIDE_ (\ide -> ide {debugState = Nothing})+ modifyIDE_ (\ide -> ide {debugState = Nothing, autoCommand = return ()}) triggerEventIDE (Sensitivity [(SensitivityInterpreting, False)]) -- Kick of a build if one is not already due modifiedPacks <- fileCheckAll belongsToPackage@@ -701,11 +758,11 @@ -- Lets build to make sure the binaries are up to date mbPackage <- readIDE activePack case mbPackage of- Just package -> runCabalBuild True False True package True (\ _ -> return ())- Nothing -> return ()) ideRef+ Just package -> runCabalBuild True False False package True (\ _ -> return ())+ Nothing -> return () return () _ -> do- sysMessage Normal "Debugger already running"+ sysMessage Normal (__ "Debugger already running") return ()) (\(e :: SomeException) -> putStrLn (show e)) @@ -720,8 +777,8 @@ window <- lift $ getMainWindow resp <- liftIO $ do md <- messageDialogNew (Just window) [] MessageQuestion ButtonsCancel- "GHCi debugger is not running."- dialogAddButton md "_Start GHCi" (ResponseUser 1)+ (__ "GHCi debugger is not running.")+ dialogAddButton md (__ "_Start GHCi") (ResponseUser 1) dialogSetDefaultResponse md (ResponseUser 1) set md [ windowWindowPosition := WinPosCenterOnParent ] resp <- dialogRun md@@ -746,15 +803,19 @@ _ -> do return () -executeDebugCommand :: String -> (E.Iteratee ToolOutput IDEM ()) -> DebugAction+executeDebugCommand :: String -> (C.Sink ToolOutput IDEM ()) -> DebugAction executeDebugCommand command handler = do (_, ghci) <- ask lift $ do- triggerEventIDE (StatusbarChanged [CompartmentState command, CompartmentBuild True]) reifyIDE $ \ideR -> do+ liftIO $ postGUIAsync $ reflectIDE (do+ triggerEventIDE (StatusbarChanged [CompartmentState command, CompartmentBuild True])+ return ()) ideR executeGhciCommand ghci command $ do reflectIDEI handler ideR- liftIO $ postGUISync $ reflectIDE (triggerEventIDE (StatusbarChanged [CompartmentState "", CompartmentBuild False])) ideR+ liftIO $ postGUIAsync $ reflectIDE (do+ triggerEventIDE (StatusbarChanged [CompartmentState "", CompartmentBuild False])+ return ()) ideR return () allBuildInfo' :: PackageDescription -> [BuildInfo]@@ -762,6 +823,8 @@ allBuildInfo' pkg_descr = [ libBuildInfo lib | Just lib <- [library pkg_descr] ] ++ [ buildInfo exe | exe <- executables pkg_descr ] ++ [ testBuildInfo tst | tst <- testSuites pkg_descr ]+testMainPath (TestSuiteExeV10 _ f) = [f]+testMainPath _ = [] #else allBuildInfo' = allBuildInfo #endif@@ -772,12 +835,15 @@ pd <- readPackageDescription normal filePath return (Just (flattenPackageDescription pd))) (\ (e :: SomeException) -> do- reflectIDE (ideMessage Normal ("Can't activate package " ++(show e))) ideR+ reflectIDE (ideMessage Normal ((__ "Can't activate package ") ++(show e))) ideR return Nothing)) case mbPackageD of Nothing -> return Nothing Just packageD -> do let modules = Map.fromList $ myLibModules packageD ++ myExeModules packageD+#if MIN_VERSION_Cabal(1,10,0)+ ++ myTestModules packageD+#endif let mainFiles = [ (modulePath exe, buildInfo exe, False) | exe <- executables packageD ] #if MIN_VERSION_Cabal(1,10,0) ++ [ (f, bi, True) | TestSuite _ (TestSuiteExeV10 _ f) bi _ <- testSuites packageD ]@@ -786,6 +852,8 @@ let srcDirs = case (nub $ concatMap hsSourceDirs (allBuildInfo' packageD)) of [] -> [".","src"] l -> l+ let exes = [ exeName e | e <- executables packageD+ , buildable (buildInfo e) ] #if MIN_VERSION_Cabal(1,10,0) let exts = nub $ concatMap oldExtensions (allBuildInfo' packageD) let tests = [ testName t | t <- testSuites packageD@@ -801,6 +869,7 @@ ipdDepends = buildDepends packageD, ipdModules = modules, ipdHasLibs = hasLibs packageD,+ ipdExes = exes, ipdTests = tests, ipdMain = mainFiles, ipdExtraSrcs = files,
@@ -17,6 +17,7 @@ module IDE.Pane.Breakpoints ( IDEBreakpoints , BreakpointsState+, showBreakpoints , fillBreakpointList , selectBreak ) where@@ -34,6 +35,8 @@ import IDE.LogRef (showSourceSpan) import Data.List (elemIndex) import Control.Monad.IO.Class (MonadIO(..))+import IDE.Utils.GUIUtils (treeViewContextMenu, __)+import qualified Data.Text as T (unpack) -- | A breakpoints pane description@@ -50,7 +53,7 @@ instance Pane IDEBreakpoints IDEM where- primPaneName _ = "Breakpoints"+ primPaneName _ = (__ "Breakpoints") getAddedIndex _ = 0 getTopWidget = castToWidget . scrolledView paneId b = "*Breakpoints"@@ -68,7 +71,7 @@ rendererA <- cellRendererTextNew colA <- treeViewColumnNew- treeViewColumnSetTitle colA "Location"+ treeViewColumnSetTitle colA (__ "Location") treeViewColumnSetSizing colA TreeViewColumnAutosize treeViewColumnSetResizable colA True treeViewColumnSetReorderable colA True@@ -79,14 +82,14 @@ rendererB <- cellRendererTextNew colB <- treeViewColumnNew- treeViewColumnSetTitle colB "Breakpoints"+ treeViewColumnSetTitle colB (__ "Breakpoints") treeViewColumnSetSizing colB TreeViewColumnAutosize treeViewColumnSetResizable colB True treeViewColumnSetReorderable colB True treeViewAppendColumn treeView colB cellLayoutPackStart colB rendererB False cellLayoutSetAttributes colB rendererB breakpoints- $ \row -> [ cellText := refDescription row]+ $ \row -> [ cellText := T.unpack $ refDescription row] treeViewSetHeadersVisible treeView True selB <- treeViewGetSelection treeView@@ -95,11 +98,21 @@ containerAdd scrolledView treeView scrolledWindowSetPolicy scrolledView PolicyAutomatic PolicyAutomatic let pane = IDEBreakpoints scrolledView treeView breakpoints- treeView `onButtonPress` (breakpointViewPopup ideR breakpoints treeView)- cid1 <- treeView `afterFocusIn`- (\_ -> do reflectIDE (makeActive pane) ideR ; return True)- return (Just pane,[ConnectC cid1])+ cid1 <- after treeView focusInEvent $ do+ liftIO $ reflectIDE (makeActive pane) ideR+ return True+ (cid2, cid3) <- treeViewContextMenu treeView $ breakpointsContextMenu ideR breakpoints treeView+ cid4 <- treeView `on` rowActivated $ breakpointsSelect ideR breakpoints+ return (Just pane, map ConnectC [cid1, cid2, cid3, cid4]) +getBreakpoints :: IDEM IDEBreakpoints+getBreakpoints = forceGetPane (Right "*Breakpoints")++showBreakpoints :: IDEAction+showBreakpoints = do+ pane <- getBreakpoints+ displayPane pane False+ fillBreakpointList :: IDEAction fillBreakpointList = do mbBreakpoints <- getPane@@ -136,47 +149,42 @@ Nothing -> return () Just ind -> treeSelectionSelectPath selection [ind] -breakpointViewPopup :: IDERef- -> TreeStore LogRef- -> TreeView- -> Event- -> IO (Bool)-breakpointViewPopup ideR store treeView (Button _ click _ _ _ _ button _ _)- = do- if button == RightButton- then do- theMenu <- menuNew- item1 <- menuItemNewWithLabel "Remove breakpoint"- item1 `onActivateLeaf` do- sel <- getSelectedBreakpoint treeView store- case sel of- Just ref -> reflectIDE (deleteBreakpoint ref) ideR- otherwise -> sysMessage Normal "Debugger>> breakpointViewPopup: no selection2"- sep1 <- separatorMenuItemNew- item2 <- menuItemNewWithLabel "Remove all breakpoints"- item2 `onActivateLeaf` (reflectIDE debugDeleteAllBreakpoints ideR)- item3 <- menuItemNewWithLabel "Update"- item3 `onActivateLeaf` (reflectIDE debugShowBreakpoints ideR)- mapM_ (menuShellAppend theMenu) [castToMenuItem item1, castToMenuItem sep1,- castToMenuItem item2, castToMenuItem item3]- menuPopup theMenu Nothing- widgetShowAll theMenu- return True- else if button == LeftButton && click == DoubleClick- then do sel <- getSelectedBreakpoint treeView store- case sel of- Just ref -> reflectIDE (setCurrentBreak (Just ref)) ideR- otherwise -> sysMessage Normal "Debugger>> breakpointViewPopup: no selection2"- return True- else return False-breakpointViewPopup _ _ _ _ = throwIDE "breakpointViewPopup wrong event type"+breakpointsContextMenu :: IDERef+ -> TreeStore LogRef+ -> TreeView+ -> Menu+ -> IO ()+breakpointsContextMenu ideR store treeView theMenu = do+ item1 <- menuItemNewWithLabel (__ "Remove breakpoint")+ item1 `on` menuItemActivate $ do+ sel <- getSelectedBreakpoint treeView store+ case sel of+ Just ref -> reflectIDE (deleteBreakpoint ref) ideR+ otherwise -> sysMessage Normal (__ "Debugger>> breakpointViewPopup: no selection2")+ sep1 <- separatorMenuItemNew+ item2 <- menuItemNewWithLabel (__ "Remove all breakpoints")+ item2 `on` menuItemActivate $ reflectIDE debugDeleteAllBreakpoints ideR+ item3 <- menuItemNewWithLabel (__ "Update")+ item3 `on` menuItemActivate $ reflectIDE debugShowBreakpoints ideR+ mapM_ (menuShellAppend theMenu) [castToMenuItem item1, castToMenuItem sep1,+ castToMenuItem item2, castToMenuItem item3] +breakpointsSelect :: IDERef+ -> TreeStore LogRef+ -> TreePath+ -> TreeViewColumn+ -> IO ()+breakpointsSelect ideR store path _ = do+ ref <- treeStoreGetValue store path+ reflectIDE (setCurrentBreak (Just ref)) ideR++ deleteBreakpoint :: LogRef -> IDEAction deleteBreakpoint logRef = case logRefType logRef of- BreakpointRef -> debugDeleteBreakpoint ((words (refDescription logRef)) !! 1) logRef- _ -> sysMessage Normal "Debugger>>deleteBreakpoint: Not a breakpoint"+ BreakpointRef -> debugDeleteBreakpoint ((words (T.unpack $ refDescription logRef)) !! 1) logRef+ _ -> sysMessage Normal (__ "Debugger>>deleteBreakpoint: Not a breakpoint")
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleInstances, RecordWildCards, TypeSynonymInstances,- MultiParamTypeClasses, DeriveDataTypeable #-}+ MultiParamTypeClasses, DeriveDataTypeable, OverloadedStrings #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Pane.Errors@@ -29,11 +29,15 @@ (Click(..), MouseButton(..)) import Graphics.UI.Gtk.Gdk.Events (Event(..)) import IDE.ImportTool- (addPackage, parseHiddenModule, addImport, parseNotInScope,- resolveErrors)+ (addResolveMenuItems, resolveErrors) import Data.List (elemIndex) import IDE.LogRef (showSourceSpan) import Control.Monad.IO.Class (MonadIO(..))+import IDE.Utils.GUIUtils (treeViewContextMenu, __)+import Data.Maybe (isJust)+import Control.Monad (when)+import Data.Text (Text)+import qualified Data.Text as T (unpack) -- | A breakpoints pane description --@@ -43,14 +47,14 @@ , errorStore :: TreeStore ErrColumn } deriving Typeable -data ErrColumn = ErrColumn {logRef :: LogRef, string :: String, index :: Int}+data ErrColumn = ErrColumn {logRef :: LogRef, text :: Text, index :: Int} data ErrorsState = ErrorsState { } deriving(Eq,Ord,Read,Show,Typeable) instance Pane IDEErrors IDEM where- primPaneName _ = "Errors"+ primPaneName _ = (__ "Errors") getTopWidget = castToWidget . scrolledView paneId b = "*Errors" @@ -75,7 +79,7 @@ rendererA <- cellRendererTextNew colA <- treeViewColumnNew- treeViewColumnSetTitle colA "Location"+ treeViewColumnSetTitle colA (__ "Location") treeViewColumnSetSizing colA TreeViewColumnAutosize treeViewColumnSetResizable colA True treeViewColumnSetReorderable colA True@@ -88,14 +92,14 @@ else "red" ] rendererB <- cellRendererTextNew colB <- treeViewColumnNew- treeViewColumnSetTitle colB "Description"+ treeViewColumnSetTitle colB (__ "Description") treeViewColumnSetSizing colB TreeViewColumnAutosize treeViewColumnSetResizable colB True treeViewColumnSetReorderable colB True treeViewAppendColumn treeView colB cellLayoutPackStart colB rendererB False cellLayoutSetAttributes colB rendererB errorStore- $ \row -> [ cellText := string row]+ $ \row -> [ cellText := T.unpack $ text row] treeViewSetHeadersVisible treeView True selB <- treeViewGetSelection treeView@@ -104,10 +108,12 @@ containerAdd scrolledView treeView scrolledWindowSetPolicy scrolledView PolicyAutomatic PolicyAutomatic let pane = IDEErrors scrolledView treeView errorStore- treeView `onButtonPress` (errorViewPopup ideR errorStore treeView)- cid1 <- treeView `afterFocusIn`- (\_ -> do reflectIDE (makeActive pane) ideR ; return True)- return (Just pane,[ConnectC cid1])+ cid1 <- after treeView focusInEvent $ do+ liftIO $ reflectIDE (makeActive pane) ideR+ return True+ (cid2, cid3) <- treeViewContextMenu treeView $ errorsContextMenu ideR errorStore treeView+ cid4 <- treeView `on` rowActivated $ errorsSelect ideR errorStore+ return (Just pane, map ConnectC [cid1, cid2, cid3, cid4]) getErrors :: Maybe PanePath -> IDEM IDEErrors getErrors Nothing = forceGetPane (Right "*Errors")@@ -157,53 +163,29 @@ Nothing -> return () Just ind -> treeSelectionSelectPath selection [ind] -errorViewPopup :: IDERef- -> TreeStore ErrColumn- -> TreeView- -> Event- -> IO Bool-errorViewPopup ideR store treeView (Button _ click _ _ _ _ button _ _)- = do- if button == RightButton- then do- mbSel <- getSelectedError treeView store- theMenu <- menuNew- item0 <- menuItemNewWithLabel "Resolve Errors"- item0 `onActivateLeaf` do- reflectIDE resolveErrors ideR- menuShellAppend theMenu item0- case mbSel of- Just sel -> do- case parseNotInScope (refDescription sel) of- Nothing -> do- return ()- Just _ -> do- item1 <- menuItemNewWithLabel "Add Import"- item1 `onActivateLeaf` do- reflectIDE (addImport sel [] (\ _ -> return ())) ideR- menuShellAppend theMenu item1- case parseHiddenModule (refDescription sel) of- Nothing -> do- return ()- Just _ -> do- item1 <- menuItemNewWithLabel "Add Package"- item1 `onActivateLeaf` do- reflectIDE (addPackage sel >> return ()) ideR- menuShellAppend theMenu item1- Nothing -> return ()- menuPopup theMenu Nothing- widgetShowAll theMenu- return True- else if button == LeftButton && click == DoubleClick- then liftIO $ do- sel <- getSelectedError treeView store- case sel of- Just ref -> reflectIDE (setCurrentError (Just ref)) ideR- otherwise -> sysMessage Normal "Error>> errorViewPopup: no selection2"- return True- else return False-errorViewPopup _ _ _ _ = throwIDE "errorViewPopup wrong event type"+errorsContextMenu :: IDERef+ -> TreeStore ErrColumn+ -> TreeView+ -> Menu+ -> IO ()+errorsContextMenu ideR store treeView theMenu = do+ mbSel <- getSelectedError treeView store+ item0 <- menuItemNewWithLabel (__ "Resolve Errors")+ item0 `on` menuItemActivate $ do+ reflectIDE resolveErrors ideR+ menuShellAppend theMenu item0+ case mbSel of+ Just sel -> addResolveMenuItems ideR theMenu sel+ Nothing -> return () +errorsSelect :: IDERef+ -> TreeStore ErrColumn+ -> TreePath+ -> TreeViewColumn+ -> IO ()+errorsSelect ideR store path _ = do+ ref <- treeStoreGetValue store path+ reflectIDE (setCurrentError (Just (logRef ref))) ideR
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleInstances, DeriveDataTypeable, MultiParamTypeClasses,- TypeSynonymInstances, RecordWildCards #-}+ TypeSynonymInstances, RecordWildCards, ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Pane.Files@@ -21,12 +21,13 @@ , refreshFiles ) where +import Prelude hiding (catch) import Graphics.UI.Gtk- (onSelectionChanged, treeStoreRemove, treeModelIterNext,+ (treeSelectionSelectionChanged, treeStoreRemove, treeModelIterNext, treeModelGetRow, treeStoreInsert, treeModelIterNthChild, treeModelGetPath, TreeIter, treeModelGetIter, TreePath,- treeSelectionGetSelectedRows, onRowActivated, treeStoreGetValue,- onRowExpanded, afterFocusIn, scrolledWindowSetPolicy, containerAdd,+ treeSelectionGetSelectedRows, rowActivated, treeStoreGetValue,+ rowExpanded, on, after, focusInEvent, scrolledWindowSetPolicy, containerAdd, scrolledWindowNew, treeSelectionSetMode, treeViewGetSelection, treeViewSetHeadersVisible, cellText, cellLayoutSetAttributes, cellLayoutPackStart, treeViewAppendColumn,@@ -47,7 +48,7 @@ import Control.Applicative ((<$>)) import System.FilePath ((</>), takeFileName, dropFileName) import Distribution.Package (PackageIdentifier(..))-import System.Directory (doesDirectoryExist, getDirectoryContents)+import System.Directory (doesDirectoryExist, getDirectoryContents, getPermissions, readable) import IDE.Core.CTypes (Location(..), packageIdentifierToString) import Graphics.UI.Frame.Panes@@ -58,6 +59,8 @@ (PolicyType(..), SelectionMode(..), TreeViewColumnSizing(..)) import System.Glib.Attributes (AttrOp(..)) import Control.Monad.IO.Class (MonadIO(..))+import IDE.Utils.GUIUtils (__)+import Control.Exception (catch) data FileRecord = FileRecord FilePath@@ -85,7 +88,7 @@ instance Pane IDEFiles IDEM where- primPaneName _ = "Files"+ primPaneName _ = (__ "Files") getAddedIndex _ = 0 getTopWidget = castToWidget . scrolledView paneId b = "*Files"@@ -104,7 +107,7 @@ renderer1 <- cellRendererTextNew renderer10 <- cellRendererPixbufNew col1 <- treeViewColumnNew- treeViewColumnSetTitle col1 "File"+ treeViewColumnSetTitle col1 (__ "File") treeViewColumnSetSizing col1 TreeViewColumnAutosize treeViewColumnSetResizable col1 True treeViewColumnSetReorderable col1 True@@ -124,24 +127,25 @@ let files = IDEFiles {..} - cid1 <- treeView `afterFocusIn`- (\_ -> do reflectIDE (makeActive files) ideR ; return True)- cid2 <- treeView `onRowExpanded` \ iter path -> do+ cid1 <- after treeView focusInEvent $ do+ liftIO $ reflectIDE (makeActive files) ideR+ return True+ cid2 <- on treeView rowExpanded $ \ iter path -> do record <- treeStoreGetValue fileStore path reflectIDE (do case record of DirRecord f -> liftIO $ refreshDir fileStore path f PackageRecord _ f -> liftIO $ refreshDir fileStore path f- _ -> ideMessage Normal "Unexpected Expansion in Files Pane") ideR- treeView `onRowActivated` \ path col -> do+ _ -> ideMessage Normal (__ "Unexpected Expansion in Files Pane")) ideR+ on treeView rowActivated $ \ path col -> do record <- treeStoreGetValue fileStore path reflectIDE (do case record of FileRecord f -> (goToSourceDefinition f $ Just $ Location 1 0 1 0) >> return () DirRecord f -> liftIO $ refreshDir fileStore path f PackageRecord _ f -> liftIO $ refreshDir fileStore path f- _ -> ideMessage Normal "Unexpected Activation in Files Pane") ideR- sel `onSelectionChanged` do+ _ -> ideMessage Normal (__ "Unexpected Activation in Files Pane")) ideR+ on sel treeSelectionSelectionChanged $ do paths <- treeSelectionGetSelectedRows sel forM_ paths $ \ path -> do record <- treeStoreGetValue fileStore path@@ -150,7 +154,7 @@ FileRecord _ -> return () DirRecord f -> liftIO $ refreshDir fileStore path f PackageRecord _ f -> liftIO $ refreshDir fileStore path f- _ -> ideMessage Normal "Unexpected Selection in Files Pane") ideR+ _ -> ideMessage Normal (__ "Unexpected Selection in Files Pane")) ideR return (Just files,[ConnectC cid1]) @@ -183,14 +187,13 @@ refreshDir store path dir = do mbIter <- treeModelGetIter store path when (isJust mbIter) $ do- exists <- doesDirectoryExist dir- contents <- if exists- then filter ((/= '.').head) <$>- getDirectoryContents dir >>= mapM (\f -> do- let full = dir </> f- isDir <- doesDirectoryExist full- return $ if isDir then DirRecord full else FileRecord full)- else return []+ contents <- do+ filter ((/= '.').head) <$>+ getDirectoryContents dir >>= mapM (\f -> do+ let full = dir </> f+ isDir <- doesDirectoryExist full+ return $ if isDir then DirRecord full else FileRecord full)+ `catch` \ (e :: IOError) -> return [] setDirectories store mbIter contents setDirectories :: TreeStore FileRecord -> Maybe TreeIter -> [FileRecord] -> IO ()
@@ -1,5 +1,10 @@-{-# LANGUAGE CPP, FlexibleInstances, DeriveDataTypeable, MultiParamTypeClasses,- TypeSynonymInstances, RecordWildCards #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE CPP #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Pane.Grep@@ -28,6 +33,7 @@ import qualified Text.ParserCombinators.Parsec.Token as P import Data.Maybe import Data.Typeable+import Data.List (isPrefixOf) import IDE.Core.State import IDE.BufferMode import IDE.Utils.Tool (runTool, ToolOutput(..), getProcessExitCode, interruptProcessGroupOf)@@ -41,18 +47,22 @@ import Control.Applicative ((<$>)) import System.FilePath ((</>), dropFileName) import System.Exit (ExitCode(..))-import IDE.Pane.Log (getLog)+import IDE.Pane.Log (getLog, getDefaultLogLaunch) import Control.DeepSeq-import qualified Data.Enumerator as E- (Step(..), run_, Iteratee(..), run)-import qualified Data.Enumerator.List as EL- (foldM, head, dropWhile, isolate)-import Data.Enumerator (($$), (>>==))-import qualified Data.List as L ()+import qualified Data.Conduit as C+ (Sink)+import qualified Data.Conduit.List as CL+ (foldM, head, isolate, sinkNull)+import Data.Conduit (($$), (=$)) import Control.Monad (foldM, when) import Control.Monad.Trans.Reader (ask) import Control.Monad.Trans.Class (MonadTrans(..)) import Control.Monad.IO.Class (MonadIO(..))+import IDE.Utils.GUIUtils (__)+import System.Directory (getDirectoryContents)+import qualified Data.Text as T (unpack)+import System.Log.Logger (debugM)+import Control.Exception (SomeException, catch) data GrepRecord = GrepRecord { file :: FilePath@@ -80,7 +90,7 @@ instance Pane IDEGrep IDEM where- primPaneName _ = "Grep"+ primPaneName _ = (__ "Grep") getAddedIndex _ = 0 getTopWidget = castToWidget . scrolledView paneId b = "*Grep"@@ -97,21 +107,19 @@ treeViewSetModel treeView grepStore renderer1 <- cellRendererTextNew- renderer10 <- cellRendererPixbufNew col1 <- treeViewColumnNew- treeViewColumnSetTitle col1 "File"+ treeViewColumnSetTitle col1 (__ "File") treeViewColumnSetSizing col1 TreeViewColumnAutosize treeViewColumnSetResizable col1 True treeViewColumnSetReorderable col1 True treeViewAppendColumn treeView col1- cellLayoutPackStart col1 renderer10 False cellLayoutPackStart col1 renderer1 True cellLayoutSetAttributes col1 renderer1 grepStore $ \row -> [ cellText := file row] renderer2 <- cellRendererTextNew col2 <- treeViewColumnNew- treeViewColumnSetTitle col2 "Line"+ treeViewColumnSetTitle col2 (__ "Line") treeViewColumnSetSizing col2 TreeViewColumnAutosize treeViewColumnSetResizable col2 True treeViewColumnSetReorderable col2 True@@ -121,14 +129,12 @@ $ \row -> [ cellText := show $ line row] renderer3 <- cellRendererTextNew- renderer30 <- cellRendererPixbufNew col3 <- treeViewColumnNew- treeViewColumnSetTitle col3 "Context"+ treeViewColumnSetTitle col3 (__ "Context") treeViewColumnSetSizing col3 TreeViewColumnAutosize treeViewColumnSetResizable col3 True treeViewColumnSetReorderable col3 True treeViewAppendColumn treeView col3- cellLayoutPackStart col3 renderer30 False cellLayoutPackStart col3 renderer3 True cellLayoutSetAttributes col3 renderer3 grepStore $ \row -> [ cellText := context row]@@ -154,19 +160,18 @@ case record of GrepRecord {file=f, line=l, parDir=Just pp} -> (goToSourceDefinition (pp </> f) $ Just $ Location l 0 l 0)- ?>>= (\b -> when focus $ grabFocus (sourceView b))+ ?>>= (\(IDEBuffer {sourceView = sv}) -> when focus $ grabFocus sv) _ -> return ()) ideR Nothing -> return () return True- cid1 <- treeView `afterFocusIn`- (\_ -> do reflectIDE (makeActive grep) ideR ; return True)- cid2 <- treeView `onKeyPress`- (\e ->- case e of- k@(Gdk.Key _ _ _ _ _ _ _ _ _ _)- | Gdk.eventKeyName k == "Return" -> do- gotoSource True- | Gdk.eventKeyName k == "Escape" -> do+ cid1 <- after treeView focusInEvent $ do+ liftIO $ reflectIDE (makeActive grep) ideR+ return True+ cid2 <- on treeView keyPressEvent $ do+ name <- eventKeyName+ liftIO $ case name of+ "Return" -> gotoSource True+ "Escape" -> do reflectIDE (do lastActiveBufferPane ?>>= \paneName -> do (PaneC pane) <- paneFromName paneName@@ -175,11 +180,8 @@ triggerEventIDE StartFindInitial) ideR return True -- gotoSource True- | otherwise -> do- return False- _ -> return False- )- sel `onSelectionChanged` (gotoSource False >> return ())+ _ -> return False+ on sel treeSelectionSelectionChanged (gotoSource False >> return ()) return (Just grep,[ConnectC cid1])@@ -218,6 +220,7 @@ p:_ -> Just <$> treeStoreGetValue grepStore p _ -> return Nothing +--TODO srp use default loglaunch probably grepWorkspace :: String -> Bool -> WorkspaceAction grepWorkspace "" caseSensitive = return () grepWorkspace regexString caseSensitive = do@@ -227,9 +230,9 @@ Just active -> active : (filter (/= active) $ wsPackages ws) Nothing -> wsPackages ws lift $ grepDirectories regexString caseSensitive $- map (\p -> (dropFileName (ipdCabalFile p), ipdSrcDirs p)) $ packages+ map (\p -> (dropFileName $ ipdCabalFile p)) $ packages -grepDirectories :: String -> Bool -> [(FilePath, [FilePath])] -> IDEAction+grepDirectories :: String -> Bool -> [FilePath] -> IDEAction grepDirectories regexString caseSensitive dirs = do grep <- getGrep Nothing let store = grepStore grep@@ -243,7 +246,10 @@ postGUISync $ treeStoreClear store - totalFound <- foldM (\a (dir, subDirs) -> do+ totalFound <- foldM (\a dir -> do+ subDirs <- filter (\f ->+ (not ("." `isPrefixOf` f))+ && (not (f `elem` ["_darcs", "dist", "vendor"]))) <$> getDirectoryContents dir nooneWaiting <- isEmptyMVar (waitingGrep grep) found <- if nooneWaiting then do@@ -256,36 +262,37 @@ #endif regexString] ++ subDirs) (Just dir) reflectIDE (do- E.run_ $ output $$ do+ output $$ do let max = 1000- step <- EL.isolate (toInteger max) $$ setGrepResults dir- case step of- E.Continue _ -> do- liftIO $ interruptProcessGroupOf pid- liftIO $ postGUISync $ do+ CL.isolate max =$ do+ n <- setGrepResults dir+ when (n >= max) . liftIO $ do+ debugM "leksah" $ "interrupting grep process"+ interruptProcessGroupOf pid+ `catch` \(_::SomeException) -> return ()+ postGUISync $ do nDir <- treeModelIterNChildren store Nothing- liftIO $ treeStoreChange store [nDir-1] (\r -> r{ context = "(Stoped Searching)" })+ treeStoreChange store [nDir-1] (\r -> r{ context = (__ "(Stoped Searching)") }) return ()- EL.dropWhile (const True)- return max- E.Yield n _ -> return n- _ -> return 0) ideRef+ CL.sinkNull+ return n) ideRef else return 0 return $ a + found) 0 dirs nooneWaiting <- isEmptyMVar (waitingGrep grep) when nooneWaiting $ postGUISync $ do nDir <- treeModelIterNChildren store Nothing- treeStoreInsert store [] nDir $ GrepRecord "Search Complete" totalFound "" Nothing+ treeStoreInsert store [] nDir $ GrepRecord (__ "Search Complete") totalFound "" Nothing takeMVar (activeGrep grep) >> return () return () -setGrepResults :: FilePath -> E.Iteratee ToolOutput IDEM Int+setGrepResults :: FilePath -> C.Sink ToolOutput IDEM Int setGrepResults dir = do ideRef <- lift ask grep <- lift $ getGrep Nothing log <- lift $ getLog+ defaultLogLaunch <- lift $ getDefaultLogLaunch let store = grepStore grep view = treeView grep nDir <- liftIO $ postGUISync $ do@@ -293,10 +300,10 @@ treeStoreInsert store [] nDir $ GrepRecord dir 0 "" Nothing when (nDir == 0) (widgetGrabFocus view >> return()) return nDir- EL.foldM (\count line -> do+ CL.foldM (\count line -> do if isError line then do- liftIO $ postGUISync $ reflectIDE (defaultLineLogger log line >> return ()) ideRef+ liftIO $ postGUISync $ reflectIDE (defaultLineLogger log defaultLogLaunch line >> return ()) ideRef return count else do case process dir line of@@ -313,7 +320,7 @@ return (count+1)) 0 where process pp (ToolOutput line) =- case parse grepLineParser "" line of+ case parse grepLineParser "" $ T.unpack line of Right record -> Just record{parDir = Just pp} _ -> Nothing process _ _ = Nothing
@@ -0,0 +1,277 @@+{-# LANGUAGE CPP, FlexibleInstances, DeriveDataTypeable, MultiParamTypeClasses,+ TypeSynonymInstances, RecordWildCards #-}+-----------------------------------------------------------------------------+--+-- Module : IDE.Pane.HLint+-- Copyright : (c) Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GNU-GPL+--+-- Maintainer : <maintainer at leksah.org>+-- Stability : provisional+-- Portability : portable+--+-- | The pane of ide where HLint results are displayed+--+-----------------------------------------------------------------------------++module IDE.Pane.HLint (+ IDEHLint(..)+, refreshHLint+, HLintState(..)+, getHLint+) where+++import Graphics.UI.Gtk hiding (get)+import qualified Graphics.UI.Gtk.Gdk.Events as Gdk+import Text.ParserCombinators.Parsec.Language+import Text.ParserCombinators.Parsec hiding(Parser)+import qualified Text.ParserCombinators.Parsec.Token as P+import Data.Maybe+import Data.Typeable+import IDE.Core.State+import IDE.BufferMode+import IDE.LogRef (logOutput, defaultLineLogger)+import IDE.Pane.SourceBuffer+ (goToSourceDefinition, maybeActiveBuf, IDEBuffer(..))+import IDE.TextEditor (grabFocus)+import Control.Applicative ((<$>))+import System.FilePath ((</>), dropFileName)+import System.Exit (ExitCode(..))+import IDE.Pane.Log (getLog)+import Control.Monad (forM_, foldM, when)+import Control.Monad.Trans.Reader (ask)+import Control.Monad.Trans.Class (MonadTrans(..))+import Control.Monad.IO.Class (MonadIO(..))+import Language.Haskell.HLint (Suggestion(..), suggestionLocation)+import Language.Haskell.Exts (SrcLoc(..))+import qualified Language.Haskell.HLint as H (hlint)+import IDE.Utils.GUIUtils (__)++data HLintRecord = HLintRecord {+ file :: FilePath+ , line :: Int+ , context :: String+ , parDir :: Maybe FilePath+ } deriving (Eq)++isDir HLintRecord{parDir = Nothing} = True+isDir otherwies = False++-- | A HLint pane description+--++data IDEHLint = IDEHLint {+ scrolledView :: ScrolledWindow+, treeView :: TreeView+, hlintStore :: TreeStore HLintRecord+} deriving Typeable++data HLintState = HLintState+ deriving(Eq,Ord,Read,Show,Typeable)++instance Pane IDEHLint IDEM+ where+ primPaneName _ = "HLint"+ getAddedIndex _ = 0+ getTopWidget = castToWidget . scrolledView+ paneId b = "*HLint"++instance RecoverablePane IDEHLint HLintState IDEM where+ saveState p = do+ return (Just HLintState)+ recoverState pp HLintState = do+ nb <- getNotebook pp+ buildPane pp nb builder+ builder pp nb windows = reifyIDE $ \ ideR -> do+ hlintStore <- treeStoreNew []+ treeView <- treeViewNew+ treeViewSetModel treeView hlintStore++ renderer1 <- cellRendererTextNew+ renderer10 <- cellRendererPixbufNew+ col1 <- treeViewColumnNew+ treeViewColumnSetTitle col1 (__ "Context")+ treeViewColumnSetSizing col1 TreeViewColumnAutosize+ treeViewColumnSetResizable col1 True+ treeViewColumnSetReorderable col1 True+ treeViewAppendColumn treeView col1+ cellLayoutPackStart col1 renderer10 False+ cellLayoutPackStart col1 renderer1 True+ cellLayoutSetAttributes col1 renderer1 hlintStore+ $ \row -> [ cellText := context row ]++ treeViewSetHeadersVisible treeView False+ sel <- treeViewGetSelection treeView+ treeSelectionSetMode sel SelectionSingle++ scrolledView <- scrolledWindowNew Nothing Nothing+ containerAdd scrolledView treeView+ scrolledWindowSetPolicy scrolledView PolicyAutomatic PolicyAutomatic++ let hlint = IDEHLint {..}+ gotoSource :: Bool -> IO Bool+ gotoSource focus = do+ sel <- getSelectionHLintRecord treeView hlintStore+ case sel of+ Just record -> reflectIDE (do+ case record of+ HLintRecord {file=f, line=l, parDir=Just pp} ->+ (goToSourceDefinition (pp </> f) $ Just $ Location l 0 l 0)+ ?>>= (\(IDEBuffer {sourceView = sv}) -> when focus $ grabFocus sv)+ _ -> return ()) ideR+ Nothing -> return ()+ return True+ cid1 <- after treeView focusInEvent $ do+ liftIO $ reflectIDE (makeActive hlint) ideR+ return True+ cid2 <- on treeView rowExpanded $ \ iter path -> do+ record <- treeStoreGetValue hlintStore path+ case record of+ HLintRecord { file = f, parDir = Nothing } -> refreshDir hlintStore iter f+ _ -> reflectIDE (ideMessage Normal (__ "Unexpected Expansion in HLint Pane")) ideR+ cid3 <- on treeView rowActivated $ \ path col -> do+ record <- treeStoreGetValue hlintStore path+ mbIter <- treeModelGetIter hlintStore path+ case (mbIter, record) of+ (Just iter, HLintRecord { file = f, parDir = Nothing }) -> refreshDir hlintStore iter f+ _ -> return ()+ cid4 <- on treeView keyPressEvent $ do+ name <- eventKeyName+ liftIO $ case name of+ "Return" -> gotoSource True+ "Escape" -> do+ reflectIDE (do+ lastActiveBufferPane ?>>= \paneName -> do+ (PaneC pane) <- paneFromName paneName+ makeActive pane+ return ()+ triggerEventIDE StartFindInitial) ideR+ return True+ -- gotoSource True+ _ -> return False+ on sel treeSelectionSelectionChanged (gotoSource False >> return ())++ return (Just hlint,map ConnectC [cid1, cid2, cid3, cid4])++getHLint :: Maybe PanePath -> IDEM IDEHLint+getHLint Nothing = forceGetPane (Right "*HLint")+getHLint (Just pp) = forceGetPane (Left pp)++hlintLineParser :: CharParser () HLintRecord+hlintLineParser = try (do+ file <- many (noneOf ":")+ char ':'+ line <- int+ char ':'+ context <- many anyChar+ let parDir = Nothing+ return $ HLintRecord {..}+ <?> "hlintLineParser")++lexer = P.makeTokenParser emptyDef+lexeme = P.lexeme lexer+whiteSpace = P.whiteSpace lexer+hexadecimal = P.hexadecimal lexer+symbol = P.symbol lexer+identifier = P.identifier lexer+colon = P.colon lexer+int = fmap fromInteger $ P.integer lexer++getSelectionHLintRecord :: TreeView+ -> TreeStore HLintRecord+ -> IO (Maybe HLintRecord)+getSelectionHLintRecord treeView hlintStore = do+ treeSelection <- treeViewGetSelection treeView+ paths <- treeSelectionGetSelectedRows treeSelection+ case paths of+ p:_ -> Just <$> treeStoreGetValue hlintStore p+ _ -> return Nothing++refreshHLint :: WorkspaceAction+refreshHLint = do+ ws <- ask+ maybeActive <- lift $ readIDE activePack+ let packages = case maybeActive of+ Just active -> active : (filter (/= active) $ wsPackages ws)+ Nothing -> wsPackages ws+ lift $ hlintDirectories $+ concatMap (\p -> map (dropFileName (ipdCabalFile p) </>) $ ipdSrcDirs p) $ packages++hlintDirectories :: [FilePath] -> IDEAction+hlintDirectories dirs = do+ hlint <- getHLint Nothing+ let store = hlintStore hlint+ liftIO $ do+ treeStoreClear store+ forM_ dirs $ \ dir -> do+ nDir <- treeModelIterNChildren store Nothing+ treeStoreInsert store [] nDir $ HLintRecord dir 0 dir Nothing+ treeStoreInsert store [nDir] 0 $ HLintRecord dir 0 dir Nothing++refreshDir :: TreeStore HLintRecord -> TreeIter -> FilePath -> IO ()+refreshDir store iter dir = do+ mbHlintDir <- leksahSubDir "hlint"+ let datadirOpt = case mbHlintDir of+ Just d -> "--datadir":[d]+ Nothing -> []+ suggestions <- take 1000 <$> H.hlint ("--quiet":dir:datadirOpt)+ setHLintResults store iter dir suggestions+ return ()++hlintRecord dir suggestion = HLintRecord {+ file = srcFilename loc,+ line = srcLine loc,+ context = show suggestion,+ parDir = Just dir}+ where+ loc = suggestionLocation suggestion++setHLintResults :: TreeStore HLintRecord -> TreeIter -> FilePath -> [Suggestion] -> IO Int+setHLintResults store parent dir suggestions = do+ parentPath <- treeModelGetPath store parent+ forM_ (zip [0..] records) $ \(n, record) -> do+ mbChild <- treeModelIterNthChild store (Just parent) n+ findResult <- find record store mbChild+ case (mbChild, findResult) of+ (_, WhereExpected _) -> return ()+ (Just iter, Found _) -> do+ path <- treeModelGetPath store iter+ removeUntil record store path+ _ -> do+ treeStoreInsert store parentPath n $ record+ removeRemaining store (parentPath++[nRecords])+ return nRecords+ where+ records = map (hlintRecord dir) suggestions+ nRecords = length records++data FindResult = WhereExpected TreeIter | Found TreeIter | NotFound++find :: Eq a => a -> TreeStore a -> Maybe TreeIter -> IO FindResult+find _ _ Nothing = return NotFound+find a store (Just iter) = do+ row <- treeModelGetRow store iter+ if row == a+ then return $ WhereExpected iter+ else treeModelIterNext store iter >>= find'+ where+ find' :: Maybe TreeIter -> IO FindResult+ find' Nothing = return NotFound+ find' (Just iter) = do+ row <- treeModelGetRow store iter+ if row == a+ then return $ Found iter+ else treeModelIterNext store iter >>= find'++removeUntil :: Eq a => a -> TreeStore a -> TreePath -> IO ()+removeUntil a store path = do+ row <- treeStoreGetValue store path+ when (row /= a) $ do+ found <- treeStoreRemove store path+ when found $ removeUntil a store path++removeRemaining :: TreeStore a -> TreePath -> IO ()+removeRemaining store path = do+ found <- treeStoreRemove store path+ when found $ removeRemaining store path
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleInstances, DeriveDataTypeable, MultiParamTypeClasses,- CPP, ScopedTypeVariables, TypeSynonymInstances #-}+ CPP, ScopedTypeVariables, TypeSynonymInstances, GADTs, RecordWildCards #-} {-# OPTIONS_GHC -fwarn-unused-imports #-} ----------------------------------------------------------------------------- --@@ -17,13 +17,14 @@ module IDE.Pane.Info ( IDEInfo-, InfoState+, InfoState(..)+, showInfo , setInfo+, setInfoStyle , replayInfoHistory , openDocu ) where -import Graphics.UI.Gtk hiding (afterToggleOverwrite) import Control.Monad import Data.IORef import Data.Typeable@@ -33,18 +34,23 @@ import IDE.Core.State import IDE.SymbolNavigation import IDE.Pane.SourceBuffer-import IDE.TextEditor (EditorIter(..))-import IDE.Utils.GUIUtils (openBrowser,controlIsPressed)-import Graphics.UI.Gtk.SourceView+import IDE.TextEditor (newDefaultBuffer, TextEditor(..), EditorView(..))+import IDE.Utils.GUIUtils (getDarkState, openBrowser, __) import Control.Monad.IO.Class (MonadIO(..))-+import Control.Monad.Reader.Class (MonadReader(..))+import Graphics.UI.Gtk+ (widgetHide, widgetShowAll, menuShellAppend,+ menuItemActivate, menuItemNewWithLabel, containerGetChildren, Menu,+ scrolledWindowSetPolicy, castToWidget, ScrolledWindow)+import Graphics.UI.Gtk.General.Enums (PolicyType(..))+import System.Glib.Signals (on) -- | An info pane description ---data IDEInfo = IDEInfo {- sw :: VBox+data IDEInfo = forall editor. TextEditor editor => IDEInfo {+ sw :: ScrolledWindow , currentDescr :: IORef (Maybe Descr)-, descriptionView :: SourceView+, descriptionView :: EditorView editor } deriving Typeable data InfoState = InfoState (Maybe Descr)@@ -52,7 +58,7 @@ instance Pane IDEInfo IDEM where- primPaneName _ = "Info"+ primPaneName _ = (__ "Info") getAddedIndex _ = 0 getTopWidget = castToWidget . sw paneId b = "*Info"@@ -67,88 +73,45 @@ builder pp nb windows = let idDescr = Nothing in do prefs <- readIDE prefs- reifyIDE $ \ ideR -> do- ibox <- vBoxNew False 0- -- Descr View- font <- case textviewFont prefs of- Just str -> do- fontDescriptionFromString str- Nothing -> do- f <- fontDescriptionNew- fontDescriptionSetFamily f "Monospace"- return f-- descriptionView <- sourceViewNew- descriptionBuffer <- (get descriptionView textViewBuffer) >>= (return . castToSourceBuffer)- lm <- sourceLanguageManagerNew- mbLang <- sourceLanguageManagerGuessLanguage lm Nothing (Just "text/x-haskell")-#if MIN_VERSION_gtksourceview2(0,12,0)- sourceBufferSetLanguage descriptionBuffer mbLang-#else- case mbLang of- Nothing -> return ()- Just lang -> do sourceBufferSetLanguage descriptionBuffer lang-#endif- -- This call is here because in the past I have had problems where the- -- language object became invalid if the manager was garbage collected- sourceLanguageManagerGetLanguageIds lm-- sourceBufferSetHighlightSyntax descriptionBuffer True- widgetModifyFont descriptionView (Just font)-- case sourceStyle prefs of- (False,_) -> return ()- (True,str) -> do- styleManager <- sourceStyleSchemeManagerNew- ids <- sourceStyleSchemeManagerGetSchemeIds styleManager- when (elem str ids) $ do- scheme <- sourceStyleSchemeManagerGetScheme styleManager str-#if MIN_VERSION_gtksourceview2(0,12,0)- sourceBufferSetStyleScheme descriptionBuffer $ Just scheme-#else- sourceBufferSetStyleScheme descriptionBuffer scheme-#endif-+ ideR <- ask+ descriptionBuffer <- newDefaultBuffer Nothing ""+ descriptionView <- newView descriptionBuffer (textviewFont prefs) - sw <- scrolledWindowNew Nothing Nothing- containerAdd sw descriptionView+ preferDark <- getDarkState+ setStyle preferDark descriptionBuffer $ case sourceStyle prefs of+ (False,_) -> Nothing+ (True,v) -> Just v + sw <- getScrolledWindow descriptionView - createHyperLinkSupport descriptionView sw (\_ _ iter -> do- (GtkEditorIter beg,GtkEditorIter en) <- reflectIDE (getIdentifierUnderCursorFromIter (GtkEditorIter iter, GtkEditorIter iter)) ideR- return (beg, en)) (\_ shift' slice -> do- when (slice /= []) $ do- -- liftIO$ print ("slice",slice)- reflectIDE (triggerEventIDE- (SelectInfo slice shift')) ideR- return ()- )+ createHyperLinkSupport descriptionView sw (\_ _ iter -> do+ (beg, en) <- getIdentifierUnderCursorFromIter (iter, iter)+ return (beg, en)) (\_ shift' slice -> do+ when (slice /= []) $ do+ -- liftIO$ print ("slice",slice)+ triggerEventIDE (SelectInfo slice shift')+ return ()+ ) - scrolledWindowSetPolicy sw PolicyAutomatic PolicyAutomatic+ liftIO $ scrolledWindowSetPolicy sw PolicyAutomatic PolicyAutomatic - boxPackStart ibox sw PackGrow 10+ --openType+ currentDescr' <- liftIO $ newIORef idDescr+ cids1 <- onPopulatePopup descriptionView $ \ menu -> do+ ideR <- ask+ liftIO $ populatePopupMenu ideR currentDescr' menu+ let info = IDEInfo sw currentDescr' descriptionView+ -- ids5 <- sv `onLookupInfo` selectInfo descriptionView -- obsolete by hyperlinks+ cids2 <- descriptionView `afterFocusIn` makeActive info+ return (Just info, concat [cids1, cids2]) +getInfo :: IDEM IDEInfo+getInfo = forceGetPane (Right "*Info") - --openType- currentDescr' <- newIORef idDescr-#if MIN_VERSION_gtk(0,10,5)- cid <- on descriptionView populatePopup (populatePopupMenu ideR currentDescr')-#else- cid <- descriptionView `onPopulatePopup` (populatePopupMenu ideR currentDescr')-#endif- let info = IDEInfo ibox currentDescr' descriptionView- descriptionView `widgetAddEvents` [ButtonReleaseMask]- id5 <- descriptionView `onButtonRelease`- (\ e -> do- buf <- textViewGetBuffer descriptionView- (l,r) <- textBufferGetSelectionBounds buf- symbol <- textBufferGetText buf l r True- when (controlIsPressed e)- (reflectIDE (do- triggerEventIDE (SelectInfo symbol False)- return ()) ideR)- return False)- return (Just info,[ConnectC cid])+showInfo :: IDEAction+showInfo = do+ pane <- getInfo+ displayPane pane False gotoSource :: IDEAction gotoSource = do@@ -168,14 +131,30 @@ setInfo :: Descr -> IDEAction setInfo identifierDescr = do- info <- forceGetPane (Right "*Info")- oldDescr <- liftIO $ readIORef (currentDescr info)- liftIO $ do- writeIORef (currentDescr info) (Just identifierDescr)- tb <- get (descriptionView info) textViewBuffer- textBufferSetText tb (show (Present identifierDescr) ++ "\n") -- EOL for text iters to work- recordInfoHistory (Just identifierDescr) oldDescr+ info <- getInfo+ setInfo' info+ displayPane info False+ where+ setInfo' (info@IDEInfo{descriptionView = v}) = do+ oldDescr <- liftIO $ readIORef (currentDescr info)+ liftIO $ writeIORef (currentDescr info) (Just identifierDescr)+ tb <- getBuffer v+ setText tb (show (Present identifierDescr) ++ "\n") -- EOL for text iters to work+ recordInfoHistory (Just identifierDescr) oldDescr +setInfoStyle :: IDEAction+setInfoStyle = getPane >>= setInfoStyle'+ where+ setInfoStyle' Nothing = return ()+ setInfoStyle' (Just IDEInfo{..}) = do+ prefs <- readIDE prefs+ preferDark <- getDarkState+ buffer <- getBuffer descriptionView+ setStyle preferDark buffer $ case sourceStyle prefs of+ (False,_) -> Nothing+ (True,v) -> Just v++ getInfoCont :: IDEM (Maybe (Descr)) getInfoCont = do mbPane <- getPane@@ -211,12 +190,12 @@ populatePopupMenu :: IDERef -> IORef (Maybe Descr) -> Menu -> IO () populatePopupMenu ideR currentDescr' menu = do items <- containerGetChildren menu- item0 <- menuItemNewWithLabel "Goto Definition"- item0 `onActivateLeaf` (reflectIDE gotoSource ideR)- item1 <- menuItemNewWithLabel "Select Module"- item1 `onActivateLeaf` (reflectIDE gotoModule' ideR )- item2 <- menuItemNewWithLabel "Open Documentation"- item2 `onActivateLeaf` (reflectIDE openDocu ideR )+ item0 <- menuItemNewWithLabel (__ "Goto Definition")+ item0 `on` menuItemActivate $ reflectIDE gotoSource ideR+ item1 <- menuItemNewWithLabel (__ "Select Module")+ item1 `on` menuItemActivate $ reflectIDE gotoModule' ideR+ item2 <- menuItemNewWithLabel (__ "Open Documentation")+ item2 `on` menuItemActivate $ reflectIDE openDocu ideR menuShellAppend menu item0 menuShellAppend menu item1 menuShellAppend menu item2
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, FlexibleInstances, ScopedTypeVariables, DeriveDataTypeable,+{-# LANGUAGE FlexibleInstances, ScopedTypeVariables, DeriveDataTypeable, MultiParamTypeClasses, TypeSynonymInstances, ParallelListComp #-} -- -- Module : IDE.Pane.Log@@ -16,56 +16,72 @@ module IDE.Pane.Log ( IDELog(..)-, LogState+, LogState(..) , LogTag(..) , showLog , clearLog , getLog -- :: beta alpha , appendLog -- :: alpha -> String -> LogTag -> IO Int , markErrorInLog -- :: alpha -> (Int, Int) -> IO ()--, readOut-, readErr-, runExternal+, getActiveOrDefaultLogLaunch+, getDefaultLogLaunch+, buildLogLaunchByName+, buildLogLaunchByPackage+, buildLogLaunchByPackageId+, addLogLaunchData+, showLogLaunch+, showDefaultLogLaunch+, showDefaultLogLaunch' ) where import Data.Typeable (Typeable(..)) import IDE.Core.State-import Graphics.UI.Gtk.Gdk.Events+import IDE.Core.Types(LogLaunch)+import Control.Monad.Trans (liftIO)+import Control.Monad.Reader import IDE.Pane.SourceBuffer (markRefInSourceBuf,selectSourceBuf) import System.IO import Prelude hiding (catch) import Control.Exception hiding (try) import IDE.ImportTool- (addPackage, parseHiddenModule, addImport, parseNotInScope,- resolveErrors)-import IDE.Utils.Tool (runInteractiveProcess, ProcessHandle)+ (resolveErrors, addResolveMenuItems)+import IDE.Utils.Tool+ (terminateProcess, runInteractiveProcess, ProcessHandle) import Graphics.UI.Gtk (textBufferSetText, textViewScrollToMark,- textBufferGetIterAtLineOffset, textViewScrollMarkOnscreen,+ textBufferGetIterAtLineOffset, textViewScrollMarkOnscreen, textViewSetBuffer, textBufferGetMark, textBufferMoveMarkByName, textBufferApplyTagByName, textBufferGetIterAtOffset, textBufferGetCharCount, textBufferInsert, textBufferSelectRange,- widgetHide, widgetShowAll, menuShellAppend, onActivateLeaf,+ widgetHide, widgetShowAll, menuShellAppend, menuItemNewWithLabel, containerGetChildren, textIterGetLine, textViewGetLineAtY, textViewWindowToBufferCoords, widgetGetPointer,-#if MIN_VERSION_gtk(0,10,5)- on, populatePopup,-#else- onPopulatePopup,-#endif- onButtonPress, afterFocusIn,+ on, populatePopup, eventCoordinates, eventClick, eventButton,+ buttonPressEvent, focusInEvent, textBufferNew, scrolledWindowSetShadowType, scrolledWindowSetPolicy, containerAdd,+ containerForeach, containerRemove, changed, Click(..), MouseButton(..), scrolledWindowNew, widgetModifyFont, fontDescriptionSetFamily, fontDescriptionNew, fontDescriptionFromString, textViewSetEditable, textTagBackground, textTagTableAdd, textTagForeground, textTagNew, textBufferGetTagTable, textBufferCreateMark, textBufferGetEndIter, textViewGetBuffer, textViewNew, Window, Notebook, castToWidget,- ScrolledWindow, TextView, Menu, AttrOp(..), set,- TextWindowType(..), ShadowType(..), PolicyType(..),- priorityDefaultIdle, idleAdd)-import Control.Monad.IO.Class (MonadIO(..))-+ ScrolledWindow, TextView, Container, ComboBox, HBox, VBox, Menu, AttrOp(..), set,+ TextWindowType(..), ShadowType(..), PolicyType(..), hBoxNew, buttonNewWithLabel,+ vBoxNew, comboBoxNewText, menuItemActivate,+ comboBoxAppendText, comboBoxSetActive, comboBoxGetActiveText,+ priorityDefaultIdle, idleAdd,Frame, frameNew,buttonActivated,+ boxPackStart, boxPackEnd, Packing(..), comboBoxGetActive, comboBoxRemoveText,+ comboBoxGetModelText, listStoreToList, after) --TODO remove import for logging only+import qualified Data.Map as Map+import Data.Maybe+import Distribution.Package+import Data.Char+import IDE.Utils.GUIUtils (__)+import Text.Printf (printf)+import Data.Text (Text)+import qualified Data.Text as T (length, unpack)+import Data.Monoid ((<>))+import Data.List (isPrefixOf, isSuffixOf, findIndex) ------------------------------------------------------------------------------- --@@ -77,19 +93,153 @@ -- -data IDELog = IDELog {- textView :: TextView-, scrolledWindowL :: ScrolledWindow+data IDELog = IDELog {+ logMainContainer :: VBox+, logLaunchTextView :: TextView+, logButtons :: HBox+, logLaunchBox :: ComboBox } deriving Typeable +getActiveOrDefaultLogLaunch :: IDEM LogLaunch+getActiveOrDefaultLogLaunch = do+ log <- getLog+ let comboBox = logLaunchBox log+ launches <- readIDE logLaunches+ active <- liftIO $ comboBoxGetActiveText comboBox+ case active of+ Nothing -> getDefaultLogLaunch+ Just key -> return $ logLaunch $ launches Map.! key++getDefaultLogLaunch :: IDEM LogLaunch+getDefaultLogLaunch = do+ launches <- readIDE logLaunches+ return $ logLaunch $ launches Map.! defaultLogName++buildLogLaunchByPackage :: IDEPackage+ -> IDEM (LogLaunch, String)+buildLogLaunchByPackage = buildLogLaunchByShownPackageId . getLogLaunchNameByPackage++buildLogLaunchByPackageId :: PackageIdentifier+ -> IDEM (LogLaunch, String)+buildLogLaunchByPackageId = buildLogLaunchByShownPackageId . getLogLaunchNameByPackageId++buildLogLaunchByShownPackageId :: String+ -> IDEM (LogLaunch, String)+buildLogLaunchByShownPackageId = buildLogLaunchByName++buildLogLaunchByName :: String+ -> IDEM (LogLaunch, String)+buildLogLaunchByName logName = do+ log <- getLog+ launches <- readIDE logLaunches+ let mbLogLaunch = Map.lookup logName launches+ let name = getNextFreeName logName launches+ newLogLaunch <- liftIO $ createNewLogLaunch+ return (newLogLaunch, name)+ where+ getNextFreeName prevName launches = case (Map.lookup prevName launches) of+ Nothing -> prevName+ Just _ -> getNextFreeName (incrementName prevName) launches+ incrementName name = case (parseName name) of+ Nothing -> createNewName name 0+ Just (number,name) -> createNewName name number+ createNewName name number = concat [name, " (", show (number+1), ")"]+ parseName name = if surroundedByParenth $ getLaunchString name+ then+ if isNumberAndNotEmpty $ init $ tail $ getLaunchString name+ then -- check if+ Just $ (read $ init $ tail $ getLaunchString name,+ reverse $ drop 4 $ reverse name)+ else Nothing+ else Nothing+ surroundedByParenth string = ("(" `isPrefixOf` string ) && (")" `isSuffixOf` string) && (isNotBlank string)+ isNumberAndNotEmpty string = (foldr ((&&) . isNumber) True $ string) && (isNotBlank string) -- check if+ getLaunchString name = reverse $ take 3 $ reverse name+ isNotBlank [] = False+ isNotBlank _ = True+++getLogLaunchNameByPackage :: IDEPackage -> String+getLogLaunchNameByPackage package = getLogLaunchNameByPackageId (ipdPackageId package)++getLogLaunchNameByPackageId :: PackageIdentifier -> String+getLogLaunchNameByPackageId (PackageIdentifier pkgName pkgVersion) = show pkgName ++ show pkgVersion++defaultLogName = "default"++-- ^ adds arguments to ide to process them later.+-- ^ e.g. using processhandle to kill process and name to switch between view+addLogLaunchData :: String -> LogLaunch -> ProcessHandle -> IDEM ()+addLogLaunchData name logLaunch pid = do+ log <- getLog+ let comboBox = logLaunchBox log+ liftIO $ comboBoxAppendText comboBox name+ launches <- readIDE logLaunches+ let newLaunches = Map.insert name (LogLaunchData logLaunch (Just pid)) launches+ modifyIDE_ (\ide -> ide {logLaunches = newLaunches})+ showLogLaunch name+++removeActiveLogLaunchData :: IDEM ()+removeActiveLogLaunchData = do+-- liftIO $ putStrLn $ "Attempting to remove active log launchdata from ide" --TODO remove logging+ log <- getLog+ let comboBox = logLaunchBox log++ index <- liftIO $ comboBoxGetActive comboBox+ mbTitle <- liftIO $ comboBoxGetActiveText comboBox+-- liftIO $ putStrLn $ "Lauch to remove: index " ++ (show index) ++ ", mbTitle: "++ (show mbTitle)+ let title = fromJust mbTitle++-- model <- liftIO $ comboBoxGetModelText comboBox+-- list <- liftIO $ listStoreToList model+-- liftIO $ putStrLn $ "Underlying model " ++ (show list)+++ liftIO $ showDefaultLogLaunch comboBox+ liftIO $ comboBoxRemoveText comboBox index+-- liftIO $ putStrLn $ "Removed launch from combobox."+ launches <- readIDE logLaunches+-- liftIO $ putStrLn $ "Number of available launches: "++(show $ length $ Map.toList launches)+ let newLaunches = Map.delete title launches+ modifyIDE_ (\ide -> ide {logLaunches = newLaunches})+-- liftIO $ putStrLn $ "Removed log launch data successfully from ide"++showDefaultLogLaunch :: ComboBox -> IO()+showDefaultLogLaunch comboBox = comboBoxSetActive comboBox 0++showDefaultLogLaunch' :: IDEM ()+showDefaultLogLaunch' = do+ log <- getLog+ let comboBox = logLaunchBox log++ liftIO $ showDefaultLogLaunch comboBox++showLogLaunch :: String -> IDEM ()+showLogLaunch name = do+ liftIO $ putStrLn $ "showLogLaunch: name = " ++ name+ log <- getLog+ let comboBox = logLaunchBox log++ model <- liftIO $ comboBoxGetModelText comboBox+ list <- liftIO $ listStoreToList model+ let mbIndex = findIndex (==name) list++ liftIO $ putStrLn $ "showLogLaunch: mbIndex = " ++ show mbIndex++ case mbIndex of+ Nothing -> return() -- TODO errorCalls+ Just index -> liftIO $ comboBoxSetActive comboBox index+ liftIO $ putStrLn $ "switched to loglaunch"+ data LogState = LogState deriving(Eq,Ord,Read,Show,Typeable) instance Pane IDELog IDEM where- primPaneName _ = "Log"+ primPaneName _ = (__ "Log") getAddedIndex _ = 0- getTopWidget = castToWidget . scrolledWindowL+ getTopWidget = castToWidget . logMainContainer paneId b = "*Log" instance RecoverablePane IDELog LogState IDEM where@@ -109,35 +259,63 @@ -- * Implementation -- +createNewLogLaunch :: IO LogLaunch+createNewLogLaunch = do+ buf <- textBufferNew Nothing+ iter <- textBufferGetEndIter buf+ textBufferCreateMark buf (Just "end") iter True+ tags <- textBufferGetTagTable buf++ errtag <- textTagNew (Just "err")+ set errtag[textTagForeground := "red"]+ textTagTableAdd tags errtag++ frametag <- textTagNew (Just "frame")+ set frametag[textTagForeground := "dark green"]+ textTagTableAdd tags frametag++ activeErrtag <- textTagNew (Just "activeErr")+ set activeErrtag[textTagBackground := "yellow"]+ textTagTableAdd tags activeErrtag++ intputTag <- textTagNew (Just "input")+ set intputTag[textTagForeground := "blue"]+ textTagTableAdd tags intputTag++ infoTag <- textTagNew (Just "info")+ set infoTag[textTagForeground := "grey"]+ textTagTableAdd tags infoTag++ return $ LogLaunch buf+ builder' :: PanePath -> Notebook -> Window -> IDEM (Maybe IDELog,Connections) builder' pp nb windows = do prefs <- readIDE prefs+ newLogLaunch <- liftIO $ createNewLogLaunch+ let emptyMap = Map.empty :: Map.Map String LogLaunchData+ let map = Map.insert defaultLogName (LogLaunchData newLogLaunch Nothing) emptyMap+ modifyIDE_ $ \ide -> ide { logLaunches = map}++ ideR <- ask reifyIDE $ \ideR -> do- tv <- textViewNew- buf <- textViewGetBuffer tv- iter <- textBufferGetEndIter buf- textBufferCreateMark buf (Just "end") iter True+ mainContainer <- vBoxNew False 0 - tags <- textBufferGetTagTable buf- errtag <- textTagNew (Just "err")- set errtag[textTagForeground := "red"]- textTagTableAdd tags errtag- frametag <- textTagNew (Just "frame")- set frametag[textTagForeground := "dark green"]- textTagTableAdd tags frametag- activeErrtag <- textTagNew (Just "activeErr")- set activeErrtag[textTagBackground := "yellow"]- textTagTableAdd tags activeErrtag- intputTag <- textTagNew (Just "input")- set intputTag[textTagForeground := "blue"]- textTagTableAdd tags intputTag- infoTag <- textTagNew (Just "info")- set infoTag[textTagForeground := "grey"]- textTagTableAdd tags infoTag+ -- top, buttons and combobox+ hBox <- hBoxNew False 0+ boxPackStart mainContainer hBox PackNatural 0 + terminateBtn <- buttonNewWithLabel (__ "Terminate process")+ boxPackStart hBox terminateBtn PackNatural 0+ removeBtn <- buttonNewWithLabel (__ "Remove launch")+ boxPackStart hBox removeBtn PackNatural 0+ comboBox <- comboBoxNewText+ boxPackEnd hBox comboBox PackGrow 0++ -- bot, launch textview in a scrolled window+ tv <- textViewNew textViewSetEditable tv False fd <- case logviewFont prefs of Just str -> do@@ -152,26 +330,87 @@ scrolledWindowSetPolicy sw PolicyAutomatic PolicyAutomatic scrolledWindowSetShadowType sw ShadowIn - let buf = IDELog tv sw- cid1 <- tv `afterFocusIn`- (\_ -> do reflectIDE (makeActive buf) ideR ; return False)- cid2 <- tv `onButtonPress`- (\ b -> do reflectIDE (clicked b buf) ideR ; return False)+ boxPackEnd mainContainer sw PackGrow 0 -#if MIN_VERSION_gtk(0,10,5)- cid3 <- tv `on` populatePopup $ populatePopupMenu buf ideR-#else- cid3 <- tv `onPopulatePopup` (populatePopupMenu buf ideR)-#endif- return (Just buf,[ConnectC cid1, ConnectC cid2])+ -- add default launch+ textViewSetBuffer tv (logBuffer newLogLaunch)+ index <- comboBoxAppendText comboBox defaultLogName+ comboBoxSetActive comboBox index -clicked :: Event -> IDELog -> IDEAction-clicked (Button _ SingleClick _ _ _ _ LeftButton x y) ideLog = do+ on comboBox changed $ do+ mbTitle <- comboBoxGetActiveText comboBox+ case mbTitle of+ Nothing -> showDefaultLogLaunch comboBox+ Just title -> reflectIDE (+ do+ launches <- readIDE logLaunches+ log <- getLog+ let tv = logLaunchTextView log+ let logL = logLaunch $ (Map.!) launches title+ let buf = logBuffer logL++ liftIO $ textViewSetBuffer tv buf+ )+ ideR++ on terminateBtn buttonActivated $ do+ mbTitle <- comboBoxGetActiveText comboBox+ case mbTitle of+ Nothing -> return()+ Just title -> reflectIDE (+ do+ launches <- readIDE logLaunches+ terminateLogLaunch title launches+ )+ ideR++ on removeBtn buttonActivated $ do+ mbTitle <- comboBoxGetActiveText comboBox+ case mbTitle of+ Nothing -> return()+ Just title -> if not $ title == defaultLogName then+ reflectIDE (+ do+ launches <- readIDE logLaunches+ removeActiveLogLaunchData+ terminateLogLaunch title launches+++ )+ ideR+ else+ return ()+++ let buf = IDELog mainContainer tv hBox comboBox+ cid1 <- after tv focusInEvent $ do+ liftIO $ reflectIDE (makeActive buf) ideR+ return False+ cid2 <- on tv buttonPressEvent $ do+ click <- eventClick+ button <- eventButton+ (x, y) <- eventCoordinates+ liftIO $ reflectIDE (clicked click button x y buf) ideR+ return False+ cid3 <- on tv populatePopup $ populatePopupMenu buf ideR+ return (Just buf, [ConnectC cid1, ConnectC cid2])+ where+ terminateLogLaunch title launches = do+ let mbPH = mbPid $ fromJust $ Map.lookup title launches+ case mbPH of+ Nothing -> return ()+ Just ph -> liftIO $ terminateProcess ph+++clicked :: Click -> MouseButton -> Double -> Double -> IDELog -> IDEAction+clicked SingleClick LeftButton x y log = do logRefs' <- readIDE allLogRefs+ log <- getLog line' <- liftIO $ do- (x,y) <- widgetGetPointer (textView ideLog)- (_,y') <- textViewWindowToBufferCoords (textView ideLog) TextWindowWidget (x,y)- (iter,_) <- textViewGetLineAtY (textView ideLog) y'+ let tv = logLaunchTextView log+ (x,y) <- widgetGetPointer tv+ (_,y') <- textViewWindowToBufferCoords tv TextWindowWidget (x,y)+ (iter,_) <- textViewGetLineAtY tv y' textIterGetLine iter case filter (\(es,_) -> fst (logLines es) <= (line'+1) && snd (logLines es) >= (line'+1)) (zip logRefs' [0..(length logRefs')]) of@@ -181,47 +420,35 @@ Just buf -> markRefInSourceBuf n buf thisRef True Nothing -> return () log :: IDELog <- getLog- liftIO $ markErrorInLog log (logLines thisRef)+ markErrorInLog log (logLines thisRef) case logRefType thisRef of BreakpointRef -> setCurrentBreak (Just thisRef) _ -> setCurrentError (Just thisRef) otherwise -> return ()-clicked _ _ = return ()+clicked _ _ _ _ _ = return () populatePopupMenu :: IDELog -> IDERef -> Menu -> IO ()-populatePopupMenu ideLog ideR menu = do+populatePopupMenu log ideR menu = do items <- containerGetChildren menu- item0 <- menuItemNewWithLabel "Resolve Errors"- item0 `onActivateLeaf` do+ item0 <- menuItemNewWithLabel (__ "Resolve Errors")+ item0 `on` menuItemActivate $ do reflectIDE resolveErrors ideR menuShellAppend menu item0 res <- reflectIDE (do+ log <- getLog logRefs' <- readIDE allLogRefs+ activeLogLaunch <- getActiveOrDefaultLogLaunch -- TODO srp get active log launch here line' <- reifyIDE $ \ideR -> do- (x,y) <- widgetGetPointer (textView ideLog)- (_,y') <- textViewWindowToBufferCoords (textView ideLog) TextWindowWidget (x,y)- (iter,_) <- textViewGetLineAtY (textView ideLog) y'+ let tv = logLaunchTextView log+ (x,y) <- widgetGetPointer tv+ (_,y') <- textViewWindowToBufferCoords tv TextWindowWidget (x,y)+ (iter,_) <- textViewGetLineAtY tv y' textIterGetLine iter return $ filter (\(es,_) -> fst (logLines es) <= (line'+1) && snd (logLines es) >= (line'+1)) (zip logRefs' [0..(length logRefs')])) ideR case res of [(thisRef,n)] -> do- case parseNotInScope (refDescription thisRef) of- Nothing -> do- return ()- Just _ -> do- item1 <- menuItemNewWithLabel "Add Import"- item1 `onActivateLeaf` do- reflectIDE (addImport thisRef [] (\_ -> return ())) ideR- menuShellAppend menu item1- case parseHiddenModule (refDescription thisRef) of- Nothing -> do- return ()- Just _ -> do- item2 <- menuItemNewWithLabel "Add Package"- item2 `onActivateLeaf` do- reflectIDE (addPackage thisRef >> return ()) ideR- menuShellAppend menu item2+ addResolveMenuItems ideR menu thisRef widgetShowAll menu return () otherwise -> return ()@@ -231,7 +458,7 @@ getLog = do mbPane <- getOrBuildPane (Right "*Log") case mbPane of- Nothing -> throwIDE "Can't init log"+ Nothing -> throwIDE (__ "Can't init log") Just p -> return p showLog :: IDEAction@@ -239,18 +466,17 @@ l <- getLog displayPane l False -simpleLog :: String -> IDEAction-simpleLog str = do- log :: IDELog <- getLog- liftIO $ appendLog log str LogTag- return ()--appendLog :: IDELog -> String -> LogTag -> IO Int-appendLog l@(IDELog tv _) string tag = do- buf <- textViewGetBuffer tv+{- the workhorse for logging: appends given text with given tag to given loglaunch -}+appendLog :: IDELog+ -> LogLaunch+ -> Text+ -> LogTag+ -> IO Int+appendLog log logLaunch text tag = do+ let buf = logBuffer logLaunch iter <- textBufferGetEndIter buf textBufferSelectRange buf iter iter- textBufferInsert buf iter string+ textBufferInsert buf iter (T.unpack text) iter2 <- textBufferGetEndIter buf let tagName = case tag of LogTag -> Nothing@@ -258,12 +484,12 @@ FrameTag -> Just "frame" InputTag -> Just "input" InfoTag -> Just "info"-+ let tv = logLaunchTextView log case tagName of Nothing -> return () Just name -> do len <- textBufferGetCharCount buf- strti <- textBufferGetIterAtOffset buf (len - length string)+ strti <- textBufferGetIterAtOffset buf (len - T.length text) textBufferApplyTagByName buf name iter2 strti textBufferMoveMarkByName buf "end" iter2@@ -274,9 +500,10 @@ Just mark -> textViewScrollMarkOnscreen tv mark return line -markErrorInLog :: IDELog -> (Int,Int) -> IO ()-markErrorInLog (IDELog tv _) (l1,l2) = do- idleAdd (do+markErrorInLog :: IDELog -> (Int,Int) -> IDEAction+markErrorInLog log (l1,l2) = do+ let tv = logLaunchTextView log+ liftIO $ idleAdd (do buf <- textViewGetBuffer tv iter <- textBufferGetIterAtLineOffset buf (l1-1) 0 iter2 <- textBufferGetIterAtLineOffset buf l2 0@@ -295,52 +522,9 @@ clearLog :: IDEAction clearLog = do log <- getLog- buf <- liftIO$ textViewGetBuffer $textView log- liftIO $textBufferSetText buf ""+ buf <- liftIO $ textViewGetBuffer $ logLaunchTextView log+ liftIO $ textBufferSetText buf "" -- modifyIDE_ (\ide -> ide{allLogRefs = []}) -- setCurrentError Nothing -- setCurrentBreak Nothing TODO: Check with Hamish------ ------------------------------------------------------------------------ ** Spawning external processes-----readOut :: IDELog -> Handle -> IO ()-readOut log hndl =- catch (readAndShow)- (\(e :: SomeException) -> do- --appendLog log ("----------------------------------------\n") FrameTag- hClose hndl- return ())- where- readAndShow = do- line <- hGetLine hndl- appendLog log (line ++ "\n") LogTag- readAndShow--readErr :: IDELog -> Handle -> IO ()-readErr log hndl =- catch (readAndShow)- (\(e :: SomeException) -> do- hClose hndl- return ())- where- readAndShow = do- line <- hGetLine hndl- appendLog log (line ++ "\n") ErrorTag- readAndShow--runExternal :: FilePath -> [String] -> IO (Handle, Handle, Handle, ProcessHandle)-runExternal path args = do- putStrLn $ "Run external called with args " ++ show args- hndls@(inp, out, err, _) <- runInteractiveProcess path args Nothing Nothing- sysMessage Normal $ "Starting external tool: " ++ path ++ " with args " ++ (show args)- hSetBuffering out NoBuffering- hSetBuffering err NoBuffering- hSetBuffering inp NoBuffering- hSetBinaryMode out True- hSetBinaryMode err True- return hndls
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleInstances, DeriveDataTypeable, MultiParamTypeClasses,+{-# LANGUAGE CPP, FlexibleInstances, DeriveDataTypeable, MultiParamTypeClasses, ScopedTypeVariables, TypeSynonymInstances #-} ----------------------------------------------------------------------------- --@@ -18,7 +18,8 @@ module IDE.Pane.Modules ( IDEModules(..) , ModulesState(..)---, showInterface+, ExpanderState(..)+, showModules , selectIdentifier , reloadKeepSelection , replaySelHistory@@ -50,19 +51,24 @@ import System.FilePath (takeBaseName, (</>),dropFileName) import System.Directory (doesFileExist,createDirectoryIfMissing, removeFile) import Graphics.UI.Editor.MakeEditor (buildEditor,FieldDescription(..),mkField)-import Graphics.UI.Editor.Parameters (paraMultiSel,Parameter(..),emptyParams,(<<<-),paraName)+import Graphics.UI.Editor.Parameters+ (paraMinSize, paraMultiSel, Parameter(..), emptyParams, (<<<-),+ paraName) import Graphics.UI.Editor.Simple (boolEditor,staticListEditor,stringEditor) import qualified System.IO.UTF8 as UTF8 (writeFile)-import IDE.Utils.GUIUtils (stockIdFromType)+import IDE.Utils.GUIUtils (stockIdFromType, __) import IDE.Metainfo.Provider (getSystemInfo, getWorkspaceInfo, getPackageInfo)-import System.Log.Logger (infoM)+import System.Log.Logger (debugM) import Default (Default(..)) import IDE.Workspaces (packageTry) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad (when) import Control.Monad.Trans.Class (MonadTrans(..)) import Control.Monad.Trans.Reader (ask)+import IDE.Utils.GUIUtils (treeViewContextMenu)+import System.Glib.Properties (newAttrFromMaybeStringProperty)+import Text.Printf (printf) -- | A modules pane description --@@ -112,7 +118,7 @@ instance Pane IDEModules IDEM where- primPaneName _ = "Modules"+ primPaneName _ = (__ "Modules") getAddedIndex _ = 0 getTopWidget = castToWidget . outer paneId b = "*Modules"@@ -122,6 +128,10 @@ getModules Nothing = forceGetPane (Right "*Modules") getModules (Just pp) = forceGetPane (Left pp) +showModules :: IDEAction+showModules = do+ pane <- getModules Nothing+ displayPane pane False instance RecoverablePane IDEModules ModulesState IDEM where saveState p = do@@ -164,11 +174,11 @@ --treeViewSetRulesHint treeView True renderer0 <- cellRendererPixbufNew- set renderer0 [ cellPixbufStockId := "" ]+ set renderer0 [ newAttrFromMaybeStringProperty "stock-id" := Nothing ] renderer <- cellRendererTextNew col <- treeViewColumnNew- treeViewColumnSetTitle col "Module"+ treeViewColumnSetTitle col (__ "Module") treeViewColumnSetSizing col TreeViewColumnAutosize treeViewColumnSetResizable col True treeViewColumnSetReorderable col True@@ -179,16 +189,16 @@ $ \row -> [ cellText := fst row] cellLayoutSetAttributes col renderer0 treeStore $ \row -> [- cellPixbufStockId :=+ newAttrFromMaybeStringProperty "stock-id" := case snd row of- Nothing -> ""+ Nothing -> Nothing Just pair -> if isJust (mdMbSourcePath (fst pair))- then "ide_source"- else ""]+ then Just "ide_source"+ else Nothing] renderer2 <- cellRendererTextNew col2 <- treeViewColumnNew- treeViewColumnSetTitle col2 "Package"+ treeViewColumnSetTitle col2 (__ "Package") treeViewColumnSetSizing col2 TreeViewColumnAutosize treeViewColumnSetResizable col2 True treeViewColumnSetReorderable col2 True@@ -213,7 +223,7 @@ renderer31 <- cellRendererPixbufNew renderer3 <- cellRendererTextNew col <- treeViewColumnNew- treeViewColumnSetTitle col "Interface"+ treeViewColumnSetTitle col (__ "Interface") --treeViewColumnSetSizing col TreeViewColumnAutosize treeViewAppendColumn descrView col cellLayoutPackStart col renderer30 False@@ -233,7 +243,7 @@ if dscExported row then "ide_source" else "ide_source_local"- else ""]+ else "ide_empty"] treeViewSetHeadersVisible descrView True treeViewSetEnableSearch descrView True treeViewSetSearchEqualFunc descrView (Just (descrViewSearch descrView descrStore))@@ -246,15 +256,15 @@ scrolledWindowSetPolicy sw2 PolicyAutomatic PolicyAutomatic panedAdd1 pane' sw panedAdd2 pane' sw2- (x,y) <- widgetGetSize nb+ (Rectangle _ _ x y) <- liftIO $ widgetGetAllocation nb panedSetPosition pane' (max 200 (x `quot` 2)) box <- hBoxNew True 2- rb1 <- radioButtonNewWithLabel "Package"- rb2 <- radioButtonNewWithLabelFromWidget rb1 "Workspace"- rb3 <- radioButtonNewWithLabelFromWidget rb1 "System"+ rb1 <- radioButtonNewWithLabel (__ "Package")+ rb2 <- radioButtonNewWithLabelFromWidget rb1 (__ "Workspace")+ rb3 <- radioButtonNewWithLabelFromWidget rb1 (__ "System") toggleButtonSetActive rb3 True- cb2 <- checkButtonNewWithLabel "Imports"- cb <- checkButtonNewWithLabel "Blacklist"+ cb2 <- checkButtonNewWithLabel (__ "Imports")+ cb <- checkButtonNewWithLabel (__ "Blacklist") boxPackStart box rb1 PackGrow 2 boxPackStart box rb2 PackGrow 2@@ -271,35 +281,36 @@ scopeRef <- newIORef (SystemScope,True) let modules = IDEModules boxOuter pane' treeView treeStore descrView descrStore rb1 rb2 rb3 cb2 cb oldState expanderState- cid3 <- treeView `onRowActivated`- (\ treePath _ -> do- treeViewExpandRow treeView treePath False- return ())- cid1 <- treeView `afterFocusIn`- (\_ -> do reflectIDE (makeActive modules) ideR; return True)- cid2 <- descrView `afterFocusIn`- (\_ -> do reflectIDE (makeActive modules) ideR; return True)- treeView `onButtonPress` (treeViewPopup ideR treeStore treeView)- descrView `onButtonPress` (descrViewPopup ideR descrStore descrView)- rb1 `onToggled` (reflectIDE scopeSelection ideR)- rb2 `onToggled` (reflectIDE scopeSelection ideR)- rb3 `onToggled` (reflectIDE scopeSelection ideR)- cb `onToggled` (reflectIDE scopeSelection ideR)- cb2 `onToggled` (reflectIDE scopeSelection ideR)+ cid1 <- after treeView focusInEvent $ do+ liftIO $ reflectIDE (makeActive modules) ideR+ return True+ cid2 <- after descrView focusInEvent $ do+ liftIO $ reflectIDE (makeActive modules) ideR+ return True+ (cid3, cid4) <- treeViewContextMenu treeView $ modulesContextMenu ideR treeStore treeView+ cid5 <- treeView `on` rowActivated $ modulesSelect ideR treeStore treeView+ (cid6, cid7) <- treeViewContextMenu descrView $ descrViewContextMenu ideR descrStore descrView+ cid8 <- descrView `on` rowActivated $ descrViewSelect ideR descrStore+ on rb1 toggled (reflectIDE scopeSelection ideR)+ on rb2 toggled (reflectIDE scopeSelection ideR)+ on rb3 toggled (reflectIDE scopeSelection ideR)+ on cb toggled (reflectIDE scopeSelection ideR)+ on cb2 toggled (reflectIDE scopeSelection ideR) sel <- treeViewGetSelection treeView- sel `onSelectionChanged` do+ on sel treeSelectionSelectionChanged $ do fillFacets treeView treeStore descrView descrStore reflectIDE recordSelHistory ideR return () sel2 <- treeViewGetSelection descrView- sel2 `onSelectionChanged` do+ on sel2 treeSelectionSelectionChanged $ do fillInfo descrView descrStore ideR reflectIDE recordSelHistory ideR return ()- return (Just modules,[ConnectC cid1,ConnectC cid2, ConnectC cid3])+ return (Just modules,map ConnectC [cid1, cid2, cid3, cid4, cid5, cid6, cid7, cid8]) selectIdentifier :: Descr -> Bool -> IDEAction selectIdentifier idDescr openSource= do+ liftIO $ debugM "leksah" "selectIdentifier" systemScope <- getSystemInfo workspaceScope <- getWorkspaceInfo packageScope <- getPackageInfo@@ -350,6 +361,7 @@ selectIdentifier' moduleName symbol = let nameArray = components moduleName in do+ liftIO $ debugM "leksah" "selectIdentifier'" mods <- getModules Nothing mbTree <- liftIO $ treeStoreGetTreeSave (treeStore mods) [] case treePathFromNameArray mbTree nameArray [] of@@ -362,7 +374,7 @@ mbFacetTree <- treeStoreGetTreeSave (descrStore mods) [] selF <- treeViewGetSelection (descrView mods) case findPathFor symbol mbFacetTree of- Nothing -> sysMessage Normal "no path found"+ Nothing -> sysMessage Normal (__ "no path found") Just path -> do treeViewExpandToPath (descrView mods) path treeSelectionSelectPath selF path@@ -402,6 +414,7 @@ -> TreeIter -> IO Bool treeViewSearch treeView treeStore string iter = do+ liftIO $ debugM "leksah" "treeViewSearch" path <- treeModelGetPath treeStore iter val <- treeStoreGetValue treeStore path mbTree <- treeStoreGetTreeSave treeStore path@@ -434,6 +447,7 @@ -> TreeIter -> IO Bool descrViewSearch descrView descrStore string iter = do+ liftIO $ debugM "leksah" "descrViewSearch" path <- treeModelGetPath descrStore iter val <- treeStoreGetValue descrStore path tree <- treeStoreGetTree descrStore path@@ -458,6 +472,7 @@ -> TreeStore Descr -> IO () fillFacets treeView treeStore descrView descrStore = do+ liftIO $ debugM "leksah" "fillFacets" sel <- getSelectionTree treeView treeStore case sel of Just (_,Just (mod,package))@@ -477,6 +492,7 @@ -> TreeStore (String, Maybe (ModuleDescr,PackageDescr)) -> IO (Maybe (String, Maybe (ModuleDescr,PackageDescr))) getSelectionTree treeView treeStore = do+ liftIO $ debugM "leksah" "getSelectionTree" treeSelection <- treeViewGetSelection treeView paths <- treeSelectionGetSelectedRows treeSelection case paths of@@ -489,6 +505,7 @@ -> TreeStore Descr -> IO (Maybe Descr) getSelectionDescr treeView treeStore = do+ liftIO $ debugM "leksah" "getSelectionDescr" treeSelection <- treeViewGetSelection treeView paths <- treeSelectionGetSelectedRows treeSelection case paths of@@ -503,6 +520,7 @@ -> IDERef -> IO () fillInfo treeView lst ideR = do+ liftIO $ debugM "leksah" "fillInfo" treeSelection <- treeViewGetSelection treeView paths <- treeSelectionGetSelectedRows treeSelection case paths of@@ -526,6 +544,7 @@ fillModulesList :: (Scope,Bool) -> IDEAction fillModulesList (scope,useBlacklist) = do+ liftIO $ debugM "leksah" "fillModulesList" mods <- getModules Nothing prefs <- readIDE prefs case scope of@@ -734,13 +753,13 @@ (found,rest) -> Node p (insertNodesInTree tl (head found) : tail found ++ rest) insertNodesInTree [] n = n-insertNodesInTree _ _ = error "Modules>>insertNodesInTree: Should not happen2"+insertNodesInTree _ _ = error (__ "Modules>>insertNodesInTree: Should not happen2") makeNodes :: [(String,Maybe (ModuleDescr,PackageDescr))] -> ModTree makeNodes [(str,mbPair)] = Node (str,mbPair) [] makeNodes ((str,mbPair):tl) = Node (str,mbPair) [makeNodes tl]-makeNodes _ = throwIDE "Impossible in makeNodes"+makeNodes _ = throwIDE (__ "Impossible in makeNodes") instance Ord a => Ord (Tree a) where compare (Node l1 _) (Node l2 _) = compare l1 l2@@ -748,129 +767,118 @@ sortTree :: Ord a => Tree a -> Tree a sortTree (Node l forest) = Node l (sort (map sortTree forest)) -treeViewPopup :: IDERef- -> TreeStore (String, Maybe (ModuleDescr,PackageDescr))- -> TreeView- -> Event- -> IO (Bool)-treeViewPopup ideR store treeView (Button _ click _ _ _ _ button _ _) = do- if button == RightButton- then do- theMenu <- menuNew- item1 <- menuItemNewWithLabel "Edit source"- item1 `onActivateLeaf` do- sel <- getSelectionTree treeView store- case sel of- Just (_,Just (m,_)) -> case mdMbSourcePath m of- Nothing -> return ()- Just fp -> do- reflectIDE (selectSourceBuf fp) ideR+modulesContextMenu :: IDERef+ -> TreeStore (String, Maybe (ModuleDescr,PackageDescr))+ -> TreeView+ -> Menu+ -> IO ()+modulesContextMenu ideR store treeView theMenu = do+ liftIO $ debugM "leksah" "modulesContextMenu"+ item1 <- menuItemNewWithLabel (__ "Edit source")+ item1 `on` menuItemActivate $ do+ sel <- getSelectionTree treeView store+ case sel of+ Just (_,Just (m,_)) -> case mdMbSourcePath m of+ Nothing -> return ()+ Just fp -> do+ reflectIDE (selectSourceBuf fp) ideR+ return ()+ otherwise -> return ()+ sep1 <- separatorMenuItemNew+ item2 <- menuItemNewWithLabel (__ "Expand here")+ item2 `on` menuItemActivate $ expandHere treeView+ item3 <- menuItemNewWithLabel (__ "Collapse here")+ item3 `on` menuItemActivate $ collapseHere treeView+ item4 <- menuItemNewWithLabel (__ "Expand all")+ item4 `on` menuItemActivate $ treeViewExpandAll treeView+ item5 <- menuItemNewWithLabel (__ "Collapse all")+ item5 `on` menuItemActivate $ treeViewCollapseAll treeView+ sep2 <- separatorMenuItemNew+ item6 <- menuItemNewWithLabel (__ "Add module")+ item6 `on` menuItemActivate $ reflectIDE (packageTry $ addModule' treeView store) ideR+ item7 <- menuItemNewWithLabel (__ "Delete module")+ item7 `on` menuItemActivate $ do+ sel <- getSelectionTree treeView store+ case sel of+ Just (_,Just (m,_)) -> case mdMbSourcePath m of+ Nothing -> return ()+ Just fp -> do+ resp <- reflectIDE (respDelModDialog)ideR+ if (resp == False) then return ()+ else do+ exists <- doesFileExist fp+ if exists+ then do+ reflectIDE (liftIO $ removeFile fp) ideR+ reflectIDE (packageTry $ delModule treeView store)ideR+ else do+ reflectIDE (packageTry $ delModule treeView store)ideR+ reflectIDE (packageTry packageConfig) ideR return ()- otherwise -> return ()- sep1 <- separatorMenuItemNew- item2 <- menuItemNewWithLabel "Expand here"- item2 `onActivateLeaf` (expandHere treeView)- item3 <- menuItemNewWithLabel "Collapse here"- item3 `onActivateLeaf` (collapseHere treeView)- item4 <- menuItemNewWithLabel "Expand all"- item4 `onActivateLeaf` (treeViewExpandAll treeView)- item5 <- menuItemNewWithLabel "Collapse all"- item5 `onActivateLeaf` (treeViewCollapseAll treeView)- sep2 <- separatorMenuItemNew- item6 <- menuItemNewWithLabel "Add module"- item6 `onActivateLeaf` (reflectIDE (packageTry $ addModule' treeView store) ideR)- item7 <- menuItemNewWithLabel "Delete module"- item7 `onActivateLeaf` do- sel <- getSelectionTree treeView store- case sel of- Just (_,Just (m,_)) -> case mdMbSourcePath m of- Nothing -> return ()- Just fp -> do- resp <- reflectIDE (respDelModDialog)ideR- if (resp == False) then return ()- else do- exists <- doesFileExist fp- if exists- then do- reflectIDE (liftIO $ removeFile fp) ideR- reflectIDE (packageTry $ delModule treeView store)ideR- else do- reflectIDE (packageTry $ delModule treeView store)ideR- reflectIDE (packageTry packageConfig) ideR- return ()- otherwise -> return ()- sel <- getSelectionTree treeView store- case sel of- Just (s, Nothing) -> do- mapM_ (menuShellAppend theMenu) [castToMenuItem item1, castToMenuItem sep1, castToMenuItem item2,- castToMenuItem item3, castToMenuItem item4, castToMenuItem item5, castToMenuItem sep2,- castToMenuItem item6]- menuPopup theMenu Nothing- widgetShowAll theMenu- return True- Just (_,Just (m,_)) -> do- mapM_ (menuShellAppend theMenu) [castToMenuItem item1, castToMenuItem sep1, castToMenuItem item2,- castToMenuItem item3, castToMenuItem item4, castToMenuItem item5, castToMenuItem sep2,- castToMenuItem item6, castToMenuItem item7]- menuPopup theMenu Nothing- widgetShowAll theMenu- return True- otherwise -> return True-- else if button == LeftButton && click == DoubleClick- then do sel <- getSelectionTree treeView store- case sel of- Just (_,Just (m,_)) -> case mdMbSourcePath m of- Nothing -> return ()- Just fp -> do- reflectIDE (selectSourceBuf fp) ideR- return ()- otherwise -> return ()- return True- else return False+ otherwise -> return ()+ sel <- getSelectionTree treeView store+ case sel of+ Just (s, Nothing) -> do+ mapM_ (menuShellAppend theMenu) [castToMenuItem item1, castToMenuItem sep1, castToMenuItem item2,+ castToMenuItem item3, castToMenuItem item4, castToMenuItem item5, castToMenuItem sep2,+ castToMenuItem item6]+ Just (_,Just (m,_)) -> do+ mapM_ (menuShellAppend theMenu) [castToMenuItem item1, castToMenuItem sep1, castToMenuItem item2,+ castToMenuItem item3, castToMenuItem item4, castToMenuItem item5, castToMenuItem sep2,+ castToMenuItem item6, castToMenuItem item7]+ otherwise -> return () -treeViewPopup _ _ _ _ = throwIDE "treeViewPopup wrong event type"+modulesSelect :: IDERef+ -> TreeStore (String, Maybe (ModuleDescr,PackageDescr))+ -> TreeView+ -> TreePath+ -> TreeViewColumn+ -> IO ()+modulesSelect ideR store treeView path _ = do+ liftIO $ debugM "leksah" "modulesSelect"+ treeViewExpandRow treeView path False+ sel <- treeStoreGetValue store path+ case sel of+ (_,Just (m,_)) -> do+ case mdMbSourcePath m of+ Nothing -> return ()+ Just fp -> liftIO $ reflectIDE (selectSourceBuf fp) ideR >> return ()+ _ -> return () -descrViewPopup :: IDERef- -> TreeStore Descr- -> TreeView- -> Event- -> IO (Bool)-descrViewPopup ideR store descrView (Button _ click _ _ _ _ button _ _) = do- if button == RightButton- then do- theMenu <- menuNew- item1 <- menuItemNewWithLabel "Go to definition"- item1 `onActivateLeaf` do- sel <- getSelectionDescr descrView store- case sel of- Just descr -> reflectIDE (goToDefinition descr) ideR- otherwise -> sysMessage Normal "Modules>> descrViewPopup: no selection"- item2 <- menuItemNewWithLabel "Insert in buffer"- item2 `onActivateLeaf` do- sel <- getSelectionDescr descrView store- case sel of- Just descr -> reflectIDE (insertInBuffer descr) ideR- otherwise -> sysMessage Normal "Modules>> descrViewPopup: no selection"- mapM_ (menuShellAppend theMenu) [item1, item2]- menuPopup theMenu Nothing- widgetShowAll theMenu- return True- else if button == LeftButton && click == DoubleClick- then do sel <- getSelectionDescr descrView store- case sel of- Just descr -> reflectIDE (goToDefinition descr) ideR- otherwise -> sysMessage Normal "Modules>> descrViewPopup: no selection2"- return True- else do- mbPane :: Maybe IDEInfo <- reflectIDE getPane ideR- when (isJust mbPane) $ bringPaneToFront (fromJust mbPane)- return False+descrViewContextMenu :: IDERef+ -> TreeStore Descr+ -> TreeView+ -> Menu+ -> IO ()+descrViewContextMenu ideR store descrView theMenu = do+ liftIO $ debugM "leksah" "descrViewContextMenu"+ item1 <- menuItemNewWithLabel (__ "Go to definition")+ item1 `on` menuItemActivate $ do+ sel <- getSelectionDescr descrView store+ case sel of+ Just descr -> reflectIDE (goToDefinition descr) ideR+ otherwise -> sysMessage Normal (__ "Modules>> descrViewPopup: no selection")+ item2 <- menuItemNewWithLabel (__ "Insert in buffer")+ item2 `on` menuItemActivate $ do+ sel <- getSelectionDescr descrView store+ case sel of+ Just descr -> reflectIDE (insertInBuffer descr) ideR+ otherwise -> sysMessage Normal (__ "Modules>> descrViewPopup: no selection")+ mapM_ (menuShellAppend theMenu) [item1, item2] -descrViewPopup _ _ _ _ = throwIDE "descrViewPopup wrong event type"+descrViewSelect :: IDERef+ -> TreeStore Descr+ -> TreePath+ -> TreeViewColumn+ -> IO ()+descrViewSelect ideR store path _ = do+ liftIO $ debugM "leksah" "descrViewSelect"+ descr <- treeStoreGetValue store path+ reflectIDE (goToDefinition descr) ideR setScope :: (Scope,Bool) -> IDEAction setScope (sc,bl) = do+ liftIO $ debugM "leksah" "setScope" mods <- getModules Nothing case sc of (PackageScope False) -> liftIO $ do@@ -897,6 +905,7 @@ getScope :: IDEM (Scope,Bool) getScope = do+ liftIO $ debugM "leksah" "getScope" mods <- getModules Nothing rb1s <- liftIO $ toggleButtonGetActive (packageScopeB mods) rb2s <- liftIO $ toggleButtonGetActive (workspaceScopeB mods)@@ -912,12 +921,14 @@ scopeSelection :: IDEAction scopeSelection = do+ liftIO $ debugM "leksah" "scopeSelection" (sc,bl) <- getScope setScope (sc,bl) selectScope (sc,bl) selectScope :: (Scope,Bool) -> IDEAction selectScope (sc,bl) = do+ liftIO $ debugM "leksah" "selectScope" recordExpanderState mods <- getModules Nothing mbTreeSelection <- liftIO $ getSelectionTree (treeView mods) (treeStore mods)@@ -941,6 +952,7 @@ selectNames :: (Maybe ModuleName, Maybe String) -> IDEAction selectNames (mbModuleName, mbIdName) = do+ liftIO $ debugM "leksah" "selectIdentifier" mods <- getModules Nothing case mbModuleName of Nothing -> liftIO $ do@@ -969,7 +981,7 @@ mbDescrTree <- treeStoreGetTreeSave (descrStore mods) [] selF <- treeViewGetSelection (descrView mods) case findPathFor symbol mbDescrTree of- Nothing -> sysMessage Normal "no path found"+ Nothing -> sysMessage Normal (__ "no path found") Just path -> do treeSelectionSelectPath selF path col <- treeViewGetColumn (descrView mods) 0@@ -978,7 +990,7 @@ reloadKeepSelection :: Bool -> IDEAction reloadKeepSelection isInitial = do- liftIO $ infoM "leksah" (">>>Info Changed!!! " ++ show isInitial)+ liftIO $ debugM "leksah" ((__ ">>>Info Changed!!! ") ++ show isInitial) mbMod <- getPane case mbMod of Nothing -> return ()@@ -1012,11 +1024,13 @@ treeStoreGetTreeSave :: TreeStore a -> TreePath -> IO (Maybe (Tree a)) treeStoreGetTreeSave treeStore treePath = catch (do+ liftIO $ debugM "leksah" "treeStoreGetTreeSave" res <- treeStoreGetTree treeStore treePath return (Just res)) (\ (_ :: SomeException) -> return Nothing) expandHere :: TreeView -> IO () expandHere treeView = do+ liftIO $ debugM "leksah" "expandHere" sel <- treeViewGetSelection treeView paths <- treeSelectionGetSelectedRows sel case paths of@@ -1025,6 +1039,7 @@ collapseHere :: TreeView -> IO () collapseHere treeView = do+ liftIO $ debugM "leksah" "collapseHere" sel <- treeViewGetSelection treeView paths <- treeSelectionGetSelectedRows sel case paths of@@ -1033,6 +1048,7 @@ delModule :: TreeView -> TreeStore (String, Maybe (ModuleDescr,PackageDescr)) -> PackageAction delModule treeview store = do+ liftIO $ debugM "leksah" "delModule" window <- lift $ getMainWindow sel <- liftIO $ treeViewGetSelection treeview paths <- liftIO $ treeSelectionGetSelectedRows sel@@ -1041,11 +1057,11 @@ (treePath:_) -> liftIO $ mapM (treeStoreGetValue store) $ map (\n -> take n treePath) [1 .. length treePath] - lift $ ideMessage Normal ("categories: " ++ (show categories))+ lift $ ideMessage Normal (printf (__ "categories: %s") (show categories)) let modPacDescr = snd(last categories) case modPacDescr of- Nothing -> lift $ ideMessage Normal "This should never be shown!"+ Nothing -> lift $ ideMessage Normal (__ "This should never be shown!") Just(md,_) -> do let modName = modu.mdModuleId $ md lift $ ideMessage Normal ("modName: " ++ (show modName))@@ -1053,10 +1069,11 @@ respDelModDialog :: IDEM (Bool) respDelModDialog = do+ liftIO $ debugM "leksah" "respDelModDialog" window <- getMainWindow resp <- liftIO $ do- dia <- messageDialogNew (Just window) [] MessageQuestion ButtonsCancel "Are you sure?"- dialogAddButton dia "_Delete Module" (ResponseUser 1)+ dia <- messageDialogNew (Just window) [] MessageQuestion ButtonsCancel (__ "Are you sure?")+ dialogAddButton dia (__ "_Delete Module") (ResponseUser 1) dialogSetDefaultResponse dia ResponseCancel set dia [ windowWindowPosition := WinPosCenterOnParent ] resp <- dialogRun dia@@ -1066,6 +1083,7 @@ addModule' :: TreeView -> TreeStore (String, Maybe (ModuleDescr,PackageDescr)) -> PackageAction addModule' treeView store = do+ liftIO $ debugM "leksah" "addModule'" sel <- liftIO $ treeViewGetSelection treeView paths <- liftIO $ treeSelectionGetSelectedRows sel categories <- case paths of@@ -1075,9 +1093,10 @@ addModule categories addModule categories = do+ liftIO $ debugM "leksah" "selectIdentifier" mbPD <- lift $ getPackageDescriptionAndPath case mbPD of- Nothing -> lift $ ideMessage Normal "No package description"+ Nothing -> lift $ ideMessage Normal (__ "No package description") Just (pd,cabalPath) -> let srcPaths = nub $ concatMap hsSourceDirs $ allBuildInfo pd rootPath = dropFileName cabalPath modPath = foldr (\a b -> a ++ "." ++ b) ""@@ -1089,14 +1108,14 @@ Nothing -> return () Just (AddModule modPath srcPath isExposed) -> case simpleParse modPath of- Nothing -> lift $ ideMessage Normal ("Not a valid module name :" ++ modPath)+ Nothing -> lift $ ideMessage Normal (printf (__ "Not a valid module name : %s") modPath) Just moduleName -> do let target = srcPath </> toFilePath moduleName ++ ".hs" liftIO $ createDirectoryIfMissing True (dropFileName target) alreadyExists <- liftIO $ doesFileExist target if alreadyExists then do- lift $ ideMessage Normal ("File already exists! Importing existing file " ++ takeBaseName target ++ ".hs")+ lift $ ideMessage Normal (printf (__ "File already exists! Importing existing file %s.hs") (takeBaseName target)) addModuleToPackageDescr moduleName isExposed packageConfig else do@@ -1113,10 +1132,15 @@ addModuleDialog :: Window -> String -> [String] -> IO (Maybe AddModule) addModuleDialog parent modString sourceRoots = do+ liftIO $ debugM "leksah" "addModuleDialog" dia <- dialogNew- windowSetTransientFor dia parent- windowSetTitle dia "Construct new module"+ set dia [ windowTransientFor := parent+ , windowTitle := (__ "Construct new module") ]+#ifdef MIN_VERSION_gtk3+ upper <- dialogGetContentArea dia+#else upper <- dialogGetUpper dia+#endif lower <- dialogGetActionArea dia (widget,inj,ext,_) <- buildEditor (moduleFields sourceRoots) (AddModule modString (head sourceRoots) False)@@ -1125,10 +1149,10 @@ save <- buttonNewFromStock "gtk-ok" boxPackEnd bb closeB PackNatural 0 boxPackEnd bb save PackNatural 0- save `onClicked` (dialogResponse dia ResponseOk)- closeB `onClicked` (dialogResponse dia ResponseCancel)- boxPackStart upper widget PackGrow 7- boxPackStart lower bb PackNatural 7+ on save buttonActivated (dialogResponse dia ResponseOk)+ on closeB buttonActivated (dialogResponse dia ResponseCancel)+ boxPackStart (castToBox upper) widget PackGrow 7+ boxPackStart (castToBox lower) bb PackNatural 7 set save [widgetCanDefault := True] widgetGrabDefault save widgetShowAll dia@@ -1143,20 +1167,21 @@ moduleFields :: [FilePath] -> FieldDescription AddModule moduleFields list = VFD emptyParams [ mkField- (paraName <<<- ParaName ("New module ")+ (paraName <<<- ParaName ((__ "New module ")) $ emptyParams) moduleName (\ a b -> b{moduleName = a}) (stringEditor (const True) True), mkField- (paraName <<<- ParaName ("Root of the source path")+ (paraName <<<- ParaName ((__ "Root of the source path")) $ paraMultiSel <<<- ParaMultiSel False- $ emptyParams)+ $ paraMinSize <<<- ParaMinSize (-1, 120)+ $ emptyParams) (\a -> sourceRoot a) (\ a b -> b{sourceRoot = a}) (staticListEditor list id), mkField- (paraName <<<- ParaName ("Is this an exposed library module")+ (paraName <<<- ParaName ((__ "Is this an exposed library module")) $ emptyParams) isExposed (\ a b -> b{isExposed = a})@@ -1168,6 +1193,7 @@ recordExpanderState :: IDEAction recordExpanderState = do+ liftIO $ debugM "leksah" "recordExpanderState" m <- getModules Nothing liftIO $ do oldSel <- readIORef (oldSelection m)@@ -1194,6 +1220,7 @@ getExpandedRows :: TreeView -> TreeStore alpha -> IO [TreePath] getExpandedRows view store = do+ liftIO $ debugM "leksah" "getExpandedRows" mbIter <- treeModelGetIterFirst store case mbIter of Nothing -> return []@@ -1218,6 +1245,7 @@ applyExpanderState :: IDEAction applyExpanderState = do+ liftIO $ debugM "leksah" "applyExpanderState" m <- getModules Nothing (sc,bl) <- getScope liftIO $ do@@ -1240,6 +1268,7 @@ recordSelHistory :: IDEAction recordSelHistory = do+ liftIO $ debugM "leksah" "selectIdentifier" mods <- getModules Nothing ideR <- ask selTree <- liftIO $ getSelectionTree (treeView mods) (treeStore mods)@@ -1258,6 +1287,7 @@ replaySelHistory :: Maybe ModuleName -> Maybe String -> IDEAction replaySelHistory mbModName mbFacetName = do+ liftIO $ debugM "leksah" "replaySelHistory" mods <- getModules Nothing selectNames (mbModName, mbFacetName) oldSel <- liftIO $ readIORef (oldSelection mods)@@ -1266,6 +1296,7 @@ recordScopeHistory :: IDEAction recordScopeHistory = do+ liftIO $ debugM "leksah" "recordScopeHistory" (sc,bl) <- getScope ideR <- ask mods <- getModules Nothing@@ -1277,6 +1308,7 @@ replayScopeHistory :: Scope -> Bool -> IDEAction replayScopeHistory sc bl = do+ liftIO $ debugM "leksah" "selectIdentifier" mods <- getModules Nothing liftIO $ do toggleButtonSetActive (blacklistB mods) bl
@@ -1,1388 +1,1604 @@-{-# LANGUAGE FlexibleInstances, ScopedTypeVariables, DeriveDataTypeable, - CPP, MultiParamTypeClasses, TypeSynonymInstances #-} ------------------------------------------------------------------------------ --- --- Module : IDE.Pane.PackageEditor --- Copyright : (c) Juergen Nicklisch-Franken, Hamish Mackenzie --- License : GNU-GPL --- --- Maintainer : Juergen Nicklisch-Franken <info@leksah.org> --- Stability : provisional --- Portability : portable --- --- | Module for editing of cabal packages and build infos --- ------------------------------------------------------------------------------------ - - -module IDE.Pane.PackageEditor ( - packageNew' -, packageEdit -, choosePackageDir -, choosePackageFile - -, hasConfigs -, standardSetup -) where - -import Graphics.UI.Gtk -import Distribution.Package -import Distribution.PackageDescription -import Distribution.Verbosity -import System.FilePath -import Data.Maybe -import System.Directory - -import IDE.Core.State -import IDE.Utils.FileUtils -import Graphics.UI.Editor.MakeEditor -import Distribution.PackageDescription.Parse (readPackageDescription) -import Distribution.PackageDescription.Configuration (flattenPackageDescription) -import Distribution.ModuleName(ModuleName) -import Data.Typeable (Typeable(..)) -import Graphics.UI.Editor.Composite - (versionEditor, - versionRangeEditor, - dependenciesEditor, - stringsEditor, - filesEditor, - tupel3Editor, - eitherOrEditor, - maybeEditor, - pairEditor, - ColumnDescr(..), - multisetEditor) -import Distribution.Text (simpleParse, display) -import MyMissing -import Graphics.UI.Editor.Parameters - (paraInnerPadding, - paraInnerAlignment, - paraOuterPadding, - paraOuterAlignment, - Parameter(..), - paraPack, - Direction(..), - paraDirection, - paraMinSize, - paraShadow, - paraSynopsis, - (<<<-), - emptyParams, - paraName, - getParameterPrim) -import Graphics.UI.Editor.Simple - (staticListMultiEditor, - intEditor, - boolEditor, - fileEditor, - comboSelectionEditor, - multilineStringEditor, - stringEditor) -import Graphics.UI.Editor.Basics - (Notifier, Editor(..), GUIEventSelector(..), GUIEvent(..)) -import Distribution.Compiler - (CompilerFlavor(..)) -#if !MIN_VERSION_Cabal(1,11,0) -import Distribution.Simple (knownExtensions) -#endif -import Distribution.Simple (Extension(..), VersionRange, anyVersion) -import Default (Default(..)) -import IDE.Utils.GUIUtils -import IDE.Pane.SourceBuffer (fileOpenThis) -import Control.Event (EventSource(..)) -#if !MIN_VERSION_Cabal(1,8,0) -import Distribution.License -#endif - -import qualified Graphics.UI.Gtk.Gdk.Events as GTK (Event(..)) -import Data.List (sort,nub) -import Control.Monad.Trans.Reader (ask) -import Control.Monad.IO.Class (MonadIO(..)) -import Control.Monad.Trans.Class (lift) -import Control.Monad (when) -#if MIN_VERSION_Cabal(1,10,0) -import Distribution.PackageDescription.PrettyPrintCopied - (writeGenericPackageDescription) -#else -import Distribution.PackageDescription.Parse - (writePackageDescription) -#endif -import Distribution.Version (Version(..), orLaterVersion)- --------------------------------------------------------------------------- --- Handling of Generic Package Descriptions - -#if MIN_VERSION_Cabal(1,10,0) -toGenericPackageDescription :: PackageDescription -> GenericPackageDescription -toGenericPackageDescription pd = - GenericPackageDescription { - packageDescription = pd{ - library = Nothing, - executables = [], - testSuites = [], - buildDepends = []}, - genPackageFlags = [], - condLibrary = case library pd of - Nothing -> Nothing - Just lib -> Just (buildCondTreeLibrary lib), - condExecutables = map buildCondTreeExe (executables pd), - condTestSuites = map buildCondTreeTest (testSuites pd)} - where - buildCondTreeLibrary lib = - CondNode { - condTreeData = lib, - condTreeConstraints = buildDepends pd, - condTreeComponents = []} - buildCondTreeExe exe = - (exeName exe, CondNode { - condTreeData = exe, - condTreeConstraints = buildDepends pd, - condTreeComponents = []}) - buildCondTreeTest test = - (testName test, CondNode { - condTreeData = test, - condTreeConstraints = buildDepends pd, - condTreeComponents = []}) -#endif - --- --------------------------------------------------------------------- --- The exported stuff goes here --- - -choosePackageDir :: Window -> Maybe FilePath -> IO (Maybe FilePath) -choosePackageDir window mbDir = chooseDir window "Select root folder for package" mbDir - -choosePackageFile :: Window -> Maybe FilePath -> IO (Maybe FilePath) -choosePackageFile window mbDir = chooseFile window "Select cabal package file (.cabal)" mbDir - -packageEdit :: PackageAction -packageEdit = do - idePackage <- ask - let dirName = dropFileName (ipdCabalFile idePackage) - modules <- liftIO $ allModules dirName - package <- liftIO $ readPackageDescription normal (ipdCabalFile idePackage) - if hasConfigs package - then do - lift $ ideMessage High ("Cabal file with configurations can't be edited with the " - ++ "current version of the editor") - lift $ fileOpenThis $ ipdCabalFile idePackage - return () - else do- let flat = flattenPackageDescription package-#if MIN_VERSION_Cabal(1,10,0) - if hasUnknownTestTypes flat- then do - lift $ ideMessage High ("Cabal file with tests of this type can't be edited with the " - ++ "current version of the editor") - lift $ fileOpenThis $ ipdCabalFile idePackage - return ()- else do - lift $ editPackage flat dirName modules (\ _ -> return ()) - return () -#else- lift $ editPackage flat dirName modules (\ _ -> return ()) - return () -#endif- -hasConfigs :: GenericPackageDescription -> Bool -hasConfigs gpd = - let libConds = case condLibrary gpd of - Nothing -> False - Just condTree -> not (null (condTreeComponents condTree)) - exeConds = foldr (\ (_,condTree) hasConfigs -> - if hasConfigs - then True - else not (null (condTreeComponents condTree))) - False (condExecutables gpd) -#if MIN_VERSION_Cabal(1,10,0) - testConds = foldr (\ (_,condTree) hasConfigs -> - if hasConfigs - then True - else not (null (condTreeComponents condTree))) - False (condTestSuites gpd) - in libConds || exeConds || testConds -#else- in libConds || exeConds -#endif--#if MIN_VERSION_Cabal(1,10,0) -hasUnknownTestTypes :: PackageDescription -> Bool -hasUnknownTestTypes pd =- not . null . filter unknown $ testSuites pd- where- unknown (TestSuite _ (TestSuiteExeV10 _ _) _ _) = False- unknown _ = True -#endif- -packageNew' :: Maybe FilePath -> (Bool -> FilePath -> IDEAction) -> IDEAction -packageNew' mbDir activateAction = do - windows <- getWindows - mbDirName <- liftIO $ choosePackageDir (head windows) mbDir - case mbDirName of - Nothing -> return () - Just dirName -> do - mbCabalFile <- liftIO $ cabalFileName dirName- window <- getMainWindow - case mbCabalFile of - Just cfn -> do - add <- liftIO $ do - md <- messageDialogNew (Just window) [] MessageQuestion ButtonsCancel - $ "There is already file " ++ takeFileName cfn ++ " in this directory. " - ++ "Would you like to add this package to the workspace?" - dialogAddButton md "_Add Package" (ResponseUser 1) - dialogSetDefaultResponse md (ResponseUser 1) - set md [ windowWindowPosition := WinPosCenterOnParent ] - rid <- dialogRun md - widgetDestroy md - return $ rid == ResponseUser 1 - when add $ activateAction False cfn - Nothing -> do- isEmptyDir <- liftIO $ isEmptyDirectory dirName- make <- if isEmptyDir- then return True- else liftIO $ do - md <- messageDialogNew (Just window) [] MessageQuestion ButtonsCancel - $ "The path you have choosen " ++ dirName ++ " is not an empty directory. " - ++ "Are you sure you want to make a new package here?" - dialogAddButton md "_Make Package Here" (ResponseUser 1) - dialogSetDefaultResponse md (ResponseUser 1) - set md [ windowWindowPosition := WinPosCenterOnParent ] - rid <- dialogRun md - widgetDestroy md - return $ rid == ResponseUser 1 - when make $ do- modules <- liftIO $ do - b1 <- doesFileExist (dirName </> "Setup.hs") - b2 <- doesFileExist (dirName </> "Setup.lhs") - if not (b1 || b2) - then do - sysMessage Normal "Setup.(l)hs does not exist. Writing Standard" - writeFile (dirName </> "Setup.lhs") standardSetup - else sysMessage Normal "Setup.(l)hs already exist" - allModules dirName - let Just initialVersion = simpleParse "0.0.1" - editPackage emptyPackageDescription{- package = PackageIdentifier (PackageName $ takeBaseName dirName) - initialVersion, - buildType = Just Simple, -#if MIN_VERSION_Cabal(1,10,0) - specVersionRaw = Right (orLaterVersion (Version [1,2] [])), -#endif- buildDepends = [- Dependency (PackageName "base") anyVersion- , Dependency (PackageName "QuickCheck") anyVersion], - executables = [emptyExecutable { - exeName = (takeBaseName dirName) - , modulePath = "Main.hs" - , buildInfo = emptyBuildInfo {- hsSourceDirs = ["src"]}}]-#if MIN_VERSION_Cabal(1,10,0) - , testSuites = [emptyTestSuite {- testName = "test-" ++ takeBaseName dirName- , testInterface = (TestSuiteExeV10 (Version [1,0] []) "Main.hs") - , testBuildInfo = emptyBuildInfo {- hsSourceDirs = ["src"]- , cppOptions = ["-DMAIN_FUNCTION=testMain"]}}]-#endif- } dirName modules (activateAction True) - return () - -standardSetup = "#!/usr/bin/runhaskell \n" - ++ "> module Main where\n" - ++ "> import Distribution.Simple\n" - ++ "> main :: IO ()\n" - ++ "> main = defaultMain\n\n" - --- --------------------------------------------------------------------- --- | We do some twist for handling build infos seperately to edit them in one editor together --- with the other stuff. This type show what we really edit here --- - -data PackageDescriptionEd = PDE { - pd :: PackageDescription, - exes :: [Executable'], -#if MIN_VERSION_Cabal(1,10,0) - tests :: [Test'], -#endif- mbLib :: Maybe Library', - bis :: [BuildInfo]} - deriving Eq - -comparePDE a b = do - when (pd a /= pd b) $ putStrLn "pd" - when (exes a /= exes b) $ putStrLn "exes" -#if MIN_VERSION_Cabal(1,10,0) - when (tests a /= tests b) $ putStrLn "tests" -#endif- when (mbLib a /= mbLib b) $ putStrLn "mbLib" - when (bis a /= bis b) $ putStrLn "bis" - -fromEditor :: PackageDescriptionEd -> PackageDescription -fromEditor (PDE pd exes'-#if MIN_VERSION_Cabal(1,10,0) - tests'-#endif- mbLib' buildInfos) = - let exes = map (\ (Executable' s fb bii) -> if bii + 1 > length buildInfos - then Executable s fb (buildInfos !! (length buildInfos - 1)) - else Executable s fb (buildInfos !! bii)) exes' -#if MIN_VERSION_Cabal(1,10,0) - tests = map (\ (Test' s fb bii) -> if bii + 1 > length buildInfos - then TestSuite s fb (buildInfos !! (length buildInfos - 1)) False - else TestSuite s fb (buildInfos !! bii) False) tests' -#endif- mbLib = case mbLib' of - Nothing -> Nothing - Just (Library' mn b bii) -> if bii + 1 > length buildInfos - then Just (Library mn b (buildInfos !! (length buildInfos - 1))) - else Just (Library mn b (buildInfos !! bii)) - in pd {- library = mbLib- , executables = exes-#if MIN_VERSION_Cabal(1,10,0) - , testSuites = tests-#endif- } - -toEditor :: PackageDescription -> PackageDescriptionEd -toEditor pd = - let (exes,exeBis) = unzip $ map (\((Executable s fb bi), i) -> ((Executable' s fb i), bi)) - (zip (executables pd) [0..]) -#if MIN_VERSION_Cabal(1,10,0) - (tests,testBis) = unzip $ map (\((TestSuite s fb bi _), i) -> ((Test' s fb i), bi)) - (zip (testSuites pd) [length exeBis..])- bis = exeBis++testBis -#else- bis = exeBis -#endif- (mbLib,bis2) = case library pd of - Nothing -> (Nothing,bis) - Just (Library mn b bi) -> (Just (Library' (sort mn) b (length bis)), bis ++ [bi]) - bis3 = if null bis2 - then [emptyBuildInfo] - else bis2 - in PDE (pd {library = Nothing , executables = []})- exes-#if MIN_VERSION_Cabal(1,10,0) - tests-#endif- mbLib- bis3 - --- --------------------------------------------------------------------- --- The pane stuff --- - -data PackagePane = PackagePane { - packageBox :: VBox, - packageNotifer :: Notifier -} deriving Typeable - - -data PackageState = PackageState - deriving (Read, Show, Typeable) - -instance Pane PackagePane IDEM - where - primPaneName _ = "Package" - getAddedIndex _ = 0 - getTopWidget = castToWidget . packageBox - paneId b = "*Package" - -instance RecoverablePane PackagePane PackageState IDEM where - saveState p = return Nothing - recoverState pp st = return Nothing - buildPane panePath notebook builder = return Nothing - builder pp nb w = return (Nothing,[]) - -editPackage :: PackageDescription -> FilePath -> [ModuleName] -> (FilePath -> IDEAction) -> IDEAction -editPackage packageD packagePath modules afterSaveAction = do - mbPane :: Maybe PackagePane <- getPane - case mbPane of - Nothing -> do - pp <- getBestPathForId "*Package" - nb <- getNotebook pp - packageInfos <- liftIO $ getInstalledPackageIds - let packageEd = toEditor packageD - initPackage packagePath packageEd - (packageDD - packageInfos - (takeDirectory packagePath) - modules - (length (bis packageEd)) - (concatMap (buildInfoD (Just (takeDirectory packagePath)) modules) - [0..length (bis packageEd) - 1])) - pp nb modules afterSaveAction packageEd - Just p -> liftIO $ bringPaneToFront p - -initPackage :: FilePath - -> PackageDescriptionEd - -> FieldDescription PackageDescriptionEd - -> PanePath - -> Notebook - -> [ModuleName] - -> (FilePath -> IDEAction) - -> PackageDescriptionEd - -> IDEM () -initPackage packageDir packageD packageDescr panePath nb modules afterSaveAction origPackageD = do - let fields = flattenFieldDescription packageDescr - let initialPackagePath = packageDir </> (display . pkgName . package . pd) packageD ++ ".cabal" - packageInfos <- liftIO $ getInstalledPackageIds - mbP <- buildThisPane panePath nb - (builder' packageDir packageD packageDescr afterSaveAction - initialPackagePath modules packageInfos fields origPackageD) - case mbP of - Nothing -> return () - Just (PackagePane{packageNotifer = pn}) -> do - liftIO $ triggerEvent pn (GUIEvent { - selector = MayHaveChanged, - gtkEvent = GTK.Event True, - eventText = "", - gtkReturn = True}) - return () - -builder' :: FilePath -> - PackageDescriptionEd -> - FieldDescription PackageDescriptionEd -> - (FilePath -> IDEAction) -> - FilePath -> - [ModuleName] -> - [PackageId] -> - [FieldDescription PackageDescriptionEd] -> - PackageDescriptionEd -> - PanePath -> - Notebook -> - Window -> - IDEM (Maybe PackagePane,Connections) -builder' packageDir packageD packageDescr afterSaveAction initialPackagePath modules packageInfos fields - origPackageD panePath nb window = reifyIDE $ \ ideR -> do - vb <- vBoxNew False 0 - bb <- hButtonBoxNew - save <- buttonNewFromStock "gtk-save" - widgetSetSensitive save False - closeB <- buttonNewFromStock "gtk-close" - addB <- buttonNewFromStock "Add Build Info" - removeB <- buttonNewFromStock "Remove Build Info" - label <- labelNew Nothing - boxPackStart bb addB PackNatural 0 - boxPackStart bb removeB PackNatural 0 - boxPackEnd bb closeB PackNatural 0 - boxPackEnd bb save PackNatural 0 - (widget, setInj, getExt, notifier) <- buildEditor packageDescr packageD - let packagePane = PackagePane vb notifier - boxPackStart vb widget PackGrow 7 - boxPackStart vb label PackNatural 0 - boxPackEnd vb bb PackNatural 7 - - let fieldNames = map (\fd -> case getParameterPrim paraName (parameters fd) of - Just s -> s - Nothing -> "Unnamed") fields - addB `onClicked` (do - mbNewPackage' <- extract packageD [getExt] - case mbNewPackage' of - Nothing -> sysMessage Normal "Content doesn't validate" - Just pde -> reflectIDE (do - closePane packagePane - initPackage packageDir pde {bis = bis pde ++ [bis pde !! 0]} - (packageDD - (packageInfos) - packageDir - modules - (length (bis pde) + 1) - (concatMap (buildInfoD (Just packageDir) modules) - [0..length (bis pde)])) - panePath nb modules afterSaveAction origPackageD) ideR) - removeB `onClicked` (do - mbNewPackage' <- extract packageD [getExt] - case mbNewPackage' of - Nothing -> sysMessage Normal "Content doesn't validate" - Just pde | length (bis pde) == 1 -> sysMessage Normal "Just one Build Info" - | otherwise -> reflectIDE (do - closePane packagePane - initPackage packageDir pde{bis = take (length (bis pde) - 1) (bis pde)} - (packageDD - packageInfos - packageDir - modules - (length (bis pde) - 1) - (concatMap (buildInfoD (Just packageDir) modules) - [0..length (bis pde) - 2])) - panePath nb modules afterSaveAction origPackageD) ideR) - closeB `onClicked` (do - mbP <- extract packageD [getExt] - let hasChanged = case mbP of - Nothing -> False - Just p -> p /= origPackageD - if not hasChanged - then reflectIDE (closePane packagePane >> return ()) ideR - else do - md <- messageDialogNew (Just window) [] - MessageQuestion - ButtonsYesNo - "Unsaved changes. Close anyway?" - set md [ windowWindowPosition := WinPosCenterOnParent ] - resp <- dialogRun md - widgetDestroy md - case resp of - ResponseYes -> do - reflectIDE (closePane packagePane >> return ()) ideR - _ -> return ()) - save `onClicked` (do - mbNewPackage' <- extract packageD [getExt] - case mbNewPackage' of - Nothing -> return () - Just newPackage' -> let newPackage = fromEditor newPackage' in do - let packagePath = packageDir </> (display . pkgName . package . pd) newPackage' - ++ ".cabal" -#if MIN_VERSION_Cabal(1,10,0) - writeGenericPackageDescription packagePath (toGenericPackageDescription newPackage) -#else - writePackageDescription packagePath newPackage -#endif - reflectIDE (do - afterSaveAction packagePath - closePane packagePane - return ()) ideR) - registerEvent notifier MayHaveChanged (\ e -> do - mbP <- extract packageD [getExt] - let hasChanged = case mbP of - Nothing -> False - Just p -> p /= origPackageD - when (isJust mbP) $ labelSetMarkup label "" - when (isJust mbP) $ comparePDE (fromJust mbP) packageD - markLabel nb (getTopWidget packagePane) hasChanged - widgetSetSensitive save hasChanged - return (e{gtkReturn=False})) - registerEvent notifier ValidationError (\e -> do - labelSetMarkup label $ "<span foreground=\"red\" size=\"x-large\">The following fields have invalid values: " - ++ eventText e ++ "</span>" - return e) - return (Just packagePane,[]) - --- --------------------------------------------------------------------- --- The description with some tricks --- - -packageDD :: [PackageIdentifier] - -> FilePath - -> [ModuleName] - -> Int - -> [(String, FieldDescription PackageDescriptionEd)] - -> FieldDescription PackageDescriptionEd -packageDD packages fp modules numBuildInfos extras = NFD ([ - ("Package", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Synopsis" - $ paraSynopsis <<<- ParaSynopsis "A one-line summary of this package" - $ emptyParams) - (synopsis . pd) - (\ a b -> b{pd = (pd b){synopsis = a}}) - (stringEditor (const True) True) - , mkField - (paraName <<<- ParaName "Package Identifier" $ emptyParams) - (package . pd) - (\ a b -> b{pd = (pd b){package = a}}) - packageEditor - , mkField - (paraName <<<- ParaName "Description" - $ paraSynopsis <<<- ParaSynopsis "A more verbose description of this package" - $ paraShadow <<<- ParaShadow ShadowOut - $ paraMinSize <<<- ParaMinSize (-1,210) - $ emptyParams) - (description . pd) - (\ a b -> b{pd = (pd b){description = if null a then " " else a}}) - multilineStringEditor - , mkField - (paraName <<<- ParaName "Homepage" $ emptyParams) - (homepage . pd) - (\ a b -> b{pd = (pd b){homepage = a}}) - (stringEditor (const True) True) - , mkField - (paraName <<<- ParaName "Package URL" $ emptyParams) - (pkgUrl . pd) - (\ a b -> b{pd = (pd b){pkgUrl = a}}) - (stringEditor (const True) True) - , mkField - (paraName <<<- ParaName "Category" $ emptyParams) - (category . pd) - (\ a b -> b{pd = (pd b){category = a}}) - (stringEditor (const True) True) - ]), - ("Description", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Stability" $ emptyParams) - (stability . pd) - (\ a b -> b{pd = (pd b){stability = a}}) - (stringEditor (const True) True) -#if MIN_VERSION_Cabal(1,8,0) - -- TODO -#else - , mkField - (paraName <<<- ParaName "License" $ emptyParams) - (license . pd) - (\ a b -> b{pd = (pd b){license = a}}) - (comboSelectionEditor [GPL, LGPL, BSD3, BSD4, PublicDomain, AllRightsReserved, OtherLicense] show) -#endif - , mkField - (paraName <<<- ParaName "License File" $ emptyParams) - (licenseFile . pd) - (\ a b -> b{pd = (pd b){licenseFile = a}}) - (fileEditor (Just fp) FileChooserActionOpen "Select file") - , mkField - (paraName <<<- ParaName "Copyright" $ emptyParams) - (copyright . pd) - (\ a b -> b{pd = (pd b){copyright = a}}) - (stringEditor (const True) True) - , mkField - (paraName <<<- ParaName "Author" $ emptyParams) - (author . pd) - (\ a b -> b{pd = (pd b){author = a}}) - (stringEditor (const True) True) - , mkField - (paraName <<<- ParaName "Maintainer" $ emptyParams) - (maintainer . pd) - (\ a b -> b{pd = (pd b){maintainer = a}}) - (stringEditor (const True) True) - , mkField - (paraName <<<- ParaName "Bug Reports" $ emptyParams) - (bugReports . pd) - (\ a b -> b{pd = (pd b){bugReports = a}}) - (stringEditor (const True) True) - ]), --- ("Repositories", VFD emptyParams [ --- mkField --- (paraName <<<- ParaName "Source Repositories" $ emptyParams) --- (sourceRepos . pd) --- (\ a b -> b{pd = (pd b){sourceRepos = a}}) --- reposEditor]), - ("Dependencies ", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Build Dependencies" - $ paraSynopsis <<<- ParaSynopsis "Does this package depends on other packages?" - $ paraDirection <<<- ParaDirection Vertical - $ paraMinSize <<<- ParaMinSize (-1,250) - $ emptyParams) - (nub . buildDepends . pd) - (\ a b -> b{pd = (pd b){buildDepends = a}}) - (dependenciesEditor packages) - ]), - ("Meta Dep.", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Cabal version" - $ paraSynopsis <<<- ParaSynopsis - "Does this package depends on a specific version of Cabal?" - $ paraShadow <<<- ParaShadow ShadowIn $ emptyParams) - (descCabalVersion . pd) -#if MIN_VERSION_Cabal(1,10,0) - (\ a b -> b{pd = (pd b){specVersionRaw = Right a}}) -#else - (\ a b -> b{pd = (pd b){descCabalVersion = a}}) -#endif - versionRangeEditor - , mkField - (paraName <<<- ParaName "Tested with compiler" - $ paraShadow <<<- ParaShadow ShadowIn - $ paraDirection <<<- ParaDirection Vertical - $ emptyParams) - (\a -> case (testedWith . pd) a of - [] -> []--(GHC,anyVersion)] - l -> l) - (\ a b -> b{pd = (pd b){testedWith = a}}) - testedWithEditor - ]), - ("Data Files", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Data Files" - $ paraSynopsis <<<- ParaSynopsis - "A list of files to be installed for run-time use by the package." - $ paraDirection <<<- ParaDirection Vertical - $ paraMinSize <<<- ParaMinSize (-1,250) - $ emptyParams) - (dataFiles . pd) - (\ a b -> b{pd = (pd b){dataFiles = a}}) - (filesEditor (Just fp) FileChooserActionOpen "Select File") - , mkField - (paraName <<<- ParaName "Data directory" $ emptyParams) - (dataDir . pd) - (\ a b -> b{pd = (pd b){dataDir = a}}) - (fileEditor (Just fp) FileChooserActionSelectFolder "Select file") - ]), - ("Extra Files", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Extra Source Files" - $ paraSynopsis <<<- ParaSynopsis - "A list of additional files to be included in source distributions." - $ paraDirection <<<- ParaDirection Vertical - $ paraMinSize <<<- ParaMinSize (-1,120) - $ emptyParams) - (extraSrcFiles . pd) - (\ a b -> b{pd = (pd b){extraSrcFiles = a}}) - (filesEditor (Just fp) FileChooserActionOpen "Select File") - , mkField - (paraName <<<- ParaName "Extra Tmp Files" - $ paraSynopsis <<<- ParaSynopsis - "A list of additional files or directories to be removed by setup clean." - $ paraDirection <<<- ParaDirection Vertical - $ paraMinSize <<<- ParaMinSize (-1,120) - $ emptyParams) - (extraTmpFiles . pd) - (\ a b -> b{pd = (pd b){extraTmpFiles = a}}) - (filesEditor (Just fp) FileChooserActionOpen "Select File") - ]), - ("Other",VFD emptyParams [ - mkField - (paraName <<<- ParaName "Build Type" - $ paraSynopsis <<<- ParaSynopsis - "Describe executable programs contained in the package" - $ paraShadow <<<- ParaShadow ShadowIn - $ paraDirection <<<- ParaDirection Vertical - $ emptyParams) - (buildType . pd) - (\ a b -> b{pd = (pd b){buildType = a}}) - (maybeEditor (buildTypeEditor, emptyParams) True "Specify?") - , mkField - (paraName <<<- ParaName "Custom Fields" - $ paraShadow <<<- ParaShadow ShadowIn - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - (customFieldsPD . pd) - (\ a b -> b{pd = (pd b){customFieldsPD = a}}) - (multisetEditor - (ColumnDescr True [("Name",\(n,_) -> [cellText := n]) - ,("Value",\(_,v) -> [cellText := v])]) - ((pairEditor - (stringxEditor (const True),emptyParams) - (stringEditor (const True) True,emptyParams)),emptyParams) - Nothing - Nothing) - ]), - ("Executables",VFD emptyParams [ - mkField - (paraName <<<- ParaName "Executables" - $ paraSynopsis <<<- ParaSynopsis - "Describe executable programs contained in the package" - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - exes - (\ a b -> b{exes = a}) - (executablesEditor (Just fp) modules numBuildInfos) - ]), -#if MIN_VERSION_Cabal(1,10,0) - ("Tests",VFD emptyParams [ - mkField - (paraName <<<- ParaName "Tests" - $ paraSynopsis <<<- ParaSynopsis - "Describe tests contained in the package" - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - tests - (\ a b -> b{tests = a}) - (testsEditor (Just fp) modules numBuildInfos) - ]), -#endif- ("Library", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Library" - $ paraSynopsis <<<- ParaSynopsis - "If the package contains a library, specify the exported modules here" - $ paraDirection <<<- ParaDirection Vertical - $ paraShadow <<<- ParaShadow ShadowIn $ emptyParams) - mbLib - (\ a b -> b{mbLib = a}) - (maybeEditor (libraryEditor (Just fp) modules numBuildInfos, - paraName <<<- ParaName "Specify exported modules" - $ emptyParams) True - "Does this package contain a library?") - ]) - ] ++ extras) - -update :: [BuildInfo] -> Int -> (BuildInfo -> BuildInfo) -> [BuildInfo] -update bis index func = - map (\(bi,ind) -> if ind == index - then func bi - else bi) - (zip bis [0..length bis - 1]) - -buildInfoD :: Maybe FilePath -> [ModuleName] -> Int -> [(String,FieldDescription PackageDescriptionEd)] -buildInfoD fp modules i = [ - (show (i + 1) ++ " Build Info", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Component is buildable here" $ emptyParams) - (buildable . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{buildable = a})}) - boolEditor - , mkField - (paraName <<<- ParaName - "Where to look for the source hierarchy" - $ paraSynopsis <<<- ParaSynopsis - "Root directories for the source hierarchy." - $ paraShadow <<<- ParaShadow ShadowIn - $ paraDirection <<<- ParaDirection Vertical - $ emptyParams) - (hsSourceDirs . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{hsSourceDirs = a})}) - (filesEditor fp FileChooserActionSelectFolder "Select folder") - , mkField - (paraName <<<- ParaName "Non-exposed or non-main modules" - $ paraSynopsis <<<- ParaSynopsis ("A list of modules used by the component but " - ++ "not exposed to users.") - $ paraShadow <<<- ParaShadow ShadowIn - $ paraDirection <<<- ParaDirection Vertical - $ paraMinSize <<<- ParaMinSize (-1,300) - $ paraPack <<<- ParaPack PackGrow - $ emptyParams) - (map display. otherModules . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> - bi{otherModules = (map (\i -> forceJust (simpleParse i) - " PackageEditor >> buildInfoD: no parse for moduile name" ) a)})}) - (modulesEditor modules) - ]), - (show (i + 1) ++ " Compiler ", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Options for haskell compilers" - $ paraDirection <<<- ParaDirection Vertical - $ paraShadow <<<- ParaShadow ShadowIn - $ paraPack <<<- ParaPack PackGrow $ emptyParams) - (options . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{options = a})}) - (multisetEditor - (ColumnDescr True [("Compiler Flavor",\(cv,_) -> [cellText := show cv]) - ,("Options",\(_,op) -> [cellText := concatMap (\s -> ' ' : s) op])]) - ((pairEditor - (compilerFlavorEditor,emptyParams) - (optsEditor,emptyParams)), - (paraDirection <<<- ParaDirection Vertical - $ paraShadow <<<- ParaShadow ShadowIn $ emptyParams)) - Nothing - Nothing) - , mkField - (paraName <<<- ParaName "Additional options for GHC when built with profiling" - $ emptyParams) - (ghcProfOptions . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{ghcProfOptions = a})}) - optsEditor - , mkField - (paraName <<<- ParaName "Additional options for GHC when the package is built as shared library" - $ emptyParams) - (ghcSharedOptions . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{ghcSharedOptions = a})}) - optsEditor - ]), - (show (i + 1) ++ " Extensions ", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Extensions" - $ paraSynopsis <<<- ParaSynopsis - "A list of Haskell extensions used by every module." - $ paraMinSize <<<- ParaMinSize (-1,400) - $ paraPack <<<- ParaPack PackGrow - $ emptyParams) -#if MIN_VERSION_Cabal(1,10,0) - (oldExtensions . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{oldExtensions = a})}) -#else - (extensions . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{extensions = a})}) -#endif - extensionsEditor - ]), - (show (i + 1) ++ " Build Tools ", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Tools needed for a build" - $ paraDirection <<<- ParaDirection Vertical - $ paraMinSize <<<- ParaMinSize (-1,120) - $ emptyParams) - (buildTools . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{buildTools = a})}) - (dependenciesEditor []) - ]), - (show (i + 1) ++ " Pkg Config ", VFD emptyParams [ - mkField - (paraName <<<- ParaName "A list of pkg-config packages, needed to build this package" - $ paraDirection <<<- ParaDirection Vertical - $ paraMinSize <<<- ParaMinSize (-1,120) - $ emptyParams) - (pkgconfigDepends . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{pkgconfigDepends = a})}) - (dependenciesEditor []) - ]), - (show (i + 1) ++ " Opts C -1-", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Options for C compiler" - $ paraDirection <<<- ParaDirection Vertical - $ emptyParams) - (ccOptions . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{ccOptions = a})}) - optsEditor - , mkField - (paraName <<<- ParaName "Options for linker" - $ paraDirection <<<- ParaDirection Vertical - $ emptyParams) - (ldOptions . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{ldOptions = a})}) - optsEditor - , mkField - (paraName <<<- ParaName "A list of header files to use when compiling" - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - (includes . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{includes = a})}) - (stringsEditor (const True) True) - , mkField - (paraName <<<- ParaName "A list of header files to install" - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - (installIncludes . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{installIncludes = a})}) - (filesEditor fp FileChooserActionOpen "Select File") - ]), - (show (i + 1) ++ " Opts C -2-", VFD emptyParams [ - mkField - (paraName <<<- ParaName "A list of directories to search for header files" - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - (includeDirs . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{includeDirs = a})}) - (filesEditor fp FileChooserActionSelectFolder "Select Folder") - , mkField - (paraName <<<- ParaName - "A list of C source files to be compiled,linked with the Haskell files." - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - (cSources . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{cSources = a})}) - (filesEditor fp FileChooserActionOpen "Select file") - ]), - (show (i + 1) ++ " Opts Libs ", VFD emptyParams [ - mkField - (paraName <<<- ParaName "A list of extra libraries to link with" - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - (extraLibs . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{extraLibs = a})}) - (stringsEditor (const True) True) - , mkField - (paraName <<<- ParaName "A list of directories to search for libraries." - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - (extraLibDirs . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{extraLibDirs = a})}) - (filesEditor fp FileChooserActionSelectFolder "Select Folder") - ]), - (show (i + 1) ++ " Other", VFD emptyParams [ - mkField - (paraName <<<- ParaName "Options for C preprocessor" - $ paraDirection <<<- ParaDirection Vertical - $ emptyParams) - (cppOptions . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{cppOptions = a})}) - optsEditor - , mkField - (paraName <<<- ParaName "Support frameworks for Mac OS X" - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - (frameworks . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{frameworks = a})}) - (stringsEditor (const True) True) - , mkField - (paraName <<<- ParaName "Custom fields build info" - $ paraShadow <<<- ParaShadow ShadowIn - $ paraDirection <<<- ParaDirection Vertical $ emptyParams) - (customFieldsBI . (\a -> a !! i) . bis) - (\ a b -> b{bis = update (bis b) i (\bi -> bi{customFieldsBI = a})}) - (multisetEditor - (ColumnDescr True [("Name",\(n,_) -> [cellText := n]) - ,("Value",\(_,v) -> [cellText := v])]) - ((pairEditor - (stringxEditor (const True),emptyParams) - (stringEditor (const True) True,emptyParams)),emptyParams) - Nothing - Nothing) - ])] - -stringxEditor :: (String -> Bool) -> Editor String -stringxEditor val para noti = do - (wid,inj,ext) <- stringEditor val True para noti - let - xinj ("") = inj "" - xinj ('x':'-':rest) = inj rest - xinj _ = throwIDE "PackageEditor>>stringxEditor: field without leading x-" - xext = do - res <- ext - case res of - Nothing -> return Nothing - Just str -> return (Just ("x-" ++ str)) - return (wid,xinj,xext) - -optsEditor :: Editor [String] -optsEditor para noti = do - (wid,inj,ext) <- stringEditor (const True) True para noti - let - oinj = inj . unwords - oext = do - res <- ext - case res of - Nothing -> return Nothing - Just str -> return (Just (words str)) - return (wid,oinj,oext) - -packageEditor :: Editor PackageIdentifier -packageEditor para noti = do - (wid,inj,ext) <- pairEditor - (stringEditor (\s -> not (null s)) True, paraName <<<- ParaName "Name" $ emptyParams) - (versionEditor, paraName <<<- ParaName "Version" $ emptyParams) - (paraDirection <<<- ParaDirection Horizontal - $ paraShadow <<<- ParaShadow ShadowIn - $ para) noti - let pinj (PackageIdentifier (PackageName n) v) = inj (n,v) - let pext = do - mbp <- ext - case mbp of - Nothing -> return Nothing - Just (n,v) -> do - if null n - then return Nothing - else return (Just $PackageIdentifier (PackageName n) v) - return (wid,pinj,pext) - -testedWithEditor :: Editor [(CompilerFlavor, VersionRange)] -testedWithEditor para = do - multisetEditor - (ColumnDescr True [("Compiler Flavor",\(cv,_) -> [cellText := show cv]) - ,("Version Range",\(_,vr) -> [cellText := display vr])]) - (pairEditor - (compilerFlavorEditor, paraShadow <<<- (ParaShadow ShadowNone) $ emptyParams) - (versionRangeEditor, paraShadow <<<- (ParaShadow ShadowNone) $ emptyParams), - (paraDirection <<<- (ParaDirection Vertical) $ emptyParams)) - Nothing - (Just (==)) - para - -compilerFlavorEditor :: Editor CompilerFlavor -compilerFlavorEditor para noti = do - (wid,inj,ext) <- eitherOrEditor - (comboSelectionEditor flavors show, paraName <<<- (ParaName "Select compiler") $ emptyParams) - (stringEditor (\s -> not (null s)) True, paraName <<<- (ParaName "Specify compiler") $ emptyParams) - "Other" - (paraName <<<- ParaName "Select" $ para) - noti - let cfinj comp = case comp of - (OtherCompiler str) -> inj (Right str) - other -> inj (Left other) - let cfext = do - mbp <- ext - case mbp of - Nothing -> return Nothing - Just (Right s) -> return (Just $OtherCompiler s) - Just (Left other) -> return (Just other) - return (wid,cfinj,cfext) - where - flavors = [GHC, NHC, Hugs, HBC, Helium, JHC] - -buildTypeEditor :: Editor BuildType -buildTypeEditor para noti = do - (wid,inj,ext) <- eitherOrEditor - (comboSelectionEditor flavors show, paraName <<<- (ParaName "Select") $ emptyParams) - (stringEditor (const True) True, paraName <<<- (ParaName "Unknown") $ emptyParams) - "Unknown" - (paraName <<<- ParaName "Select" $ para) - noti - let cfinj comp = case comp of - (UnknownBuildType str) -> inj (Right str) - other -> inj (Left other) - let cfext = do - mbp <- ext - case mbp of - Nothing -> return Nothing - Just (Right s) -> return (Just $ UnknownBuildType s) - Just (Left other) -> return (Just other) - return (wid,cfinj,cfext) - where - flavors = [Simple, Configure, Make, Custom] - -extensionsEditor :: Editor [Extension] -extensionsEditor = staticListMultiEditor extensionsL show - - -extensionsL :: [Extension] -#if MIN_VERSION_Cabal(1,11,0) -extensionsL = map EnableExtension [minBound..maxBound] -#else -extensionsL = knownExtensions -#endif - -{-- -reposEditor :: Editor [SourceRepo] -reposEditor p noti = - multisetEditor - (ColumnDescr False [("",\repo -> [cellText := display repo])]) - (repoEditor, - paraOuterAlignment <<<- ParaInnerAlignment (0.0, 0.5, 1.0, 1.0) - $ paraInnerAlignment <<<- ParaOuterAlignment (0.0, 0.5, 1.0, 1.0) - $ emptyParams) - Nothing - Nothing - (paraShadow <<<- ParaShadow ShadowIn $ - paraOuterAlignment <<<- ParaInnerAlignment (0.0, 0.5, 1.0, 1.0) - $ paraInnerAlignment <<<- ParaOuterAlignment (0.0, 0.5, 1.0, 1.0) - $ paraDirection <<<- ParaDirection Vertical - $ paraPack <<<- ParaPack PackGrow - $ p) - noti - -instance Text SourceRepo where - disp (SourceRepo repoKind repoType repoLocation repoModule repoBranch repoTag repoSubdir) - = disp repoKind - <+> case repoType of - Nothing -> empty - Just repoT -> disp repoT - <+> case repoLocation of - Nothing -> empty - Just repoL -> text repoL - -repoEditor :: Editor SourceRepo -repoEditor paras noti = do - (widg,inj,ext) <- tupel7Editor - (repoKindEditor,noBorder) - (maybeEditor (repoTypeEditor,noBorder) True "Specify a type", emptyParams) - (maybeEditor (stringEditor (const True) True,noBorder) True "Specify a location", emptyParams) - (maybeEditor (stringEditor (const True) True,noBorder) True "Specify a module", emptyParams) - (maybeEditor (stringEditor (const True) True,noBorder) True "Specify a branch", emptyParams) - (maybeEditor (stringEditor (const True) True,noBorder) True "Specify a tag", emptyParams) - (maybeEditor (stringEditor (const True) True,noBorder) True "Specify a subdir", emptyParams) - (paraDirection <<<- ParaDirection Vertical $ noBorder) - noti - return (widg, - (\ r -> inj (repoKind r,repoType r,repoLocation r,repoModule r,repoBranch r,repoTag r,repoSubdir r)), - (do - mb <- ext - case mb of - Nothing -> return Nothing - Just (a,b,c,d,e,f,g) -> return (Just (SourceRepo a b c d e f g)))) - where noBorder = paraOuterAlignment <<<- ParaOuterAlignment (0.0, 0.0, 0.0, 0.0) - $ paraOuterPadding <<<- ParaOuterPadding (0, 0, 0, 0) - $ paraInnerAlignment <<<- ParaInnerAlignment (0.0, 0.0, 0.0, 0.0) - $ paraInnerPadding <<<- ParaInnerPadding (0, 0, 0, 0) - $ emptyParams - -repoKindEditor :: Editor RepoKind -repoKindEditor paras noti = do - (widg,inj,ext) <- pairEditor - (comboSelectionEditor selectionList show, emptyParams) - (stringEditor (const True) True,emptyParams) - paras - noti - return (widg, - (\kind -> case kind of - RepoKindUnknown str -> inj (RepoKindUnknown "",str) - other -> inj (other,"")), - (do - mbRes <- ext - case mbRes of - Nothing -> return Nothing - Just (RepoKindUnknown "",str) -> return (Just (RepoKindUnknown str)) - Just (other,_) -> return (Just other))) - where selectionList = [RepoHead, RepoThis, RepoKindUnknown ""] - -repoTypeEditor :: Editor RepoType -repoTypeEditor paras noti = do - (widg,inj,ext) <- pairEditor - (comboSelectionEditor selectionList show, emptyParams) - (stringEditor (const True) True,emptyParams) - paras - noti - return (widg, - (\kind -> case kind of - OtherRepoType str -> inj (OtherRepoType "",str) - other -> inj (other,"")), - (do - mbRes <- ext - case mbRes of - Nothing -> return Nothing - Just (OtherRepoType "",str) -> return (Just (OtherRepoType str)) - Just (other,_) -> return (Just other))) - where selectionList = [Darcs, Git, SVN, CVS, Mercurial, GnuArch, Bazaar, Monotone, OtherRepoType ""] ---} - --- ------------------------------------------------------------ --- * BuildInfos --- ------------------------------------------------------------ - -data Library' = Library'{ - exposedModules' :: [ModuleName] -, libExposed' :: Bool -, libBuildInfoIdx :: Int} - deriving (Show, Eq) - -data Executable' = Executable'{ - exeName' :: String -, modulePath' :: FilePath -, buildInfoIdx :: Int} - deriving (Show, Eq) - -#if MIN_VERSION_Cabal(1,10,0) -data Test' = Test'{ - testName' :: String -, testInterface' :: TestSuiteInterface -, testBuildInfoIdx :: Int} - deriving (Show, Eq) -#endif- -instance Default Library' - where getDefault = Library' [] getDefault getDefault - -instance Default Executable' - where getDefault = Executable' getDefault getDefault getDefault --#if MIN_VERSION_Cabal(1,10,0) -instance Default Test' - where getDefault = Test' getDefault (TestSuiteExeV10 (Version [1,0] []) getDefault) getDefault -#endif- -libraryEditor :: Maybe FilePath -> [ModuleName] -> Int -> Editor Library' -libraryEditor fp modules numBuildInfos para noti = do - (wid,inj,ext) <- - tupel3Editor - (boolEditor, - paraName <<<- ParaName "Exposed" - $ paraSynopsis <<<- ParaSynopsis "Is the lib to be exposed by default?" - $ emptyParams) - (modulesEditor (sort modules), - paraName <<<- ParaName "Exposed Modules" - $ paraMinSize <<<- ParaMinSize (-1,300) - $ para) - (buildInfoEditorP numBuildInfos, paraName <<<- ParaName "Build Info" - $ paraPack <<<- ParaPack PackNatural - $ para) - (paraDirection <<<- ParaDirection Vertical - $ emptyParams) - noti - let pinj (Library' em exp bi) = inj (exp, map display em,bi) - let pext = do - mbp <- ext - case mbp of - Nothing -> return Nothing - Just (exp,em,bi) -> return (Just $ Library' (map (\s -> forceJust (simpleParse s) - "SpecialEditor >> libraryEditor: no parse for moduile name") em) exp bi) - return (wid,pinj,pext) - ---moduleEditor :: [ModuleName] -> Editor String ---moduleEditor modules = comboSelectionEditor (map display modules) - -modulesEditor :: [ModuleName] -> Editor [String] -modulesEditor modules = staticListMultiEditor (map display modules) id - -executablesEditor :: Maybe FilePath -> [ModuleName] -> Int -> Editor [Executable'] -executablesEditor fp modules countBuildInfo p = - multisetEditor - (ColumnDescr True [("Executable Name",\(Executable' exeName _ _) -> [cellText := exeName]) - ,("Module Path",\(Executable' _ mp _) -> [cellText := mp]) - - ,("Build info index",\(Executable' _ _ bii) -> [cellText := show (bii + 1)])]) - (executableEditor fp modules countBuildInfo,emptyParams) - Nothing - Nothing - (paraShadow <<<- ParaShadow ShadowIn $ p) - -executableEditor :: Maybe FilePath -> [ModuleName] -> Int -> Editor Executable' -executableEditor fp modules countBuildInfo para noti = do - (wid,inj,ext) <- tupel3Editor - (stringEditor (\s -> not (null s)) True, - paraName <<<- ParaName "Executable Name" - $ emptyParams) - (stringEditor (\s -> not (null s)) True, - paraDirection <<<- ParaDirection Vertical - $ paraName <<<- ParaName "File with main function" - $ emptyParams) - (buildInfoEditorP countBuildInfo, paraName <<<- ParaName "Build Info" - $ paraOuterAlignment <<<- ParaOuterAlignment (0.0, 0.0, 0.0, 0.0) - $ paraOuterPadding <<<- ParaOuterPadding (0, 0, 0, 0) - $ paraInnerAlignment <<<- ParaInnerAlignment (0.0, 0.0, 0.0, 0.0) - $ paraInnerPadding <<<- ParaInnerPadding (0, 0, 0, 0) - $ emptyParams) - (paraDirection <<<- ParaDirection Vertical $ para) - noti - let pinj (Executable' s f bi) = inj (s,f,bi) - let pext = do - mbp <- ext - case mbp of - Nothing -> return Nothing - Just (s,f,bi) -> return (Just $Executable' s f bi) - return (wid,pinj,pext) - -#if MIN_VERSION_Cabal(1,10,0) -testsEditor :: Maybe FilePath -> [ModuleName] -> Int -> Editor [Test'] -testsEditor fp modules countBuildInfo p = - multisetEditor - (ColumnDescr True [("Test Name",\(Test' testName _ _) -> [cellText := testName]) - ,("Interface",\(Test' _ i _) -> [cellText := interfaceName i]) - - ,("Build info index",\(Test' _ _ bii) -> [cellText := show (bii + 1)])]) - (testEditor fp modules countBuildInfo,emptyParams) - Nothing - Nothing - (paraShadow <<<- ParaShadow ShadowIn $ p)- where- interfaceName (TestSuiteExeV10 _ f) = f- interfaceName i = show i - -testEditor :: Maybe FilePath -> [ModuleName] -> Int -> Editor Test' -testEditor fp modules countBuildInfo para noti = do - (wid,inj,ext) <- tupel3Editor - (stringEditor (\s -> not (null s)) True, - paraName <<<- ParaName "Test Name" - $ emptyParams) - (stringEditor (\s -> not (null s)) True, - paraDirection <<<- ParaDirection Vertical - $ paraName <<<- ParaName "File with main function" - $ emptyParams) - (buildInfoEditorP countBuildInfo, paraName <<<- ParaName "Build Info" - $ paraOuterAlignment <<<- ParaOuterAlignment (0.0, 0.0, 0.0, 0.0) - $ paraOuterPadding <<<- ParaOuterPadding (0, 0, 0, 0) - $ paraInnerAlignment <<<- ParaInnerAlignment (0.0, 0.0, 0.0, 0.0) - $ paraInnerPadding <<<- ParaInnerPadding (0, 0, 0, 0) - $ emptyParams) - (paraDirection <<<- ParaDirection Vertical $ para) - noti - let pinj (Test' s (TestSuiteExeV10 (Version [1,0] []) f) bi) = inj (s,f,bi)- pinj _ = error "Unexpected Test Interface" - let pext = do- mbp <- ext - case mbp of - Nothing -> return Nothing - Just (s,f,bi) -> return (Just $Test' s (TestSuiteExeV10 (Version [1,0] []) f) bi) - return (wid,pinj,pext) -#endif- -buildInfoEditorP :: Int -> Editor Int -buildInfoEditorP numberOfBuildInfos para noti = do - (wid,inj,ext) <- intEditor (1.0,fromIntegral numberOfBuildInfos,1.0) - (paraName <<<- ParaName "Build Info" $para) noti - let pinj i = inj (i + 1) - let pext = do - mbV <- ext - case mbV of - Nothing -> return Nothing - Just i -> return (Just (i - 1)) - return (wid,pinj,pext) - --- ------------------------------------------------------------ --- * (Boring) default values --- ------------------------------------------------------------ - - -instance Default CompilerFlavor - where getDefault = GHC - -instance Default BuildInfo - where getDefault = emptyBuildInfo - -instance Default Library - where getDefault = Library [] getDefault getDefault - -instance Default Executable - where getDefault = Executable getDefault getDefault getDefault - -instance Default RepoType - where getDefault = Darcs - -instance Default RepoKind - where getDefault = RepoThis - -instance Default SourceRepo - where getDefault = SourceRepo getDefault getDefault getDefault getDefault getDefault - getDefault getDefault - -instance Default BuildType - where getDefault = Simple - - +{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE FlexibleInstances, ScopedTypeVariables, DeriveDataTypeable,+ CPP, MultiParamTypeClasses, TypeSynonymInstances #-}+-----------------------------------------------------------------------------+--+-- Module : IDE.Pane.PackageEditor+-- Copyright : (c) Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GNU-GPL+--+-- Maintainer : Juergen Nicklisch-Franken <info@leksah.org>+-- Stability : provisional+-- Portability : portable+--+-- | Module for editing of cabal packages and build infos+--+-----------------------------------------------------------------------------------+++module IDE.Pane.PackageEditor (+ packageNew'+, packageClone+, packageEdit+, packageEditText+, choosePackageDir+, choosePackageFile++, hasConfigs+, standardSetup+) where++import Graphics.UI.Gtk+import Distribution.Package+import Distribution.PackageDescription+import Distribution.Verbosity+import System.FilePath+import Data.Maybe+import System.Directory+import System.IO (withFile, IOMode(..))+import System.IO.Strict (hGetContents)++import IDE.Core.State+import IDE.Utils.FileUtils+import Graphics.UI.Editor.MakeEditor+import Distribution.PackageDescription.Parse (readPackageDescription)+import Distribution.PackageDescription.Configuration (flattenPackageDescription)+import Distribution.ModuleName(ModuleName)+import Data.Typeable (Typeable(..))+import Graphics.UI.Editor.Composite+ (versionEditor,+ versionRangeEditor,+ dependenciesEditor,+ stringsEditor,+ filesEditor,+ tupel3Editor,+ eitherOrEditor,+ maybeEditor,+ pairEditor,+ ColumnDescr(..),+ multisetEditor)+import Distribution.Text (simpleParse, display)+import MyMissing+import Graphics.UI.Editor.Parameters+ (paraInnerPadding,+ paraInnerAlignment,+ paraOuterPadding,+ paraOuterAlignment,+ Parameter(..),+ paraPack,+ Direction(..),+ paraDirection,+ paraMinSize,+ paraShadow,+ paraSynopsis,+ (<<<-),+ emptyParams,+ paraName,+ getParameterPrim)+import Graphics.UI.Editor.Simple+ (staticListMultiEditor,+ intEditor,+ boolEditor,+ fileEditor,+ comboSelectionEditor,+ multilineStringEditor,+ stringEditor)+import Graphics.UI.Editor.Basics+ (Notifier, Editor(..), GUIEventSelector(..), GUIEvent(..))+import Distribution.Compiler+ (CompilerFlavor(..))+#if !MIN_VERSION_Cabal(1,11,0)+import Distribution.Simple (knownExtensions)+#endif+import Distribution.Simple (Extension(..), VersionRange, anyVersion)+import Default (Default(..))+import IDE.Utils.GUIUtils+import IDE.Pane.SourceBuffer (fileOpenThis)+import Control.Event (EventSource(..))+#if !MIN_VERSION_Cabal(1,8,0)+import Distribution.License+#endif++import qualified Graphics.UI.Gtk.Gdk.Events as GTK (Event(..))+import Data.List (isPrefixOf, sort, nub)+import Control.Monad.Trans.Reader (ask)+import Control.Monad.IO.Class (MonadIO(..))+import Control.Monad.Trans.Class (lift)+import Control.Monad (when)+#if MIN_VERSION_Cabal(1,10,0)+import Distribution.PackageDescription.PrettyPrintCopied+ (writeGenericPackageDescription)+#else+import Distribution.PackageDescription.Parse+ (writePackageDescription)+#endif+import Distribution.Version (Version(..), orLaterVersion)++import Text.Printf (printf)+import Control.Applicative ((<*>), (<$>))+import qualified Data.Conduit.Util as CU (zipSinks)+import IDE.Utils.Tool (ToolOutput(..))+import System.Exit (ExitCode(..))+import qualified Data.Conduit.List as CL (fold)+import qualified Data.Conduit as C (Sink)+import IDE.Utils.ExternalTool (runExternalTool')+import Data.Char (toLower)++-- | Get the last item+sinkLast = CL.fold (\_ a -> Just a) Nothing++--------------------------------------------------------------------------+-- Handling of Generic Package Descriptions++#if MIN_VERSION_Cabal(1,10,0)+toGenericPackageDescription :: PackageDescription -> GenericPackageDescription+toGenericPackageDescription pd =+ GenericPackageDescription {+ packageDescription = pd{+ library = Nothing,+ executables = [],+ testSuites = [],+ buildDepends = []},+ genPackageFlags = [],+ condLibrary = case library pd of+ Nothing -> Nothing+ Just lib -> Just (buildCondTreeLibrary lib),+ condExecutables = map buildCondTreeExe (executables pd),+ condTestSuites = map buildCondTreeTest (testSuites pd)}+ where+ buildCondTreeLibrary lib =+ CondNode {+ condTreeData = lib,+ condTreeConstraints = buildDepends pd,+ condTreeComponents = []}+ buildCondTreeExe exe =+ (exeName exe, CondNode {+ condTreeData = exe,+ condTreeConstraints = buildDepends pd,+ condTreeComponents = []})+ buildCondTreeTest test =+ (testName test, CondNode {+ condTreeData = test,+ condTreeConstraints = buildDepends pd,+ condTreeComponents = []})+#endif++-- ---------------------------------------------------------------------+-- The exported stuff goes here+--++choosePackageDir :: Window -> Maybe FilePath -> IO (Maybe FilePath)+choosePackageDir window mbDir = chooseDir window (__ "Select root folder for package") mbDir++choosePackageFile :: Window -> Maybe FilePath -> IO (Maybe FilePath)+choosePackageFile window mbDir = chooseFile window (__ "Select cabal package file (.cabal)") mbDir++packageEdit :: PackageAction+packageEdit = do+ idePackage <- ask+ let dirName = dropFileName (ipdCabalFile idePackage)+ modules <- liftIO $ allModules dirName+ package <- liftIO $ readPackageDescription normal (ipdCabalFile idePackage)+ if hasConfigs package+ then do+ lift $ ideMessage High+ (__ "Cabal file with configurations can't be edited with the current version of the editor")+ lift $ fileOpenThis $ ipdCabalFile idePackage+ return ()+ else do+ let flat = flattenPackageDescription package+#if MIN_VERSION_Cabal(1,10,0)+ if hasUnknownTestTypes flat+ then do+ lift $ ideMessage High+ (__ "Cabal file with tests of this type can't be edited with the current version of the editor")+ lift $ fileOpenThis $ ipdCabalFile idePackage+ return ()+ else do+ lift $ editPackage flat dirName modules (\ _ -> return ())+ return ()+#else+ lift $ editPackage flat dirName modules (\ _ -> return ())+ return ()+#endif++packageEditText :: PackageAction+packageEditText = do+ idePackage <- ask+ lift $ fileOpenThis $ ipdCabalFile idePackage+ return ()++hasConfigs :: GenericPackageDescription -> Bool+hasConfigs gpd =+ let libConds = case condLibrary gpd of+ Nothing -> False+ Just condTree -> not (null (condTreeComponents condTree))+ exeConds = foldr (\ (_,condTree) hasConfigs ->+ if hasConfigs+ then True+ else not (null (condTreeComponents condTree)))+ False (condExecutables gpd)+#if MIN_VERSION_Cabal(1,10,0)+ testConds = foldr (\ (_,condTree) hasConfigs ->+ if hasConfigs+ then True+ else not (null (condTreeComponents condTree)))+ False (condTestSuites gpd)+ in libConds || exeConds || testConds+#else+ in libConds || exeConds+#endif++#if MIN_VERSION_Cabal(1,10,0)+hasUnknownTestTypes :: PackageDescription -> Bool+hasUnknownTestTypes pd =+ not . null . filter unknown $ testSuites pd+ where+ unknown (TestSuite _ (TestSuiteExeV10 _ _) _ _) = False+ unknown _ = True+#endif++data NewPackage = NewPackage {+ newPackageName :: String,+ newPackageParentDir :: FilePath,+ templatePackage :: String}++packageFields :: FilePath -> FieldDescription NewPackage+packageFields workspaceDir = VFD emptyParams [+ mkField+ (paraName <<<- ParaName ((__ "New package name"))+ $ emptyParams)+ newPackageName+ (\ a b -> b{newPackageName = a})+ (stringEditor (const True) True),+ mkField+ (paraName <<<- ParaName ((__ "Parent directory"))+ $ paraMinSize <<<- ParaMinSize (-1, 120)+ $ emptyParams)+ (\a -> newPackageParentDir a)+ (\ a b -> b{newPackageParentDir = a})+ (fileEditor (Just workspaceDir) FileChooserActionSelectFolder "Select"),+ mkField+ (paraName <<<- ParaName ((__ "Existing package to copy"))+ $ emptyParams)+ templatePackage+ (\ a b -> b{templatePackage = a})+ (stringEditor (const True) True)]++newPackageDialog :: Window -> FilePath -> IO (Maybe NewPackage)+newPackageDialog parent workspaceDir = do+ dia <- dialogNew+ set dia [ windowTransientFor := parent+ , windowTitle := (__ "Create New Package") ]+#ifdef MIN_VERSION_gtk3+ upper <- dialogGetContentArea dia+#else+ upper <- dialogGetUpper dia+#endif+ lower <- dialogGetActionArea dia+ (widget,inj,ext,_) <- buildEditor (packageFields workspaceDir)+ (NewPackage "" workspaceDir "hello")+ bb <- hButtonBoxNew+ closeB <- buttonNewFromStock "gtk-cancel"+ save <- buttonNewFromStock "gtk-ok"+ boxPackEnd bb closeB PackNatural 0+ boxPackEnd bb save PackNatural 0+ on save buttonActivated (dialogResponse dia ResponseOk)+ on closeB buttonActivated (dialogResponse dia ResponseCancel)+ boxPackStart (castToBox upper) widget PackGrow 7+ boxPackStart (castToBox lower) bb PackNatural 7+ set save [widgetCanDefault := True]+ widgetGrabDefault save+ widgetShowAll dia+ resp <- dialogRun dia+ value <- ext (NewPackage "" workspaceDir "hello")+ widgetDestroy dia+ --find+ case resp of+ ResponseOk -> return value+ _ -> return Nothing++packageNew' :: FilePath -> C.Sink ToolOutput IDEM () -> (Bool -> FilePath -> IDEAction) -> IDEAction+packageNew' workspaceDir log activateAction = do+ windows <- getWindows+ mbNewPackage <- liftIO $ newPackageDialog (head windows) workspaceDir+ case mbNewPackage of+ Nothing -> return ()+ Just NewPackage{..} | null templatePackage -> do+ let dirName = newPackageParentDir </> newPackageName+ mbCabalFile <- liftIO $ cabalFileName dirName+ window <- getMainWindow+ case mbCabalFile of+ Just cfn -> do+ add <- liftIO $ do+ md <- messageDialogNew (Just window) [] MessageQuestion ButtonsCancel+ $ (printf (__+ "There is already file %s in this directory. Would you like to add this package to the workspace?")+ (takeFileName cfn) )+ dialogAddButton md (__ "_Add Package") (ResponseUser 1)+ dialogSetDefaultResponse md (ResponseUser 1)+ set md [ windowWindowPosition := WinPosCenterOnParent ]+ rid <- dialogRun md+ widgetDestroy md+ return $ rid == ResponseUser 1+ when add $ activateAction False cfn+ Nothing -> do+ liftIO $ createDirectoryIfMissing True dirName+ isEmptyDir <- liftIO $ isEmptyDirectory dirName+ make <- if isEmptyDir+ then return True+ else liftIO $ do+ md <- messageDialogNew (Just window) [] MessageQuestion ButtonsCancel+ $ (printf (__+ "The path you have choosen %s is not an empty directory. Are you sure you want to make a new package here?")+ dirName)+ dialogAddButton md (__ "_Make Package Here") (ResponseUser 1)+ dialogSetDefaultResponse md (ResponseUser 1)+ set md [ windowWindowPosition := WinPosCenterOnParent ]+ rid <- dialogRun md+ widgetDestroy md+ return $ rid == ResponseUser 1+ when make $ do+ modules <- liftIO $ allModules dirName+ let Just initialVersion = simpleParse "0.0.1"+ editPackage emptyPackageDescription{+ package = PackageIdentifier (PackageName newPackageName)+ initialVersion,+ buildType = Just Simple,+#if MIN_VERSION_Cabal(1,10,0)+ specVersionRaw = Right (orLaterVersion (Version [1,2] [])),+#endif+ buildDepends = [+ Dependency (PackageName "base") anyVersion+ , Dependency (PackageName "QuickCheck") anyVersion],+ executables = [emptyExecutable {+ exeName = newPackageName+ , modulePath = "Main.hs"+ , buildInfo = emptyBuildInfo {+ hsSourceDirs = ["src"]}}]+#if MIN_VERSION_Cabal(1,10,0)+ , testSuites = [emptyTestSuite {+ testName = "test-" ++ newPackageName+ , testInterface = (TestSuiteExeV10 (Version [1,0] []) "Main.hs")+ , testBuildInfo = emptyBuildInfo {+ hsSourceDirs = ["src"]+ , cppOptions = ["-DMAIN_FUNCTION=testMain"]}}]+#endif+ } dirName modules (activateAction True)+ return ()+ Just NewPackage{..} -> cabalUnpack newPackageParentDir templatePackage False (Just newPackageName) log (activateAction False)++standardSetup = "#!/usr/bin/runhaskell \n"+ ++ "> module Main where\n"+ ++ "> import Distribution.Simple\n"+ ++ "> main :: IO ()\n"+ ++ "> main = defaultMain\n\n"++data ClonePackageSourceRepo = ClonePackageSourceRepo {+ packageToClone :: String,+ cloneParentDir :: FilePath}++cloneFields :: FilePath -> FieldDescription ClonePackageSourceRepo+cloneFields workspaceDir = VFD emptyParams [+ mkField+ (paraName <<<- ParaName ((__ "Existing package to clone source repository"))+ $ emptyParams)+ packageToClone+ (\ a b -> b{packageToClone = a})+ (stringEditor (const True) True),+ mkField+ (paraName <<<- ParaName ((__ "Parent directory"))+ $ paraMinSize <<<- ParaMinSize (-1, 120)+ $ emptyParams)+ (\a -> cloneParentDir a)+ (\ a b -> b{cloneParentDir = a})+ (fileEditor (Just workspaceDir) FileChooserActionSelectFolder "Select")]++clonePackageSourceDialog :: Window -> FilePath -> IO (Maybe ClonePackageSourceRepo)+clonePackageSourceDialog parent workspaceDir = do+ dia <- dialogNew+ set dia [ windowTransientFor := parent+ , windowTitle := (__ "Clone Package") ]+#ifdef MIN_VERSION_gtk3+ upper <- dialogGetContentArea dia+#else+ upper <- dialogGetUpper dia+#endif+ lower <- dialogGetActionArea dia+ (widget,inj,ext,_) <- buildEditor (cloneFields workspaceDir)+ (ClonePackageSourceRepo "" workspaceDir)+ bb <- hButtonBoxNew+ closeB <- buttonNewFromStock "gtk-cancel"+ save <- buttonNewFromStock "gtk-ok"+ boxPackEnd bb closeB PackNatural 0+ boxPackEnd bb save PackNatural 0+ on save buttonActivated (dialogResponse dia ResponseOk)+ on closeB buttonActivated (dialogResponse dia ResponseCancel)+ boxPackStart (castToBox upper) widget PackGrow 7+ boxPackStart (castToBox lower) bb PackNatural 7+ set save [widgetCanDefault := True]+ widgetGrabDefault save+ widgetShowAll dia+ resp <- dialogRun dia+ value <- ext (ClonePackageSourceRepo "" workspaceDir)+ widgetDestroy dia+ --find+ case resp of+ ResponseOk -> return value+ _ -> return Nothing++packageClone :: FilePath -> C.Sink ToolOutput IDEM () -> (FilePath -> IDEAction) -> IDEAction+packageClone workspaceDir log activateAction = do+ windows <- getWindows+ mbResult <- liftIO $ clonePackageSourceDialog (head windows) workspaceDir+ case mbResult of+ Nothing -> return ()+ Just ClonePackageSourceRepo{..} -> cabalUnpack cloneParentDir packageToClone True Nothing log activateAction++cabalUnpack :: FilePath -> String -> Bool -> Maybe String -> C.Sink ToolOutput IDEM () -> (FilePath -> IDEAction) -> IDEAction+cabalUnpack parentDir packageToUnpack sourceRepo mbNewName log activateAction = do+ let tempDir = parentDir </> (packageToUnpack ++ ".leksah.temp")+ liftIO $ do+ oldDirExists <- doesDirectoryExist tempDir+ when oldDirExists $ removeDirectoryRecursive tempDir+ createDirectory tempDir+ runExternalTool' (__ "Unpacking") "cabal" (["unpack"]+ ++ (if sourceRepo then ["--source-repository"] else [])+ ++ ["--destdir=" ++ tempDir, packageToUnpack]) tempDir $ do+ (mbLastOutput, _) <- CU.zipSinks sinkLast log+ case mbLastOutput of+ Just (ToolExit ExitSuccess) -> do+ contents <- liftIO $ getDirectoryContents tempDir+ case filter (not . isPrefixOf ".") contents of+ [] -> do+ liftIO $ removeDirectoryRecursive tempDir+ lift $ ideMessage High $ "Nothing found in " ++ tempDir ++ " after doing a cabal unpack."+ [repoName] -> do+ let destDir = parentDir </> (fromMaybe repoName mbNewName)+ exists <- liftIO $ (||) <$> doesDirectoryExist destDir <*> doesFileExist destDir+ if exists+ then lift $ ideMessage High $ destDir ++ " already exists"+ else do+ liftIO $ renameDirectory (tempDir </> repoName) destDir+ mbCabalFile <- liftIO $ cabalFileName destDir+ window <- lift $ getMainWindow+ lift $ case (mbCabalFile, mbNewName) of+ (Just cfn, Just newName) -> do+ let newCfn = takeDirectory cfn </> newName ++ ".cabal"+ when (cfn /= newCfn) . liftIO $ do+ s <- withFile cfn ReadMode $ hGetContents+ writeFile newCfn $ renameCabalFile (takeBaseName cfn) newName s+ removeFile cfn+ activateAction newCfn+ (Just cfn, _) -> activateAction cfn+ _ -> ideMessage High $ "Unpacked source reposity to " ++ destDir ++ " but it does not contain a .cabal file in the root directory."+ liftIO $ removeDirectoryRecursive tempDir+ _ -> do+ liftIO $ removeDirectoryRecursive tempDir+ lift $ ideMessage High $ "More than one subdirectory found in " ++ tempDir ++ " after doing a cabal unpack."++ _ -> do+ liftIO $ removeDirectoryRecursive tempDir+ lift $ ideMessage High $ "Failed to unpack source reposity to " ++ tempDir++renameCabalFile :: String -> String -> String -> String+renameCabalFile oldName newName = unlines . map renameLine . lines+ where+ prefixes = ["name:", "executable ", "test-suite "]+ prefixesWithLength = zip prefixes $ map length prefixes+ renameLine :: String -> String+ renameLine line =+ case catMaybes $ map (rename (line, map toLower line)) prefixesWithLength of+ l:_ -> l+ [] -> line+ rename :: (String, String) -> (String, Int) -> Maybe String+ rename (line, lcLine) (lcPrefix, pLen) | lcPrefix `isPrefixOf` lcLine =+ let (prefix, rest) = splitAt pLen line+ (spaces, value) = span (==' ') rest in+ Just $ prefix ++ spaces ++ replace oldName newName value+ rename _ _ = Nothing++-- ---------------------------------------------------------------------+-- | We do some twist for handling build infos seperately to edit them in one editor together+-- with the other stuff. This type show what we really edit here+--++data PackageDescriptionEd = PDE {+ pd :: PackageDescription,+ exes :: [Executable'],+#if MIN_VERSION_Cabal(1,10,0)+ tests :: [Test'],+#endif+ mbLib :: Maybe Library',+ bis :: [BuildInfo]}+ deriving Eq++comparePDE a b = do+ when (pd a /= pd b) $ putStrLn "pd"+ when (exes a /= exes b) $ putStrLn "exes"+#if MIN_VERSION_Cabal(1,10,0)+ when (tests a /= tests b) $ putStrLn "tests"+#endif+ when (mbLib a /= mbLib b) $ putStrLn "mbLib"+ when (bis a /= bis b) $ putStrLn "bis"++fromEditor :: PackageDescriptionEd -> PackageDescription+fromEditor (PDE pd exes'+#if MIN_VERSION_Cabal(1,10,0)+ tests'+#endif+ mbLib' buildInfos) =+ let exes = map (\ (Executable' s fb bii) -> if bii + 1 > length buildInfos+ then Executable s fb (buildInfos !! (length buildInfos - 1))+ else Executable s fb (buildInfos !! bii)) exes'+#if MIN_VERSION_Cabal(1,10,0)+ tests = map (\ (Test' s fb bii) -> if bii + 1 > length buildInfos+ then TestSuite s fb (buildInfos !! (length buildInfos - 1)) False+ else TestSuite s fb (buildInfos !! bii) False) tests'+#endif+ mbLib = case mbLib' of+ Nothing -> Nothing+ Just (Library' mn b bii) -> if bii + 1 > length buildInfos+ then Just (Library mn b (buildInfos !! (length buildInfos - 1)))+ else Just (Library mn b (buildInfos !! bii))+ in pd {+ library = mbLib+ , executables = exes+#if MIN_VERSION_Cabal(1,10,0)+ , testSuites = tests+#endif+ }++toEditor :: PackageDescription -> PackageDescriptionEd+toEditor pd =+ let (exes,exeBis) = unzip $ map (\((Executable s fb bi), i) -> ((Executable' s fb i), bi))+ (zip (executables pd) [0..])+#if MIN_VERSION_Cabal(1,10,0)+ (tests,testBis) = unzip $ map (\((TestSuite s fb bi _), i) -> ((Test' s fb i), bi))+ (zip (testSuites pd) [length exeBis..])+ bis = exeBis++testBis+#else+ bis = exeBis+#endif+ (mbLib,bis2) = case library pd of+ Nothing -> (Nothing,bis)+ Just (Library mn b bi) -> (Just (Library' (sort mn) b (length bis)), bis ++ [bi])+ bis3 = if null bis2+ then [emptyBuildInfo]+ else bis2+ in PDE (pd {library = Nothing , executables = []})+ exes+#if MIN_VERSION_Cabal(1,10,0)+ tests+#endif+ mbLib+ bis3++-- ---------------------------------------------------------------------+-- The pane stuff+--++data PackagePane = PackagePane {+ packageBox :: VBox,+ packageNotifer :: Notifier+} deriving Typeable+++data PackageState = PackageState+ deriving (Read, Show, Typeable)++instance Pane PackagePane IDEM+ where+ primPaneName _ = (__ "Package")+ getAddedIndex _ = 0+ getTopWidget = castToWidget . packageBox+ paneId b = "*Package"++instance RecoverablePane PackagePane PackageState IDEM where+ saveState p = return Nothing+ recoverState pp st = return Nothing+ buildPane panePath notebook builder = return Nothing+ builder pp nb w = return (Nothing,[])++editPackage :: PackageDescription -> FilePath -> [ModuleName] -> (FilePath -> IDEAction) -> IDEAction+editPackage packageD packagePath modules afterSaveAction = do+ mbPane :: Maybe PackagePane <- getPane+ case mbPane of+ Nothing -> do+ pp <- getBestPathForId "*Package"+ nb <- getNotebook pp+ packageInfos <- liftIO $ getInstalledPackageIds+ let packageEd = toEditor packageD+ initPackage packagePath packageEd+ (packageDD+ packageInfos+ (takeDirectory packagePath)+ modules+ (length (bis packageEd))+ (concatMap (buildInfoD (Just (takeDirectory packagePath)) modules)+ [0..length (bis packageEd) - 1]))+ pp nb modules afterSaveAction packageEd+ Just p -> liftIO $ bringPaneToFront p++initPackage :: FilePath+ -> PackageDescriptionEd+ -> FieldDescription PackageDescriptionEd+ -> PanePath+ -> Notebook+ -> [ModuleName]+ -> (FilePath -> IDEAction)+ -> PackageDescriptionEd+ -> IDEM ()+initPackage packageDir packageD packageDescr panePath nb modules afterSaveAction origPackageD = do+ let fields = flattenFieldDescription packageDescr+ let initialPackagePath = packageDir </> (display . pkgName . package . pd) packageD ++ ".cabal"+ packageInfos <- liftIO $ getInstalledPackageIds+ mbP <- buildThisPane panePath nb+ (builder' packageDir packageD packageDescr afterSaveAction+ initialPackagePath modules packageInfos fields origPackageD)+ case mbP of+ Nothing -> return ()+ Just (PackagePane{packageNotifer = pn}) -> do+ liftIO $ triggerEvent pn (GUIEvent {+ selector = MayHaveChanged,+ eventText = "",+ gtkReturn = True})+ return ()++builder' :: FilePath ->+ PackageDescriptionEd ->+ FieldDescription PackageDescriptionEd ->+ (FilePath -> IDEAction) ->+ FilePath ->+ [ModuleName] ->+ [PackageId] ->+ [FieldDescription PackageDescriptionEd] ->+ PackageDescriptionEd ->+ PanePath ->+ Notebook ->+ Window ->+ IDEM (Maybe PackagePane,Connections)+builder' packageDir packageD packageDescr afterSaveAction initialPackagePath modules packageInfos fields+ origPackageD panePath nb window = reifyIDE $ \ ideR -> do+ vb <- vBoxNew False 0+ bb <- hButtonBoxNew+ save <- buttonNewFromStock "gtk-save"+ widgetSetSensitive save False+ closeB <- buttonNewFromStock "gtk-close"+ addB <- buttonNewFromStock (__ "Add Build Info")+ removeB <- buttonNewFromStock (__ "Remove Build Info")+ label <- labelNew Nothing+ boxPackStart bb addB PackNatural 0+ boxPackStart bb removeB PackNatural 0+ boxPackEnd bb closeB PackNatural 0+ boxPackEnd bb save PackNatural 0+ (widget, setInj, getExt, notifier) <- buildEditor packageDescr packageD+ let packagePane = PackagePane vb notifier+ boxPackStart vb widget PackGrow 7+ boxPackStart vb label PackNatural 0+ boxPackEnd vb bb PackNatural 7++ let fieldNames = map (\fd -> case getParameterPrim paraName (parameters fd) of+ Just s -> s+ Nothing -> (__ "Unnamed")) fields+ on addB buttonActivated $ do+ mbNewPackage' <- extract packageD [getExt]+ case mbNewPackage' of+ Nothing -> sysMessage Normal (__ "Content doesn't validate")+ Just pde -> reflectIDE (do+ closePane packagePane+ initPackage packageDir pde {bis = bis pde ++ [bis pde !! 0]}+ (packageDD+ (packageInfos)+ packageDir+ modules+ (length (bis pde) + 1)+ (concatMap (buildInfoD (Just packageDir) modules)+ [0..length (bis pde)]))+ panePath nb modules afterSaveAction origPackageD) ideR+ on removeB buttonActivated $ do+ mbNewPackage' <- extract packageD [getExt]+ case mbNewPackage' of+ Nothing -> sysMessage Normal (__ "Content doesn't validate")+ Just pde | length (bis pde) == 1 -> sysMessage Normal (__ "Just one Build Info")+ | otherwise -> reflectIDE (do+ closePane packagePane+ initPackage packageDir pde{bis = take (length (bis pde) - 1) (bis pde)}+ (packageDD+ packageInfos+ packageDir+ modules+ (length (bis pde) - 1)+ (concatMap (buildInfoD (Just packageDir) modules)+ [0..length (bis pde) - 2]))+ panePath nb modules afterSaveAction origPackageD) ideR+ on closeB buttonActivated $ do+ mbP <- extract packageD [getExt]+ let hasChanged = case mbP of+ Nothing -> False+ Just p -> p /= origPackageD+ if not hasChanged+ then reflectIDE (closePane packagePane >> return ()) ideR+ else do+ md <- messageDialogNew (Just window) []+ MessageQuestion+ ButtonsYesNo+ (__ "Unsaved changes. Close anyway?")+ set md [ windowWindowPosition := WinPosCenterOnParent ]+ resp <- dialogRun md+ widgetDestroy md+ case resp of+ ResponseYes -> do+ reflectIDE (closePane packagePane >> return ()) ideR+ _ -> return ()+ on save buttonActivated $ do+ mbNewPackage' <- extract packageD [getExt]+ case mbNewPackage' of+ Nothing -> return ()+ Just newPackage' -> let newPackage = fromEditor newPackage' in do+ let packagePath = packageDir </> (display . pkgName . package . pd) newPackage'+ ++ ".cabal"+#if MIN_VERSION_Cabal(1,10,0)+ writeGenericPackageDescription packagePath (toGenericPackageDescription newPackage)+#else+ writePackageDescription packagePath newPackage+#endif+ reflectIDE (do+ afterSaveAction packagePath+ closePane packagePane+ return ()) ideR+ registerEvent notifier MayHaveChanged (\ e -> do+ mbP <- extract packageD [getExt]+ let hasChanged = case mbP of+ Nothing -> False+ Just p -> p /= origPackageD+ when (isJust mbP) $ labelSetMarkup label ""+ when (isJust mbP) $ comparePDE (fromJust mbP) packageD+ markLabel nb (getTopWidget packagePane) hasChanged+ widgetSetSensitive save hasChanged+ return (e{gtkReturn=False}))+ registerEvent notifier ValidationError (\e -> do+ labelSetMarkup label $ "<span foreground=\"red\" size=\"x-large\">The following fields have invalid values: "+ ++ eventText e ++ "</span>"+ return e)+ return (Just packagePane,[])++-- ---------------------------------------------------------------------+-- The description with some tricks+--++packageDD :: [PackageIdentifier]+ -> FilePath+ -> [ModuleName]+ -> Int+ -> [(String, FieldDescription PackageDescriptionEd)]+ -> FieldDescription PackageDescriptionEd+packageDD packages fp modules numBuildInfos extras = NFD ([+ ((__ "Package"), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Synopsis")+ $ paraSynopsis <<<- ParaSynopsis (__ "A one-line summary of this package")+ $ emptyParams)+ (synopsis . pd)+ (\ a b -> b{pd = (pd b){synopsis = a}})+ (stringEditor (const True) True)+ , mkField+ (paraName <<<- ParaName (__ "Package Identifier") $ emptyParams)+ (package . pd)+ (\ a b -> b{pd = (pd b){package = a}})+ packageEditor+ , mkField+ (paraName <<<- ParaName (__ "Description")+ $ paraSynopsis <<<- ParaSynopsis (__ "A more verbose description of this package")+ $ paraShadow <<<- ParaShadow ShadowOut+ $ paraMinSize <<<- ParaMinSize (-1,210)+ $ emptyParams)+ (description . pd)+ (\ a b -> b{pd = (pd b){description = if null a then " " else a}})+ multilineStringEditor+ , mkField+ (paraName <<<- ParaName (__ "Homepage") $ emptyParams)+ (homepage . pd)+ (\ a b -> b{pd = (pd b){homepage = a}})+ (stringEditor (const True) True)+ , mkField+ (paraName <<<- ParaName (__ "Package URL") $ emptyParams)+ (pkgUrl . pd)+ (\ a b -> b{pd = (pd b){pkgUrl = a}})+ (stringEditor (const True) True)+ , mkField+ (paraName <<<- ParaName (__ "Category") $ emptyParams)+ (category . pd)+ (\ a b -> b{pd = (pd b){category = a}})+ (stringEditor (const True) True)+ ]),+ ((__ "Description"), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Stability") $ emptyParams)+ (stability . pd)+ (\ a b -> b{pd = (pd b){stability = a}})+ (stringEditor (const True) True)+#if MIN_VERSION_Cabal(1,8,0)+ -- TODO+#else+ , mkField+ (paraName <<<- ParaName (__ "License") $ emptyParams)+ (license . pd)+ (\ a b -> b{pd = (pd b){license = a}})+ (comboSelectionEditor [GPL, LGPL, BSD3, BSD4, PublicDomain, AllRightsReserved, OtherLicense] show)+#endif+ , mkField+ (paraName <<<- ParaName (__ "License File") $ emptyParams)+ (licenseFile . pd)+ (\ a b -> b{pd = (pd b){licenseFile = a}})+ (fileEditor (Just fp) FileChooserActionOpen (__ "Select file"))+ , mkField+ (paraName <<<- ParaName (__ "Copyright") $ emptyParams)+ (copyright . pd)+ (\ a b -> b{pd = (pd b){copyright = a}})+ (stringEditor (const True) True)+ , mkField+ (paraName <<<- ParaName (__ "Author") $ emptyParams)+ (author . pd)+ (\ a b -> b{pd = (pd b){author = a}})+ (stringEditor (const True) True)+ , mkField+ (paraName <<<- ParaName (__ "Maintainer") $ emptyParams)+ (maintainer . pd)+ (\ a b -> b{pd = (pd b){maintainer = a}})+ (stringEditor (const True) True)+ , mkField+ (paraName <<<- ParaName (__ "Bug Reports") $ emptyParams)+ (bugReports . pd)+ (\ a b -> b{pd = (pd b){bugReports = a}})+ (stringEditor (const True) True)+ ]),+-- ("Repositories", VFD emptyParams [+-- mkField+-- (paraName <<<- ParaName "Source Repositories" $ emptyParams)+-- (sourceRepos . pd)+-- (\ a b -> b{pd = (pd b){sourceRepos = a}})+-- reposEditor]),+ ((__ "Dependencies "), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Build Dependencies")+ $ paraSynopsis <<<- ParaSynopsis (__ "Does this package depends on other packages?")+ $ paraDirection <<<- ParaDirection Vertical+ $ paraMinSize <<<- ParaMinSize (-1,250)+ $ emptyParams)+ (nub . buildDepends . pd)+ (\ a b -> b{pd = (pd b){buildDepends = a}})+ (dependenciesEditor packages)+ ]),+ ((__ "Meta Dep."), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Cabal version")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "Does this package depends on a specific version of Cabal?")+ $ paraShadow <<<- ParaShadow ShadowIn $ emptyParams)+ (descCabalVersion . pd)+#if MIN_VERSION_Cabal(1,10,0)+ (\ a b -> b{pd = (pd b){specVersionRaw = Right a}})+#else+ (\ a b -> b{pd = (pd b){descCabalVersion = a}})+#endif+ versionRangeEditor+ , mkField+ (paraName <<<- ParaName (__ "Tested with compiler")+ $ paraShadow <<<- ParaShadow ShadowIn+ $ paraDirection <<<- ParaDirection Vertical+ $ paraMinSize <<<- ParaMinSize (-1,150)+ $ emptyParams)+ (\a -> case (testedWith . pd) a of+ [] -> []--(GHC,anyVersion)]+ l -> l)+ (\ a b -> b{pd = (pd b){testedWith = a}})+ testedWithEditor+ ]),+ ((__ "Data Files"), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Data Files")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "A list of files to be installed for run-time use by the package.")+ $ paraDirection <<<- ParaDirection Vertical+ $ paraMinSize <<<- ParaMinSize (-1,250)+ $ emptyParams)+ (dataFiles . pd)+ (\ a b -> b{pd = (pd b){dataFiles = a}})+ (filesEditor (Just fp) FileChooserActionOpen (__ "Select File"))+ , mkField+ (paraName <<<- ParaName (__ "Data directory") $ emptyParams)+ (dataDir . pd)+ (\ a b -> b{pd = (pd b){dataDir = a}})+ (fileEditor (Just fp) FileChooserActionSelectFolder (__ "Select file"))+ ]),+ ((__ "Extra Files"), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Extra Source Files")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "A list of additional files to be included in source distributions.")+ $ paraDirection <<<- ParaDirection Vertical+ $ paraMinSize <<<- ParaMinSize (-1,120)+ $ emptyParams)+ (extraSrcFiles . pd)+ (\ a b -> b{pd = (pd b){extraSrcFiles = a}})+ (filesEditor (Just fp) FileChooserActionOpen (__ "Select File"))+ , mkField+ (paraName <<<- ParaName (__ "Extra Tmp Files")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "A list of additional files or directories to be removed by setup clean.")+ $ paraDirection <<<- ParaDirection Vertical+ $ paraMinSize <<<- ParaMinSize (-1,120)+ $ emptyParams)+ (extraTmpFiles . pd)+ (\ a b -> b{pd = (pd b){extraTmpFiles = a}})+ (filesEditor (Just fp) FileChooserActionOpen (__ "Select File"))+ ]),+ ((__ "Other"),VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Build Type")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "Describe executable programs contained in the package")+ $ paraShadow <<<- ParaShadow ShadowIn+ $ paraDirection <<<- ParaDirection Vertical+ $ emptyParams)+ (buildType . pd)+ (\ a b -> b{pd = (pd b){buildType = a}})+ (maybeEditor (buildTypeEditor, emptyParams) True (__ "Specify?"))+ , mkField+ (paraName <<<- ParaName (__ "Custom Fields")+ $ paraShadow <<<- ParaShadow ShadowIn+ $ paraMinSize <<<- ParaMinSize (-1,150)+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ (customFieldsPD . pd)+ (\ a b -> b{pd = (pd b){customFieldsPD = a}})+ (multisetEditor+ (ColumnDescr True [((__ "Name"),\(n,_) -> [cellText := n])+ ,((__ "Value"),\(_,v) -> [cellText := v])])+ ((pairEditor+ (stringxEditor (const True),emptyParams)+ (stringEditor (const True) True,emptyParams)),emptyParams)+ Nothing+ Nothing)+ ]),+ ((__ "Executables"),VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Executables")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "Describe executable programs contained in the package")+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ exes+ (\ a b -> b{exes = a})+ (executablesEditor (Just fp) modules numBuildInfos)+ ]),+#if MIN_VERSION_Cabal(1,10,0)+ ((__ "Tests"),VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Tests")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "Describe tests contained in the package")+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ tests+ (\ a b -> b{tests = a})+ (testsEditor (Just fp) modules numBuildInfos)+ ]),+#endif+ ((__ "Library"), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Library")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "If the package contains a library, specify the exported modules here")+ $ paraDirection <<<- ParaDirection Vertical+ $ paraShadow <<<- ParaShadow ShadowIn $ emptyParams)+ mbLib+ (\ a b -> b{mbLib = a})+ (maybeEditor (libraryEditor (Just fp) modules numBuildInfos,+ paraName <<<- ParaName (__ "Specify exported modules")+ $ emptyParams) True+ (__ "Does this package contain a library?"))+ ])+ ] ++ extras)++update :: [BuildInfo] -> Int -> (BuildInfo -> BuildInfo) -> [BuildInfo]+update bis index func =+ map (\(bi,ind) -> if ind == index+ then func bi+ else bi)+ (zip bis [0..length bis - 1])++buildInfoD :: Maybe FilePath -> [ModuleName] -> Int -> [(String,FieldDescription PackageDescriptionEd)]+buildInfoD fp modules i = [+ ((printf (__ "%s Build Info") (show (i + 1))), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Component is buildable here") $ emptyParams)+ (buildable . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{buildable = a})})+ boolEditor+ , mkField+ (paraName <<<- ParaName+ (__ "Where to look for the source hierarchy")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "Root directories for the source hierarchy.")+ $ paraShadow <<<- ParaShadow ShadowIn+ $ paraDirection <<<- ParaDirection Vertical+ $ paraMinSize <<<- ParaMinSize (-1,150)+ $ emptyParams)+ (hsSourceDirs . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{hsSourceDirs = a})})+ (filesEditor fp FileChooserActionSelectFolder (__ "Select folder"))+ , mkField+ (paraName <<<- ParaName (__ "Non-exposed or non-main modules")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "A list of modules used by the component but not exposed to users.")+ $ paraShadow <<<- ParaShadow ShadowIn+ $ paraDirection <<<- ParaDirection Vertical+ $ paraMinSize <<<- ParaMinSize (-1,300)+ $ paraPack <<<- ParaPack PackGrow+ $ emptyParams)+ (map display. otherModules . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi ->+ bi{otherModules = (map (\i -> forceJust (simpleParse i)+ " PackageEditor >> buildInfoD: no parse for moduile name" ) a)})})+ (modulesEditor modules)+ ]),+ ((printf (__ "%s Compiler ") (show (i + 1))), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Options for haskell compilers")+ $ paraDirection <<<- ParaDirection Vertical+ $ paraShadow <<<- ParaShadow ShadowIn+ $ paraPack <<<- ParaPack PackGrow $ emptyParams)+ (options . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{options = a})})+ (multisetEditor+ (ColumnDescr True [( (__ "Compiler Flavor"),\(cv,_) -> [cellText := show cv])+ ,( (__ "Options"),\(_,op) -> [cellText := concatMap (\s -> ' ' : s) op])])+ ((pairEditor+ (compilerFlavorEditor,emptyParams)+ (optsEditor,emptyParams)),+ (paraDirection <<<- ParaDirection Vertical+ $ paraShadow <<<- ParaShadow ShadowIn $ emptyParams))+ Nothing+ Nothing)+ , mkField+ (paraName <<<- ParaName (__ "Additional options for GHC when built with profiling")+ $ emptyParams)+ (ghcProfOptions . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{ghcProfOptions = a})})+ optsEditor+ , mkField+ (paraName <<<- ParaName (__ "Additional options for GHC when the package is built as shared library")+ $ emptyParams)+ (ghcSharedOptions . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{ghcSharedOptions = a})})+ optsEditor+ ]),+ ((printf (__ "%s Extensions ") (show (i + 1))), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Extensions")+ $ paraSynopsis <<<- ParaSynopsis+ (__ "A list of Haskell extensions used by every module.")+ $ paraMinSize <<<- ParaMinSize (-1,400)+ $ paraPack <<<- ParaPack PackGrow+ $ emptyParams)+#if MIN_VERSION_Cabal(1,10,0)+ (oldExtensions . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{oldExtensions = a})})+#else+ (extensions . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{extensions = a})})+#endif+ extensionsEditor+ ]),+ ((printf (__ "%s Build Tools ") (show (i + 1))), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Tools needed for a build")+ $ paraDirection <<<- ParaDirection Vertical+ $ paraMinSize <<<- ParaMinSize (-1,120)+ $ emptyParams)+ (buildTools . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{buildTools = a})})+ (dependenciesEditor [])+ ]),+ ( (printf (__ "%s Pkg Config ") (show (i + 1))), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "A list of pkg-config packages, needed to build this package")+ $ paraDirection <<<- ParaDirection Vertical+ $ paraMinSize <<<- ParaMinSize (-1,120)+ $ emptyParams)+ (pkgconfigDepends . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{pkgconfigDepends = a})})+ (dependenciesEditor [])+ ]),+ ( (printf (__ "%s Opts C -1-") (show (i + 1))), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Options for C compiler")+ $ paraDirection <<<- ParaDirection Vertical+ $ emptyParams)+ (ccOptions . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{ccOptions = a})})+ optsEditor+ , mkField+ (paraName <<<- ParaName (__ "Options for linker")+ $ paraDirection <<<- ParaDirection Vertical+ $ emptyParams)+ (ldOptions . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{ldOptions = a})})+ optsEditor+ , mkField+ (paraName <<<- ParaName (__ "A list of header files to use when compiling")+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ (includes . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{includes = a})})+ (stringsEditor (const True) True)+ , mkField+ (paraName <<<- ParaName (__ "A list of header files to install")+ $ paraMinSize <<<- ParaMinSize (-1,150)+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ (installIncludes . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{installIncludes = a})})+ (filesEditor fp FileChooserActionOpen (__ "Select File"))+ ]),+ ((printf (__ "%s Opts C -2-") (show (i + 1))), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "A list of directories to search for header files")+ $ paraMinSize <<<- ParaMinSize (-1,150)+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ (includeDirs . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{includeDirs = a})})+ (filesEditor fp FileChooserActionSelectFolder (__ "Select Folder"))+ , mkField+ (paraName <<<- ParaName+ (__ "A list of C source files to be compiled,linked with the Haskell files.")+ $ paraMinSize <<<- ParaMinSize (-1,150)+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ (cSources . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{cSources = a})})+ (filesEditor fp FileChooserActionOpen (__ "Select file"))+ ]),+ ((printf (__ "%s Opts Libs ") (show (i + 1))), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "A list of extra libraries to link with")+ $ paraMinSize <<<- ParaMinSize (-1,150)+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ (extraLibs . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{extraLibs = a})})+ (stringsEditor (const True) True)+ , mkField+ (paraName <<<- ParaName (__ "A list of directories to search for libraries.")+ $ paraMinSize <<<- ParaMinSize (-1,150)+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ (extraLibDirs . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{extraLibDirs = a})})+ (filesEditor fp FileChooserActionSelectFolder (__ "Select Folder"))+ ]),+ ( (printf (__ "%s Other") (show (i + 1))), VFD emptyParams [+ mkField+ (paraName <<<- ParaName (__ "Options for C preprocessor")+ $ paraDirection <<<- ParaDirection Vertical+ $ emptyParams)+ (cppOptions . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{cppOptions = a})})+ optsEditor+ , mkField+ (paraName <<<- ParaName (__ "Support frameworks for Mac OS X")+ $ paraMinSize <<<- ParaMinSize (-1,150)+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ (frameworks . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{frameworks = a})})+ (stringsEditor (const True) True)+ , mkField+ (paraName <<<- ParaName (__ "Custom fields build info")+ $ paraShadow <<<- ParaShadow ShadowIn+ $ paraMinSize <<<- ParaMinSize (-1,150)+ $ paraDirection <<<- ParaDirection Vertical $ emptyParams)+ (customFieldsBI . (\a -> a !! i) . bis)+ (\ a b -> b{bis = update (bis b) i (\bi -> bi{customFieldsBI = a})})+ (multisetEditor+ (ColumnDescr True [((__ "Name"),\(n,_) -> [cellText := n])+ ,((__ "Value"),\(_,v) -> [cellText := v])])+ ((pairEditor+ (stringxEditor (const True),emptyParams)+ (stringEditor (const True) True,emptyParams)),emptyParams)+ Nothing+ Nothing)+ ])]++stringxEditor :: (String -> Bool) -> Editor String+stringxEditor val para noti = do+ (wid,inj,ext) <- stringEditor val True para noti+ let+ xinj ("") = inj ""+ xinj ('x':'-':rest) = inj rest+ xinj _ = throwIDE "PackageEditor>>stringxEditor: field without leading x-"+ xext = do+ res <- ext+ case res of+ Nothing -> return Nothing+ Just str -> return (Just ("x-" ++ str))+ return (wid,xinj,xext)++optsEditor :: Editor [String]+optsEditor para noti = do+ (wid,inj,ext) <- stringEditor (const True) True para noti+ let+ oinj = inj . unwords+ oext = do+ res <- ext+ case res of+ Nothing -> return Nothing+ Just str -> return (Just (words str))+ return (wid,oinj,oext)++packageEditor :: Editor PackageIdentifier+packageEditor para noti = do+ (wid,inj,ext) <- pairEditor+ (stringEditor (\s -> not (null s)) True, paraName <<<- ParaName (__ "Name") $ emptyParams)+ (versionEditor, paraName <<<- ParaName (__ "Version") $ emptyParams)+ (paraDirection <<<- ParaDirection Horizontal+ $ paraShadow <<<- ParaShadow ShadowIn+ $ para) noti+ let pinj (PackageIdentifier (PackageName n) v) = inj (n,v)+ let pext = do+ mbp <- ext+ case mbp of+ Nothing -> return Nothing+ Just (n,v) -> do+ if null n+ then return Nothing+ else return (Just $PackageIdentifier (PackageName n) v)+ return (wid,pinj,pext)++testedWithEditor :: Editor [(CompilerFlavor, VersionRange)]+testedWithEditor para = do+ multisetEditor+ (ColumnDescr True [((__ "Compiler Flavor"),\(cv,_) -> [cellText := show cv])+ ,((__ "Version Range"),\(_,vr) -> [cellText := display vr])])+ (pairEditor+ (compilerFlavorEditor, paraShadow <<<- (ParaShadow ShadowNone) $ emptyParams)+ (versionRangeEditor, paraShadow <<<- (ParaShadow ShadowNone) $ emptyParams),+ (paraDirection <<<- (ParaDirection Vertical) $ emptyParams))+ Nothing+ (Just (==))+ para++compilerFlavorEditor :: Editor CompilerFlavor+compilerFlavorEditor para noti = do+ (wid,inj,ext) <- eitherOrEditor+ (comboSelectionEditor flavors show, paraName <<<- (ParaName (__ "Select compiler")) $ emptyParams)+ (stringEditor (\s -> not (null s)) True, paraName <<<- (ParaName (__ "Specify compiler")) $ emptyParams)+ (__ "Other")+ (paraName <<<- ParaName (__ "Select") $ para)+ noti+ let cfinj comp = case comp of+ (OtherCompiler str) -> inj (Right str)+ other -> inj (Left other)+ let cfext = do+ mbp <- ext+ case mbp of+ Nothing -> return Nothing+ Just (Right s) -> return (Just $OtherCompiler s)+ Just (Left other) -> return (Just other)+ return (wid,cfinj,cfext)+ where+ flavors = [GHC, NHC, Hugs, HBC, Helium, JHC]++buildTypeEditor :: Editor BuildType+buildTypeEditor para noti = do+ (wid,inj,ext) <- eitherOrEditor+ (comboSelectionEditor flavors show, paraName <<<- (ParaName (__ "Select")) $ emptyParams)+ (stringEditor (const True) True, paraName <<<- (ParaName (__ "Unknown")) $ emptyParams)+ (__ "Unknown")+ (paraName <<<- ParaName (__ "Select") $ para)+ noti+ let cfinj comp = case comp of+ (UnknownBuildType str) -> inj (Right str)+ other -> inj (Left other)+ let cfext = do+ mbp <- ext+ case mbp of+ Nothing -> return Nothing+ Just (Right s) -> return (Just $ UnknownBuildType s)+ Just (Left other) -> return (Just other)+ return (wid,cfinj,cfext)+ where+ flavors = [Simple, Configure, Make, Custom]++extensionsEditor :: Editor [Extension]+extensionsEditor = staticListMultiEditor extensionsL show+++extensionsL :: [Extension]+#if MIN_VERSION_Cabal(1,11,0)+extensionsL = map EnableExtension [minBound..maxBound]+#else+extensionsL = knownExtensions+#endif++{--+reposEditor :: Editor [SourceRepo]+reposEditor p noti =+ multisetEditor+ (ColumnDescr False [("",\repo -> [cellText := display repo])])+ (repoEditor,+ paraOuterAlignment <<<- ParaInnerAlignment (0.0, 0.5, 1.0, 1.0)+ $ paraInnerAlignment <<<- ParaOuterAlignment (0.0, 0.5, 1.0, 1.0)+ $ emptyParams)+ Nothing+ Nothing+ (paraShadow <<<- ParaShadow ShadowIn $+ paraOuterAlignment <<<- ParaInnerAlignment (0.0, 0.5, 1.0, 1.0)+ $ paraInnerAlignment <<<- ParaOuterAlignment (0.0, 0.5, 1.0, 1.0)+ $ paraDirection <<<- ParaDirection Vertical+ $ paraPack <<<- ParaPack PackGrow+ $ p)+ noti++instance Text SourceRepo where+ disp (SourceRepo repoKind repoType repoLocation repoModule repoBranch repoTag repoSubdir)+ = disp repoKind+ <+> case repoType of+ Nothing -> empty+ Just repoT -> disp repoT+ <+> case repoLocation of+ Nothing -> empty+ Just repoL -> text repoL++repoEditor :: Editor SourceRepo+repoEditor paras noti = do+ (widg,inj,ext) <- tupel7Editor+ (repoKindEditor,noBorder)+ (maybeEditor (repoTypeEditor,noBorder) True "Specify a type", emptyParams)+ (maybeEditor (stringEditor (const True) True,noBorder) True "Specify a location", emptyParams)+ (maybeEditor (stringEditor (const True) True,noBorder) True "Specify a module", emptyParams)+ (maybeEditor (stringEditor (const True) True,noBorder) True "Specify a branch", emptyParams)+ (maybeEditor (stringEditor (const True) True,noBorder) True "Specify a tag", emptyParams)+ (maybeEditor (stringEditor (const True) True,noBorder) True "Specify a subdir", emptyParams)+ (paraDirection <<<- ParaDirection Vertical $ noBorder)+ noti+ return (widg,+ (\ r -> inj (repoKind r,repoType r,repoLocation r,repoModule r,repoBranch r,repoTag r,repoSubdir r)),+ (do+ mb <- ext+ case mb of+ Nothing -> return Nothing+ Just (a,b,c,d,e,f,g) -> return (Just (SourceRepo a b c d e f g))))+ where noBorder = paraOuterAlignment <<<- ParaOuterAlignment (0.0, 0.0, 0.0, 0.0)+ $ paraOuterPadding <<<- ParaOuterPadding (0, 0, 0, 0)+ $ paraInnerAlignment <<<- ParaInnerAlignment (0.0, 0.0, 0.0, 0.0)+ $ paraInnerPadding <<<- ParaInnerPadding (0, 0, 0, 0)+ $ emptyParams++repoKindEditor :: Editor RepoKind+repoKindEditor paras noti = do+ (widg,inj,ext) <- pairEditor+ (comboSelectionEditor selectionList show, emptyParams)+ (stringEditor (const True) True,emptyParams)+ paras+ noti+ return (widg,+ (\kind -> case kind of+ RepoKindUnknown str -> inj (RepoKindUnknown "",str)+ other -> inj (other,"")),+ (do+ mbRes <- ext+ case mbRes of+ Nothing -> return Nothing+ Just (RepoKindUnknown "",str) -> return (Just (RepoKindUnknown str))+ Just (other,_) -> return (Just other)))+ where selectionList = [RepoHead, RepoThis, RepoKindUnknown ""]++repoTypeEditor :: Editor RepoType+repoTypeEditor paras noti = do+ (widg,inj,ext) <- pairEditor+ (comboSelectionEditor selectionList show, emptyParams)+ (stringEditor (const True) True,emptyParams)+ paras+ noti+ return (widg,+ (\kind -> case kind of+ OtherRepoType str -> inj (OtherRepoType "",str)+ other -> inj (other,"")),+ (do+ mbRes <- ext+ case mbRes of+ Nothing -> return Nothing+ Just (OtherRepoType "",str) -> return (Just (OtherRepoType str))+ Just (other,_) -> return (Just other)))+ where selectionList = [Darcs, Git, SVN, CVS, Mercurial, GnuArch, Bazaar, Monotone, OtherRepoType ""]+--}++-- ------------------------------------------------------------+-- * BuildInfos+-- ------------------------------------------------------------++data Library' = Library'{+ exposedModules' :: [ModuleName]+, libExposed' :: Bool+, libBuildInfoIdx :: Int}+ deriving (Show, Eq)++data Executable' = Executable'{+ exeName' :: String+, modulePath' :: FilePath+, buildInfoIdx :: Int}+ deriving (Show, Eq)++#if MIN_VERSION_Cabal(1,10,0)+data Test' = Test'{+ testName' :: String+, testInterface' :: TestSuiteInterface+, testBuildInfoIdx :: Int}+ deriving (Show, Eq)+#endif++instance Default Library'+ where getDefault = Library' [] getDefault getDefault++instance Default Executable'+ where getDefault = Executable' getDefault getDefault getDefault++#if MIN_VERSION_Cabal(1,10,0)+instance Default Test'+ where getDefault = Test' getDefault (TestSuiteExeV10 (Version [1,0] []) getDefault) getDefault+#endif++libraryEditor :: Maybe FilePath -> [ModuleName] -> Int -> Editor Library'+libraryEditor fp modules numBuildInfos para noti = do+ (wid,inj,ext) <-+ tupel3Editor+ (boolEditor,+ paraName <<<- ParaName (__ "Exposed")+ $ paraSynopsis <<<- ParaSynopsis (__ "Is the lib to be exposed by default?")+ $ emptyParams)+ (modulesEditor (sort modules),+ paraName <<<- ParaName (__ "Exposed Modules")+ $ paraMinSize <<<- ParaMinSize (-1,300)+ $ para)+ (buildInfoEditorP numBuildInfos, paraName <<<- ParaName (__ "Build Info")+ $ paraPack <<<- ParaPack PackNatural+ $ para)+ (paraDirection <<<- ParaDirection Vertical+ $ emptyParams)+ noti+ let pinj (Library' em exp bi) = inj (exp, map display em,bi)+ let pext = do+ mbp <- ext+ case mbp of+ Nothing -> return Nothing+ Just (exp,em,bi) -> return (Just $ Library' (map (\s -> forceJust (simpleParse s)+ "SpecialEditor >> libraryEditor: no parse for moduile name") em) exp bi)+ return (wid,pinj,pext)++--moduleEditor :: [ModuleName] -> Editor String+--moduleEditor modules = comboSelectionEditor (map display modules)++modulesEditor :: [ModuleName] -> Editor [String]+modulesEditor modules = staticListMultiEditor (map display modules) id++executablesEditor :: Maybe FilePath -> [ModuleName] -> Int -> Editor [Executable']+executablesEditor fp modules countBuildInfo p =+ multisetEditor+ (ColumnDescr True [( (__ "Executable Name"),\(Executable' exeName _ _) -> [cellText := exeName])+ ,( (__ "Module Path"),\(Executable' _ mp _) -> [cellText := mp])++ ,( (__ "Build info index"),\(Executable' _ _ bii) -> [cellText := show (bii + 1)])])+ (executableEditor fp modules countBuildInfo,emptyParams)+ Nothing+ Nothing+ (paraShadow <<<- ParaShadow ShadowIn+ $ paraMinSize <<<- ParaMinSize (-1,200) $ p)++executableEditor :: Maybe FilePath -> [ModuleName] -> Int -> Editor Executable'+executableEditor fp modules countBuildInfo para noti = do+ (wid,inj,ext) <- tupel3Editor+ (stringEditor (\s -> not (null s)) True,+ paraName <<<- ParaName (__ "Executable Name")+ $ emptyParams)+ (stringEditor (\s -> not (null s)) True,+ paraDirection <<<- ParaDirection Vertical+ $ paraName <<<- ParaName (__ "File with main function")+ $ emptyParams)+ (buildInfoEditorP countBuildInfo, paraName <<<- ParaName (__ "Build Info")+ $ paraOuterAlignment <<<- ParaOuterAlignment (0.0, 0.0, 0.0, 0.0)+ $ paraOuterPadding <<<- ParaOuterPadding (0, 0, 0, 0)+ $ paraInnerAlignment <<<- ParaInnerAlignment (0.0, 0.0, 0.0, 0.0)+ $ paraInnerPadding <<<- ParaInnerPadding (0, 0, 0, 0)+ $ emptyParams)+ (paraDirection <<<- ParaDirection Vertical $ para)+ noti+ let pinj (Executable' s f bi) = inj (s,f,bi)+ let pext = do+ mbp <- ext+ case mbp of+ Nothing -> return Nothing+ Just (s,f,bi) -> return (Just $Executable' s f bi)+ return (wid,pinj,pext)++#if MIN_VERSION_Cabal(1,10,0)+testsEditor :: Maybe FilePath -> [ModuleName] -> Int -> Editor [Test']+testsEditor fp modules countBuildInfo p =+ multisetEditor+ (ColumnDescr True [( (__ "Test Name"),\(Test' testName _ _) -> [cellText := testName])+ ,( (__ "Interface"),\(Test' _ i _) -> [cellText := interfaceName i])++ ,( (__ "Build info index"),\(Test' _ _ bii) -> [cellText := show (bii + 1)])])+ (testEditor fp modules countBuildInfo,emptyParams)+ Nothing+ Nothing+ (paraShadow <<<- ParaShadow ShadowIn+ $ paraMinSize <<<- ParaMinSize (-1,200) $ p)+ where+ interfaceName (TestSuiteExeV10 _ f) = f+ interfaceName i = show i++testEditor :: Maybe FilePath -> [ModuleName] -> Int -> Editor Test'+testEditor fp modules countBuildInfo para noti = do+ (wid,inj,ext) <- tupel3Editor+ (stringEditor (\s -> not (null s)) True,+ paraName <<<- ParaName (__ "Test Name")+ $ emptyParams)+ (stringEditor (\s -> not (null s)) True,+ paraDirection <<<- ParaDirection Vertical+ $ paraName <<<- ParaName (__ "File with main function")+ $ emptyParams)+ (buildInfoEditorP countBuildInfo, paraName <<<- ParaName (__ "Build Info")+ $ paraOuterAlignment <<<- ParaOuterAlignment (0.0, 0.0, 0.0, 0.0)+ $ paraOuterPadding <<<- ParaOuterPadding (0, 0, 0, 0)+ $ paraInnerAlignment <<<- ParaInnerAlignment (0.0, 0.0, 0.0, 0.0)+ $ paraInnerPadding <<<- ParaInnerPadding (0, 0, 0, 0)+ $ emptyParams)+ (paraDirection <<<- ParaDirection Vertical $ para)+ noti+ let pinj (Test' s (TestSuiteExeV10 (Version [1,0] []) f) bi) = inj (s,f,bi)+ pinj _ = error "Unexpected Test Interface"+ let pext = do+ mbp <- ext+ case mbp of+ Nothing -> return Nothing+ Just (s,f,bi) -> return (Just $Test' s (TestSuiteExeV10 (Version [1,0] []) f) bi)+ return (wid,pinj,pext)+#endif++buildInfoEditorP :: Int -> Editor Int+buildInfoEditorP numberOfBuildInfos para noti = do+ (wid,inj,ext) <- intEditor (1.0,fromIntegral numberOfBuildInfos,1.0)+ (paraName <<<- ParaName (__ "Build Info") $para) noti+ let pinj i = inj (i + 1)+ let pext = do+ mbV <- ext+ case mbV of+ Nothing -> return Nothing+ Just i -> return (Just (i - 1))+ return (wid,pinj,pext)++-- ------------------------------------------------------------+-- * (Boring) default values+-- ------------------------------------------------------------+++instance Default CompilerFlavor+ where getDefault = GHC++instance Default BuildInfo+ where getDefault = emptyBuildInfo++instance Default Library+ where getDefault = Library [] getDefault getDefault++instance Default Executable+ where getDefault = Executable getDefault getDefault getDefault++instance Default RepoType+ where getDefault = Darcs++instance Default RepoKind+ where getDefault = RepoThis++instance Default SourceRepo+ where getDefault = SourceRepo getDefault getDefault getDefault getDefault getDefault+ getDefault getDefault++instance Default BuildType+ where getDefault = Simple++
@@ -42,6 +42,7 @@ mkFieldPP) import Text.ParserCombinators.Parsec hiding(Parser) import Debug.Trace (trace)+import IDE.Utils.GUIUtils (__) data IDEFlags = IDEFlags { flagsBox :: VBox@@ -52,7 +53,7 @@ instance Pane IDEFlags IDEM where- primPaneName _ = "Package Flags"+ primPaneName _ = (__ "Package Flags") getAddedIndex _ = 0 getTopWidget = castToWidget . flagsBox paneId b = "*Flags"@@ -89,24 +90,24 @@ saveB <- buttonNewFromStock "gtk-save" widgetSetSensitive saveB False cancelB <- buttonNewFromStock "gtk-cancel"- boxPackStartDefaults bb cancelB- boxPackStartDefaults bb saveB+ boxPackStart bb cancelB PackGrow 0+ boxPackStart bb saveB PackGrow 0 (widget,injb,ext,notifier) <- buildEditor flagsDesc idePackage sw <- scrolledWindowNew Nothing Nothing scrolledWindowAddWithViewport sw widget scrolledWindowSetPolicy sw PolicyAutomatic PolicyAutomatic- saveB `onClicked` (do+ on saveB buttonActivated (do mbPackWithNewFlags <- extract idePackage [ext] case mbPackWithNewFlags of Nothing -> return () Just packWithNewFlags -> do reflectIDE (do- changePackage packWithNewFlags- closePane flagsPane) ideR+ changePackage packWithNewFlags+ closePane flagsPane) ideR writeFields ((dropExtension (ipdCabalFile packWithNewFlags)) ++ leksahFlagFileExtension) packWithNewFlags flatFlagsDescription)- cancelB `onClicked` (reflectIDE (closePane flagsPane >> return ()) ideR)+ on cancelB buttonActivated (reflectIDE (closePane flagsPane >> return ()) ideR) registerEvent notifier FocusIn (\e -> do reflectIDE (makeActive flagsPane) ideR return (e{gtkReturn=False}))@@ -172,7 +173,7 @@ flagsDescription :: FieldDescriptionPP IDEPackage IDEM flagsDescription = VFDPP emptyParams [ mkFieldPP- (paraName <<<- ParaName "Config flags" $ emptyParams)+ (paraName <<<- ParaName (__ "Config flags") $ emptyParams) (PP.text . show) readParser (\p -> unargs (ipdConfigFlags p))@@ -180,7 +181,7 @@ (stringEditor (const True) True) (\ _ -> return ()) , mkFieldPP- (paraName <<<- ParaName "Build flags" $ emptyParams)+ (paraName <<<- ParaName (__ "Build flags") $ emptyParams) (PP.text . show) readParser (\p -> unargs (ipdBuildFlags p))@@ -188,7 +189,7 @@ (stringEditor (const True) True) (\ _ -> return ()) , mkFieldPP- (paraName <<<- ParaName "Test flags" $ emptyParams)+ (paraName <<<- ParaName (__ "Test flags") $ emptyParams) (PP.text . show) readParser (\p -> unargs (ipdTestFlags p))@@ -196,7 +197,7 @@ (stringEditor (const True) True) (\ _ -> return ()) , mkFieldPP- (paraName <<<- ParaName "Haddock flags" $ emptyParams)+ (paraName <<<- ParaName (__ "Haddock flags") $ emptyParams) (PP.text . show) readParser (\p -> unargs (ipdHaddockFlags p))@@ -204,7 +205,7 @@ (stringEditor (const True) True) (\ _ -> return ()) , mkFieldPP- (paraName <<<- ParaName "Executable flags" $ emptyParams)+ (paraName <<<- ParaName (__ "Executable flags") $ emptyParams) (PP.text . show) readParser (\p -> unargs (ipdExeFlags p))@@ -212,7 +213,7 @@ (stringEditor (const True) True) (\ _ -> return ()) , mkFieldPP- (paraName <<<- ParaName "Install flags" $ emptyParams)+ (paraName <<<- ParaName (__ "Install flags") $ emptyParams) (PP.text . show) readParser (\p -> unargs (ipdInstallFlags p))@@ -220,7 +221,7 @@ (stringEditor (const True) True) (\ _ -> return ()) , mkFieldPP- (paraName <<<- ParaName "Register flags" $ emptyParams)+ (paraName <<<- ParaName (__ "Register flags") $ emptyParams) (PP.text . show) readParser (\p -> unargs (ipdRegisterFlags p))@@ -228,7 +229,7 @@ (stringEditor (const True) True) (\ _ -> return ()) , mkFieldPP- (paraName <<<- ParaName "Unregister flags" $ emptyParams)+ (paraName <<<- ParaName (__ "Unregister flags") $ emptyParams) (PP.text . show) readParser (\p -> unargs (ipdUnregisterFlags p))@@ -236,7 +237,7 @@ (stringEditor (const True) True) (\ _ -> return ()) , mkFieldPP- (paraName <<<- ParaName "Source Distribution flags" $ emptyParams)+ (paraName <<<- ParaName (__ "Source Distribution flags") $ emptyParams) (PP.text . show) readParser (\p -> unargs (ipdSdistFlags p))
@@ -29,7 +29,7 @@ import Graphics.UI.Gtk (widgetDestroy, dialogRun, windowWindowPosition, dialogAddButton, messageDialogNew, labelSetMarkup, labelNew, widgetSetSensitive,- cellText, widgetModifyFont, onClicked, boxPackEnd, boxPackStart,+ cellText, widgetModifyFont, on, buttonActivated, boxPackEnd, boxPackStart, buttonNewFromStock, hButtonBoxNew, vBoxNew, castToWidget, VBox, ShadowType(..), Packing(..), fontDescriptionFromString, AttrOp(..), FileChooserAction(..), Color(..), ResponseId(..))@@ -50,6 +50,7 @@ import IDE.TextEditor import IDE.Pane.SourceBuffer import IDE.Pane.Log+import IDE.Pane.Info (setInfoStyle) import IDE.Utils.FileUtils import IDE.Utils.GUIUtils import IDE.Debug@@ -58,12 +59,13 @@ debugSetBreakOnException, debugSetPrintEvldWithShow) import Graphics.UI.Gtk.SourceView- (sourceStyleSchemeManagerGetSchemeIds, sourceStyleSchemeManagerNew)+ (sourceStyleSchemeManagerAppendSearchPath,+ sourceStyleSchemeManagerGetSchemeIds, sourceStyleSchemeManagerNew) import System.Time (getClockTime) import qualified IDE.StrippedPrefs as SP import Control.Exception(SomeException,catch) import Prelude hiding(catch)-import Data.List (sortBy)+import Data.List (isSuffixOf, sortBy) import Data.Maybe (isJust) import Graphics.UI.Gtk.Windows.MessageDialog (ButtonsType(..), MessageType(..))@@ -71,6 +73,7 @@ import Graphics.UI.Gtk.General.Enums (WindowPosition(..)) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad (forM_, when)+import System.FilePath ((</>)) -- --------------------------------------------------------------------- -- This needs to be incremented, when the preferences format changes@@ -91,7 +94,7 @@ instance Pane IDEPrefs IDEM where- primPaneName _ = "Prefs"+ primPaneName _ = (__ "Prefs") getAddedIndex _ = 0 getTopWidget = castToWidget . prefsBox paneId b = "*Prefs"@@ -124,15 +127,15 @@ boxPackStart vb label PackNatural 0 boxPackEnd vb bb PackNatural 7 let prefsPane = IDEPrefs vb- apply `onClicked` (do+ on apply buttonActivated $ do mbNewPrefs <- extract prefs [ext] case mbNewPrefs of Nothing -> return () Just newPrefs -> do lastAppliedPrefs <- readIORef lastAppliedPrefsRef mapM_ (\f -> reflectIDE (applicator f newPrefs lastAppliedPrefs) ideR) flatPrefsDesc- writeIORef lastAppliedPrefsRef newPrefs)- restore `onClicked` (do+ writeIORef lastAppliedPrefsRef newPrefs+ on restore buttonActivated (do lastAppliedPrefs <- readIORef lastAppliedPrefsRef mapM_ (\f -> reflectIDE (applicator f prefs lastAppliedPrefs) ideR) flatPrefsDesc injb prefs@@ -140,7 +143,7 @@ markLabel nb (getTopWidget prefsPane) False widgetSetSensitive save False )- save `onClicked` (do+ on save buttonActivated $ do lastAppliedPrefs <- readIORef lastAppliedPrefsRef mbNewPrefs <- extract prefs [ext] case mbNewPrefs of@@ -158,8 +161,8 @@ SP.serverPort = serverPort newPrefs, SP.endWithLastConn = endWithLastConn newPrefs}) reflectIDE (modifyIDE_ (\ide -> ide{prefs = newPrefs})) ideR- reflectIDE (closePane prefsPane >> return ()) ideR)- closeB `onClicked` do+ reflectIDE (closePane prefsPane >> return ()) ideR+ on closeB buttonActivated $ do mbP <- extract prefs [ext] let hasChanged = case mbP of Nothing -> False@@ -171,7 +174,7 @@ md <- messageDialogNew (Just windows) [] MessageQuestion ButtonsYesNo- "Unsaved changes. Close anyway?"+ (__ "Unsaved changes. Close anyway?") set md [ windowWindowPosition := WinPosCenterOnParent ] resp <- dialogRun md widgetDestroy md@@ -208,10 +211,10 @@ prefsDescription :: FilePath -> [PackageIdentifier] -> FieldDescriptionPP Prefs IDEM prefsDescription configDir packages = NFDPP [- ("Editor", VFDPP emptyParams [+ ((__ "Editor"), VFDPP emptyParams [ mkFieldPP- (paraName <<<- ParaName "Version number of preferences file format"- $ paraSynopsis <<<- ParaSynopsis "Integer"+ (paraName <<<- ParaName (__ "Version number of preferences file format")+ $ paraSynopsis <<<- ParaSynopsis (__ "Integer") $ paraShowLabel <<<- ParaShowLabel False $ emptyParams) (PP.text . show) intParser@@ -220,7 +223,7 @@ (noEditor 0) (\b -> return ()) , mkFieldPP- (paraName <<<- ParaName "Time of last storage"+ (paraName <<<- ParaName (__ "Time of last storage") $ paraShowLabel <<<- ParaShowLabel False $ emptyParams) (PP.text . show) stringParser@@ -229,8 +232,8 @@ (noEditor "") (\b -> return ()) , mkFieldPP- (paraName <<<- ParaName "Show line numbers"- $ paraSynopsis <<<- ParaSynopsis "(True/False)"+ (paraName <<<- ParaName (__ "Show line numbers")+ $ paraSynopsis <<<- ParaSynopsis (__ "(True/False)") $ emptyParams) (PP.text . show) boolParser@@ -239,9 +242,9 @@ boolEditor (\b -> do buffers <- allBuffers- mapM_ (\buf -> setShowLineNumbers (sourceView buf) b) buffers)+ mapM_ (\(IDEBuffer {sourceView = sv}) -> setShowLineNumbers sv b) buffers) , mkFieldPP- (paraName <<<- ParaName "TextView Font" $ emptyParams)+ (paraName <<<- ParaName (__ "TextView Font") $ emptyParams) (\a -> PP.text (case a of Nothing -> show ""; Just s -> show s)) (do str <- stringParser return (if null str then Nothing else Just (str)))@@ -250,26 +253,26 @@ fontEditor (\mbs -> do buffers <- allBuffers- mapM_ (\buf -> setFont (sourceView buf) mbs) buffers)+ mapM_ (\(IDEBuffer {sourceView = sv}) -> setFont sv mbs) buffers) , mkFieldPP- (paraName <<<- ParaName "Right margin"- $ paraSynopsis <<<- ParaSynopsis "Size or 0 for no right margin"+ (paraName <<<- ParaName (__ "Right margin")+ $ paraSynopsis <<<- ParaSynopsis (__ "Size or 0 for no right margin") $ paraShadow <<<- ParaShadow ShadowIn $ emptyParams) (PP.text . show) readParser rightMargin (\b a -> a{rightMargin = b})- (disableEditor (intEditor (1.0, 200.0, 5.0), paraName <<<- ParaName "Position"+ (disableEditor (intEditor (1.0, 200.0, 5.0), paraName <<<- ParaName (__ "Position") $ emptyParams)- True "Show it ?")+ True (__ "Show it ?")) (\b -> do buffers <- allBuffers- mapM_ (\buf -> setRightMargin (sourceView buf)+ mapM_ (\(IDEBuffer {sourceView = sv}) -> setRightMargin sv (case b of (True,v) -> Just v (False,_) -> Nothing)) buffers) , mkFieldPP- (paraName <<<- ParaName "Tab width" $ emptyParams)+ (paraName <<<- ParaName (__ "Tab width") $ emptyParams) (PP.text . show) intParser tabWidth@@ -277,9 +280,9 @@ (intEditor (1.0, 20.0, 1.0)) (\i -> do buffers <- allBuffers- mapM_ (\buf -> setIndentWidth (sourceView buf) i) buffers)+ mapM_ (\(IDEBuffer {sourceView = sv}) -> setIndentWidth sv i) buffers) , mkFieldPP- (paraName <<<- ParaName "Wrap lines" $ emptyParams)+ (paraName <<<- ParaName (__ "Wrap lines") $ emptyParams) (PP.text . show) boolParser wrapLines@@ -287,9 +290,9 @@ boolEditor (\b -> do buffers <- allBuffers- mapM_ (\buf -> setWrapMode (sourceView buf) b) buffers)+ mapM_ (\(IDEBuffer {sourceView = sv}) -> setWrapMode sv b) buffers) , mkFieldPP- (paraName <<<- ParaName "Use standard line ends even on windows" $ emptyParams)+ (paraName <<<- ParaName (__ "Use standard line ends even on windows") $ emptyParams) (PP.text . show) boolParser forceLineEnds@@ -297,7 +300,7 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Remove trailing blanks when saving a file" $ emptyParams)+ (paraName <<<- ParaName (__ "Remove trailing blanks when saving a file") $ emptyParams) (PP.text . show) boolParser removeTBlanks@@ -305,17 +308,17 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Source candy"+ (paraName <<<- ParaName (__ "Source candy") $ paraSynopsis <<<- ParaSynopsis- "Empty for do not use or the name of a candy file in a config dir"+ (__ "Empty for do not use or the name of a candy file in a config dir") $ paraShadow <<<- ParaShadow ShadowIn $ emptyParams) (PP.text . show) readParser sourceCandy (\b a -> a{sourceCandy = b}) (disableEditor (stringEditor (\s -> not (null s)) True,- paraName <<<- ParaName "Candy specification"+ paraName <<<- ParaName (__ "Candy specification") $ emptyParams)- True "Use it ?")+ True (__ "Use it ?")) (\cs -> case cs of (False,_) -> do setCandyState False@@ -324,22 +327,24 @@ setCandyState True editCandy) , mkFieldPP- (paraName <<<- ParaName "Editor Style" $ emptyParams)+ (paraName <<<- ParaName (__ "Editor Style") $ emptyParams) (\a -> PP.text (case a of (False,_) -> show ""; (True, s) -> show s)) (do str <- stringParser- return (if null str then (False,"classic") else (True,str)))+ return (if null str then (False,(__ "classic")) else (True,str))) sourceStyle (\b a -> a{sourceStyle = b}) styleEditor (\mbs -> do+ setInfoStyle buffers <- allBuffers- mapM_ (\buf -> do- ebuf <- getBuffer (sourceView buf)- setStyle ebuf (case mbs of+ preferDark <- getDarkState+ mapM_ (\(IDEBuffer {sourceView = sv}) -> do+ ebuf <- getBuffer sv+ setStyle preferDark ebuf (case mbs of (False,_) -> Nothing (True,s) -> Just s)) buffers) , mkFieldPP- (paraName <<<- ParaName "Found Text Background" $ emptyParams)+ (paraName <<<- ParaName (__ "Found Text Background") $ emptyParams) (PP.text . show) colorParser foundBackground@@ -347,29 +352,45 @@ colorEditor (\c -> do buffers <- allBuffers- forM_ buffers $ \buf -> do- ebuf <- getBuffer (sourceView buf)+ forM_ buffers $ \(IDEBuffer {sourceView = sv}) -> do+ ebuf <- getBuffer sv tagTable <- getTagTable ebuf mbTag <- lookupTag tagTable "found" case mbTag of Just tag -> background tag c Nothing -> return ()) , mkFieldPP- (paraName <<<- ParaName "Execution Context Text Background" $ emptyParams)+ (paraName <<<- ParaName (__ "Selection Match Text Background") $ emptyParams) (PP.text . show) colorParser+ matchBackground+ (\ b a -> a{matchBackground = b})+ colorEditor+ (\c -> do+ buffers <- allBuffers+ forM_ buffers $ \(IDEBuffer {sourceView = sv}) -> do+ ebuf <- getBuffer sv+ tagTable <- getTagTable ebuf+ mbTag <- lookupTag tagTable "match"+ case mbTag of+ Just tag -> background tag c+ Nothing -> return ())+ , mkFieldPP+ (paraName <<<- ParaName (__ "Execution Context Text Background") $ emptyParams)+ (PP.text . show)+ colorParser contextBackground (\ b a -> a{contextBackground = b}) colorEditor (\c -> do buffers <- allBuffers- forM_ buffers $ \buf -> do- ebuf <- getBuffer (sourceView buf)+ forM_ buffers $ \(IDEBuffer {sourceView = sv}) -> do+ ebuf <- getBuffer sv tagTable <- getTagTable ebuf -- TODO find and set the tag background return ()) , mkFieldPP- (paraName <<<- ParaName "Breakpoint Text Background" $ emptyParams)+ (paraName <<<- ParaName (__ "Breakpoint Text Background") $ emptyParams) (PP.text . show) colorParser breakpointBackground@@ -377,13 +398,13 @@ colorEditor (\c -> do buffers <- allBuffers- forM_ buffers $ \buf -> do- ebuf <- getBuffer (sourceView buf)+ forM_ buffers $ \(IDEBuffer {sourceView = sv}) -> do+ ebuf <- getBuffer sv tagTable <- getTagTable ebuf -- TODO find and set the tag background return ()) , mkFieldPP- (paraName <<<- ParaName "Automatically load modified files modified outside of Leksah" $ emptyParams)+ (paraName <<<- ParaName (__ "Automatically load modified files modified outside of Leksah") $ emptyParams) (PP.text . show) boolParser autoLoad@@ -391,17 +412,17 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Use Yi - Experimental feature (could wipe your files)" $ emptyParams)+ (paraName <<<- ParaName (__ "Text Editor") $ emptyParams) (PP.text . show)- boolParser- useYi- (\b a -> a{useYi = b})- boolEditor+ stringParser+ textEditor+ (\b a -> a{textEditor = b})+ (comboSelectionEditor ["GtkSourceView", "Yi", "CodeMirror"] id) (\i -> return ()) ]),- ("GUI Options", VFDPP emptyParams [+ ((__ "GUI Options"), VFDPP emptyParams [ mkFieldPP- (paraName <<<- ParaName "LogView Font" $ emptyParams)+ (paraName <<<- ParaName (__ "LogView Font") $ emptyParams) (\a -> PP.text (case a of Nothing -> show ""; Just s -> show s)) (do str <- stringParser return (if null str then Nothing else Just (str)))@@ -409,13 +430,13 @@ (\ b a -> a{logviewFont = b}) fontEditor (\mbs -> do- buffer <- getLog+ log <- getLog fdesc <- liftIO $fontDescriptionFromString (case mbs of Just str -> str; Nothing -> "")- liftIO $widgetModifyFont (castToWidget $textView buffer) (Just fdesc))+ liftIO $widgetModifyFont (castToWidget $ logLaunchTextView log) (Just fdesc)) , mkFieldPP- (paraName <<<- ParaName "Window default size"+ (paraName <<<- ParaName (__ "Window default size") $ paraSynopsis <<<- ParaSynopsis- "Default size of the main ide window specified as pair (int,int)"+ (__ "Default size of the main ide window specified as pair (int,int)") $ paraShadow <<<- ParaShadow ShadowIn $ emptyParams) (PP.text.show) (pairParser intParser)@@ -426,7 +447,7 @@ paraName <<<- ParaName "Y" $ emptyParams)) (\a -> return ()) , mkFieldPP- (paraName <<<- ParaName "Use ctrl Tab for Notebook flipper" $ emptyParams)+ (paraName <<<- ParaName (__ "Use ctrl Tab for Notebook flipper") $ emptyParams) (PP.text . show) boolParser useCtrlTabFlipping@@ -434,7 +455,7 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Complete only on Hotkey" $ emptyParams)+ (paraName <<<- ParaName (__ "Complete only on Hotkey") $ emptyParams) (PP.text . show) boolParser completeRestricted@@ -442,9 +463,9 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Name of the keymap"+ (paraName <<<- ParaName (__ "Name of the keymap") $ paraSynopsis <<<- ParaSynopsis- "The name of a keymap file in a config dir"+ (__ "The name of a keymap file in a config dir") $ paraDirection <<<- ParaDirection Horizontal $ emptyParams) PP.text identifier@@ -453,10 +474,10 @@ (stringEditor (\s -> not (null s)) True) (\ a -> return ()) ]),- ("Initial Pane positions", VFDPP emptyParams [+ ((__ "Initial Pane positions"), VFDPP emptyParams [ mkFieldPP (paraName <<<- ParaName- "Categories for panes"+ (__ "Categories for panes") $ paraShadow <<<- ParaShadow ShadowIn $ paraDirection <<<- ParaDirection Vertical $ paraMinSize <<<- ParaMinSize (-1,130)@@ -466,8 +487,8 @@ categoryForPane (\b a -> a{categoryForPane = b}) (multisetEditor- (ColumnDescr True [("Pane Id",\(n,_) -> [cellText := n])- ,("Pane Category",\(_,v) -> [cellText := v])])+ (ColumnDescr True [((__ "Pane Id"),\(n,_) -> [cellText := n])+ ,((__ "Pane Category"),\(_,v) -> [cellText := v])]) ((pairEditor (stringEditor (\s -> not (null s)) True,emptyParams) (stringEditor (\s -> not (null s)) True,emptyParams)),emptyParams)@@ -476,7 +497,7 @@ (\i -> return ()) , mkFieldPP (paraName <<<- ParaName- "Pane path for category"+ (__ "Pane path for category") $ paraShadow <<<- ParaShadow ShadowIn $ paraDirection <<<- ParaDirection Vertical $ paraMinSize <<<- ParaMinSize (-1,130)@@ -486,8 +507,8 @@ pathForCategory (\b a -> a{pathForCategory = b}) (multisetEditor- (ColumnDescr True [("Pane category",\(n,_) -> [cellText := n])- ,("Pane path",\(_,v) -> [cellText := show v])])+ (ColumnDescr True [((__ "Pane category"),\(n,_) -> [cellText := n])+ ,((__ "Pane path"),\(_,v) -> [cellText := show v])]) ((pairEditor (stringEditor (\s -> not (null s)) True,emptyParams) (genericEditor,emptyParams)),emptyParams)@@ -495,7 +516,7 @@ (Just (\(a,_) (a2,_) -> a == a2))) (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Default pane path" $ emptyParams)+ (paraName <<<- ParaName (__ "Default pane path") $ emptyParams) (PP.text . show) readParser defaultPath@@ -503,20 +524,20 @@ genericEditor (\i -> return ()) ]),- ("Metadata", VFDPP emptyParams [+ ((__ "Metadata"), VFDPP emptyParams [ mkFieldPP (paraName <<<- ParaName- "Paths under which haskell sources for packages may be found"+ (__ "Paths under which haskell sources for packages may be found") $ paraMinSize <<<- ParaMinSize (-1,100) $ emptyParams) (PP.text . show) readParser sourceDirectories (\b a -> a{sourceDirectories = b})- (filesEditor Nothing FileChooserActionSelectFolder "Select folder")+ (filesEditor Nothing FileChooserActionSelectFolder (__ "Select folder")) (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Unpack source for cabal packages to" $ emptyParams)+ (paraName <<<- ParaName (__ "Unpack source for cabal packages to") $ emptyParams) (PP.text . show) readParser unpackDirectory@@ -524,7 +545,7 @@ (maybeEditor (stringEditor (\ _ -> True) True,emptyParams) True "") (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "URL from which to download prebuilt metadata" $ emptyParams)+ (paraName <<<- ParaName (__ "URL from which to download prebuilt metadata") $ emptyParams) (PP.text . show) stringParser retrieveURL@@ -532,15 +553,15 @@ (stringEditor (const True) True) (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Strategy for downloading prebuilt metadata" $ emptyParams)+ (paraName <<<- ParaName (__ "Strategy for downloading prebuilt metadata") $ emptyParams) (PP.text . show) readParser retrieveStrategy (\b a -> a{retrieveStrategy = b})- (enumEditor ["Try to download and then build locally if that fails","Try to build locally and then download if that fails","Never download (just try to build locally)"])+ (enumEditor [(__ "Try to download and then build locally if that fails"),(__ "Try to build locally and then download if that fails"),(__ "Never download (just try to build locally)")]) (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Update metadata at startup" $ emptyParams)+ (paraName <<<- ParaName (__ "Update metadata at startup") $ emptyParams) (PP.text . show) boolParser collectAtStart@@ -548,7 +569,7 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Port number for leksah to comunicate with leksah-server" $ emptyParams)+ (paraName <<<- ParaName (__ "Port number for leksah to comunicate with leksah-server") $ emptyParams) (PP.text . show) intParser serverPort@@ -556,7 +577,7 @@ (intEditor (1.0, 65535.0, 1.0)) (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "IP address for leksah to comunicate with leksah-server" $ emptyParams)+ (paraName <<<- ParaName (__ "IP address for leksah to comunicate with leksah-server") $ emptyParams) (PP.text . show) stringParser serverIP@@ -564,7 +585,7 @@ (stringEditor (\ s -> not $ null s) True) (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Stop the leksah-server process when leksah disconnects" $ emptyParams)+ (paraName <<<- ParaName (__ "Stop the leksah-server process when leksah disconnects") $ emptyParams) (PP.text . show) boolParser endWithLastConn@@ -572,10 +593,10 @@ boolEditor (\i -> return ()) ]),- ("Blacklist", VFDPP emptyParams [+ ((__ "Blacklist"), VFDPP emptyParams [ mkFieldPP (paraName <<<- ParaName- "Packages which are excluded from the modules pane"+ (__ "Packages which are excluded from the modules pane") $ paraMinSize <<<- ParaMinSize (-1,200) $ emptyParams) (PP.text . show)@@ -585,9 +606,9 @@ (dependenciesEditor packages) (\i -> return ()) ]),- ("Build", VFDPP emptyParams [+ ((__ "Build"), VFDPP emptyParams [ mkFieldPP- (paraName <<<- ParaName "Automatically save all files before building" $ emptyParams)+ (paraName <<<- ParaName (__ "Automatically save all files before building") $ emptyParams) (PP.text . show) boolParser saveAllBeforeBuild@@ -595,7 +616,7 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Select first warning if built without errors" $ emptyParams)+ (paraName <<<- ParaName (__ "Select first warning if built without errors") $ emptyParams) (PP.text . show) boolParser jumpToWarnings@@ -603,7 +624,7 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Background build" $ emptyParams)+ (paraName <<<- ParaName (__ "Background build") $ emptyParams) (PP.text . show) boolParser backgroundBuild@@ -611,7 +632,7 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Run unit tests when building" $ emptyParams)+ (paraName <<<- ParaName (__ "Run unit tests when building") $ emptyParams) (PP.text . show) boolParser runUnitTests@@ -619,16 +640,16 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Make mode" $ emptyParams)+ (paraName <<<- ParaName (__ "Make mode") $ emptyParams) (PP.text . show) boolParser makeMode (\b a -> a{makeMode = b})- (boolEditor2 "Single mode")+ (boolEditor2 (__ "Single mode")) (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Single build without linking" $ emptyParams)+ (paraName <<<- ParaName (__ "Single build without linking") $ emptyParams) (PP.text . show) boolParser singleBuildWithoutLinking@@ -636,7 +657,7 @@ boolEditor (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "Don't install last package" $ emptyParams)+ (paraName <<<- ParaName (__ "Don't install last package") $ emptyParams) (PP.text . show) boolParser dontInstallLast@@ -644,10 +665,27 @@ boolEditor (\i -> return ()) + , mkFieldPP+ (paraName <<<- ParaName (__ "Use vado to run commands on the remote machine") $ emptyParams)+ (PP.text . show)+ boolParser+ useVado+ (\b a -> a{useVado = b})+ boolEditor+ (\i -> return ())++ , mkFieldPP+ (paraName <<<- ParaName (__ "Use cabal-dev") $ emptyParams)+ (PP.text . show)+ boolParser+ useCabalDev+ (\b a -> a{useCabalDev = b})+ boolEditor+ (\i -> return ()) ]),- ("Debug", VFDPP emptyParams [+ ((__ "Debug"), VFDPP emptyParams [ mkFieldPP- (paraName <<<- ParaName "Enable usage of Show instances in :print" $ emptyParams)+ (paraName <<<- ParaName (__ "Enable usage of Show instances in :print") $ emptyParams) (PP.text . show) boolParser printEvldWithShow@@ -655,7 +693,7 @@ boolEditor debugSetPrintEvldWithShow , mkFieldPP- (paraName <<<- ParaName "Break on any exception thrown" $ emptyParams)+ (paraName <<<- ParaName (__ "Break on any exception thrown") $ emptyParams) (PP.text . show) boolParser breakOnException@@ -663,7 +701,7 @@ boolEditor debugSetBreakOnException , mkFieldPP- (paraName <<<- ParaName "Break on uncaught exceptions and errors" $ emptyParams)+ (paraName <<<- ParaName (__ "Break on uncaught exceptions and errors") $ emptyParams) (PP.text . show) boolParser breakOnError@@ -671,7 +709,7 @@ boolEditor debugSetBreakOnError , mkFieldPP- (paraName <<<- ParaName "Turn on printing of binding results in GHCi" $ emptyParams)+ (paraName <<<- ParaName (__ "Turn on printing of binding results in GHCi") $ emptyParams) (PP.text . show) boolParser printBindResult@@ -679,9 +717,9 @@ boolEditor debugSetPrintBindResult ]),- ("Help", VFDPP emptyParams [+ ((__ "Help"), VFDPP emptyParams [ mkFieldPP- (paraName <<<- ParaName "Browser" $ emptyParams)+ (paraName <<<- ParaName (__ "Browser") $ emptyParams) (PP.text . show) stringParser browser@@ -689,7 +727,7 @@ (stringEditor (\s -> not (null s)) True) (\i -> return ()) , mkFieldPP- (paraName <<<- ParaName "URL for searching documentation" $+ (paraName <<<- ParaName (__ "URL for searching documentation") $ paraSynopsis <<<- ParaSynopsis ("e.g Hoogle: http://www.haskell.org/hoogle/?q= or " ++ "Hayoo: http://holumbus.fh-wedel.de/hayoo/hayoo.html?query=")@@ -706,8 +744,11 @@ styleEditor :: Editor (Bool, String) styleEditor p n = do styleManager <- sourceStyleSchemeManagerNew+ dataDir <- getDataDir+ sourceStyleSchemeManagerAppendSearchPath styleManager $ dataDir </> "data/styles" ids <- sourceStyleSchemeManagerGetSchemeIds styleManager- disableEditor (comboSelectionEditor ids id, p) True "Select a special style?" p n+ let notDarkIds = filter (not . isSuffixOf "-dark") ids+ disableEditor (comboSelectionEditor notDarkIds id, p) True (__ "Select a special style?") p n defaultPrefs = Prefs {@@ -724,9 +765,10 @@ , textviewFont = Nothing , sourceStyle = (False,"classic") , foundBackground = Color 65535 65535 32768+ , matchBackground = Color 32768 32768 32768 , contextBackground = Color 65535 49152 49152 , breakpointBackground = Color 65535 49152 32768- , useYi = False+ , textEditor = "GtkSourceView" , autoLoad = False , logviewFont = Nothing , defaultSize = (1024,800)@@ -739,17 +781,25 @@ ] , defaultPath = [SplitP (LeftP)] , categoryForPane = [ ("*ClassHierarchy","ToolCategory")+ , ("*Breakpoints","LogCategory")+ , ("*Browser","ToolCategory") , ("*Debug","ToolCategory")- , ("*Flags","ToolCategory")+ , ("*Errors","ToolCategory") , ("*Files","ToolCategory")+ , ("*Flags","ToolCategory") , ("*Grep","ToolCategory")- , ("*Info","ToolCategory")+ , ("*HLint","ToolCategory")+ , ("*Doc","ToolCategory")+ , ("*Info","LogCategory") , ("*Log","LogCategory") , ("*Modules","ToolCategory")- , ("*Package","ToolCategory")- , ("*Prefs","ToolCategory")- , ("*References","ToolCategory")- , ("*Search","ToolCategory")]+ , ("*Out","ToolCategory")+ , ("*Package","EditorCategory")+ , ("*Prefs","EditorCategory")+ , ("*Search","ToolCategory")+ , ("*Trace","LogCategory")+ , ("*Variables","LogCategory")+ , ("*Workspace","LogCategory")] , collectAtStart = True , unpackDirectory = Nothing , retrieveURL = "http://www.leksah.org"@@ -759,6 +809,8 @@ , completeRestricted = False , saveAllBeforeBuild = True , jumpToWarnings = True+ , useVado = False+ , useCabalDev = False , backgroundBuild = True , runUnitTests = False , makeMode = True
@@ -23,13 +23,12 @@ ) where import Graphics.UI.Gtk- (cellTextScaleSet, cellTextScale, listStoreGetValue,- treeSelectionGetSelectedRows, widgetShowAll, menuPopup,- menuShellAppend, onActivateLeaf, menuItemNewWithLabel, menuNew,- listStoreAppend, listStoreClear, entrySetText, afterKeyRelease,- onKeyPress, onButtonPress, toggleButtonGetActive,- widgetSetSensitivity, onToggled, afterFocusIn, vBoxNew, entryNew,- scrolledWindowSetPolicy, containerAdd, scrolledWindowNew,+ (rowActivated, Menu, menuAttachToWidget, cellTextScaleSet,+ cellTextScale, listStoreGetValue, treeSelectionGetSelectedRows,+ widgetShowAll, menuPopup, menuShellAppend, menuItemActivate,+ menuItemNewWithLabel, menuNew, listStoreAppend, listStoreClear,+ entrySetText, toggleButtonGetActive, widgetSetSensitivity, vBoxNew,+ entryNew, scrolledWindowSetPolicy, containerAdd, scrolledWindowNew, treeSelectionSetMode, treeViewGetSelection, treeViewSetHeadersVisible, cellPixbufStockId, cellText, cellLayoutSetAttributes, cellLayoutPackStart, treeViewAppendColumn,@@ -39,14 +38,16 @@ treeViewNew, listStoreNew, boxPackEnd, boxPackStart, checkButtonNewWithLabel, toggleButtonSetActive, ResponseId(..), dialogRun, radioButtonNewWithLabelFromWidget,- radioButtonNewWithLabel, buttonNewFromStock, windowSetTransientFor,- hButtonBoxNew, dialogGetUpper, dialogGetActionArea,- widgetGrabDefault, set, get, dialogNew, onClicked, dialogResponse,- widgetHideAll, buttonSetLabel, widgetCanDefault, hBoxNew,+ radioButtonNewWithLabel, buttonNewFromStock, windowTransientFor,+ hButtonBoxNew, dialogGetActionArea,+ widgetGrabDefault, set, get, dialogNew, dialogResponse,+ widgetHide, buttonSetLabel, widgetCanDefault, hBoxNew, entryGetText, castToWidget, Entry, VBox, ListStore, TreeView, ScrolledWindow, PolicyType(..), SelectionMode(..),- TreeViewColumnSizing(..), AttrOp(..), Packing(..))-import Graphics.UI.Gtk.Gdk.Events+ TreeViewColumnSizing(..), AttrOp(..), Packing(..), focusInEvent,+ toggled, buttonPressEvent, keyPressEvent, keyReleaseEvent)+import Graphics.UI.Gtk.Gdk.EventM+import System.Glib.Signals (on, after) import Data.IORef (newIORef) import Data.IORef (writeIORef,readIORef,IORef(..)) -- import IDE.Pane.SourceBuffer (goToDefinition)@@ -59,6 +60,7 @@ import Control.Event (triggerEvent) import Control.Monad.IO.Class (MonadIO(..)) import qualified Data.ByteString.Char8 as BS (empty, unpack)+import System.Glib.Properties (newAttrFromMaybeStringProperty) -- | A search pane description --@@ -85,7 +87,7 @@ instance Pane IDESearch IDEM where- primPaneName _ = "Search"+ primPaneName _ = (__ "Search") getAddedIndex _ = 0 getTopWidget = castToWidget . topBox paneId b = "*Search"@@ -113,11 +115,11 @@ in reifyIDE $ \ ideR -> do scopebox <- hBoxNew True 2- rb1 <- radioButtonNewWithLabel "Package"- rb2 <- radioButtonNewWithLabelFromWidget rb1 "Workspace"- rb3 <- radioButtonNewWithLabelFromWidget rb1 "System"+ rb1 <- radioButtonNewWithLabel (__ "Package")+ rb2 <- radioButtonNewWithLabelFromWidget rb1 (__ "Workspace")+ rb3 <- radioButtonNewWithLabelFromWidget rb1 (__ "System") toggleButtonSetActive rb3 True- cb2 <- checkButtonNewWithLabel "Imports"+ cb2 <- checkButtonNewWithLabel (__ "Imports") boxPackStart scopebox rb1 PackGrow 2 boxPackStart scopebox rb2 PackGrow 2@@ -125,15 +127,15 @@ boxPackEnd scopebox cb2 PackNatural 2 modebox <- hBoxNew True 2- mb1 <- radioButtonNewWithLabel "Exact"- mb2 <- radioButtonNewWithLabelFromWidget mb1 "Prefix"- mb3 <- radioButtonNewWithLabelFromWidget mb1 "Regex"+ mb1 <- radioButtonNewWithLabel (__ "Exact")+ mb2 <- radioButtonNewWithLabelFromWidget mb1 (__ "Prefix")+ mb3 <- radioButtonNewWithLabelFromWidget mb1 (__ "Regex") toggleButtonSetActive (case mode of Exact _ -> mb1 Prefix _ -> mb2 Regex _ -> mb3) True- mb4 <- checkButtonNewWithLabel "Case sensitive"+ mb4 <- checkButtonNewWithLabel (__ "Case sensitive") toggleButtonSetActive mb4 (caseSense mode) boxPackStart modebox mb1 PackNatural 2 boxPackStart modebox mb2 PackNatural 2@@ -147,7 +149,7 @@ renderer3 <- cellRendererTextNew renderer30 <- cellRendererPixbufNew col3 <- treeViewColumnNew- treeViewColumnSetTitle col3 "Symbol"+ treeViewColumnSetTitle col3 (__ "Symbol") treeViewColumnSetSizing col3 TreeViewColumnAutosize treeViewColumnSetResizable col3 True treeViewColumnSetReorderable col3 True@@ -164,7 +166,7 @@ renderer1 <- cellRendererTextNew renderer10 <- cellRendererPixbufNew col1 <- treeViewColumnNew- treeViewColumnSetTitle col1 "Module"+ treeViewColumnSetTitle col1 (__ "Module") treeViewColumnSetSizing col1 TreeViewColumnAutosize treeViewColumnSetResizable col1 True treeViewColumnSetReorderable col1 True@@ -176,16 +178,16 @@ Nothing -> "" Just pm -> display $ modu pm] cellLayoutSetAttributes col1 renderer10 listStore- $ \row -> [- cellPixbufStockId := if isReexported row- then "ide_reexported"+ $ \row -> [newAttrFromMaybeStringProperty "stock-id"+ := if isReexported row+ then Just "ide_reexported" else if isJust (dscMbLocation row)- then "ide_source"- else ""]+ then Just "ide_source"+ else Nothing] renderer2 <- cellRendererTextNew col2 <- treeViewColumnNew- treeViewColumnSetTitle col2 "Package"+ treeViewColumnSetTitle col2 (__ "Package") treeViewColumnSetSizing col2 TreeViewColumnAutosize treeViewColumnSetResizable col2 True treeViewColumnSetReorderable col2 True@@ -198,7 +200,7 @@ renderer3 <- cellRendererTextNew col3 <- treeViewColumnNew- treeViewColumnSetTitle col3 "Type/Kind"+ treeViewColumnSetTitle col3 (__ "Type/Kind") treeViewColumnSetSizing col3 TreeViewColumnAutosize treeViewColumnSetResizable col3 True treeViewColumnSetReorderable col3 True@@ -281,37 +283,37 @@ else return (SystemScope) scopeSelection_ scope - cid1 <- treeView `afterFocusIn`- (\_ -> do reflectIDE (makeActive search) ideR ; return True)- rb1 `onToggled` (reflectIDE (scopeSelection' rb1 rb2 rb3 cb2) ideR )- rb2 `onToggled` (reflectIDE (scopeSelection' rb1 rb2 rb3 cb2) ideR )- rb3 `onToggled` (reflectIDE (scopeSelection' rb1 rb2 rb3 cb2) ideR )- cb2 `onToggled` (reflectIDE (scopeSelection' rb1 rb2 rb3 cb2) ideR)- mb1 `onToggled` do+ cid1 <- treeView `after` focusInEvent $ liftIO $ do+ reflectIDE (makeActive search) ideR+ return True+ rb1 `on` toggled $ liftIO (reflectIDE (scopeSelection' rb1 rb2 rb3 cb2) ideR )+ rb2 `on` toggled $ liftIO (reflectIDE (scopeSelection' rb1 rb2 rb3 cb2) ideR )+ rb3 `on` toggled $ liftIO (reflectIDE (scopeSelection' rb1 rb2 rb3 cb2) ideR )+ cb2 `on` toggled $ liftIO (reflectIDE (scopeSelection' rb1 rb2 rb3 cb2) ideR)+ mb1 `on` toggled $ liftIO $ do widgetSetSensitivity mb4 False active <- toggleButtonGetActive mb4 (reflectIDE (modeSelection_ (Exact active)) ideR )- mb2 `onToggled`do+ mb2 `on` toggled $ liftIO $ do widgetSetSensitivity mb4 True active <- toggleButtonGetActive mb4 (reflectIDE (modeSelection_ (Prefix active)) ideR )- mb3 `onToggled` do+ mb3 `on` toggled $ liftIO $ do widgetSetSensitivity mb4 True active <- toggleButtonGetActive mb4 (reflectIDE (modeSelection_ (Regex active)) ideR )- mb4 `onToggled` do+ mb4 `on` toggled $ liftIO $ do active <- toggleButtonGetActive mb4 (reflectIDE (modeSelectionCase active) ideR )- treeView `onButtonPress` (handleEvent ideR listStore treeView)- treeView `onButtonPress` (handleEvent ideR listStore treeView)- treeView `onKeyPress` (handleEvent ideR listStore treeView)+ (cid2, cid3) <- treeViewContextMenu treeView $ searchContextMenu ideR listStore treeView+ cid4 <- treeView `on` rowActivated $ selectDescr ideR listStore -- sel `onSelectionChanged` do -- fillInfo search ideR- entry `afterKeyRelease` (\ event -> do+ entry `on` keyReleaseEvent $ liftIO $ do text <- entryGetText entry reflectIDE (searchMetaGUI_ text) ideR- return False)- return (Just search,[ConnectC cid1])+ return False+ return (Just search, map ConnectC [cid1, cid2, cid3, cid4]) getScope :: IDESearch -> IO Scope@@ -324,46 +326,29 @@ getSearch Nothing = forceGetPane (Right "*Search") getSearch (Just pp) = forceGetPane (Left pp) ---handleEvent :: IDERef- -> ListStore Descr- -> TreeView- -> Event- -> IO (Bool)-handleEvent ideR store descrView (Button {eventClick = click, eventButton = button}) = do- if button == RightButton- then do- theMenu <- menuNew- item1 <- menuItemNewWithLabel "Go to definition"- item1 `onActivateLeaf` (goToDef ideR store descrView)-- menuShellAppend theMenu item1- menuPopup theMenu Nothing- widgetShowAll theMenu- return True- else if button == LeftButton && click == DoubleClick- then selectDescr ideR store descrView- else return False-handleEvent ideR store descrView (Key { eventKeyName = "Return"}) =- selectDescr ideR store descrView-handleEvent _ _ _ _ = return False-+searchContextMenu :: IDERef+ -> ListStore Descr+ -> TreeView+ -> Menu+ -> IO ()+searchContextMenu ideR store descrView theMenu = do+ item1 <- menuItemNewWithLabel (__ "Go to definition")+ item1 `on` menuItemActivate $ liftIO $ goToDef ideR store descrView+ menuShellAppend theMenu item1 goToDef ideR store descrView = do sel <- getSelectionDescr descrView store case sel of Just descr -> reflectIDE (triggerEvent ideR (GotoDefinition descr)) ideR >> return () -- (goToDefinition descr) ideR- otherwise -> sysMessage Normal "Search >> listViewPopup: no selection"+ otherwise -> sysMessage Normal (__ "Search >> listViewPopup: no selection") -selectDescr ideR store descrView= do- sel <- getSelectionDescr descrView store- case sel of- Just descr -> reflectIDE (triggerEvent ideR (SelectIdent descr))- ideR >> return ()- otherwise -> sysMessage Normal "Search >> listViewPopup: no selection2"- return True+selectDescr ideR store [i] col = do+ descr <- listStoreGetValue store i+ liftIO $ reflectIDE (triggerEvent ideR (SelectIdent descr)) ideR+ return ()++selectDescr _ _ _ _ = liftIO $ sysMessage Normal (__ "Search >> selectDescr: invalid path") getSelectionDescr :: TreeView -> ListStore Descr
@@ -29,6 +29,7 @@ , fileNew , fileOpenThis , fileOpen+, filePrint , fileRevert , fileClose , fileCloseAll@@ -86,10 +87,9 @@ import Data.Maybe import Data.Char import Data.Typeable-import qualified Data.Set as Set import IDE.Core.State-import IDE.Utils.GUIUtils(getCandyState)+import IDE.Utils.GUIUtils import IDE.Utils.FileUtils import IDE.SourceCandy import IDE.SymbolNavigation@@ -97,20 +97,18 @@ import IDE.TextEditor import qualified System.IO.UTF8 as UTF8 import Data.IORef (writeIORef,readIORef,newIORef)--- import Data.Char (isAlphaNum, isSymbol) import Control.Event (triggerEvent) import IDE.Metainfo.Provider (getSystemInfo, getWorkspaceInfo) import Distribution.Text (simpleParse) import Distribution.ModuleName (ModuleName)-import Distribution.PackageDescription (hsSourceDirs)---import qualified Data.Set as Set (member) import Graphics.UI.Gtk (Notebook, clipboardGet, selectionClipboard, dialogAddButton, widgetDestroy, fileChooserGetFilename, widgetShow, fileChooserDialogNew, notebookGetNthPage, notebookPageNum, widgetHide, dialogRun, messageDialogNew, scrolledWindowSetShadowType,- scrolledWindowSetPolicy, dialogSetDefaultResponse, postGUIAsync,- fileChooserSetCurrentFolder, fileChooserSelectFilename)+ scrolledWindowSetPolicy, dialogSetDefaultResponse,+ fileChooserSetCurrentFolder, fileChooserSelectFilename,+ TextSearchFlags(..)) import System.Glib.MainLoop (priorityDefaultIdle, idleAdd) import qualified Graphics.UI.Gtk as Gtk hiding (eventKeyName) import Graphics.UI.Gtk.Windows.Window@@ -118,28 +116,29 @@ (ShadowType(..), PolicyType(..)) import Graphics.UI.Gtk.Windows.MessageDialog (ButtonsType(..), MessageType(..))-#if MIN_VERSION_gtk(0,10,5) import Graphics.UI.Gtk.Windows.Dialog (ResponseId(..))-import Graphics.UI.Gtk (Underline(..))-#else-import Graphics.UI.Gtk.General.Structs (ResponseId(..))-import Graphics.UI.Gtk.Pango.Types (Underline(..))-#endif+import Graphics.UI.Gtk+ (eventModifier, eventKeyName, eventKeyVal, Underline(..)) import Graphics.UI.Gtk.Selectors.FileChooser (FileChooserAction(..)) import System.Glib.Attributes (AttrOp(..), set)-import qualified Graphics.UI.Gtk.Gdk.Events as GtkOld import IDE.BufferMode import Control.Monad.Trans.Reader (ask) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad (foldM, forM, filterM, unless, when)+import Control.Exception as E (catch, SomeException) +import qualified IDE.Command.Print as Print+import Control.Monad.Trans.Class (MonadTrans(..))+import System.Log.Logger (debugM)+ allBuffers :: IDEM [IDEBuffer] allBuffers = getPanes instance RecoverablePane IDEBuffer BufferState IDEM where- saveState p = do buf <- getBuffer (sourceView p)+ saveState (p@IDEBuffer {sourceView=v}) = do+ buf <- getBuffer v ins <- getInsertMark buf iter <- getIterAtMark buf ins offset <- getOffset iter@@ -152,38 +151,41 @@ recoverState pp (BufferState n i) = do mbbuf <- newTextBuffer pp (takeFileName n) (Just n) case mbbuf of- Just buf -> do- gtkBuf <- getBuffer (sourceView buf)- iter <- getIterAtOffset gtkBuf i- placeCursor gtkBuf iter- mark <- getInsertMark gtkBuf+ Just (IDEBuffer {sourceView=v}) -> do ideR <- ask- liftIO $ idleAdd (do- reflectIDE (scrollToMark (sourceView buf) mark 0.0 (Just (0.3,0.3))) ideR- return False) priorityDefaultIdle- return (Just buf)+ liftIO . (`idleAdd` priorityDefaultIdle) . (`reflectIDE` ideR) $ do+ liftIO $ debugM "leksah" "SourceBuffer recoverState idle callback"+ gtkBuf <- getBuffer v+ iter <- getIterAtOffset gtkBuf i+ placeCursor gtkBuf iter+ mark <- getInsertMark gtkBuf+ scrollToMark v mark 0.0 (Just (0.3,0.3))+ liftIO $ debugM "leksah" "SourceBuffer recoverState done"+ return False+ return mbbuf Nothing -> return Nothing recoverState pp (BufferStateTrans bn text i) = do mbbuf <- newTextBuffer pp bn Nothing case mbbuf of- Just buf -> do- useCandy <- useCandyFor buf- gtkBuf <- getBuffer (sourceView buf)- setText gtkBuf text- when useCandy $ modeTransformToCandy (mode buf)- (modeEditInCommentOrString (mode buf)) gtkBuf- iter <- getIterAtOffset gtkBuf i- placeCursor gtkBuf iter- mark <- getInsertMark gtkBuf- ideR <- ask- liftIO $ idleAdd (do- reflectIDE (scrollToMark (sourceView buf) mark 0.0 (Just (0.3,0.3))) ideR- return False) priorityDefaultIdle+ Just (buf@IDEBuffer {sourceView=v}) -> do+ ideR <- ask+ liftIO . (`idleAdd` priorityDefaultIdle) . (`reflectIDE` ideR) $ do+ liftIO $ debugM "leksah" "SourceBuffer recoverState idle callback"+ useCandy <- useCandyFor buf+ gtkBuf <- getBuffer v+ setText gtkBuf text+ when useCandy $ modeTransformToCandy (mode buf)+ (modeEditInCommentOrString (mode buf)) gtkBuf+ iter <- getIterAtOffset gtkBuf i+ placeCursor gtkBuf iter+ mark <- getInsertMark gtkBuf+ scrollToMark v mark 0.0 (Just (0.3,0.3))+ liftIO $ debugM "leksah" "SourceBuffer recoverState done"+ return False return (Just buf) Nothing -> return Nothing- makeActive actbuf = do+ makeActive (actbuf@IDEBuffer {sourceView=sv}) = do ideR <- ask- let sv = sourceView actbuf eBuf <- getBuffer sv writeCursorPositionInStatusbar sv writeOverwriteInStatusbar sv@@ -207,7 +209,7 @@ currentState' <- readIDE currentState case mbBuf of Nothing -> return ()- Just buf -> complete (sourceView buf) True+ Just (IDEBuffer {sourceView=v}) -> complete v True selectSourceBuf :: FilePath -> IDEM (Maybe IDEBuffer) selectSourceBuf fp = do@@ -226,10 +228,12 @@ then do prefs <- readIDE prefs pp <- getBestPathForId "*Buffer"+ liftIO $ debugM "lekash" "selectSourceBuf calling newTextBuffer" nbuf <- newTextBuffer pp (takeFileName fpc) (Just fpc)+ liftIO $ debugM "lekash" "selectSourceBuf newTextBuffer returned" return nbuf else do- ideMessage Normal ("File path not found " ++ fpc)+ ideMessage Normal ((__ "File path not found ") ++ fpc) return Nothing goToDefinition :: Descr -> IDEAction@@ -265,8 +269,9 @@ -- liftIO $ putStrLn $ "goToSourceDefinition " ++ fp mbBuf <- selectSourceBuf fp when (isJust mbBuf && isJust dscMbLocation) $- inActiveBufContext () $ \_ ebuf buf _ -> do+ inActiveBufContext () $ \_ sv ebuf _ _ -> do let location = fromJust dscMbLocation+ liftIO $ debugM "lekash" "goToSourceDefinition calculating range" lines <- getLineCount ebuf iterTemp <- getIterAtLine ebuf (max 0 (min (lines-1) ((locationSLine location) -1)))@@ -276,14 +281,14 @@ ((locationELine location) -1))) chars2 <- getCharsInLine iter2Temp iter2 <- atLineOffset iter2Temp (max 0 (min (chars2-1) (locationECol location)))- placeCursor ebuf iter- smark <- getSelectionBoundMark ebuf- moveMark ebuf smark iter2 -- ### we had a problem before using this idleAdd thing ideR <- ask- liftIO $ idleAdd (do- reflectIDE (scrollToIter (sourceView buf) iter 0.0 (Just (0.3,0.3))) ideR- return False) priorityDefaultIdle+ liftIO . (`idleAdd` priorityDefaultIdle) . (`reflectIDE` ideR) $ do+ liftIO $ debugM "lekash" "goToSourceDefinition triggered selectRange"+ selectRange ebuf iter iter2+ liftIO $ debugM "lekash" "goToSourceDefinition triggered scrollToIter"+ scrollToIter sv iter 0.0 (Just (0.3,0.3))+ return False return () return mbBuf @@ -298,7 +303,7 @@ case mbBuf of Nothing -> return () Just buf ->- inBufContext () buf $ \_ ebuf buf _ -> do+ inBufContext () buf $ \_ _ ebuf buf _ -> do mark <- getInsertMark ebuf iter <- getIterAtMark ebuf mark insert ebuf iter (dscName idDescr)@@ -309,15 +314,14 @@ candy' <- readIDE candy contextRefs <- readIDE contextRefs prefs <- readIDE prefs- inBufContext () buf $ \_ ebuf buf _ -> do+ inBufContext () buf $ \_ sv ebuf buf _ -> do let tagName = (show $ logRefType logRef) ++ show index+ liftIO . debugM "lekash" $ "markRefInSourceBuf getting or creating tag " ++ tagName tagTable <- getTagTable ebuf mbTag <- lookupTag tagTable tagName case mbTag of Just existingTag -> do- i1 <- getStartIter ebuf- i2 <- getEndIter ebuf- removeTagByName ebuf tagName i1 i2+ removeTagByName ebuf tagName Nothing -> do errtag <- newTag tagTable tagName case logRefType logRef of@@ -330,6 +334,7 @@ ContextRef -> do background errtag $ contextBackground prefs + liftIO $ debugM "lekash" "markRefInSourceBuf calculating range" let start' = (srcSpanStartLine (logRefSrcSpan logRef), srcSpanStartColumn (logRefSrcSpan logRef)) let end' = (srcSpanEndLine (logRefSrcSpan logRef),@@ -361,16 +366,19 @@ let isOldContext = case (logRefType logRef, latest) of (ContextRef, Just ctx) | ctx /= logRef -> True _ -> False- unless isOldContext $ applyTagByName ebuf tagName iter iter2- when scrollTo $ placeCursor ebuf iter- mark <- getInsertMark ebuf+ unless isOldContext $ do+ liftIO $ debugM "lekash" "markRefInSourceBuf calling applyTagByName"+ applyTagByName ebuf tagName iter iter2 when scrollTo $ do- ideR <- ask- liftIO $ idleAdd (do- reflectIDE (do- scrollToMark (sourceView buf) mark 0.3 Nothing- when (isOldContext && scrollTo) $ selectRange ebuf iter iter2) ideR- return False) priorityDefaultIdle+ ideR <- ask+ liftIO . (`idleAdd` priorityDefaultIdle) . (`reflectIDE` ideR) $ do+ liftIO $ debugM "lekash" "markRefInSourceBuf triggered placeCursor"+ placeCursor ebuf iter+ mark <- getInsertMark ebuf+ liftIO $ debugM "lekash" "markRefInSourceBuf trigged scrollToMark"+ scrollToMark sv mark 0.3 Nothing+ when isOldContext $ selectRange ebuf iter iter2+ return False return () newTextBuffer :: PanePath -> String -> Maybe FilePath -> IDEM (Maybe IDEBuffer)@@ -387,7 +395,7 @@ (ind,rbn) <- figureOutPaneName bn 0 buildThisPane panePath nb (builder' bs mbfn ind bn rbn ct prefs) else do- ideMessage Normal ("File does not exist " ++ (fromJust mbfn))+ ideMessage Normal ((__ "File does not exist ") ++ (fromJust mbfn)) return Nothing data CharacterCategory = IdentifierCharacter | SpaceCharacter | SyntaxCharacter@@ -411,7 +419,6 @@ Gtk.Window -> IDEM (Maybe IDEBuffer,Connections) builder' bs mbfn ind bn rbn ct prefs pp nb windows = do- ideR <- ask -- load up and display a file (fileContents,modTime) <- case mbfn of Just fn -> do@@ -420,134 +427,206 @@ return (fc,Just mt) Nothing -> return ("\n",Nothing) - buffer <- (if useYi prefs then newYiBuffer else newGtkBuffer) mbfn fileContents- tagTable <- getTagTable buffer- foundTag <- newTag tagTable "found"- background foundTag $ foundBackground prefs+ case textEditor prefs of+ "GtkSourceView" -> newGtkBuffer mbfn fileContents >>= makeBuffer modTime+ "Yi" -> newYiBuffer mbfn fileContents >>= makeBuffer modTime+ "CodeMirror" -> newCMBuffer mbfn fileContents >>= makeBuffer modTime+ _ -> newDefaultBuffer mbfn fileContents >>= makeBuffer modTime - beginNotUndoableAction buffer- let mod = modFromFileName mbfn- when (bs && isHaskellMode mod) $ modeTransformToCandy mod- (modeEditInCommentOrString mod) buffer- endNotUndoableAction buffer- setModified buffer False- siter <- getStartIter buffer- placeCursor buffer siter- iter <- getEndIter buffer+ where+ makeBuffer modTime buffer = do+ ideR <- ask - -- create a new SourceView Widget- sv <- newView buffer (textviewFont prefs)- setShowLineNumbers sv $ showLineNumbers prefs- setRightMargin sv $ case rightMargin prefs of+ tagTable <- getTagTable buffer+ foundTag <- newTag tagTable "found"+ background foundTag $ foundBackground prefs++ beginNotUndoableAction buffer+ let mod = modFromFileName mbfn+ when (bs && isHaskellMode mod) $ modeTransformToCandy mod+ (modeEditInCommentOrString mod) buffer+ endNotUndoableAction buffer+ setModified buffer False+ siter <- getStartIter buffer+ placeCursor buffer siter+ iter <- getEndIter buffer++ -- create a new SourceView Widget+ sv <- newView buffer (textviewFont prefs)+ setShowLineNumbers sv $ showLineNumbers prefs+ setRightMargin sv $ case rightMargin prefs of+ (False,_) -> Nothing+ (True,v) -> Just v+ setIndentWidth sv $ tabWidth prefs+ setTabWidth sv $ 8 -- GHC treats tabs as 8 we should display them that way+ drawTabs sv+ preferDark <- getDarkState+ setStyle preferDark buffer $ case sourceStyle prefs of (False,_) -> Nothing (True,v) -> Just v- setIndentWidth sv $ tabWidth prefs- setTabWidth sv $ 8 -- GHC treats tabs as 8 we should display them that way- drawTabs sv- setStyle buffer $ case sourceStyle prefs of- (False,_) -> Nothing- (True,v) -> Just v - -- put it in a scrolled window- sw <- getScrolledWindow sv- if wrapLines prefs- then liftIO $ scrolledWindowSetPolicy sw PolicyNever PolicyAutomatic- else liftIO $ scrolledWindowSetPolicy sw PolicyAutomatic PolicyAutomatic- liftIO $ scrolledWindowSetShadowType sw ShadowIn- modTimeRef <- liftIO $ newIORef modTime- let buf = IDEBuffer {- fileName = mbfn,- bufferName = bn,- addedIndex = ind,- sourceView =sv,- scrolledWindow = sw,- modTime = modTimeRef,- mode = mod}- -- events- ids1 <- sv `afterFocusIn` makeActive buf- ids2 <- onCompletion sv (do- Completion.complete sv False) $ do- Completion.cancel- ids3 <- sv `onButtonPress`- \event -> do- liftIO $ reflectIDE (do- case GtkOld.eventClick event of- GtkOld.DoubleClick -> do- (start, end) <- getIdentifierUnderCursor buffer- liftIO $ postGUIAsync $ reflectIDE (selectRange buffer start end) ideR- return True- _ -> return False) ideR- (GetTextPopup mbTpm) <- triggerEvent ideR (GetTextPopup Nothing)- ids4 <- case mbTpm of- Just tpm -> sv `onPopulatePopup` \menu -> liftIO $ (tpm ideR menu)- Nothing -> do- sysMessage Normal "SourceBuffer>> no text popup"- return []- ids5 <- sv `onKeyPress`- \name modifier keyval -> do- liftIO $ reflectIDE (do- let moveToNextWord iterOp sel = do- sel' <- iterOp sel- rs <- isRangeStart sel'- if rs then return sel' else moveToNextWord iterOp sel'- let calculateNewPosition iterOp = getInsertIter buffer >>= moveToNextWord iterOp- let continueSelection keepSelBound nsel = do- im <- getInsertMark buffer- moveMark buffer im nsel- scrollToIter sv nsel 0 Nothing- when (not keepSelBound) $ do- sb <- getSelectionBoundMark buffer- moveMark buffer sb nsel- case (name, map mapControlCommand modifier, keyval) of- ("Left",[GtkOld.Control],_) -> do- calculateNewPosition backwardCharC >>= continueSelection False- return True- ("Left",[GtkOld.Shift, GtkOld.Control],_) -> do- calculateNewPosition backwardCharC >>= continueSelection True- return True- ("Right",[GtkOld.Control],_) -> do- calculateNewPosition forwardCharC >>= continueSelection False --placeCursor buffer- return True- ("Right",[GtkOld.Shift, GtkOld.Control],_) -> do- calculateNewPosition forwardCharC >>= continueSelection True- return True- ("BackSpace",[GtkOld.Control],_) -> do -- delete word- here <- getInsertIter buffer- there <- calculateNewPosition backwardCharC- delete buffer here there- return True- ("underscore",[GtkOld.Shift, GtkOld.Control],_) -> do- (start, end) <- getIdentifierUnderCursor buffer- slice <- getSlice buffer start end True- triggerEventIDE (SelectInfo slice False)- return True- -- Redundant should become a go to definition directly- ("minus",[GtkOld.Control],_) -> do+ -- put it in a scrolled window+ sw <- getScrolledWindow sv+ if wrapLines prefs+ then liftIO $ scrolledWindowSetPolicy sw PolicyNever PolicyAutomatic+ else liftIO $ scrolledWindowSetPolicy sw PolicyAutomatic PolicyAutomatic+ liftIO $ scrolledWindowSetShadowType sw ShadowIn+ modTimeRef <- liftIO $ newIORef modTime+ let buf = IDEBuffer {+ fileName = mbfn,+ bufferName = bn,+ addedIndex = ind,+ sourceView =sv,+ scrolledWindow = sw,+ modTime = modTimeRef,+ mode = mod}+ -- events+ ids1 <- sv `afterFocusIn` makeActive buf+ ids2 <- onCompletion sv (do+ Completion.complete sv False) $ do+ Completion.cancel+ ids3 <- onButtonPress sv $ do+ click <- lift $ Gtk.eventClick+ liftIDE $+ case click of+ Gtk.DoubleClick -> do (start, end) <- getIdentifierUnderCursor buffer- slice <- getSlice buffer start end True- triggerEventIDE (SelectInfo slice True)+ selectRange buffer start end return True- _ -> do- -- liftIO $ print ("sourcebuffer key:",name,modifier,keyval)- return False- ) ideR- ids6 <- case sv of- GtkEditorView sv -> do- (liftIO $ createHyperLinkSupport sv sw (\ctrl shift iter -> do- (GtkEditorIter beg,GtkEditorIter en) <- reflectIDE (getIdentifierUnderCursorFromIter (GtkEditorIter iter, GtkEditorIter iter)) ideR- return (beg, if ctrl then en else beg)) (\_ shift' slice -> do- when (slice /= []) $ do- -- liftIO$ print ("slice",slice)- reflectIDE (triggerEventIDE- (SelectInfo slice shift')) ideR- return ()- ))+ _ -> return False -#ifdef LEKSAH_WITH_YI- _ -> return []-#endif- return (Just buf,concat [ids1, ids2, ids3, ids4, ids5, ids6])+ (GetTextPopup mbTpm) <- triggerEvent ideR (GetTextPopup Nothing)+ ids4 <- case mbTpm of+ Just tpm -> sv `onPopulatePopup` \menu -> liftIO $ (tpm ideR menu)+ Nothing -> do+ sysMessage Normal "SourceBuffer>> no text popup"+ return [] + --TODO refactor this+ ids5 <- onMotionNotifyEvent sv $ do+ liftIDE $ do+ candy' <- readIDE candy+ inActiveBufContext () $ \_ _ ebuf currentBuffer _ -> do+ let tagName = "match"+ tagTable <- getTagTable ebuf+ mbTag <- lookupTag tagTable tagName+ case mbTag of+ Just existingTag -> do+ removeTagByName ebuf tagName+ Nothing -> do+ tag <- newTag tagTable tagName+ background tag $ matchBackground prefs++ hasSelection <- hasSelection ebuf+ when hasSelection $ do+ (si1,si2) <- getSelectionBounds ebuf++ sTxt <- getCandylessPart candy' ebuf si1 si2+ let strippedSTxt = strip' sTxt+ case strippedSTxt of+ [] -> return ()+ _ -> do+ bi1 <- getStartIter ebuf+ bi2 <- getEndIter ebuf+ forwardApplying bi1 strippedSTxt (Just si1) tagName ebuf+ forwardApplying si2 strippedSTxt (Just bi2) tagName ebuf+ return False++ ids6 <- onKeyPress sv $ do+ keyval <- lift eventKeyVal+ name <- lift eventKeyName+ modifier <- lift eventModifier+ liftIDE $ do+ let moveToNextWord iterOp sel = do+ sel' <- iterOp sel+ rs <- isRangeStart sel'+ if rs then return sel' else moveToNextWord iterOp sel'+ let calculateNewPosition iterOp = getInsertIter buffer >>= moveToNextWord iterOp+ let continueSelection keepSelBound nsel = do+ if keepSelBound+ then do+ sb <- getSelectionBoundMark buffer >>= getIterAtMark buffer+ selectRange buffer nsel sb+ else+ placeCursor buffer nsel+ scrollToIter sv nsel 0 Nothing+ case (name, map mapControlCommand modifier, keyval) of+ ("Left",[Gtk.Control],_) -> do+ calculateNewPosition backwardCharC >>= continueSelection False+ return True+ ("Left",[Gtk.Shift, Gtk.Control],_) -> do+ calculateNewPosition backwardCharC >>= continueSelection True+ return True+ ("Right",[Gtk.Control],_) -> do+ calculateNewPosition forwardCharC >>= continueSelection False --placeCursor buffer+ return True+ ("Right",[Gtk.Shift, Gtk.Control],_) -> do+ calculateNewPosition forwardCharC >>= continueSelection True+ return True+ ("BackSpace",[Gtk.Control],_) -> do -- delete word+ here <- getInsertIter buffer+ there <- calculateNewPosition backwardCharC+ delete buffer here there+ return True+ ("underscore",[Gtk.Shift, Gtk.Control],_) -> do+ (start, end) <- getIdentifierUnderCursor buffer+ slice <- getSlice buffer start end True+ triggerEventIDE (SelectInfo slice False)+ return True+ -- Redundant should become a go to definition directly+ ("minus",[Gtk.Control],_) -> do+ (start, end) <- getIdentifierUnderCursor buffer+ slice <- getSlice buffer start end True+ triggerEventIDE (SelectInfo slice True)+ return True+ _ -> do+ -- liftIO $ print ("sourcebuffer key:",name,modifier,keyval)+ return False+ ids7 <- do+ ideR <- ask+ sw <- getScrolledWindow sv+ createHyperLinkSupport sv sw (\ctrl shift iter -> do+ (beg, en) <- getIdentifierUnderCursorFromIter (iter, iter)+ return (beg, if ctrl then en else beg)) (\_ shift' slice -> do+ when (slice /= []) $ do+ -- liftIO$ print ("slice",slice)+ triggerEventIDE (SelectInfo slice shift')+ return ()+ )+ return (Just buf,concat [ids1, ids2, ids3, ids4, ids5, ids6, ids7])+ wschars' :: String+ wschars' = " \t\r\n"++ strip' :: String -> String+ strip' = lstrip' . rstrip'++ lstrip' :: String -> String+ lstrip' s = case s of+ [] -> []+ (x:xs) -> if elem x wschars'+ then lstrip' xs+ else s+ rstrip' :: String -> String+ rstrip' = reverse . lstrip' . reverse+ forwardApplying :: TextEditor editor+ => EditorIter editor+ -> String -- txt+ -> Maybe (EditorIter editor)+ -> String -- tagname+ -> EditorBuffer editor+ -> IDEM ()+ forwardApplying tI txt mbTi tagName ebuf = do+ mbFTxt <- forwardSearch tI txt [TextSearchVisibleOnly, TextSearchTextOnly] mbTi+ case mbFTxt of+ Just (start, end) -> do+ startsWord <- startsWord start+ endsWord <- endsWord end+ if (startsWord && endsWord)+ then applyTagByName ebuf tagName start end+ else return ()+ forwardApplying end txt mbTi tagName ebuf+ Nothing -> return()+ isIdent a = isAlphaNum a || a == '\'' || a == '_' -- parts of haskell identifiers isRangeStart sel = do -- if char and previous char are of different char categories@@ -556,12 +635,12 @@ mbPrevCharCat <- getCharacterCategory <$> (backwardCharC sel >>= getChar) return $ currentChar == Nothing || currentChar == Just '\n' || mbStartCharCat /= mbPrevCharCat && (mbStartCharCat == SyntaxCharacter || mbStartCharCat == IdentifierCharacter) -getIdentifierUnderCursor :: EditorBuffer -> IDEM (EditorIter, EditorIter)+getIdentifierUnderCursor :: forall editor. TextEditor editor => EditorBuffer editor -> IDEM (EditorIter editor, EditorIter editor) getIdentifierUnderCursor buffer = do (startSel, endSel) <- getSelectionBounds buffer getIdentifierUnderCursorFromIter (startSel, endSel) -getIdentifierUnderCursorFromIter :: (EditorIter, EditorIter) -> IDEM (EditorIter, EditorIter)+getIdentifierUnderCursorFromIter :: TextEditor editor => (EditorIter editor, EditorIter editor) -> IDEM (EditorIter editor, EditorIter editor) getIdentifierUnderCursorFromIter (startSel, endSel) = do let isIdent a = isAlphaNum a || a == '\'' || a == '_' let isOp a = isSymbol a || a == ':' || a == '\\' || a == '*' || a == '/' || a == '-'@@ -616,7 +695,7 @@ load <- readIDE (autoLoad . prefs) if load then do- ideMessage Normal $ "Auto Loading " ++ fn+ ideMessage Normal $ (__ "Auto Loading ") ++ fn revert buf return (False, True) else do@@ -626,10 +705,10 @@ (Just window) [] MessageQuestion ButtonsNone- ("File \"" ++ name ++ "\" has changed on disk.")- dialogAddButton md "_Load From Disk" (ResponseUser 1)- dialogAddButton md "_Always Load From Disk" (ResponseUser 2)- dialogAddButton md "_Don't Load" (ResponseUser 3)+ ((__"File \"") ++ name ++ (__ "\" has changed on disk."))+ dialogAddButton md (__ "_Load From Disk") (ResponseUser 1)+ dialogAddButton md (__ "_Always Load From Disk") (ResponseUser 2)+ dialogAddButton md (__ "_Don't Load") (ResponseUser 3) dialogSetDefaultResponse md (ResponseUser 1) set md [ windowWindowPosition := WinPosCenterOnParent ] resp <- dialogRun md@@ -657,23 +736,27 @@ let name = paneName buf case fileName buf of Nothing -> return ()- Just fn -> liftIO $ do- nmt <- getModificationTime fn- writeIORef (modTime buf) (Just nmt)+ Just fn -> liftIO $ E.catch+ (do+ nmt <- getModificationTime fn+ writeIORef (modTime buf) (Just nmt))+ (\(e::SomeException) -> do+ sysMessage Normal (show e)+ return ()) fileRevert :: IDEAction-fileRevert = inActiveBufContext () $ \ _ _ currentBuffer _ -> do+fileRevert = inActiveBufContext () $ \ _ _ _ currentBuffer _ -> do revert currentBuffer revert :: IDEBuffer -> IDEAction-revert buf = do+revert (buf@IDEBuffer{sourceView = sv}) = do useCandy <- useCandyFor buf ct <- readIDE candy let name = paneName buf case fileName buf of Nothing -> return () Just fn -> do- buffer <- getBuffer (sourceView buf)+ buffer <- getBuffer sv fc <- liftIO $ UTF8.readFile fn mt <- liftIO $ getModificationTime fn beginNotUndoableAction buffer@@ -687,7 +770,7 @@ return mt liftIO $ writeIORef (modTime buf) (Just mt) -writeCursorPositionInStatusbar :: EditorView -> IDEAction+writeCursorPositionInStatusbar :: TextEditor editor => EditorView editor -> IDEAction writeCursorPositionInStatusbar sv = do buf <- getBuffer sv mark <- getInsertMark buf@@ -697,13 +780,13 @@ triggerEventIDE (StatusbarChanged [CompartmentBufferPos (line,col)]) return () -writeOverwriteInStatusbar :: EditorView -> IDEAction+writeOverwriteInStatusbar :: TextEditor editor => EditorView editor -> IDEAction writeOverwriteInStatusbar sv = do mode <- getOverwrite sv triggerEventIDE (StatusbarChanged [CompartmentOverlay mode]) return () -selectInfo :: EditorView -> IDEAction+selectInfo :: TextEditor editor => EditorView editor -> IDEAction selectInfo sv = do ideR <- ask buf <- getBuffer sv@@ -725,13 +808,13 @@ Just buf -> markLabelAsChanged nb buf markLabelAsChanged :: Notebook -> IDEBuffer -> IDEAction-markLabelAsChanged nb buf = do- ebuf <- getBuffer (sourceView buf)+markLabelAsChanged nb (buf@IDEBuffer{sourceView = sv}) = do+ ebuf <- getBuffer sv modified <- getModified ebuf liftIO $ markLabel nb (getTopWidget buf) modified -fileSaveBuffer :: Bool -> Notebook -> EditorBuffer -> IDEBuffer -> Int -> IDEM Bool-fileSaveBuffer query nb ebuf ideBuf i = do+fileSaveBuffer :: TextEditor editor => Bool -> Notebook -> EditorView editor -> EditorBuffer editor -> IDEBuffer -> Int -> IDEM Bool+fileSaveBuffer query nb _ ebuf (ideBuf@IDEBuffer{sourceView = sv}) i = do ideR <- ask window <- getMainWindow prefs <- readIDE prefs@@ -741,7 +824,7 @@ let mbfn = fileName ideBuf mbpage <- liftIO $ notebookGetNthPage nb i case mbpage of- Nothing -> throwIDE "fileSave: Page not found"+ Nothing -> throwIDE (__ "fileSave: Page not found") Just page -> if isJust mbfn && query == False then do (modifiedOnDiskNotLoaded, modifiedOnDisk) <- checkModTime ideBuf -- The user is given option to reload@@ -755,7 +838,7 @@ else return modifiedOnDisk else reifyIDE $ \ideR -> do dialog <- fileChooserDialogNew- (Just $ "Save File")+ (Just $ (__ "Save File")) (Just window) FileChooserActionSave [("gtk-cancel" --buttons to display@@ -781,8 +864,8 @@ then do md <- messageDialogNew (Just window) [] MessageQuestion ButtonsCancel- "File already exist."- dialogAddButton md "_Overwrite" ResponseYes+ (__ "File already exist.")+ dialogAddButton md (__ "_Overwrite") ResponseYes dialogSetDefaultResponse md ResponseCancel set md [ windowWindowPosition := WinPosCenterOnParent ] resp <- dialogRun md@@ -803,13 +886,13 @@ where fileSave' :: Bool -> Bool -> Notebook -> IDEBuffer -> Bool -> CandyTable -> FilePath -> IDEAction fileSave' forceLineEnds removeTBlanks nb ideBuf useCandy candyTable fn = do- buf <- getBuffer $ sourceView ideBuf+ buf <- getBuffer $ sv text <- getCandylessText candyTable buf let text' = if removeTBlanks then unlines $ map removeTrailingBlanks $lines text else text- succ <- liftIO $ catch (do UTF8.writeFile fn text'; return True)- (\e -> do+ succ <- liftIO $ E.catch (do UTF8.writeFile fn text'; return True)+ (\(e :: SomeException) -> do sysMessage Normal (show e) return False) setModified buf (not succ)@@ -827,8 +910,8 @@ results <- forM filtered (\buf -> inBufContext False buf (fileSaveBuffer False)) return $ True `elem` results -fileCheckBuffer :: Notebook -> EditorBuffer -> IDEBuffer -> Int -> IDEM Bool-fileCheckBuffer nb ebuf ideBuf i = do+fileCheckBuffer :: TextEditor editor => Notebook -> EditorView editor -> EditorBuffer editor -> IDEBuffer -> Int -> IDEM Bool+fileCheckBuffer nb _ ebuf ideBuf i = do let mbfn = fileName ideBuf if isJust mbfn then do (_, modifiedOnDisk) <- checkModTime ideBuf -- The user is given option to reload@@ -853,14 +936,14 @@ fileNew = do prefs <- readIDE prefs pp <- getBestPathForId "*Buffer"- newTextBuffer pp "Unnamed" Nothing+ newTextBuffer pp (__ "Unnamed") Nothing return () fileClose :: IDEM Bool fileClose = inActiveBufContext True $ fileClose' -fileClose' :: Notebook -> EditorBuffer -> IDEBuffer -> Int -> IDEM Bool-fileClose' nb ebuf currentBuffer i = do+fileClose' :: TextEditor editor => Notebook -> EditorView editor -> EditorBuffer editor -> IDEBuffer -> Int -> IDEM Bool+fileClose' nb _ ebuf currentBuffer i = do window <- getMainWindow modified <- getModified ebuf cancel <- reifyIDE $ \ideR -> do@@ -869,11 +952,11 @@ md <- messageDialogNew (Just window) [] MessageQuestion ButtonsCancel- ("Save changes to document: "+ ((__ "Save changes to document: ") ++ paneName currentBuffer ++ "?")- dialogAddButton md "_Save" ResponseYes- dialogAddButton md "_Don't Save" ResponseNo+ dialogAddButton md (__ "_Save") ResponseYes+ dialogAddButton md (__ "_Don't Save") ResponseNo set md [ windowWindowPosition := WinPosCenterOnParent ] resp <- dialogRun md widgetDestroy md@@ -913,19 +996,19 @@ when (not (null bufs) && isJust mbActivePack) $ do mapM_ (close' (fromJust mbActivePack)) bufs where- close' activePack buf = do+ close' activePack (buf@IDEBuffer {sourceView = sv}) = do (pane,_) <- guiPropertiesFromName (paneName buf) nb <- getNotebook pane mbI <- liftIO $notebookPageNum nb (scrolledWindow buf) case mbI of- Nothing -> throwIDE "notebook page not found: unexpected"+ Nothing -> throwIDE (__ "notebook page not found: unexpected") Just i -> do- ebuf <- getBuffer (sourceView buf)+ ebuf <- getBuffer sv let dir = dropFileName $ ipdCabalFile activePack when (isJust (fileName buf)) $ do modified <- getModified ebuf when (not modified && not (isSubPath dir (fromJust (fileName buf))))- $ do fileClose' nb ebuf buf i; return ()+ $ do fileClose' nb sv ebuf buf i; return () fileCloseAllButWorkspace :: IDEAction fileCloseAllButWorkspace = do@@ -934,18 +1017,18 @@ when (not (null bufs) && isJust mbWorkspace) $ do mapM_ (close' (fromJust mbWorkspace)) bufs where- close' workspace buf = do+ close' workspace (buf@IDEBuffer {sourceView = sv}) = do (pane,_) <- guiPropertiesFromName (paneName buf) nb <- getNotebook pane mbI <- liftIO $notebookPageNum nb (scrolledWindow buf) case mbI of- Nothing -> throwIDE "notebook page not found: unexpected"+ Nothing -> throwIDE (__ "notebook page not found: unexpected") Just i -> do- ebuf <- getBuffer (sourceView buf)+ ebuf <- getBuffer sv when (isJust (fileName buf)) $ do modified <- getModified ebuf when (not modified && not (isSubPathOfAny workspace (fromJust (fileName buf))))- $ do fileClose' nb ebuf buf i; return ()+ $ do fileClose' nb sv ebuf buf i; return () isSubPathOfAny workspace fileName = let pathes = map (dropFileName . ipdCabalFile) (wsPackages workspace) in or (map (\dir -> isSubPath dir fileName) pathes)@@ -958,7 +1041,7 @@ mbBuf <- maybeActiveBuf mbFileName <- liftIO $ do dialog <- fileChooserDialogNew- (Just $ "Open File")+ (Just $ (__ "Open File")) (Just window) FileChooserActionOpen [("gtk-cancel"@@ -989,6 +1072,7 @@ fileOpenThis :: FilePath -> IDEAction fileOpenThis fp = do+ liftIO . debugM "leksah" $ "fileOpenThis " ++ fp prefs <- readIDE prefs fpc <- liftIO $ myCanonicalizePath fp buffers <- allBuffers@@ -1003,9 +1087,9 @@ (Just window) [] MessageQuestion ButtonsNone- "Buffer already open."- dialogAddButton md "Make _Active" (ResponseUser 1)- dialogAddButton md "_Open Second" (ResponseUser 2)+ (__ "Buffer already open.")+ dialogAddButton md (__ "Make _Active") (ResponseUser 1)+ dialogAddButton md (__ "_Open Second") (ResponseUser 2) dialogSetDefaultResponse md (ResponseUser 1) set md [ windowWindowPosition := WinPosCenterOnParent ] resp <- dialogRun md@@ -1021,39 +1105,105 @@ newTextBuffer pp (takeFileName fpc) (Just fpc) return () +filePrint :: IDEAction+filePrint = inActiveBufContext () $ filePrint'++filePrint' :: TextEditor editor => Notebook -> EditorView view -> EditorBuffer editor -> IDEBuffer -> Int -> IDEM ()+filePrint' nb _ ebuf currentBuffer _ = do+ let pName = paneName currentBuffer+ window <- getMainWindow+ print <- reifyIDE $ \ideR -> do+ md <- messageDialogNew (Just window) []+ MessageQuestion+ ButtonsNone+ ("Print document: "+ ++ pName+ ++ "?")+ dialogAddButton md "_Print" ResponseYes+ dialogAddButton md "_Don't Print" ResponseNo+ set md [ windowWindowPosition := WinPosCenterOnParent ]+ resp <- dialogRun md+ widgetDestroy md+ case resp of+ ResponseYes -> do+ return True+ ResponseCancel -> return False+ ResponseNo -> return False+ _ -> return False+ if not print+ then return ()+ else do+ --real code+ modified <- getModified ebuf+ cancel <- reifyIDE $ \ideR -> do+ if modified+ then do+ md <- messageDialogNew (Just window) []+ MessageQuestion+ ButtonsNone+ ("Save changes to document: "+ ++ pName+ ++ "?")+ dialogAddButton md "_Save" ResponseYes+ dialogAddButton md "_Don't Save" ResponseNo+ dialogAddButton md "_Cancel Printing" ResponseCancel+ set md [ windowWindowPosition := WinPosCenterOnParent ]+ resp <- dialogRun md+ widgetDestroy md+ case resp of+ ResponseYes -> do+ reflectIDE (fileSave False) ideR+ return False+ ResponseCancel -> return True+ ResponseNo -> return False+ _ -> return False+ else+ return False+ if cancel+ then return ()+ else do+ case fileName currentBuffer of+ Just name -> do+ status <- liftIO $ Print.print name+ case status of+ Left error -> liftIO $ showDialog (show error) MessageError+ Right _ -> liftIO $ showDialog "Print job has been sent successfully" MessageInfo+ return ()+ Nothing -> return ()+ editUndo :: IDEAction-editUndo = inActiveBufContext () $ \_ buf _ _ -> do+editUndo = inActiveBufContext () $ \_ _ buf _ _ -> do can <- canUndo buf when can $ undo buf editRedo :: IDEAction-editRedo = inActiveBufContext () $ \_ buf _ _ -> do+editRedo = inActiveBufContext () $ \_ _ buf _ _ -> do can <- canRedo buf when can $ redo buf editDelete :: IDEAction-editDelete = inActiveBufContext () $ \_ ebuf _ _ -> do- deleteSelection ebuf True True+editDelete = inActiveBufContext () $ \_ _ ebuf _ _ -> do+ deleteSelection ebuf return () editSelectAll :: IDEAction-editSelectAll = inActiveBufContext () $ \_ ebuf _ _ -> do+editSelectAll = inActiveBufContext () $ \_ _ ebuf _ _ -> do start <- getStartIter ebuf end <- getEndIter ebuf selectRange ebuf start end editCut :: IDEAction-editCut = inActiveBufContext () $ \_ ebuf _ _ -> do+editCut = inActiveBufContext () $ \_ _ ebuf _ _ -> do clip <- liftIO $ clipboardGet selectionClipboard cutClipboard ebuf clip True editCopy :: IDEAction-editCopy = inActiveBufContext () $ \_ ebuf _ _ -> do+editCopy = inActiveBufContext () $ \_ _ ebuf _ _ -> do clip <- liftIO $ clipboardGet selectionClipboard copyClipboard ebuf clip editPaste :: IDEAction-editPaste = inActiveBufContext () $ \_ ebuf _ _ -> do+editPaste = inActiveBufContext () $ \_ _ ebuf _ _ -> do mark <- getInsertMark ebuf iter <- getIterAtMark ebuf mark clip <- liftIO $ clipboardGet selectionClipboard@@ -1148,7 +1298,7 @@ selectedText :: IDEM (Maybe String) selectedText = do candy' <- readIDE candy- inActiveBufContext Nothing $ \_ ebuf currentBuffer _ -> do+ inActiveBufContext Nothing $ \_ _ ebuf currentBuffer _ -> do hasSelection <- hasSelection ebuf if hasSelection then do@@ -1160,7 +1310,7 @@ selectedTextOrCurrentLine :: IDEM (Maybe String) selectedTextOrCurrentLine = do candy' <- readIDE candy- inActiveBufContext Nothing $ \_ ebuf currentBuffer _ -> do+ inActiveBufContext Nothing $ \_ _ ebuf currentBuffer _ -> do hasSelection <- hasSelection ebuf (i1, i2) <- if hasSelection then getSelectionBounds ebuf@@ -1175,7 +1325,7 @@ selectedLocation :: IDEM (Maybe (Int, Int)) selectedLocation = do candy' <- readIDE candy- inActiveBufContext Nothing $ \_ ebuf currentBuffer _ -> do+ inActiveBufContext Nothing $ \_ _ ebuf currentBuffer _ -> do useCandy <- useCandyFor currentBuffer (start, _) <- getSelectionBounds ebuf line <- getLine start@@ -1188,7 +1338,7 @@ insertTextAfterSelection :: String -> IDEAction insertTextAfterSelection str = do candy' <- readIDE candy- inActiveBufContext () $ \_ ebuf currentBuffer _ -> do+ inActiveBufContext () $ \_ _ ebuf currentBuffer _ -> do useCandy <- useCandyFor currentBuffer hasSelection <- hasSelection ebuf when hasSelection $ do@@ -1202,12 +1352,9 @@ -- | Returns the package, to which this buffer belongs, if possible belongsToPackage :: IDEBuffer -> IDEM(Maybe IDEPackage)-belongsToPackage ideBuf | fileName ideBuf == Nothing = return Nothing- | not (isHaskellMode (mode ideBuf)) = return Nothing- | otherwise = do+belongsToPackage IDEBuffer{fileName = Just fp}= do bufferToProject' <- readIDE bufferProjCache ws <- readIDE workspace- let fp = fromJust (fileName ideBuf) case Map.lookup fp bufferToProject' of Just p -> return p Nothing -> case ws of@@ -1220,27 +1367,15 @@ let res = foldl (belongsToPackage' fp mbMn2) Nothing (wsPackages workspace) modifyIDE_ (\ide -> ide{bufferProjCache = Map.insert fp res bufferToProject'}) return res+belongsToPackage _ = return Nothing belongsToPackage' :: FilePath -> Maybe ModuleName -> Maybe IDEPackage -> IDEPackage -> Maybe IDEPackage belongsToPackage' _ _ r@(Just pack) _ = r belongsToPackage' fp mbModuleName Nothing pack = let basePath = dropFileName $ ipdCabalFile pack in if isSubPath basePath fp- then- let srcPaths = map (\srcP -> basePath </> srcP) (ipdSrcDirs pack)- relPaths = map (\p -> makeRelative p fp) srcPaths- in if or $- (fp `elem` possibleMains basePath) :- (map (\p -> Set.member p (ipdExtraSrcs pack)) relPaths)- then Just pack- else case mbModuleName of- Nothing -> Nothing- Just mn -> if Map.member mn (ipdModules pack)- then Just pack- else Nothing+ then Just pack else Nothing- where- possibleMains basePath = concatMap (\(f, bi, isTest) -> map (\srcDir -> basePath </> srcDir </> f) $ hsSourceDirs bi) $ ipdMain pack belongsToWorkspace b = belongsToPackage b >>= return . isJust
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleInstances, RecordWildCards, TypeSynonymInstances,- MultiParamTypeClasses, DeriveDataTypeable #-}+ MultiParamTypeClasses, DeriveDataTypeable, OverloadedStrings #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Pane.Trace@@ -17,6 +17,7 @@ module IDE.Pane.Trace ( IDETrace , TraceState+, showTrace , fillTraceList ) where @@ -47,9 +48,14 @@ import Graphics.UI.Gtk.General.Enums (MouseButton(..)) import System.Log.Logger (debugM) import IDE.Workspaces (packageTry)-import qualified Data.Enumerator.List as EL (consume)+import qualified Data.Conduit.List as CL (consume) import Control.Monad.Trans.Class (MonadTrans(..)) import Control.Monad.IO.Class (MonadIO(..))+import IDE.Utils.GUIUtils (treeViewContextMenu, __)+import Text.Printf (printf)+import Data.Text (Text)+import Data.Monoid ((<>))+import qualified Data.Text as T (unpack) -- | A debugger pane description --@@ -71,7 +77,7 @@ instance Pane IDETrace IDEM where- primPaneName _ = "Trace"+ primPaneName _ = (__ "Trace") getAddedIndex _ = 0 getTopWidget = castToWidget . scrolledView paneId b = "*Trace"@@ -84,6 +90,14 @@ buildPane pp nb builder builder = builder' +getTrace :: IDEM IDETrace+getTrace = forceGetPane (Right "*Trace")++showTrace :: IDEAction+showTrace = do+ pane <- getTrace+ displayPane pane False+ builder' :: PanePath -> Notebook -> Window ->@@ -106,7 +120,7 @@ renderer1 <- cellRendererTextNew col1 <- treeViewColumnNew- treeViewColumnSetTitle col1 "Index"+ treeViewColumnSetTitle col1 (__ "Index") treeViewColumnSetSizing col1 TreeViewColumnAutosize treeViewColumnSetResizable col1 True treeViewColumnSetReorderable col1 True@@ -117,7 +131,7 @@ renderer2 <- cellRendererTextNew col2 <- treeViewColumnNew- treeViewColumnSetTitle col2 "Function"+ treeViewColumnSetTitle col2 (__ "Function") treeViewColumnSetSizing col2 TreeViewColumnAutosize treeViewColumnSetResizable col2 True treeViewColumnSetReorderable col2 True@@ -128,7 +142,7 @@ renderer3 <- cellRendererTextNew col3 <- treeViewColumnNew- treeViewColumnSetTitle col3 "Position"+ treeViewColumnSetTitle col3 (__ "Position") treeViewColumnSetSizing col3 TreeViewColumnAutosize treeViewColumnSetResizable col3 True treeViewColumnSetReorderable col3 True@@ -147,15 +161,16 @@ let pane = IDETrace scrolledView treeView tracepoints - cid1 <- treeView `afterFocusIn`- (\_ -> do reflectIDE (makeActive pane) ideR ; return True)- sel `onSelectionChanged` do+ cid1 <- after treeView focusInEvent $ do+ liftIO $ reflectIDE (makeActive pane) ideR+ return True+ (cid2, cid3) <- treeViewContextMenu treeView $ traceContextMenu ideR tracepoints treeView+ on sel treeSelectionSelectionChanged $ do sel <- getSelectedTracepoint treeView tracepoints case sel of Just ref -> return () -- TODO reflectIDE (selectRef (Just ref)) ideR Nothing -> return ()- treeView `onButtonPress` (traceViewPopup ideR tracepoints treeView)- return (Just pane,[ConnectC cid1])+ return (Just pane, map ConnectC [cid1, cid2, cid3]) fillTraceList :: IDEAction fillTraceList = packageTry $ do@@ -164,12 +179,12 @@ case mbTraces of Nothing -> return () Just tracePane -> tryDebug $ debugCommand' ":history" $ do- to <- EL.consume+ to <- CL.consume liftIO $ postGUIAsync $ do- let parseRes = parse tracesParser "" (selectString to)+ let parseRes = parse tracesParser "" . T.unpack $ selectString to r <- case parseRes of Left err -> do- debugM "leksah" ("trace parse error " ++ show err ++ "\ninput: " ++ selectString to)+ debugM "leksah" ((printf (__ "trace parse error %s\ninput: %s") (show err) (T.unpack $ selectString to))) return [] Right traces -> return traces treeStoreClear (tracepoints tracePane)@@ -181,8 +196,8 @@ where insertTrace treeStore (tr,index) = treeStoreInsert treeStore [] index tr -selectString :: [ToolOutput] -> String-selectString (ToolOutput str:r) = '\n' : str ++ selectString r+selectString :: [ToolOutput] -> Text+selectString (ToolOutput str:r) = "\n" <> str <> selectString r selectString (_:r) = selectString r selectString [] = "" @@ -198,65 +213,48 @@ return (Just val) _ -> return Nothing -selectStrings :: [ToolOutput] -> [String]+selectStrings :: [ToolOutput] -> [Text] selectStrings (ToolOutput str:r) = str : selectStrings r selectStrings (_:r) = selectStrings r selectStrings [] = [] -traceViewPopup :: IDERef- -> TreeStore TraceHist- -> TreeView- -> Event- -> IO (Bool)-traceViewPopup ideR store treeView (Button _ click _ _ _ _ button _ _)- = do- if button == RightButton- then do- theMenu <- menuNew- item1 <- menuItemNewWithLabel "Back"- item1 `onActivateLeaf` reflectIDE debugBack ideR- sep1 <- separatorMenuItemNew- item2 <- menuItemNewWithLabel "Forward"- item2 `onActivateLeaf` (reflectIDE debugForward ideR)- item3 <- menuItemNewWithLabel "Update"- item3 `onActivateLeaf` (reflectIDE fillTraceList ideR)- mapM_ (menuShellAppend theMenu) [castToMenuItem item1, castToMenuItem sep1,- castToMenuItem item2, castToMenuItem item3]- menuPopup theMenu Nothing- widgetShowAll theMenu- return True- else return False--- if button == LeftButton && click == DoubleClick--- then do sel <- getSelectedBreakpoint treeView store--- case sel of--- Just ref -> reflectIDE (setCurrentBreak (Just ref)) ideR--- otherwise -> sysMessage Normal "Debugger>> breakpointViewPopup: no selection2"--- return True--- else return False-traceViewPopup _ _ _ _ = throwIDE "breakpointViewPopup wrong event type"-+traceContextMenu :: IDERef+ -> TreeStore TraceHist+ -> TreeView+ -> Menu+ -> IO ()+traceContextMenu ideR store treeView theMenu = do+ item1 <- menuItemNewWithLabel (__ "Back")+ item1 `on` menuItemActivate $ reflectIDE debugBack ideR+ sep1 <- separatorMenuItemNew+ item2 <- menuItemNewWithLabel (__ "Forward")+ item2 `on` menuItemActivate $ reflectIDE debugForward ideR+ item3 <- menuItemNewWithLabel (__ "Update")+ item3 `on` menuItemActivate $ reflectIDE fillTraceList ideR+ mapM_ (menuShellAppend theMenu) [castToMenuItem item1, castToMenuItem sep1,+ castToMenuItem item2, castToMenuItem item3] tracesParser :: CharParser () [TraceHist] tracesParser = try (do whiteSpace- symbol "Empty history."+ symbol (__ "Empty history.") skipMany anyChar eof return []) <|> do traces <- many (try traceParser) whiteSpace- symbol "<end of history>"+ symbol (__ "<end of history>") eof return traces <|> do whiteSpace- symbol "Not stopped at a breakpoint"+ symbol (__ "Not stopped at a breakpoint") skipMany anyChar eof return [] <?>- "traces parser"+ (__ "traces parser") traceParser :: CharParser () TraceHist traceParser = do@@ -270,7 +268,7 @@ span <- srcSpanParser symbol ")" return (TraceHist False index function span)- <?> "trace parser"+ <?> (__ "trace parser") lexer = P.makeTokenParser emptyDef colon = P.colon lexer
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleInstances, RecordWildCards, TypeSynonymInstances,- MultiParamTypeClasses, DeriveDataTypeable #-}+ MultiParamTypeClasses, DeriveDataTypeable, OverloadedStrings #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Pane.Variables@@ -17,6 +17,7 @@ module IDE.Pane.Variables ( IDEVariables , VariablesState+, showVariables , fillVariablesList , fillVariablesListQuiet ) where@@ -46,9 +47,13 @@ import Graphics.UI.Gtk.General.Enums (Click(..), MouseButton(..)) import IDE.Workspaces (packageTry, packageTryQuiet)-import qualified Data.Enumerator.List as EL (consume)+import qualified Data.Conduit.List as CL (consume) import Control.Monad.Trans.Class (MonadTrans(..)) import Control.Monad.IO.Class (MonadIO(..))+import IDE.Utils.GUIUtils (treeViewContextMenu, __)+import Data.Text (Text)+import Data.Monoid ((<>))+import qualified Data.Text as T (unpack) -- | A variables pane description --@@ -68,7 +73,7 @@ instance Pane IDEVariables IDEM where- primPaneName _ = "Variables"+ primPaneName _ = (__ "Variables") getAddedIndex _ = 0 getTopWidget = castToWidget . scrolledView paneId b = "*Variables"@@ -81,7 +86,14 @@ buildPane pp nb builder builder = builder' +getVariables :: IDEM IDEVariables+getVariables = forceGetPane (Right "*Variables") +showVariables :: IDEAction+showVariables = do+ pane <- getVariables+ displayPane pane False+ builder' :: PanePath -> Notebook -> Window ->@@ -93,7 +105,7 @@ renderer1 <- cellRendererTextNew col1 <- treeViewColumnNew- treeViewColumnSetTitle col1 "Name"+ treeViewColumnSetTitle col1 (__ "Name") treeViewColumnSetSizing col1 TreeViewColumnAutosize treeViewColumnSetResizable col1 True treeViewColumnSetReorderable col1 True@@ -104,7 +116,7 @@ renderer2 <- cellRendererTextNew col2 <- treeViewColumnNew- treeViewColumnSetTitle col2 "Type"+ treeViewColumnSetTitle col2 (__ "Type") treeViewColumnSetSizing col2 TreeViewColumnAutosize treeViewColumnSetResizable col2 True treeViewColumnSetReorderable col2 True@@ -115,7 +127,7 @@ renderer3 <- cellRendererTextNew col3 <- treeViewColumnNew- treeViewColumnSetTitle col3 "Value"+ treeViewColumnSetTitle col3 (__ "Value") treeViewColumnSetSizing col3 TreeViewColumnAutosize treeViewColumnSetResizable col3 True treeViewColumnSetReorderable col3 True@@ -133,10 +145,12 @@ scrolledWindowSetPolicy scrolledView PolicyAutomatic PolicyAutomatic let pane = IDEVariables scrolledView treeView variables- treeView `onButtonPress` (variablesViewPopup ideR variables treeView)- cid1 <- treeView `afterFocusIn`- (\_ -> do reflectIDE (makeActive pane) ideR ; return True)- return (Just pane,[ConnectC cid1])+ cid1 <- after treeView focusInEvent $ do+ liftIO $ reflectIDE (makeActive pane) ideR+ return True+ (cid2, cid3) <- treeViewContextMenu treeView $ variablesContextMenu ideR variables treeView+ cid4 <- on treeView rowActivated $ variablesSelect ideR variables+ return (Just pane, map ConnectC [cid1, cid2, cid3, cid4]) fillVariablesListQuiet :: IDEAction@@ -145,9 +159,9 @@ case mbVariables of Nothing -> return () Just var -> tryDebugQuiet $ debugCommand' ":show bindings" $ do- to <- EL.consume+ to <- CL.consume liftIO $ postGUIAsync $ do- case parse variablesParser "" (selectString to) of+ case parse variablesParser "" . T.unpack $ selectString to of Left e -> sysMessage Normal (show e) Right triples -> do treeStoreClear (variables var)@@ -162,9 +176,9 @@ case mbVariables of Nothing -> return () Just var -> tryDebug $ debugCommand' ":show bindings" $ do- to <- EL.consume+ to <- CL.consume liftIO $ postGUIAsync $ do- case parse variablesParser "" (selectString to) of+ case parse variablesParser "" . T.unpack $ selectString to of Left e -> sysMessage Normal (show e) Right triples -> do treeStoreClear (variables var)@@ -173,8 +187,8 @@ where insertBreak treeStore (v,index) = treeStoreInsert treeStore [] index v -selectString :: [ToolOutput] -> String-selectString (ToolOutput str:r) = '\n' : str ++ selectString r+selectString :: [ToolOutput] -> Text+selectString (ToolOutput str:r) = "\n" <> str <> selectString r selectString (_:r) = selectString r selectString [] = "" @@ -238,59 +252,53 @@ whiteSpace = P.whiteSpace lexer -variablesViewPopup :: IDERef- -> TreeStore VarDescription- -> TreeView- -> Event- -> IO (Bool)-variablesViewPopup ideR store treeView (Button _ click _ _ _ _ button _ _)- = do- if button == RightButton- then do- theMenu <- menuNew- item1 <- menuItemNewWithLabel "Force"- item1 `onActivateLeaf` do- mbSel <- getSelectedVariable treeView store- case mbSel of- Just (varDescr,path) -> reflectIDE (forceVariable varDescr path store) ideR- otherwise -> return ()- sep1 <- separatorMenuItemNew- item2 <- menuItemNewWithLabel "Print"- item2 `onActivateLeaf` do- mbSel <- getSelectedVariable treeView store- case mbSel of- Just (varDescr,path) -> reflectIDE (printVariable varDescr path store) ideR- otherwise -> return ()- item3 <- menuItemNewWithLabel "Update"- item3 `onActivateLeaf` (postGUIAsync (reflectIDE fillVariablesList ideR))- mapM_ (menuShellAppend theMenu) [castToMenuItem item1,- castToMenuItem item2, castToMenuItem sep1, castToMenuItem item3]- menuPopup theMenu Nothing- widgetShowAll theMenu- return True- else if button == LeftButton && click == DoubleClick- then do mbSel <- getSelectedVariable treeView store- case mbSel of- Just (varDescr,path) -> reflectIDE (forceVariable varDescr path store) ideR- otherwise -> return ()- return True- else return False-variablesViewPopup _ _ _ _ = throwIDE "variablesViewPopup wrong event type"+variablesContextMenu :: IDERef+ -> TreeStore VarDescription+ -> TreeView+ -> Menu+ -> IO ()+variablesContextMenu ideR store treeView theMenu = do+ item1 <- menuItemNewWithLabel (__ "Force")+ item1 `on` menuItemActivate $ do+ mbSel <- getSelectedVariable treeView store+ case mbSel of+ Just (varDescr,path) -> reflectIDE (forceVariable varDescr path store) ideR+ otherwise -> return ()+ sep1 <- separatorMenuItemNew+ item2 <- menuItemNewWithLabel (__ "Print")+ item2 `on` menuItemActivate $ do+ mbSel <- getSelectedVariable treeView store+ case mbSel of+ Just (varDescr,path) -> reflectIDE (printVariable varDescr path store) ideR+ otherwise -> return ()+ item3 <- menuItemNewWithLabel (__ "Update")+ item3 `on` menuItemActivate $ postGUIAsync (reflectIDE fillVariablesList ideR)+ mapM_ (menuShellAppend theMenu) [castToMenuItem item1,+ castToMenuItem item2, castToMenuItem sep1, castToMenuItem item3] +variablesSelect :: IDERef+ -> TreeStore VarDescription+ -> TreePath+ -> TreeViewColumn+ -> IO ()+variablesSelect ideR store path _ = do+ varDescr <- treeStoreGetValue store path+ reflectIDE (forceVariable varDescr path store) ideR+ forceVariable :: VarDescription -> TreePath -> TreeStore VarDescription -> IDEAction forceVariable varDescr path treeStore = packageTry $ tryDebug $ do debugCommand' (":force " ++ (varName varDescr)) $ do- to <- EL.consume+ to <- CL.consume liftIO $ postGUIAsync $ do- case parse valueParser "" (selectString to) of+ case parse valueParser "" . T.unpack $ selectString to of Left e -> sysMessage Normal (show e) Right value -> do var <- treeStoreGetValue treeStore path treeStoreSetValue treeStore path var{varValue = value} debugCommand' (":type " ++ (varName varDescr)) $ do- to <- EL.consume+ to <- CL.consume liftIO $ postGUIAsync $ do- case parse typeParser "" (selectString to) of+ case parse typeParser "" . T.unpack $ selectString to of Left e -> sysMessage Normal (show e) Right typ -> do var <- treeStoreGetValue treeStore path@@ -299,17 +307,17 @@ printVariable :: VarDescription -> TreePath -> TreeStore VarDescription -> IDEAction printVariable varDescr path treeStore = packageTry $ tryDebug $ do debugCommand' (":print " ++ (varName varDescr)) $ do- to <- EL.consume+ to <- CL.consume liftIO $ postGUIAsync $ do- case parse valueParser "" (selectString to) of+ case parse valueParser "" . T.unpack $ selectString to of Left e -> sysMessage Normal (show e) Right value -> do var <- treeStoreGetValue treeStore path treeStoreSetValue treeStore path var{varValue = value} debugCommand' (":type " ++ (varName varDescr)) $ do- to <- EL.consume+ to <- CL.consume liftIO $ postGUIAsync $ do- case parse typeParser "" (selectString to) of+ case parse typeParser "" . T.unpack $ selectString to of Left e -> sysMessage Normal (show e) Right typ -> do var <- treeStoreGetValue treeStore path
@@ -0,0 +1,157 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE DeriveDataTypeable #-}+-----------------------------------------------------------------------------+--+-- Module : IDE.Pane.WebKit.Documentation+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.Pane.WebKit.Documentation (+ IDEDocumentation(..)+ , DocumentationState(..)+ , getDocumentation+ , loadDoc+ , reloadDoc+) where++import Graphics.UI.Frame.Panes+ (RecoverablePane(..), PanePath, RecoverablePane, Pane(..))+import Graphics.UI.Gtk+ (scrolledWindowSetPolicy, scrolledWindowNew, castToWidget,+ ScrolledWindow)+import Data.Typeable (Typeable)+import IDE.Core.Types (IDEAction, IDEM)+import Control.Monad.IO.Class (MonadIO(..))+import Graphics.UI.Frame.ViewFrame (getNotebook)+import IDE.Core.State (reifyIDE)+import Graphics.UI.Gtk.General.Enums (PolicyType(..))++#ifdef WEBKITGTK+import Graphics.UI.Gtk+ (eventModifier, eventKeyName, keyPressEvent, focusInEvent,+ containerAdd, Modifier(..), after)+import Graphics.UI.Gtk.WebKit.Types (WebView(..))+import Graphics.UI.Gtk.WebKit.WebView+ (webViewUri, webViewGoBack, webViewZoomOut, webViewZoomIn,+ webViewZoomLevel, webViewReload, webViewLoadUri, webViewNew)+import System.Glib.Attributes (AttrOp(..), set, get)+import System.Glib.Signals (on)+import IDE.Core.State (reflectIDE)+import Graphics.UI.Editor.Basics (Connection(..))+#else+import Data.IORef (writeIORef, newIORef, readIORef, IORef)+import Control.Applicative ((<$>))+#endif++data IDEDocumentation = IDEDocumentation {+ scrolledView :: ScrolledWindow+#ifdef WEBKITGTK+ , webView :: WebView+#else+ , docState :: IORef DocumentationState+#endif+} deriving Typeable++data DocumentationState = DocumentationState {+ zoom :: Float+ , uri :: Maybe String+} deriving(Eq,Ord,Read,Show,Typeable)++instance Pane IDEDocumentation IDEM+ where+ primPaneName _ = "Doc"+ getAddedIndex _ = 0+ getTopWidget = castToWidget . scrolledView+ paneId b = "*Doc"++instance RecoverablePane IDEDocumentation DocumentationState IDEM where+ saveState p = liftIO $ do+#ifdef WEBKITGTK+ zoom <- webView p `get` webViewZoomLevel+ uri <- webView p `get` webViewUri+ return (Just DocumentationState{..})+#else+ Just <$> readIORef (docState p)+#endif+ recoverState pp DocumentationState {..} = do+ nb <- getNotebook pp+ mbPane <- buildPane pp nb builder+ case mbPane of+ Nothing -> return ()+ Just p -> liftIO $ do+#ifdef WEBKITGTK+ webView p `set` [webViewZoomLevel := zoom]+ maybe (return ()) (webViewLoadUri (webView p)) uri+#else+ writeIORef (docState p) DocumentationState {..}+#endif+ return mbPane+ builder pp nb windows = reifyIDE $ \ ideR -> do+ scrolledView <- scrolledWindowNew Nothing Nothing++#ifdef WEBKITGTK+ webView <- webViewNew+ containerAdd scrolledView webView+#else+ docState <- newIORef DocumentationState {zoom = 1.0, uri = Nothing}+#endif++ scrolledWindowSetPolicy scrolledView PolicyAutomatic PolicyAutomatic+ let docs = IDEDocumentation {..}++#ifdef WEBKITGTK+ cid1 <- after webView focusInEvent $ do+ liftIO $ reflectIDE (makeActive docs) ideR+ return True++ webView `set` [webViewZoomLevel := 2.0]+ cid2 <- webView `on` keyPressEvent $ do+ key <- eventKeyName+ mod <- eventModifier+ liftIO $ case (key, mod) of+ ("plus", [Shift,Control]) -> webViewZoomIn webView >> return True+ ("minus",[Control]) -> webViewZoomOut webView >> return True+ ("BackSpace", []) -> webViewGoBack webView >> return True+ _ -> return False+ return (Just docs, map ConnectC [cid1, cid2])+#else+ return (Just docs, [])+#endif+++getDocumentation :: Maybe PanePath -> IDEM IDEDocumentation+getDocumentation Nothing = forceGetPane (Right "*Doc")+getDocumentation (Just pp) = forceGetPane (Left pp)++loadDoc :: String -> IDEAction+loadDoc uri = do+#ifdef WEBKITGTK+ doc <- getDocumentation Nothing+ let view = webView doc+ liftIO $ webViewLoadUri view uri+#else+ return ()+#endif++reloadDoc :: IDEAction+reloadDoc = do+#ifdef WEBKITGTK+ doc <- getDocumentation Nothing+ let view = webView doc+ liftIO $ webViewReload view+#else+ return ()+#endif+
@@ -0,0 +1,175 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE CPP #-}+-----------------------------------------------------------------------------+--+-- Module : IDE.Pane.WebKit.Output+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.Pane.WebKit.Output (+ IDEOutput(..)+ , OutputState(..)+ , getOutputPane+ , setOutput+) where++import Graphics.UI.Frame.Panes+ (RecoverablePane(..), PanePath, RecoverablePane, Pane(..))+import Graphics.UI.Gtk+ (postGUISync, scrolledWindowSetPolicy, scrolledWindowNew,+ castToWidget, ScrolledWindow)+import Data.Typeable (Typeable)+import IDE.Core.Types (IDEAction, IDEM)+import Control.Monad.IO.Class (MonadIO(..))+import Graphics.UI.Frame.ViewFrame (getNotebook)+import IDE.Core.State (postSyncIDE, reifyIDE, leksahOrPackageDir)+import Graphics.UI.Gtk.General.Enums (PolicyType(..))++#ifdef WEBKITGTK+import Graphics.UI.Gtk+ (toggleActionActive, castToMenuItem, actionCreateMenuItem,+ toggleActionNew, menuShellAppend, toggleActionSetActive,+ menuItemActivate, menuItemNewWithLabel, eventModifier,+ eventKeyName, keyPressEvent, focusInEvent, containerAdd,+ Modifier(..), after)+import Graphics.UI.Gtk.WebKit.Types (WebView(..))+import Graphics.UI.Gtk.WebKit.WebView+ (populatePopup, webViewGoBack, webViewZoomOut, webViewZoomIn,+ webViewLoadString, webViewZoomLevel, webViewReload, webViewNew,+ webViewLoadUri)+import System.Glib.Attributes (AttrOp(..), set, get)+import System.Glib.Signals (on)+import IDE.Core.State (reflectIDE)+import Graphics.UI.Editor.Basics (Connection(..))+import Text.Show.Pretty+ (HtmlOpts(..), defaultHtmlOpts, valToHtmlPage, parseValue, getDataDir)+import System.FilePath ((</>))+#endif+import Data.IORef (writeIORef, newIORef, readIORef, IORef)+import Control.Applicative ((<$>))+import System.Log.Logger (debugM)++data IDEOutput = IDEOutput {+ scrolledView :: ScrolledWindow+#ifdef WEBKITGTK+ , webView :: WebView+ , alwaysHtmlRef :: IORef Bool+#else+ , outState :: IORef OutputState+#endif+} deriving Typeable++data OutputState = OutputState {+ zoom :: Float+ , alwaysHtml :: Bool+} deriving(Eq,Ord,Read,Show,Typeable)++instance Pane IDEOutput IDEM+ where+ primPaneName _ = "Out"+ getAddedIndex _ = 0+ getTopWidget = castToWidget . scrolledView+ paneId b = "*Out"++instance RecoverablePane IDEOutput OutputState IDEM where+ saveState p = liftIO $ do+#ifdef WEBKITGTK+ zoom <- webView p `get` webViewZoomLevel+ alwaysHtml <- readIORef $ alwaysHtmlRef p+ return (Just OutputState{..})+#else+ Just <$> readIORef (outState p)+#endif+ recoverState pp OutputState {..} = do+ nb <- getNotebook pp+ mbPane <- buildPane pp nb builder+ case mbPane of+ Nothing -> return ()+ Just p -> liftIO $ do+#ifdef WEBKITGTK+ webView p `set` [webViewZoomLevel := zoom]+ writeIORef (alwaysHtmlRef p) alwaysHtml+#else+ writeIORef (outState p) OutputState {..}+#endif+ return mbPane+ builder pp nb windows = reifyIDE $ \ ideR -> do+ scrolledView <- scrolledWindowNew Nothing Nothing++#ifdef WEBKITGTK+ webView <- webViewNew+ alwaysHtmlRef <- newIORef False+ containerAdd scrolledView webView+#else+ outState <- newIORef OutputState {zoom = 1.0}+#endif++ scrolledWindowSetPolicy scrolledView PolicyAutomatic PolicyAutomatic+ let out = IDEOutput {..}++#ifdef WEBKITGTK+ cid1 <- after webView focusInEvent $ do+ liftIO $ reflectIDE (makeActive out) ideR+ return True++ webView `set` [webViewZoomLevel := 2.0]+ cid2 <- webView `on` keyPressEvent $ do+ key <- eventKeyName+ mod <- eventModifier+ liftIO $ case (key, mod) of+ ("plus", [Shift,Control]) -> webViewZoomIn webView >> return True+ ("minus",[Control]) -> webViewZoomOut webView >> return True+ ("BackSpace", []) -> webViewGoBack webView >> return True+ _ -> return False++ cid3 <- webView `on` populatePopup $ \ menu -> do+ alwaysHtml <- readIORef alwaysHtmlRef+ action <- toggleActionNew "AlwaysHTML" "Always HTML" Nothing Nothing+ item <- castToMenuItem <$> actionCreateMenuItem action+ item `on` menuItemActivate $ writeIORef alwaysHtmlRef $ not alwaysHtml+ toggleActionSetActive action alwaysHtml+ menuShellAppend menu item+ return ()++ return (Just out, map ConnectC [cid1, cid2, cid3])+#else+ return (Just out, [])+#endif+++getOutputPane :: Maybe PanePath -> IDEM IDEOutput+getOutputPane Nothing = forceGetPane (Right "*Out")+getOutputPane (Just pp) = forceGetPane (Left pp)++setOutput :: String -> IDEAction+setOutput str = do+#ifdef WEBKITGTK+ out <- getOutputPane Nothing+ liftIO $ do+ dataDir <- leksahOrPackageDir "pretty-show" getDataDir+ alwaysHtml <- readIORef $ alwaysHtmlRef out+ let view = webView out+ html = case (alwaysHtml, parseValue str) of+ (False, Just value) -> valToHtmlPage defaultHtmlOpts value+ _ -> str+ webViewLoadString view html Nothing Nothing ("file://"+ ++ (case dataDir of+ ('/':_) -> dataDir+ _ -> '/':dataDir)+ ++ "/value.html")+#else+ return ()+#endif+
@@ -15,7 +15,7 @@ ----------------------------------------------------------------------------- module IDE.Pane.Workspace (- WorkspaceState+ WorkspaceState(..) , IDEWorkspace , updateWorkspace , getWorkspace@@ -23,7 +23,7 @@ ) where import Graphics.UI.Gtk hiding (get)-import Graphics.UI.Gtk.Gdk.Events+import Graphics.UI.Gtk.Gdk.EventM import Data.Maybe import Data.Typeable import IDE.Core.State@@ -31,8 +31,13 @@ import qualified Data.Map as Map (empty) import Data.List (sortBy) import IDE.Pane.Files (refreshFiles)+import IDE.Pane.HLint (refreshHLint) import Control.Monad (when) import Control.Monad.IO.Class (MonadIO(..))+import IDE.Utils.GUIUtils (treeViewContextMenu, __)+import System.Glib.Properties (newAttrFromMaybeStringProperty)+import Data.Tree (Tree(..))+import System.Log.Logger (debugM) -- | Workspace pane state --@@ -40,13 +45,13 @@ data IDEWorkspace = IDEWorkspace { scrolledView :: ScrolledWindow , treeViewC :: TreeView-, workspaceStore :: ListStore (Bool,IDEPackage)+, workspaceStore :: TreeStore (Bool,IDEPackage,Maybe String) , topBox :: VBox } deriving Typeable instance Pane IDEWorkspace IDEM where- primPaneName _ = "Workspace"+ primPaneName _ = (__ "Workspace") getAddedIndex _ = 0 getTopWidget = castToWidget . topBox paneId b = "*Workspace"@@ -66,45 +71,45 @@ when (isJust res) $ updateWorkspace True False return res builder pp nb windows = reifyIDE $ \ideR -> do- listStore <- listStoreNew []+ treeStore <- treeStoreNew [] treeView <- treeViewNew- treeViewSetModel treeView listStore+ treeViewSetModel treeView treeStore renderer0 <- cellRendererPixbufNew col0 <- treeViewColumnNew- treeViewColumnSetTitle col0 "Active"+ treeViewColumnSetTitle col0 (__ "Active") treeViewColumnSetSizing col0 TreeViewColumnAutosize treeViewColumnSetResizable col0 True treeViewColumnSetReorderable col0 True treeViewAppendColumn treeView col0 cellLayoutPackStart col0 renderer0 True- cellLayoutSetAttributes col0 renderer0 listStore- $ \row -> [cellPixbufStockId :=- if (\(b,_)-> b) row- then stockYes- else ""]+ cellLayoutSetAttributes col0 renderer0 treeStore+ $ \row -> [newAttrFromMaybeStringProperty "stock-id" :=+ if (\(b,_,_)-> b) row+ then Just stockYes+ else Nothing] renderer1 <- cellRendererTextNew col1 <- treeViewColumnNew- treeViewColumnSetTitle col1 "Package"+ treeViewColumnSetTitle col1 (__ "Package") treeViewColumnSetSizing col1 TreeViewColumnAutosize treeViewColumnSetResizable col1 True treeViewColumnSetReorderable col1 True treeViewAppendColumn treeView col1 cellLayoutPackStart col1 renderer1 True- cellLayoutSetAttributes col1 renderer1 listStore- $ \row -> [ cellText := (\(_,pack)-> (packageIdentifierToString . ipdPackageId) pack) row ]+ cellLayoutSetAttributes col1 renderer1 treeStore+ $ \row -> [ cellText := name row ] renderer2 <- cellRendererTextNew col2 <- treeViewColumnNew- treeViewColumnSetTitle col2 "File path"+ treeViewColumnSetTitle col2 (__ "File path") treeViewColumnSetSizing col2 TreeViewColumnAutosize treeViewColumnSetResizable col2 True treeViewColumnSetReorderable col2 True treeViewAppendColumn treeView col2 cellLayoutPackStart col2 renderer2 True- cellLayoutSetAttributes col2 renderer2 listStore- $ \row -> [ cellText := (\(_,pack)-> ipdCabalFile pack) row ]+ cellLayoutSetAttributes col2 renderer2 treeStore+ $ \row -> [ cellText := file row ] treeViewSetHeadersVisible treeView True sel <- treeViewGetSelection treeView@@ -115,13 +120,19 @@ scrolledWindowSetPolicy sw PolicyAutomatic PolicyAutomatic box <- vBoxNew False 2 boxPackEnd box sw PackGrow 0- let workspacePane = IDEWorkspace sw treeView listStore box+ let workspacePane = IDEWorkspace sw treeView treeStore box widgetShowAll box- cid1 <- treeView `afterFocusIn`- (\_ -> do reflectIDE (makeActive workspacePane) ideR ; return True)- treeView `onButtonPress` (treeViewPopup ideR workspacePane)- return (Just workspacePane,[ConnectC cid1])-+ cid1 <- treeView `after` focusInEvent $ do+ liftIO $ reflectIDE (makeActive workspacePane) ideR+ return True+ (cid2, cid3) <- treeViewContextMenu treeView $ workspaceContextMenu ideR workspacePane+ cid4 <- treeView `on` rowActivated $ workspaceSelect ideR workspacePane+ return (Just workspacePane, map ConnectC [cid1, cid2, cid3, cid4])+ where+ name (_, _, Just exe) = exe+ name (_, pack, _) = packageIdentifierToString $ ipdPackageId pack+ file (_, _, Just _) = ""+ file (_, pack, _) = ipdCabalFile pack getWorkspace :: Maybe PanePath -> IDEM IDEWorkspace getWorkspace Nothing = forceGetPane (Right "*Workspace") getWorkspace (Just pp) = forceGetPane (Left pp)@@ -132,60 +143,57 @@ displayPane l False getSelectionTree :: TreeView- -> ListStore (Bool, IDEPackage)- -> IO (Maybe (Bool, IDEPackage))-getSelectionTree treeView listStore = do- treeSelection <- treeViewGetSelection treeView- rows <- treeSelectionGetSelectedRows treeSelection+ -> TreeStore (Bool, IDEPackage, Maybe String)+ -> IO (Maybe (Bool, IDEPackage, Maybe String))+getSelectionTree treeView treeStore = do+ liftIO $ debugM "leksah" "getSelectionTree"+ treeSelection <- treeViewGetSelection treeView+ rows <- treeSelectionGetSelectedRows treeSelection case rows of- [[n]] -> do- val <- listStoreGetValue listStore n+ [path] -> do+ val <- treeStoreGetValue treeStore path return (Just val) _ -> return Nothing -treeViewPopup :: IDERef- -> IDEWorkspace- -> Event- -> IO (Bool)-treeViewPopup ideR workspacePane (Button _ click _ _ _ _ button _ _) = do- if button == RightButton- then do- theMenu <- menuNew- item1 <- menuItemNewWithLabel "Activate Package"- item2 <- menuItemNewWithLabel "Add Package"- item3 <- menuItemNewWithLabel "Remove Package"- item1 `onActivateLeaf` do- sel <- getSelectionTree (treeViewC workspacePane)- (workspaceStore workspacePane)- case sel of- Just (_,ideP) -> reflectIDE (workspaceTry $ workspaceActivatePackage ideP) ideR+workspaceContextMenu :: IDERef+ -> IDEWorkspace+ -> Menu+ -> IO ()+workspaceContextMenu ideR workspacePane theMenu = do+ item1 <- menuItemNewWithLabel (__ "Activate Package")+ item2 <- menuItemNewWithLabel (__ "Add Package")+ item3 <- menuItemNewWithLabel (__ "Remove Package")+ item1 `on` menuItemActivate $ do+ sel <- getSelectionTree (treeViewC workspacePane)+ (workspaceStore workspacePane)+ case sel of+ Just (_,ideP,mbExe) -> reflectIDE (workspaceTry $ workspaceActivatePackage ideP mbExe) ideR - otherwise -> return ()- item2 `onActivateLeaf` reflectIDE (workspaceTry $ workspaceAddPackage) ideR- item3 `onActivateLeaf` do- sel <- getSelectionTree (treeViewC workspacePane)- (workspaceStore workspacePane)- case sel of- Just (_,ideP) -> reflectIDE (workspaceTry $ workspaceRemovePackage ideP) ideR- otherwise -> return ()- menuShellAppend theMenu item1- menuShellAppend theMenu item2- menuShellAppend theMenu item3- menuPopup theMenu Nothing- widgetShowAll theMenu- return True- else if button == LeftButton && click == DoubleClick- then do sel <- getSelectionTree (treeViewC workspacePane)- (workspaceStore workspacePane)- case sel of- Just (_,ideP) -> reflectIDE (workspaceTry $ workspaceActivatePackage ideP) ideR- >> return True- otherwise -> return False- else return False-treeViewPopup _ _ _ = throwIDE "treeViewPopup wrong event type"+ otherwise -> return ()+ item2 `on` menuItemActivate $ reflectIDE (workspaceTry $ workspaceAddPackage) ideR+ item3 `on` menuItemActivate $ do+ sel <- getSelectionTree (treeViewC workspacePane)+ (workspaceStore workspacePane)+ case sel of+ Just (_,ideP,_) -> reflectIDE (workspaceTry $ workspaceRemovePackage ideP) ideR+ otherwise -> return ()+ menuShellAppend theMenu item1+ menuShellAppend theMenu item2+ menuShellAppend theMenu item3 +workspaceSelect :: IDERef+ -> IDEWorkspace+ -> TreePath+ -> TreeViewColumn+ -> IO ()+workspaceSelect ideR workspacePane path _ = do+ liftIO $ debugM "leksah" "workspaceSelect"+ (_,ideP,mbExe) <- treeStoreGetValue (workspaceStore workspacePane) path+ reflectIDE (workspaceTry $ workspaceActivatePackage ideP mbExe) ideR+ updateWorkspace :: Bool -> Bool -> IDEAction updateWorkspace showPane updateFileCache = do+ liftIO $ debugM "leksah" "updateWorkspace" mbWs <- readIDE workspace case mbWs of Nothing -> do@@ -194,19 +202,26 @@ case mbMod of Nothing -> return () Just (p :: IDEWorkspace) -> do- liftIO $ listStoreClear (workspaceStore p)+ liftIO $ treeStoreClear (workspaceStore p) when showPane $ displayPane p False+ refreshFiles Just ws -> do when updateFileCache $ modifyIDE_ (\ide -> ide{bufferProjCache = Map.empty}) mbMod <- getPane case mbMod of Nothing -> return () Just (p :: IDEWorkspace) -> do- liftIO $ listStoreClear (workspaceStore p)- let objs = map (\ ideP -> (Just (ipdCabalFile ideP) == wsActivePackFile ws, ideP))- (wsPackages ws)- let sorted = sortBy (\ (_,f) (_,s) -> compare (ipdPackageId f) (ipdPackageId s)) objs- liftIO $ mapM_ (listStoreAppend (workspaceStore p)) sorted+ liftIO $ treeStoreClear (workspaceStore p)+ let sorted = sortBy (\ f s -> compare (ipdPackageId f) (ipdPackageId s)) $ wsPackages ws+ forest = map (\ ideP ->+ Node (Just (ipdCabalFile ideP) == wsActivePackFile ws, ideP, Nothing)+ (map (\ test -> Node (+ Just (ipdCabalFile ideP) == wsActivePackFile ws &&+ Just test == wsActiveExe ws, ideP, Just test) []) $+ ipdExes ideP ++ ipdTests ideP))+ sorted+ liftIO $ treeStoreInsertForest (workspaceStore p) [] 0 forest when showPane $ displayPane p False- refreshFiles+ refreshFiles+ workspaceTry refreshHLint
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -XScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- -- Module : IDE.PaneGroups@@ -47,6 +47,7 @@ import IDE.Pane.Trace (IDETrace(..)) import IDE.Pane.Workspace (IDEWorkspace(..)) import Control.Monad.IO.Class (MonadIO(..))+import IDE.Pane.WebKit.Output (IDEOutput(..)) showBrowser :: IDEAction showBrowser = do@@ -89,6 +90,7 @@ mbBreakpoints :: Maybe IDEBreakpoints <- getPane mbVariables :: Maybe IDEVariables <- getPane mbTrace :: Maybe IDETrace <- getPane+ mbOutput :: Maybe IDEOutput <- getPane liftIO $ do case mbBreakpoints of Nothing -> return ()@@ -99,6 +101,9 @@ case mbTrace of Nothing -> return () Just idePane -> widgetSetSensitive (getTopWidget idePane) sens+ case mbOutput of+ Nothing -> return ()+ Just idePane -> widgetSetSensitive (getTopWidget idePane) sens showDebugger :: IDEAction showDebugger = do@@ -119,7 +124,8 @@ notebookSetShowTabs upper False getOrBuildPane (Left lowerP) :: IDEM (Maybe IDEBreakpoints) getOrBuildPane (Left lowerP) :: IDEM (Maybe IDEVariables)- getOrBuildPane (Left lowerP) :: IDEM (Maybe IDETrace)+ getOrBuildPane (Left lowerP) :: IDEM (Maybe IDETrace)+ getOrBuildPane (Left lowerP) :: IDEM (Maybe IDEOutput) when (null $ filter (\b -> bufferName b == "_Eval.hs") bufs) $ newTextBuffer upperP "_Eval.hs" Nothing >> return () return ()@@ -128,7 +134,8 @@ let upperP = getBestPanePath (rpp ++ [SplitP TopP]) layout' getOrBuildPane (Left lowerP) :: IDEM (Maybe IDEBreakpoints) getOrBuildPane (Left lowerP) :: IDEM (Maybe IDEVariables)- getOrBuildPane (Left lowerP) :: IDEM (Maybe IDETrace)+ getOrBuildPane (Left lowerP) :: IDEM (Maybe IDETrace)+ getOrBuildPane (Left lowerP) :: IDEM (Maybe IDEOutput) when (null $ filter (\b -> bufferName b == "_Eval.hs") bufs) $ newTextBuffer upperP "_Eval.hs" Nothing >> return () return ()
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -XTypeSynonymInstances -XScopedTypeVariables #-}+{-# LANGUAGE CPP, ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Session@@ -22,9 +22,17 @@ , sessionClosePane , loadSession , loadSessionPrompt+, viewFullScreen+, viewDark ) where +import Prelude hiding (catch) import Graphics.UI.Gtk hiding (showLayout)+#ifdef MIN_VERSION_gtk3+import Graphics.UI.Gtk.General.CssProvider (cssProviderNew, cssProviderLoadFromString)+import Graphics.UI.Gtk.General.StyleContext (styleContextAddProvider)+import Control.Applicative ((<$>))+#endif import System.FilePath import qualified Data.Map as Map import Data.Maybe@@ -40,12 +48,15 @@ import IDE.TextEditor import IDE.Pane.Modules import IDE.Pane.SourceBuffer-import IDE.Pane.Info-import IDE.Pane.Log+import IDE.Pane.Info (InfoState(..), setInfoStyle)+import IDE.Pane.Log (LogState(..)) import IDE.Pane.Preferences import IDE.Pane.PackageFlags import IDE.Pane.Search import IDE.Pane.Grep+import IDE.Pane.HLint+import IDE.Pane.WebKit.Documentation+import IDE.Pane.WebKit.Output import IDE.Pane.Files import IDE.Pane.Breakpoints import IDE.Pane.Trace@@ -54,13 +65,13 @@ import System.Time (getClockTime) import IDE.Package (deactivatePackage) import IDE.Pane.Errors (ErrorsState(..))-import Control.Exception (SomeException(..))+import Control.Exception (catch, SomeException(..)) import IDE.Pane.Workspace (WorkspaceState(..)) import IDE.Workspaces (workspaceOpenThis) import IDE.Completion (setCompletionSize) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad (forM_, forM, when)-+import System.Log.Logger (debugM) -- --------------------------------------------------------------------- -- This needs to be incremented, when the session format changes@@ -81,6 +92,9 @@ | SearchSt SearchState | FilesSt FilesState | GrepSt GrepState+ | HLintSt HLintState+ | DocumentationSt DocumentationState+ | OutputSt OutputState | BreakpointsSt BreakpointsState | TraceSt TraceState | VariablesSt VariablesState@@ -98,6 +112,9 @@ asPaneState s | isJust ((cast s) :: Maybe SearchState) = SearchSt (fromJust $ cast s) asPaneState s | isJust ((cast s) :: Maybe FilesState) = FilesSt (fromJust $ cast s) asPaneState s | isJust ((cast s) :: Maybe GrepState) = GrepSt (fromJust $ cast s)+asPaneState s | isJust ((cast s) :: Maybe HLintState) = HLintSt (fromJust $ cast s)+asPaneState s | isJust ((cast s) :: Maybe DocumentationState) = DocumentationSt (fromJust $ cast s)+asPaneState s | isJust ((cast s) :: Maybe OutputState) = OutputSt (fromJust $ cast s) asPaneState s | isJust ((cast s) :: Maybe BreakpointsState) = BreakpointsSt (fromJust $ cast s) asPaneState s | isJust ((cast s) :: Maybe TraceState) = TraceSt (fromJust $ cast s) asPaneState s | isJust ((cast s) :: Maybe VariablesState) = VariablesSt (fromJust $ cast s)@@ -115,6 +132,9 @@ recover pp (SearchSt p) = recoverState pp p >> return () recover pp (FilesSt p) = recoverState pp p >> return () recover pp (GrepSt p) = recoverState pp p >> return ()+recover pp (HLintSt p) = recoverState pp p >> return ()+recover pp (DocumentationSt p) = recoverState pp p >> return ()+recover pp (OutputSt p) = recoverState pp p >> return () recover pp (BreakpointsSt p) = recoverState pp p >> return () recover pp (TraceSt p) = recoverState pp p >> return () recover pp (VariablesSt p) = recoverState pp p >> return ()@@ -143,6 +163,8 @@ , layoutS :: PaneLayout , population :: [(Maybe PaneState,PanePath)] , windowSize :: (Int,Int)+ , fullScreen :: Bool+ , dark :: Bool , completionSize :: (Int,Int) , workspacePath :: Maybe FilePath , activePaneN :: Maybe String@@ -155,9 +177,58 @@ defaultSession = SessionState { sessionVersion = theSessionVersion , saveTime = ""- , layoutS = TerminalP Map.empty (Just TopP) (-1) Nothing Nothing- , population = []+ , layoutS = VerticalP+ (TerminalP {+ paneGroups = Map.fromList []+ , paneTabs = Just TopP+ , currentPage = -1+ , detachedId = Nothing+ , detachedSize = Nothing})+ (HorizontalP+ (TerminalP {+ paneGroups = Map.fromList [+ ("Debug",HorizontalP+ (TerminalP {+ paneGroups = Map.fromList []+ , paneTabs = Nothing+ , currentPage = -1+ , detachedId = Nothing+ , detachedSize = Nothing})+ (TerminalP {+ paneGroups = Map.fromList []+ , paneTabs = Just TopP+ , currentPage = -1+ , detachedId = Nothing+ , detachedSize = Nothing}) 167)]+ , paneTabs = Just TopP+ , currentPage = 2+ , detachedId = Nothing+ , detachedSize = Nothing})+ (TerminalP {+ paneGroups = Map.fromList []+ , paneTabs = Just TopP+ , currentPage = 1+ , detachedId = Nothing+ , detachedSize = Nothing}) 456) 693+ , population = [ (Just (InfoSt (InfoState Nothing)),[SplitP RightP,SplitP BottomP])+ , (Just (LogSt LogState),[SplitP RightP,SplitP BottomP])+ , (Just (ModulesSt+ (ModulesState 200 (SystemScope,False) (Nothing,Nothing)+ (ExpanderState {+ packageExp = ([],[])+ , packageExpNoBlack = ([],[])+ , packageDExp = ([],[])+ , packageDExpNoBlack = ([],[])+ , workspaceExp = ([],[])+ , workspaceExpNoBlack = ([],[])+ , workspaceDExp = ([],[])+ , workspaceDExpNoBlack = ([],[])+ , systemExp = ([],[])+ , systemExpNoBlack = ([],[])}))),[SplitP RightP,SplitP TopP])+ , (Just (WorkspaceSt WorkspaceState),[SplitP RightP,SplitP BottomP])] , windowSize = (1024,768)+ , fullScreen = False+ , dark = False , completionSize = (750,400) , workspacePath = Nothing , activePaneN = Nothing@@ -179,73 +250,85 @@ sessionDescr :: [FieldDescriptionS SessionState] sessionDescr = [ mkFieldS- (paraName <<<- ParaName "Version of session file format" $ emptyParams)+ (paraName <<<- ParaName ( "Version of session file format") $ emptyParams) (PP.text . show) intParser sessionVersion (\ b a -> a{sessionVersion = b}) , mkFieldS- (paraName <<<- ParaName "Time of storage" $ emptyParams)+ (paraName <<<- ParaName ( "Time of storage") $ emptyParams) (PP.text . show) stringParser saveTime (\ b a -> a{saveTime = b}) , mkFieldS- (paraName <<<- ParaName "Layout" $ emptyParams)+ (paraName <<<- ParaName ( "Layout") $ emptyParams) (PP.text . show) readParser layoutS (\ b a -> a{layoutS = b}) , mkFieldS- (paraName <<<- ParaName "Population" $ emptyParams)+ (paraName <<<- ParaName ( "Population") $ emptyParams) (PP.text . show) readParser population (\ b a -> a{population = b}) , mkFieldS- (paraName <<<- ParaName "Window size" $ emptyParams)+ (paraName <<<- ParaName ( "Window size") $ emptyParams) (PP.text . show) (pairParser intParser) windowSize (\(c,d) a -> a{windowSize = (c,d)}) , mkFieldS- (paraName <<<- ParaName "Completion size" $ emptyParams)+ (paraName <<<- ParaName ( "Full screen") $ emptyParams) (PP.text . show)+ readParser+ fullScreen+ (\b a -> a{fullScreen = b})+ , mkFieldS+ (paraName <<<- ParaName ( "Dark") $ emptyParams)+ (PP.text . show)+ readParser+ dark+ (\b a -> a{dark = b})+ , mkFieldS+ (paraName <<<- ParaName ( "Completion size") $ emptyParams)+ (PP.text . show) (pairParser intParser) completionSize (\(c,d) a -> a{completionSize = (c,d)}) , mkFieldS- (paraName <<<- ParaName "Workspace" $ emptyParams)+ (paraName <<<- ParaName ( "Workspace") $ emptyParams) (PP.text . show) readParser workspacePath (\fp a -> a{workspacePath = fp}) , mkFieldS- (paraName <<<- ParaName "Active pane" $ emptyParams)+ (paraName <<<- ParaName ( "Active pane") $ emptyParams) (PP.text . show) readParser activePaneN (\fp a -> a{activePaneN = fp}) , mkFieldS- (paraName <<<- ParaName "Toolbar visible" $ emptyParams)+ (paraName <<<- ParaName ( "Toolbar visible") $ emptyParams) (PP.text . show) readParser toolbarVisibleS (\fp a -> a{toolbarVisibleS = fp}) , mkFieldS- (paraName <<<- ParaName "FindbarState" $ emptyParams)+ (paraName <<<- ParaName ( "FindbarState") $ emptyParams) (PP.text . show) readParser findbarState (\fp a -> a{findbarState = fp}) , mkFieldS- (paraName <<<- ParaName "Recently opened files" $ emptyParams)+ (paraName <<<- ParaName ( "Recently opened files") $ emptyParams) (PP.text . show) readParser recentOpenedFiles (\fp a -> a{recentOpenedFiles = fp}) , mkFieldS- (paraName <<<- ParaName "Recently opened workspaces" $ emptyParams)+ (paraName <<<- ParaName ( "Recently opened workspaces") $ emptyParams) (PP.text . show) readParser recentOpenedWorksp@@ -269,19 +352,21 @@ saveSessionAs sessionPath mbSecondPath = do forget <- getForgetSession if forget- then ideMessage Normal "Forget this session"+ then ideMessage Normal (__ "Forget this session") else do- sysMessage Normal "Now saving session"+ sysMessage Normal (__ "Now saving session") bufs <- allBuffers case filter (\b -> bufferName b == "_Eval.hs") bufs of- [buf] -> do- ebuf <- getBuffer (sourceView buf)+ [(IDEBuffer {sourceView = sv})] -> do+ ebuf <- getBuffer sv setModified ebuf False _ -> return () wdw <- getMainWindow layout <- mkLayout population <- getPopulation size <- liftIO $ windowGetSize wdw+ fullScreen <- getFullScreenState+ dark <- getDarkState (completionSize,_) <- readIDE completion mbWs <- readIDE workspace activePane' <- getActivePane@@ -300,6 +385,8 @@ , layoutS = layout , population = population , windowSize = size+ , fullScreen = fullScreen+ , dark = dark , completionSize = completionSize , workspacePath = case mbWs of Nothing -> Nothing@@ -318,7 +405,7 @@ window <- getMainWindow response <- liftIO $ do configFolder <- getConfigDir- chooseSaveFile window "Save Session as" (Just configFolder)+ chooseSaveFile window (__ "Save Session as") (Just configFolder) case response of Just fn -> saveSessionAs (if takeExtension fn == leksahSessionFileExtension then fn@@ -332,7 +419,7 @@ response <- liftIO $ do configFolder <- getConfigDir dialog <- fileChooserDialogNew- (Just $ "Select session file")+ (Just $ (__ "Select session file")) (Just window') FileChooserActionOpen [("gtk-cancel"@@ -356,6 +443,7 @@ loadSession :: FilePath -> IDEAction loadSession sessionPath = do+ liftIO $ debugM "leksah" "loadSession" saveSession :: IDEAction deactivatePackage recentFiles' <- readIDE recentFiles@@ -459,18 +547,24 @@ recoverSession :: FilePath -> IDEM (Bool,Bool) recoverSession sessionPath = catchIDE (do+ liftIO $ debugM "leksah" "recoverSession" wdw <- getMainWindow- sessionSt <- liftIO $ readFields sessionPath sessionDescr defaultSession+ sessionSt <- liftIO $ catch+ (readFields sessionPath sessionDescr defaultSession)+ (\(_ :: SomeException) -> return defaultSession) liftIO $ windowSetDefaultSize wdw (fst (windowSize sessionSt))(snd (windowSize sessionSt)) applyLayout (layoutS sessionSt) workspaceOpenThis False (workspacePath sessionSt)+ liftIO $ debugM "leksah" "recoverSession calling populate" populate (population sessionSt)+ liftIO $ debugM "leksah" "recoverSession calling setCurrentPages" setCurrentPages (layoutS sessionSt) when (isJust (activePaneN sessionSt)) $ do mbPane <- mbPaneFromName (fromJust (activePaneN sessionSt)) case mbPane of Nothing -> return () Just (PaneC p) -> makeActive p+ liftIO $ debugM "leksah" "recoverSession setting up toolbars" setFindState ((snd . findbarState) sessionSt) if toolbarVisibleS sessionSt then showToolbar@@ -481,6 +575,11 @@ setCompletionSize (completionSize sessionSt) modifyIDE_ (\ide -> ide{recentFiles = recentOpenedFiles sessionSt, recentWorkspaces = recentOpenedWorksp sessionSt})+ setFullScreenState (fullScreen sessionSt)+ viewFullScreen+ setDarkState (dark sessionSt)+ viewDark+ liftIO $ debugM "leksah" "recoverSession done" return (toolbarVisibleS sessionSt, (fst . findbarState) sessionSt)) (\ (e :: SomeException) -> do sysMessage Normal (show e)@@ -491,7 +590,7 @@ old <- getLayout case old of TerminalP {} -> applyLayout' layoutS []- otherwise -> throwIDE "apply Layout can only be allied to empty Layout"+ otherwise -> throwIDE (__ "apply Layout can only be allied to empty Layout") where applyLayout' (TerminalP groups mbTabPos _ mbDetachedId mbDetachedSize) pp = do forM_ (Map.keys groups) $ \group -> viewNest' pp group@@ -544,6 +643,50 @@ nb <- getNotebook (reverse p) liftIO $ notebookSetCurrentPage nb ind +viewFullScreen :: IDEAction+viewFullScreen = do+ isFullScreen <- getFullScreenState+ mbWindow <- getActiveWindow+ case (mbWindow, isFullScreen) of+ (Nothing, _) -> return ()+ (Just window, True) -> liftIO $ windowFullscreen window+ (Just window, False) -> liftIO $ windowUnfullscreen window++viewDark :: IDEAction+viewDark = do+ getDarkState >>= setDark++#ifdef MIN_VERSION_gtk3+getActiveSettings :: PaneMonad alpha => alpha (Maybe Settings)+getActiveSettings = do+ mbScreen <- getActiveScreen+ case mbScreen of+ Nothing -> return Nothing+ Just screen -> liftIO $ Just <$> settingsGetForScreen screen+#endif++setDark :: Bool -> IDEM ()+setDark dark = do+ setInfoStyle+ prefs <- readIDE prefs+ buffers <- allBuffers+ mapM_ (\(IDEBuffer {sourceView = sv}) -> do+ ebuf <- getBuffer sv+ setStyle dark ebuf (case sourceStyle prefs of+ (False,_) -> Nothing+ (True,s) -> Just s)) buffers+#ifdef MIN_VERSION_gtk3+ mbSettings <- getActiveSettings+ case mbSettings of+ Just settings -> liftIO $ settingsSetLongProperty+ settings+ "gtk-application-prefer-dark-theme"+ (if dark then 1 else 0)+ "Leksah"+ Nothing -> return ()+#else+ return ()+#endif
@@ -48,7 +48,7 @@ '^','|','-','~','\'','"'] notAfterOp = notBeforeOp -keystrokeCandy :: CandyTable -> Maybe Char -> EditorBuffer -> (String -> Bool) -> IDEM ()+keystrokeCandy :: TextEditor editor => CandyTable -> Maybe Char -> EditorBuffer editor -> (String -> Bool) -> IDEM () keystrokeCandy (CT(transformTable,_)) mbc ebuf editInCommentOrString = do cursorMark <- getInsertMark ebuf endIter <- getIterAtMark ebuf cursorMark@@ -65,7 +65,7 @@ unless block $ replace mbc2 cursorMark slice offset transformTable where- replace :: Maybe Char -> EditorMark -> String -> Int -> [(Bool,String,String)] -> IDEM ()+ -- replace :: Maybe Char -> m -> String -> Int -> [(Bool,String,String)] -> IDEM () replace mbAfterChar cursorMark match offset list = replace' list where replace' [] = return ()@@ -91,7 +91,7 @@ endNotUndoableAction ebuf else replace mbAfterChar cursorMark match offset rest -transformToCandy :: CandyTable -> EditorBuffer -> (String -> Bool) -> IDEM ()+transformToCandy :: TextEditor editor => CandyTable -> EditorBuffer editor -> (String -> Bool) -> IDEM () transformToCandy (CT(transformTable,_)) ebuf editInCommentOrString = do beginUserAction ebuf modified <- getModified ebuf@@ -100,7 +100,7 @@ endUserAction ebuf -replaceTo :: EditorBuffer -> (Bool,String,String) -> Int -> (String -> Bool) -> IDEM ()+replaceTo :: TextEditor editor => EditorBuffer editor -> (Bool,String,String) -> Int -> (String -> Bool) -> IDEM () replaceTo buf (isOp,from,to) offset editInCommentOrString = replaceTo' offset where replaceTo' offset = do@@ -149,7 +149,7 @@ return () replaceTo' (stOff + 1) -transformFromCandy :: CandyTable -> EditorBuffer -> IDEM ()+transformFromCandy :: TextEditor editor => CandyTable -> EditorBuffer editor -> IDEM () transformFromCandy (CT(_,transformTableBack)) ebuf = do beginUserAction ebuf modified <- getModified ebuf@@ -157,7 +157,7 @@ endUserAction ebuf setModified ebuf modified -getCandylessText :: CandyTable -> EditorBuffer -> IDEM String+getCandylessText :: TextEditor editor => CandyTable -> EditorBuffer editor -> IDEM String getCandylessText (CT(_,transformTableBack)) ebuf = do i1 <- getStartIter ebuf i2 <- getEndIter ebuf@@ -169,7 +169,7 @@ text2 <- getText workBuffer i1 i2 True return text2 -getCandylessPart :: CandyTable -> EditorBuffer -> EditorIter -> EditorIter -> IDEM String+getCandylessPart :: TextEditor editor => CandyTable -> EditorBuffer editor -> EditorIter editor -> EditorIter editor -> IDEM String getCandylessPart (CT(_,transformTableBack)) ebuf i1 i2 = do text1 <- getText ebuf i1 i2 True workBuffer <- simpleGtkBuffer text1@@ -188,7 +188,7 @@ text2 <- getText workBuffer i1 i2 True return text2 -positionFromCandy :: CandyTable -> EditorBuffer -> (Int,Int) -> IDEM (Int,Int)+positionFromCandy :: TextEditor editor => CandyTable -> EditorBuffer editor -> (Int,Int) -> IDEM (Int,Int) positionFromCandy candyTable ebuf (line,column) = do i1 <- getIterAtLine ebuf (max 0 (line - 1)) i2 <- forwardToLineEndC i1@@ -201,7 +201,7 @@ columnNew <- getLineOffset i4 return (line,columnNew) -positionToCandy :: CandyTable -> EditorBuffer -> (Int,Int) -> IDEM (Int,Int)+positionToCandy :: TextEditor editor => CandyTable -> EditorBuffer editor -> (Int,Int) -> IDEM (Int,Int) positionToCandy candyTable ebuf (line,column) = do i1 <- getIterAtLine ebuf (max 0 (line - 1)) i2 <- forwardToLineEndC i1@@ -215,7 +215,7 @@ columnNew <- getLineOffset i4 return (line,columnNew) -replaceFrom :: EditorBuffer -> (String,String,Int) -> Int -> IDEM ()+replaceFrom :: TextEditor editor => EditorBuffer editor -> (String,String,Int) -> Int -> IDEM () replaceFrom buf (to,from,spaces) offset = replaceFrom' offset where replaceFrom' offset = do
@@ -17,20 +17,16 @@ , buildStatusbar ) where import IDE.Core.State- (getMainWindow,- widgetGet,- PaneMonad(..),- IDEAction(..),- StatusbarCompartment(..))+ (postAsyncIDE, getMainWindow, widgetGet, PaneMonad(..),+ IDEAction(..), StatusbarCompartment(..)) import Graphics.UI.Gtk- (windowSetTitle,+ (windowTitle, castToStatusbar, Statusbar(..), boxPackStart, hBoxNew, widgetSetSizeRequest, widgetSetName,- statusbarSetHasResizeGrip, statusbarNew, HBox(..), statusbarPush,@@ -42,7 +38,9 @@ IconSize(..), Image, castToImage,- imageSetFromStock+ imageSetFromStock,+ set,+ AttrOp(..) ) import Graphics.UI.Frame.Panes (IDEPane(..), paneName) import Text.Printf (printf)@@ -50,7 +48,7 @@ changeStatusbar :: [StatusbarCompartment] -> IDEAction-changeStatusbar = mapM_ changeStatusbar'+changeStatusbar = postAsyncIDE . mapM_ changeStatusbar' where changeStatusbar' (CompartmentCommand accStr) = do sb <- getSBSpecialKeys@@ -68,7 +66,7 @@ liftIO $ statusbarPush sb 1 "" return () changeStatusbar' (CompartmentState string) = do- let realStr = if '\n' `elem` string then (head $ lines string) ++ " ..." else string+ let realStr = if '\n' `elem` string then head (lines string) ++ " ..." else string sb <- getSBErrors liftIO $ statusbarPop sb 1 liftIO $ statusbarPush sb 1 realStr@@ -78,7 +76,7 @@ window <- getMainWindow liftIO $ statusbarPop sb 1 liftIO $ statusbarPush sb 1 string- liftIO $ windowSetTitle window $ "Leksah: " ++ string+ liftIO $ set window [ windowTitle := "Leksah: " ++ string ] return () changeStatusbar' (CompartmentBufferPos (line,col)) = do sb <- getStatusbarLC@@ -102,37 +100,28 @@ buildStatusbar :: IO HBox buildStatusbar = do- sb <- statusbarNew- statusbarSetHasResizeGrip sb False- sblk <- statusbarNew widgetSetName sblk "statusBarSpecialKeys"- statusbarSetHasResizeGrip sblk False widgetSetSizeRequest sblk 150 (-1) sbap <- statusbarNew widgetSetName sbap "statusBarActivePane"- statusbarSetHasResizeGrip sbap False widgetSetSizeRequest sbap 150 (-1) sbapr <- statusbarNew widgetSetName sbapr "statusBarActiveProject"- statusbarSetHasResizeGrip sbapr False widgetSetSizeRequest sbapr 150 (-1) sbe <- statusbarNew widgetSetName sbe "statusBarErrors"- statusbarSetHasResizeGrip sbe False widgetSetSizeRequest sbe 150 (-1) sblc <- statusbarNew widgetSetName sblc "statusBarLineColumn"- statusbarSetHasResizeGrip sblc True widgetSetSizeRequest sblc 150 (-1) sbio <- statusbarNew widgetSetName sbio "statusBarInsertOverwrite"- statusbarSetHasResizeGrip sbio False widgetSetSizeRequest sbio 60 (-1) buildImage <- imageNewFromStock "ide_empty" IconSizeMenu
@@ -1,3 +1,5 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TypeFamilies #-} ----------------------------------------------------------------------------- -- -- Module : IDE.SymbolNavigation@@ -17,318 +19,137 @@ mapControlCommand ) where -import Data.List-import Data.Ord-import Data.Maybe-import Data.Monoid-import Data.IORef-import IDE.Core.Types-import IDE.Core.CTypes-import IDE.Core.State-import IDE.Metainfo.Provider-import IDE.Utils.GUIUtils-import qualified Graphics.UI.Gtk.Gdk.Events as Gdk-import Graphics.UI.Gtk.Gdk.Cursor import Graphics.UI.Gtk-import Graphics.UI.Frame.ViewFrame-import qualified Data.Set as Set-import Control.Applicative-import Distribution.ModuleName-import qualified Data.Text as T-import qualified Data.ByteString as BS-import qualified Data.ByteString.Internal as BS-import qualified Graphics.UI.Gtk.Multiline.TextBuffer-import Graphics.UI.Gtk.SourceView.SourceGutter-import Graphics.UI.Gtk.SourceView-import qualified Graphics.UI.Gtk.Multiline.TextView-import qualified Graphics.UI.Gtk.Scrolling.ScrolledWindow+ (cursorNew, eventRootCoordinates, widgetAddEvents,+ buttonPressEvent, eventIsHint, motionNotifyEvent, eventModifier,+ drawWindowGetPointer, eventCoordinates, EventM, DrawWindow,+ pointerGrab, screenGetDefault,+ widgetGetAllocation, scrolledWindowGetVAdjustment,+ adjustmentGetValue, scrolledWindowGetHAdjustment, pointerUngrab,+ eventTime, leaveNotifyEvent, ScrolledWindow, Modifier(..),+ Rectangle(..), EventMask(..), Underline(..),+#ifdef MIN_VERSION_gtk3+ widgetGetWindow+#else+ widgetGetDrawWindow+#endif+ )+import System.Glib.Signals (on)+import IDE.TextEditor (TextEditor(..), EditorView(..), EditorIter(..))+import IDE.Core.Types (IDEM)+import Graphics.UI.Editor.Basics (Connection(..), Connection) import Control.Monad.IO.Class (MonadIO(..))+import Graphics.UI.Gtk.Gdk.Cursor (CursorType(..))+import IDE.Utils.GUIUtils (mapControlCommand)+import Data.IORef (writeIORef, readIORef, newIORef) import Control.Monad (when)-import Control.Monad.Trans.Reader (ask)+import Data.Maybe (fromJust, isJust)+import Control.Monad.Reader.Class (MonadReader(..))+import IDE.Core.State (reflectIDE)+import Control.Applicative ((<$>)) data Locality = LocalityPackage | LocalityWorkspace | LocalitySystem -- in which category symbol is located deriving (Ord,Eq,Show) -createHyperLinkSupport ::- SourceView -> -- ^ source buffer view- ScrolledWindow -> -- ^ container window- (Bool -> Bool -> TextIter -> IO (TextIter, TextIter)) -> -- ^ identifiermapper (bools=control,shift)- (Bool -> Bool -> String -> IO ()) -> -- ^ click handler- IO [Connection]+-- |+createHyperLinkSupport+ :: TextEditor editor+ => EditorView editor -- ^ source buffer view+ -> ScrolledWindow -- ^ container window+ -> (Bool -> Bool -> EditorIter editor -> IDEM (EditorIter editor, EditorIter editor)) -- ^ identifiermapper (bools=control,shift)+ -> (Bool -> Bool -> String -> IDEM ()) -- ^ click handler+ -> IDEM [Connection] createHyperLinkSupport sv sw identifierMapper clickHandler = do- let tv = castToTextView sv- tvb <- castToTextBuffer <$> get tv textViewBuffer :: IO TextBuffer- let myAttr = textBufferTagTable :: ReadWriteAttr TextBuffer TextTagTable TextTagTable- ttt <- castToTextTagTable <$> (get tvb myAttr) :: IO TextTagTable- -- textBuffer- noUnderline <- textTagNew Nothing- set noUnderline [ textTagUnderline := UnderlineNone, textTagUnderlineSet := True ]- underline <- textTagNew Nothing- set underline [ textTagUnderline := UnderlineSingle, textTagUnderlineSet := True ]- textTagTableAdd ttt noUnderline- textTagTableAdd ttt underline- cursor <- cursorNew Hand2- cursorDef <- cursorNew Arrow+ tv <- getEditorWidget sv+ tvb <- getBuffer sv+ ttt <- getTagTable tvb+ linkTag <- newTag ttt "link"+ underline linkTag UnderlineSingle+ cursor <- liftIO $ cursorNew Hand2 - id1 <- sw `onLeaveNotify` \e -> do- pointerUngrab (Gdk.eventTime e)+ id1 <- liftIO $ sw `on` leaveNotifyEvent $ do+ eventTime >>= (liftIO . pointerUngrab) return True - let moveOrClick e click = do- sx <- scrolledWindowGetHAdjustment sw >>= adjustmentGetValue- sy <- scrolledWindowGetVAdjustment sw >>= adjustmentGetValue+ let moveOrClick eventX eventY mods eventTime click = do+ sx <- liftIO $ scrolledWindowGetHAdjustment sw >>= adjustmentGetValue+ sy <- liftIO $ scrolledWindowGetVAdjustment sw >>= adjustmentGetValue - let ex = Gdk.eventX e + sx- ey = Gdk.eventY e + sy- mods = Gdk.eventModifier e- ctrlPressed = (mapControlCommand Gdk.Control) `elem` mods- shiftPressed = Gdk.Shift `elem` mods- iter <- textViewGetIterAtLocation tv (round ex) (round ey)- (szx, szy) <- widgetGetSize sw- if Gdk.eventX e < 0 || Gdk.eventY e < 0- || round(Gdk.eventX e) > szx || round(Gdk.eventY e) > szy then do- pointerUngrab (Gdk.eventTime e)+ let ex = eventX + sx+ ey = eventY + sy+ ctrlPressed = (mapControlCommand Control) `elem` mods+ shiftPressed = Shift `elem` mods+ iter <- getIterAtLocation sv (round ex) (round ey)+ (Rectangle _ _ szx szy) <- liftIO $ widgetGetAllocation sw+ if eventX < 0 || eventY < 0+ || round eventX > szx || round eventY > szy then do+ liftIO $ pointerUngrab eventTime return True else do (beg, en) <- identifierMapper ctrlPressed shiftPressed iter- slice <- liftIO $ textBufferGetSlice tvb beg en True- startIter <- textBufferGetStartIter tvb- endIter <- textBufferGetEndIter tvb- textBufferRemoveTag tvb underline startIter endIter- offs <- textIterGetLineOffset beg- offsc <- textIterGetLineOffset iter+ slice <- getSlice tvb beg en True+ removeTagByName tvb "link"+ offs <- getLineOffset beg+ offsc <- getLineOffset iter if (length slice > 1) then do if (click) then do- pointerUngrab (Gdk.eventTime e)+ liftIO $ pointerUngrab eventTime clickHandler ctrlPressed shiftPressed slice else do- textBufferApplyTag tvb underline beg en- Just screen <- screenGetDefault- dw <- widgetGetDrawWindow tv- pointerGrab dw False [PointerMotionMask,ButtonPressMask,LeaveNotifyMask] (Nothing :: Maybe DrawWindow) (Just cursor) (Gdk.eventTime e)- return ()- return ()+ applyTagByName tvb "link" beg en+ Just screen <- liftIO $ screenGetDefault+#ifdef MIN_VERSION_gtk3+ mbDW <- liftIO $ widgetGetWindow tv+#else+ mbDW <- liftIO $ Just <$> widgetGetDrawWindow tv+#endif+ case mbDW of+ Nothing -> return ()+ Just dw -> do+ liftIO $ pointerGrab dw False [PointerMotionMask,ButtonPressMask,LeaveNotifyMask] (Nothing :: Maybe DrawWindow) (Just cursor) eventTime+ return () else do- pointerUngrab (Gdk.eventTime e)+ liftIO $ pointerUngrab eventTime return ()- return True;- lineNumberBugFix <- newIORef Nothing- let fixBugWithX e = do- dw <- widgetGetDrawWindow tv- ptr <- drawWindowGetPointer dw- let hasNoControlModifier e = not $ (mapControlCommand Gdk.Control) `elem` (Gdk.eventModifier e)- let- eventIsHintSafe (e@Gdk.Motion {}) = Gdk.eventIsHint e- eventIsHintSafe _ = False- case ptr of- Just (_, ptrx, _, _) -> do- lnbf <- readIORef lineNumberBugFix- -- print ("ishint?, adjusted, event.x, ptr.x, adjustment,hasControl?",eventIsHintSafe e,ptrx - fromMaybe (-1000) lnbf , Gdk.eventX e, ptrx, lnbf, hasNoControlModifier e)- when (eventIsHintSafe e && hasNoControlModifier e) $ do- -- get difference between event X and pointer x- -- event X is in coordinates of sourceView text- -- pointer X is in coordinates of window (remember "show line numbers" ?)- writeIORef lineNumberBugFix $ Just (ptrx - round (Gdk.eventX e)) -- captured difference- -- When control key is pressed, mostly NON-HINT events come,- -- GTK gives (mistakenly?) X in window coordinates in such cases- let nx = if (isJust lnbf && not (eventIsHintSafe e))- then fromIntegral $ ptrx - fromJust lnbf -- translate X back- else Gdk.eventX e- return $ e { Gdk.eventX = nx}- _ -> return e- id2 <- onMotionNotify sw True $ \e -> do- ne <- fixBugWithX e- moveOrClick ne False+ return True+ lineNumberBugFix <- liftIO $ newIORef Nothing+ let fixBugWithX mods isHint (eventX, eventY) ptrx = do+ let hasNoControlModifier = not $ (mapControlCommand Control) `elem` mods+ lnbf <- readIORef lineNumberBugFix+ -- print ("ishint?, adjusted, event.x, ptr.x, adjustment,hasControl?",isHint,ptrx - fromMaybe (-1000) lnbf , eventX, ptrx, lnbf, hasNoControlModifier)+ when (isHint && hasNoControlModifier) $ do+ -- get difference between event X and pointer x+ -- event X is in coordinates of sourceView text+ -- pointer X is in coordinates of window (remember "show line numbers" ?)+ liftIO $ writeIORef lineNumberBugFix $ Just (ptrx - eventX) -- captured difference+ -- When control key is pressed, mostly NON-HINT events come,+ -- GTK gives (mistakenly?) X in window coordinates in such cases+ let nx = if (isJust lnbf && not isHint)+ then ptrx - fromJust lnbf -- translate X back+ else eventX+ return (nx, eventY)+ ideR <- ask+ id2 <- liftIO $ sw `on` motionNotifyEvent $ do+ isHint <- eventIsHint+ eventTime <- eventTime+ mods <- eventModifier+ (oldX, oldY) <- eventCoordinates+ (rootX, _) <- eventRootCoordinates+ (eventX, eventY) <- liftIO $ fixBugWithX mods isHint (oldX, oldY) rootX+ liftIO $ do+ -- print ("move adjustment: isHint, old, new root", isHint, eventX, oldX, rootX)+ (`reflectIDE` ideR) $ moveOrClick eventX eventY mods eventTime False return True- id3 <- onButtonPress sw $ \e -> do--- print ("button press")- ne <- fixBugWithX e--- print ("click adjustment: old, new", Gdk.eventX e, Gdk.eventX ne)- moveOrClick ne True-- return $ map ConnectC [id1,id2,id3]--{---launchSymbolNavigationDialog_ :: String -> (Descr -> IDEM ()) -> IDEM ()-launchSymbolNavigationDialog_ txt act = do- dia <- liftIO $ dialogNew- win <- getMainWindow- ideR <- ask- wi <- getSystemInfo- wiW <- getWorkspaceInfo- wiP <- getPackageInfo- case (wi,wiW,wiP) of- (Just (GenScopeC (PackScope _ syms)),- Just (GenScopeC (PackScope _ symsW), GenScopeC (PackScope _ _ )),- Just (GenScopeC (PackScope _ symsP), GenScopeC (PackScope _ _ ))) -> do- let symbolsT = map T.pack $ Set.toList $ (symbols syms `Set.union` symbols symsP)- liftIO $ do- print "============================"- print $ symLookup "launchAutoCompleteDialog" symsP- windowSetTransientFor dia win- windowSetTitle dia "Go to Symbol"- upper <- dialogGetUpper dia- lower <- dialogGetActionArea dia- vb <- vBoxNew False 0- boxPackStart upper vb PackNatural 7- en <- entryNew- store <- listStoreNew []- tv <- treeViewNewWithModel store- treeViewSetFixedHeightMode tv True- treeViewSetHoverExpand tv True- mapM_ (\(i,s) -> do- col <- treeViewColumnNew- renderer <- cellRendererTextNew- treeViewColumnSetSizing col TreeViewColumnFixed- treeViewColumnSetResizable col True- treeViewColumnSetFixedWidth col ([200,300,200] !! i)- treeViewAppendColumn tv col- cellLayoutPackStart col renderer True-- cellLayoutSetAttributes col renderer store- $ \(locality, _, ss) -> [cellText := replaceCR $ ss !! i] ++- case (i, locality) of- (2, _) -> [cellTextScale := 0.8, cellTextScaleSet := True]- (0, LocalityWorkspace) ->- [cellTextStyle := StyleItalic, cellTextStyleSet := True, cellTextWeightSet := False, cellTextScaleSet := False]- (0, LocalityPackage) ->- [cellTextWeight := 1000, cellTextWeightSet := True, cellTextStyleSet := False, cellTextScaleSet := False]- _ -> [cellTextStyleSet := False, cellTextWeightSet := False, cellTextScaleSet := False]-- treeViewColumnSetTitle col s) $ zip [0..] ["symbol","module","type/kind"]-- boxPackEnd vb tv PackNatural 7- boxPackEnd vb en PackNatural 0- widgetSetSizeRequest tv 900 600-- bb <- hButtonBoxNew- closeB <- buttonNewFromStock "gtk-cancel"- okB <- buttonNewFromStock "gtk-ok"- okB `onClicked` do- dialogResponse dia ResponseOk- widgetHideAll dia- closeB `onClicked` do- dialogResponse dia ResponseCancel- widgetHideAll dia- boxPackEnd bb closeB PackNatural 0- boxPackEnd bb okB PackNatural 0- boxPackStart lower bb PackNatural 7- set okB [widgetCanDefault := True]- buttonSetLabel okB "Goto"- widgetGrabDefault okB- widgetShowAll dia- entrySetText en txt- let getSymbolLocality symbolName = case (symLookup symbolName symsP, symLookup symbolName symsW) of- ((_:_),_) -> LocalityPackage- (_,(_:_)) -> LocalityWorkspace- _ -> LocalitySystem- let- compareLocalityThenLength (Real d1 ) (Real d2) =- let- desc1 = dscName' d1- desc2 = dscName' d2- l1 = getSymbolLocality $ desc1- l2 = getSymbolLocality $ desc2- lcomp = compare l1 l2- in if lcomp == EQ- then compare (length desc1) (length desc2)- else lcomp- compareLocalityThenLength _ _ = error "compareLocalityThenLength: not real desciptions"- let updateList = do- txt <- T.pack <$> entryGetText en- let ttxt = T.toLower txt- let symz_ = take 50- $ sortBy (comparing getSymbolLocality)- $ map (T.unpack)- $ filter (matchCamelCase (txt :: T.Text) (ttxt:: T.Text)) (symbolsT ::[T.Text])- let symz = sortBy compareLocalityThenLength- $ filter (not . isReexported)- $ concatMap (\sym -> symLookup sym syms `mappend` symLookup sym symsP) symz_- listStoreClear store- mapM (\descr_ -> do- case descr_ of- Real descr -> do- let modn = case dscMbModu' descr of- Just mn -> intercalate"." $ components $ modu mn- Nothing -> "?"- let symbolName = dscName' descr- let typeDesc = map BS.w2c $ BS.unpack $ fromMaybe BS.empty $ dscMbTypeStr' descr- listStoreAppend store (getSymbolLocality symbolName, descr_, [symbolName,modn,take 80 typeDesc])--- treeVie- return ()- _ -> return ()- ) symz- when (length symz > 0) $ do- treeViewSetCursor tv [0] Nothing- return ()- print ("symz found: ",length symz)- return ()- let gotoSelectedSymbol = do- cursor <- treeViewGetCursor tv- case cursor of- ([pos],_) -> do- (_,descr,_) <- listStoreGetValue store pos- dialogResponse dia ResponseCancel- widgetHideAll dia- liftIO $ reflectIDE (act descr) ideR- return ()- _ -> return ()-- updateList- let modifyTreeViewCursor :: (Int -> Int) -> IO ()- modifyTreeViewCursor op = do- cur <- treeViewGetCursor tv- case cur of- ([pos],_) -> do- let npos = op pos- storeSize <- listStoreGetSize store- let npos' = if npos < 0 then 0 else if npos >= storeSize then storeSize-1 else npos- when (npos < storeSize) $ do- treeViewSetCursor tv [npos'] Nothing- return ()- _ -> return ()- onEditableChanged en $ do- updateList- return ()- en `onKeyPress` \e -> do- case Gdk.eventKeyName e of- "Escape" -> do- dialogResponse dia ResponseCancel- widgetHideAll dia- return True- "Up" -> do- modifyTreeViewCursor (\x -> x-1)- return True- "Down" -> do- modifyTreeViewCursor (\x -> x+1)- return True- "Return" -> do- gotoSelectedSymbol- return True- nm -> do- print nm- return False- resp <- dialogRun dia- return ()- _ -> return ()- return ()----- this will be camel case one day-matchCamelCase :: T.Text -> T.Text -> T.Text -> Bool-matchCamelCase search lsearch item =- search `T.isInfixOf` item || (lsearch `T.isInfixOf` (T.toLower item))--compareLength :: [a] -> [a] -> Ordering-compareLength s1 s2 = compare (length s1) (length s2)--compareLocality :: Locality -> Locality -> Ordering-compareLocality s1 s2 = compare s1 s2+ id3 <- liftIO $ sw `on` buttonPressEvent $ do+ eventTime <- eventTime+ mods <- eventModifier+ -- liftIO $ print ("button press")+ (oldX, oldY) <- eventCoordinates+ (rootX, _) <- eventRootCoordinates+ (eventX, eventY) <- liftIO $ fixBugWithX mods False (oldX, oldY) rootX+ -- liftIO $ print ("click adjustment: old, new", eventX, oldX)+ liftIO $ (`reflectIDE` ideR) $ moveOrClick eventX eventY mods eventTime True -replaceCR [] = []-replaceCR ('\n':ss) = ' ':(replaceCR ss)-replaceCR ('\r':ss) = ' ':(replaceCR ss)-replaceCR (s:ss) = s:(replaceCR ss)+ return $ [ConnectC id1, ConnectC id2, ConnectC id3] ---}
@@ -14,1269 +14,39 @@ ----------------------------------------------------------------------------- module IDE.TextEditor (---- Data Types- EditorBuffer(..)-, EditorView(..)-, EditorMark(..)-, EditorIter(..)-, EditorTagTable(..)-, EditorTag(..)---- Buffer-, newGtkBuffer-, newYiBuffer-, simpleGtkBuffer-, applyTagByName-, beginNotUndoableAction-, beginUserAction-, canRedo-, canUndo-, copyClipboard-, createMark-, cutClipboard-, delete-, deleteSelection-, endNotUndoableAction-, endUserAction-, getEndIter-, getInsertMark-, getInsertIter-, getIterAtLine-, getIterAtMark-, getIterAtOffset-, getLineCount-, getModified-, getSelectionBoundMark-, getSelectionBounds-, getSlice-, getStartIter-, getTagTable-, getText-, hasSelection-, insert-, moveMark-, newView-, pasteClipboard-, placeCursor-, redo-, removeTagByName-, selectRange-, setModified-, setStyle-, setText-, undo---- View-, bufferToWindowCoords-, drawTabs-, getBuffer-, getDrawWindow-, getIterLocation-, getOverwrite-, getScrolledWindow-, grabFocus-, scrollToMark-, scrollToIter-, setFont-, setIndentWidth-, setWrapMode-, setRightMargin-, setShowLineNumbers-, setTabWidth---- Iterator-, backwardCharC-, backwardFindCharC-, backwardWordStartC-, backwardToLineStartC-, endsWord-, forwardCharC-, forwardCharsC-, forwardFindCharC-, forwardToLineEndC-, forwardWordEndC-, forwardSearch-, getChar-, getCharsInLine-, getLine-, getLineOffset-, getOffset-, isStart-, isEnd-, iterEqual-, startsLine-, atEnd-, atLine-, atLineOffset-, atOffset-, atStart---- Tag Table-, newTag-, lookupTag---- Tag-, background-, underline---- Events-, afterFocusIn-, afterModifiedChanged-, afterMoveCursor-, afterToggleOverwrite-, onButtonPress-, onButtonRelease-, onCompletion-, onKeyPress-, onKeyRelease-, onLookupInfo-, onMotionNotify-, onLeaveNotify-, onPopulatePopup-) where--import Prelude hiding(getChar, getLine)-import Data.Char (isAlphaNum, isSymbol)-import Data.Maybe (fromJust, maybeToList)-import Data.IORef-import Control.Monad (when)-import Control.Applicative ((<$>))--import qualified Graphics.UI.Gtk as Gtk hiding(afterToggleOverwrite)-import qualified Graphics.UI.Gtk.SourceView as Gtk-import Graphics.UI.Gtk.Multiline.TextTagTable-import qualified Graphics.UI.Gtk.Multiline.TextBuffer as Gtk-import qualified Graphics.UI.Gtk.Multiline.TextView as Gtk-import qualified Graphics.UI.Gtk.Scrolling.ScrolledWindow-import Graphics.UI.Gtk.Multiline.TextTag-import Graphics.UI.Gtk.Gdk.Cursor---import Graphics.Rendering.Pango-import System.Glib.Attributes-import System.Glib.MainLoop-import qualified Graphics.UI.Gtk.Multiline.TextView as Gtk-import qualified Graphics.UI.Gtk.Gdk.Events as GtkOld-import System.Glib.Attributes (AttrOp(..))-import System.GIO.File.ContentType (contentTypeGuess)--#ifdef LEKSAH_WITH_YI-import qualified Yi as Yi hiding(withBuffer)-import qualified Yi.UI.Pango.Control as Yi-import qualified Yi.Keymap.Cua as Yi-import Data.Time (getCurrentTime)-import Control.Monad (unless)-#endif--import IDE.Core.State-import IDE.Utils.GUIUtils(controlIsPressed)-import Paths_leksah (getDataDir)-import System.FilePath ((</>))-import Control.Monad.IO.Class (liftIO)-import Control.Monad.Trans.Reader (ask)-import qualified Control.Monad.Reader as Gtk (liftIO)---- Data types-data EditorBuffer = GtkEditorBuffer Gtk.SourceBuffer-#ifdef LEKSAH_WITH_YI- | YiEditorBuffer Yi.Buffer-#endif--data EditorView = GtkEditorView Gtk.SourceView-#ifdef LEKSAH_WITH_YI- | YiEditorView Yi.View-#endif--data EditorMark = GtkEditorMark Gtk.TextMark-#ifdef LEKSAH_WITH_YI- | YiEditorMark Yi.Mark-#endif--data EditorIter = GtkEditorIter Gtk.TextIter-#ifdef LEKSAH_WITH_YI- | YiEditorIter Yi.Iter-#endif--data EditorTagTable = GtkEditorTagTable Gtk.TextTagTable-#ifdef LEKSAH_WITH_YI- | YiEditorTagTable-#endif--data EditorTag = GtkEditorTag Gtk.TextTag-#ifdef LEKSAH_WITH_YI- | YiEditorTag-#endif---#ifdef LEKSAH_WITH_YI-withYiBuffer' :: Yi.BufferRef -> Yi.BufferM a -> IDEM a-withYiBuffer' b f = liftYi $ Yi.liftEditor $ Yi.withGivenBuffer0 b f--withYiBuffer :: Yi.Buffer -> Yi.BufferM a -> IDEM a-withYiBuffer b f = withYiBuffer' (Yi.fBufRef b) f--mkYiIter' :: Yi.BufferRef -> Yi.Point -> EditorIter-mkYiIter' b p = YiEditorIter $ Yi.Iter b p--mkYiIter :: Yi.Buffer -> Yi.Point -> EditorIter-mkYiIter b p = mkYiIter' (Yi.fBufRef b) p--iterFromYiBuffer' :: Yi.BufferRef -> Yi.BufferM Yi.Point -> IDEM EditorIter-iterFromYiBuffer' b f = mkYiIter' b <$> withYiBuffer' b f--iterFromYiBuffer :: Yi.Buffer -> Yi.BufferM Yi.Point -> IDEM EditorIter-iterFromYiBuffer b f = iterFromYiBuffer' (Yi.fBufRef b) f-#endif---- Buffer-newGtkBuffer :: Maybe FilePath -> String -> IDEM EditorBuffer-newGtkBuffer mbFilename contents = liftIO $ do- lm <- Gtk.sourceLanguageManagerNew- dataDir <- getDataDir- oldPath <- Gtk.sourceLanguageManagerGetSearchPath lm- Gtk.sourceLanguageManagerSetSearchPath lm (Just $ (dataDir </> "language-specs") : oldPath)- mbLang <- case mbFilename of- Just filename -> do- guess <- contentTypeGuess filename contents (length contents)- Gtk.sourceLanguageManagerGuessLanguage lm (Just filename) $- case guess of- (True, _) -> Nothing- (False, t) -> Just t- Nothing -> Gtk.sourceLanguageManagerGuessLanguage lm Nothing (Just "text/x-haskell")- buffer <- case mbLang of- Just sLang -> Gtk.sourceBufferNewWithLanguage sLang- Nothing -> Gtk.sourceBufferNew Nothing- Gtk.sourceBufferSetMaxUndoLevels buffer (-1)- Gtk.sourceBufferBeginNotUndoableAction buffer- Gtk.textBufferSetText buffer contents- Gtk.sourceBufferEndNotUndoableAction buffer- return $ GtkEditorBuffer buffer---- Buffer-simpleGtkBuffer :: String -> IDEM EditorBuffer-simpleGtkBuffer contents = liftIO $ do- buffer <- Gtk.sourceBufferNew Nothing- Gtk.textBufferSetText buffer contents- return $ GtkEditorBuffer buffer---newYiBuffer :: Maybe FilePath -> String -> IDEM EditorBuffer-#ifdef LEKSAH_WITH_YI-newYiBuffer mbFilename contents = liftYiControl $ do- let (filename, id) = case mbFilename of- Just fn -> (fn, Right fn)- Nothing -> ("Unknown.hs", Left "*leksah*")- buffer <- Yi.newBuffer id contents- Yi.setBufferMode filename buffer- return $ YiEditorBuffer buffer-#else-newYiBuffer = newGtkBuffer-#endif--applyTagByName :: EditorBuffer- -> String- -> EditorIter- -> EditorIter- -> IDEM ()-applyTagByName (GtkEditorBuffer sb) name (GtkEditorIter first) (GtkEditorIter last) = liftIO $- Gtk.textBufferApplyTagByName sb name first last-#ifdef LEKSAH_WITH_YI-applyTagByName (YiEditorBuffer fb) name (YiEditorIter first) (YiEditorIter last) = return () -- TODO-applyTagByName _ _ _ _ = liftIO $ fail "Mismatching TextEditor types in createMark"-#endif--beginNotUndoableAction :: EditorBuffer -> IDEM ()-beginNotUndoableAction (GtkEditorBuffer sb) = liftIO $ Gtk.sourceBufferBeginNotUndoableAction sb-#ifdef LEKSAH_WITH_YI-beginNotUndoableAction (YiEditorBuffer fb) = return () -- TODO-#endif--beginUserAction :: EditorBuffer -> IDEM ()-beginUserAction (GtkEditorBuffer sb) = liftIO $ Gtk.textBufferBeginUserAction sb-#ifdef LEKSAH_WITH_YI-beginUserAction (YiEditorBuffer fb) = return () -- TODO-#endif--canRedo :: EditorBuffer -> IDEM Bool-canRedo (GtkEditorBuffer sb) = liftIO $ Gtk.sourceBufferGetCanRedo sb-#ifdef LEKSAH_WITH_YI-canRedo (YiEditorBuffer fb) = return True -- TODO-#endif--canUndo :: EditorBuffer -> IDEM Bool-canUndo (GtkEditorBuffer sb) = liftIO $ Gtk.sourceBufferGetCanUndo sb-#ifdef LEKSAH_WITH_YI-canUndo (YiEditorBuffer fb) = return True -- TODO-#endif--copyClipboard :: EditorBuffer -> Gtk.Clipboard -> IDEM ()-copyClipboard (GtkEditorBuffer sb) clipboard = liftIO $ Gtk.textBufferCopyClipboard sb clipboard-#ifdef LEKSAH_WITH_YI-copyClipboard (YiEditorBuffer fb) _ = liftYi $ Yi.liftEditor $ Yi.copy-#endif--createMark :: EditorBuffer- -> EditorIter- -> Bool- -> IDEM EditorMark-createMark (GtkEditorBuffer sb) (GtkEditorIter i) leftGravity = liftIO $- GtkEditorMark <$> Gtk.textBufferCreateMark sb Nothing i leftGravity-#ifdef LEKSAH_WITH_YI-createMark (YiEditorBuffer b) (YiEditorIter (Yi.Iter _ p)) leftGravity = withYiBuffer b $- YiEditorMark <$> Yi.newMarkB (Yi.MarkValue p (if leftGravity then Yi.Backward else Yi.Forward))-createMark _ _ _ = liftIO $ fail "Mismatching TextEditor types in createMark"-#endif--cutClipboard :: EditorBuffer -> Gtk.Clipboard -> Bool -> IDEM ()-cutClipboard (GtkEditorBuffer sb) clipboard defaultEditable = liftIO $ Gtk.textBufferCutClipboard sb clipboard defaultEditable-#ifdef LEKSAH_WITH_YI-cutClipboard (YiEditorBuffer fb) clipboard defaultEditable = liftYi $ Yi.liftEditor $ Yi.cut-#endif--delete :: EditorBuffer -> EditorIter -> EditorIter -> IDEM ()-delete (GtkEditorBuffer sb) (GtkEditorIter first) (GtkEditorIter last) = liftIO $- Gtk.textBufferDelete sb first last-#ifdef LEKSAH_WITH_YI-delete (YiEditorBuffer b) (YiEditorIter (Yi.Iter _ first)) (YiEditorIter (Yi.Iter _ last)) =- withYiBuffer b $ Yi.deleteRegionB $ Yi.mkRegion first last-delete _ _ _ = liftIO $ fail "Mismatching TextEditor types in delete"-#endif--deleteSelection :: EditorBuffer -> Bool -> Bool -> IDEM ()-deleteSelection (GtkEditorBuffer sb) interactive defaultEditable = liftIO $- Gtk.textBufferDeleteSelection sb interactive defaultEditable >> return ()-#ifdef LEKSAH_WITH_YI-deleteSelection (YiEditorBuffer b) interactive defaultEditable = withYiBuffer b $ do- region <- Yi.getRawestSelectRegionB- Yi.deleteRegionB region -- TODO support flags-#endif--endNotUndoableAction :: EditorBuffer -> IDEM ()-endNotUndoableAction (GtkEditorBuffer sb) = liftIO $ Gtk.sourceBufferEndNotUndoableAction sb-#ifdef LEKSAH_WITH_YI-endNotUndoableAction (YiEditorBuffer fb) = return () -- TODO-#endif--endUserAction :: EditorBuffer -> IDEM ()-endUserAction (GtkEditorBuffer sb) = liftIO $ Gtk.textBufferEndUserAction sb-#ifdef LEKSAH_WITH_YI-endUserAction (YiEditorBuffer fb) = return () -- TODO-#endif--getEndIter :: EditorBuffer -> IDEM EditorIter-getEndIter (GtkEditorBuffer sb) = liftIO $ GtkEditorIter <$> Gtk.textBufferGetEndIter sb-#ifdef LEKSAH_WITH_YI-getEndIter (YiEditorBuffer b) = iterFromYiBuffer b Yi.sizeB-#endif--getInsertMark :: EditorBuffer -> IDEM EditorMark-getInsertMark (GtkEditorBuffer sb) = liftIO $ fmap GtkEditorMark $ Gtk.textBufferGetInsert sb-#ifdef LEKSAH_WITH_YI-getInsertMark (YiEditorBuffer b) = YiEditorMark <$> (withYiBuffer b $ Yi.insMark <$> Yi.askMarks)-#endif--getIterAtLine :: EditorBuffer -> Int -> IDEM EditorIter-getIterAtLine (GtkEditorBuffer sb) line = liftIO $ GtkEditorIter <$> Gtk.textBufferGetIterAtLine sb line-#ifdef LEKSAH_WITH_YI-getIterAtLine (YiEditorBuffer b) line = iterFromYiBuffer b $ Yi.pointOfLineColB line 1-#endif--getIterAtMark :: EditorBuffer -> EditorMark -> IDEM EditorIter-getIterAtMark (GtkEditorBuffer sb) (GtkEditorMark m) = liftIO $ GtkEditorIter <$> Gtk.textBufferGetIterAtMark sb m-#ifdef LEKSAH_WITH_YI-getIterAtMark (YiEditorBuffer b) (YiEditorMark m) = iterFromYiBuffer b $ Yi.getMarkPointB m-getIterAtMark _ _ = liftIO $ fail "Mismatching TextEditor types in getIterAtMark"-#endif--getIterAtOffset :: EditorBuffer -> Int -> IDEM EditorIter-getIterAtOffset (GtkEditorBuffer sb) offset = liftIO $ GtkEditorIter <$> Gtk.textBufferGetIterAtOffset sb offset-#ifdef LEKSAH_WITH_YI-getIterAtOffset (YiEditorBuffer b) offset = return $ mkYiIter b $ Yi.Point offset-#endif--getLineCount :: EditorBuffer -> IDEM Int-getLineCount (GtkEditorBuffer sb) = liftIO $ Gtk.textBufferGetLineCount sb-#ifdef LEKSAH_WITH_YI-getLineCount (YiEditorBuffer b) = withYiBuffer b $ Yi.sizeB >>= Yi.lineOf-#endif--getModified :: EditorBuffer -> IDEM Bool-getModified (GtkEditorBuffer sb) = liftIO $ Gtk.textBufferGetModified sb-#ifdef LEKSAH_WITH_YI-getModified (YiEditorBuffer b) = not <$> (withYiBuffer b $ Yi.gets Yi.isUnchangedBuffer)-#endif--getSelectionBoundMark :: EditorBuffer -> IDEM EditorMark-getSelectionBoundMark (GtkEditorBuffer sb) = liftIO $ fmap GtkEditorMark $ Gtk.textBufferGetSelectionBound sb-#ifdef LEKSAH_WITH_YI-getSelectionBoundMark (YiEditorBuffer b) = YiEditorMark . Yi.selMark <$> (withYiBuffer b $ Yi.askMarks)-#endif--getSelectionBounds :: EditorBuffer -> IDEM (EditorIter, EditorIter)-getSelectionBounds (GtkEditorBuffer sb) = liftIO $ do- (first, last) <- Gtk.textBufferGetSelectionBounds sb- return (GtkEditorIter first, GtkEditorIter last)-#ifdef LEKSAH_WITH_YI-getSelectionBounds (YiEditorBuffer b) = withYiBuffer b $ do- region <- Yi.getRawestSelectRegionB- return (mkYiIter b (Yi.regionStart region),- mkYiIter b (Yi.regionEnd region))-#endif--getInsertIter :: EditorBuffer -> IDEM EditorIter-getInsertIter (GtkEditorBuffer sb) = liftIO $ do- insertMark <- Gtk.textBufferGetInsert sb- insertIter <- Gtk.textBufferGetIterAtMark sb insertMark- return (GtkEditorIter insertIter)-#ifdef LEKSAH_WITH_YI-getInsertIter (YiEditorBuffer b) = withYiBuffer b $ do- insertMark <- Yi.insMark <$> Yi.askMarks- mkYiIter b <$> Yi.getMarkPointB insertMark-#endif---getSlice :: EditorBuffer- -> EditorIter- -> EditorIter- -> Bool- -> IDEM String-getSlice (GtkEditorBuffer sb) (GtkEditorIter first) (GtkEditorIter last) includeHidenChars = liftIO $- Gtk.textBufferGetSlice sb first last includeHidenChars-#ifdef LEKSAH_WITH_YI-getSlice (YiEditorBuffer b) (YiEditorIter first) (YiEditorIter last) includeHidenChars = liftYiControl $- Yi.getText b first last-getSlice _ _ _ _ = liftIO $ fail "Mismatching TextEditor types in getSlice"-#endif--getStartIter :: EditorBuffer -> IDEM EditorIter-getStartIter (GtkEditorBuffer sb) = liftIO $ GtkEditorIter <$> Gtk.textBufferGetStartIter sb-#ifdef LEKSAH_WITH_YI-getStartIter (YiEditorBuffer b) = return $ mkYiIter b $ Yi.Point 0-#endif--getTagTable :: EditorBuffer -> IDEM EditorTagTable-getTagTable (GtkEditorBuffer sb) = liftIO $ fmap GtkEditorTagTable $ Gtk.textBufferGetTagTable sb-#ifdef LEKSAH_WITH_YI-getTagTable (YiEditorBuffer b) = return YiEditorTagTable -- TODO-#endif--getText :: EditorBuffer- -> EditorIter- -> EditorIter- -> Bool- -> IDEM String-getText (GtkEditorBuffer sb) (GtkEditorIter first) (GtkEditorIter last) includeHidenChars = liftIO $- Gtk.textBufferGetText sb first last includeHidenChars-#ifdef LEKSAH_WITH_YI-getText (YiEditorBuffer b) (YiEditorIter first) (YiEditorIter last) includeHidenChars = liftYiControl $- Yi.getText b first last-getText _ _ _ _ = liftIO $ fail "Mismatching TextEditor types in getText"-#endif--hasSelection :: EditorBuffer -> IDEM Bool-hasSelection (GtkEditorBuffer sb) = liftIO $ Gtk.textBufferHasSelection sb-#ifdef LEKSAH_WITH_YI-hasSelection (YiEditorBuffer b) = withYiBuffer b $ do- region <- Yi.getRawestSelectRegionB- return $ not $ Yi.regionIsEmpty region-#endif--insert :: EditorBuffer -> EditorIter -> String -> IDEM ()-insert (GtkEditorBuffer sb) (GtkEditorIter i) text = liftIO $ Gtk.textBufferInsert sb i text-#ifdef LEKSAH_WITH_YI-insert (YiEditorBuffer b) (YiEditorIter (Yi.Iter _ p)) text = withYiBuffer b $ Yi.insertNAt text p-insert _ _ _ = liftIO $ fail "Mismatching TextEditor types in insert"-#endif--moveMark :: EditorBuffer -> EditorMark -> EditorIter -> IDEM ()-moveMark (GtkEditorBuffer sb) (GtkEditorMark m) (GtkEditorIter i) = liftIO $ Gtk.textBufferMoveMark sb m i-#ifdef LEKSAH_WITH_YI-moveMark (YiEditorBuffer b) (YiEditorMark m) (YiEditorIter (Yi.Iter _ p)) = withYiBuffer b $ Yi.setMarkPointB m p-moveMark _ _ _ = liftIO $ fail "Mismatching TextEditor types in moveMark"-#endif--newView :: EditorBuffer -> Maybe String -> IDEM EditorView-newView (GtkEditorBuffer sb) mbFontString = do- prefs <- readIDE prefs- fd <- fontDescription mbFontString- liftIO $ do- sv <- Gtk.sourceViewNewWithBuffer sb- Gtk.sourceViewSetHighlightCurrentLine sv True- Gtk.sourceViewSetInsertSpacesInsteadOfTabs sv True- Gtk.sourceViewSetIndentOnTab sv True- Gtk.sourceViewSetAutoIndent sv True- Gtk.sourceViewSetSmartHomeEnd sv Gtk.SourceSmartHomeEndBefore- if wrapLines prefs- then Gtk.textViewSetWrapMode sv Gtk.WrapWord- else Gtk.textViewSetWrapMode sv Gtk.WrapNone- sw <- Gtk.scrolledWindowNew Nothing Nothing- Gtk.containerAdd sw sv- Gtk.widgetModifyFont sv (Just fd)- return (GtkEditorView sv)-#ifdef LEKSAH_WITH_YI-newView (YiEditorBuffer b) mbFontString = do- fd <- fontDescription mbFontString- liftYiControl $ fmap YiEditorView $ Yi.newView b fd-#endif--pasteClipboard :: EditorBuffer- -> Gtk.Clipboard- -> EditorIter- -> Bool- -> IDEM ()-pasteClipboard (GtkEditorBuffer sb) clipboard (GtkEditorIter i) defaultEditable = liftIO $- Gtk.textBufferPasteClipboard sb clipboard i defaultEditable-#ifdef LEKSAH_WITH_YI-pasteClipboard (YiEditorBuffer b) clipboard (YiEditorIter (Yi.Iter _ p)) defaultEditable = liftYi $ Yi.liftEditor $ Yi.paste-pasteClipboard _ _ _ _ = liftIO $ fail "Mismatching TextEditor types in pasteClipboard"-#endif--placeCursor :: EditorBuffer -> EditorIter -> IDEM ()-placeCursor (GtkEditorBuffer sb) (GtkEditorIter i) = liftIO $ Gtk.textBufferPlaceCursor sb i-#ifdef LEKSAH_WITH_YI-placeCursor (YiEditorBuffer b) (YiEditorIter (Yi.Iter _ p)) = withYiBuffer b $ Yi.moveTo p-placeCursor _ _ = liftIO $ fail "Mismatching TextEditor types in placeCursor"-#endif--redo :: EditorBuffer -> IDEM ()-redo (GtkEditorBuffer sb) = liftIO $ Gtk.sourceBufferRedo sb-#ifdef LEKSAH_WITH_YI-redo (YiEditorBuffer b) = withYiBuffer b Yi.redoB-#endif--removeTagByName :: EditorBuffer- -> String- -> EditorIter- -> EditorIter- -> IDEM ()-removeTagByName (GtkEditorBuffer sb) name (GtkEditorIter first) (GtkEditorIter last) = liftIO $- Gtk.textBufferRemoveTagByName sb name first last-#ifdef LEKSAH_WITH_YI-removeTagByName (YiEditorBuffer b) name (YiEditorIter (Yi.Iter _ first)) (YiEditorIter (Yi.Iter _ last)) = return () -- TODO-removeTagByName _ _ _ _ = liftIO $ fail "Mismatching TextEditor types in removeTagByName"-#endif--selectRange :: EditorBuffer -> EditorIter -> EditorIter -> IDEM ()-selectRange (GtkEditorBuffer sb) (GtkEditorIter first) (GtkEditorIter last) = liftIO $- Gtk.textBufferSelectRange sb first last-#ifdef LEKSAH_WITH_YI-selectRange (YiEditorBuffer b) (YiEditorIter (Yi.Iter _ first)) (YiEditorIter (Yi.Iter _ last)) = withYiBuffer b $- Yi.setSelectRegionB $ Yi.mkRegion first last-selectRange _ _ _ = liftIO $ fail "Mismatching TextEditor types in selectRange"-#endif--setModified :: EditorBuffer -> Bool -> IDEM ()-setModified (GtkEditorBuffer sb) modified = liftIO $ Gtk.textBufferSetModified sb modified >> return ()-#ifdef LEKSAH_WITH_YI-setModified (YiEditorBuffer b) modified = unless modified $ do- now <- liftIO $ getCurrentTime- withYiBuffer b $ Yi.markSavedB now-#endif--setStyle :: EditorBuffer -> Maybe String -> IDEM ()-setStyle (GtkEditorBuffer sb) mbStyle = liftIO $ do- case mbStyle of- Nothing -> return ()- Just str -> do- styleManager <- Gtk.sourceStyleSchemeManagerNew- ids <- Gtk.sourceStyleSchemeManagerGetSchemeIds styleManager- when (elem str ids) $ do- scheme <- Gtk.sourceStyleSchemeManagerGetScheme styleManager str-#if MIN_VERSION_gtksourceview2(0,12,0)- Gtk.sourceBufferSetStyleScheme sb (Just scheme)-#else- Gtk.sourceBufferSetStyleScheme sb scheme-#endif--#ifdef LEKSAH_WITH_YI-setStyle (YiEditorBuffer b) mbStyle = return () -- TODO-#endif--setText :: EditorBuffer -> String -> IDEM ()-setText (GtkEditorBuffer sb) text = liftIO $ Gtk.textBufferSetText sb text-#ifdef LEKSAH_WITH_YI-setText (YiEditorBuffer b) text = liftYiControl $ Yi.setText b text-#endif--undo :: EditorBuffer -> IDEM ()-undo (GtkEditorBuffer sb) = liftIO $ Gtk.sourceBufferUndo sb-#ifdef LEKSAH_WITH_YI-undo (YiEditorBuffer b) = withYiBuffer b Yi.undoB-#endif---- View-bufferToWindowCoords :: EditorView -> (Int, Int) -> IDEM (Int, Int)-bufferToWindowCoords (GtkEditorView sv) point = liftIO $ Gtk.textViewBufferToWindowCoords sv Gtk.TextWindowWidget point-#ifdef LEKSAH_WITH_YI-bufferToWindowCoords (YiEditorView v) point = return point -- TODO-#endif--drawTabs :: EditorView -> IDEM ()-drawTabs (GtkEditorView sv) = liftIO $ Gtk.sourceViewSetDrawSpaces sv Gtk.SourceDrawSpacesTab-#ifdef LEKSAH_WITH_YI-drawTabs (YiEditorView _) = return () -- TODO-#endif--getBuffer :: EditorView -> IDEM EditorBuffer-getBuffer (GtkEditorView sv) = liftIO $ fmap (GtkEditorBuffer . Gtk.castToSourceBuffer) $ sv `Gtk.get` Gtk.textViewBuffer-#ifdef LEKSAH_WITH_YI-getBuffer (YiEditorView v) = return $ YiEditorBuffer $ Yi.getBuffer v-#endif--getDrawWindow :: EditorView -> IDEM Gtk.DrawWindow-getDrawWindow (GtkEditorView sv) = liftIO $ Gtk.widgetGetDrawWindow sv-#ifdef LEKSAH_WITH_YI-getDrawWindow (YiEditorView v) = liftIO $ Gtk.widgetGetDrawWindow (Yi.drawArea v)-#endif--getIterLocation :: EditorView -> EditorIter -> IDEM Gtk.Rectangle-getIterLocation (GtkEditorView sv) (GtkEditorIter i) = liftIO $ Gtk.textViewGetIterLocation sv i-#ifdef LEKSAH_WITH_YI-getIterLocation (YiEditorView v) (YiEditorIter i) = return $ Gtk.Rectangle 0 0 0 0 -- TODO-getIterLocation _ _ = liftIO $ fail "Mismatching TextEditor types in getIterLocation"-#endif--getOverwrite :: EditorView -> IDEM Bool-getOverwrite (GtkEditorView sv) = liftIO $ Gtk.textViewGetOverwrite sv-#ifdef LEKSAH_WITH_YI-getOverwrite (YiEditorView Yi.View{Yi.viewFBufRef = b}) = withYiBuffer' b $ not <$> Yi.getA Yi.insertingA-#endif--getScrolledWindow :: EditorView -> IDEM Gtk.ScrolledWindow-getScrolledWindow (GtkEditorView sv) = liftIO $ fmap (Gtk.castToScrolledWindow . fromJust) $ Gtk.widgetGetParent sv-#ifdef LEKSAH_WITH_YI-getScrolledWindow (YiEditorView v) = return $ Yi.scrollWin v-#endif--grabFocus :: EditorView -> IDEM ()-grabFocus (GtkEditorView sv) = liftIO $ Gtk.widgetGrabFocus sv-#ifdef LEKSAH_WITH_YI-grabFocus (YiEditorView Yi.View{Yi.drawArea = da}) = liftIO $ Gtk.widgetGrabFocus da-#endif--scrollToMark :: EditorView- -> EditorMark- -> Double- -> Maybe (Double, Double)- -> IDEM ()-scrollToMark (GtkEditorView sv) (GtkEditorMark m) withMargin mbAlign = liftIO $ Gtk.textViewScrollToMark sv m withMargin mbAlign-#ifdef LEKSAH_WITH_YI-scrollToMark (YiEditorView v) (YiEditorMark m) withMargin mbAlign = return () -- TODO-scrollToMark _ _ _ _ = liftIO $ fail "Mismatching TextEditor types in scrollToMark"-#endif--scrollToIter :: EditorView- -> EditorIter- -> Double- -> Maybe (Double, Double)- -> IDEM ()-scrollToIter (GtkEditorView sv) (GtkEditorIter i) withMargin mbAlign = liftIO $ Gtk.textViewScrollToIter sv i withMargin mbAlign >> return ()-#ifdef LEKSAH_WITH_YI-scrollToIter (YiEditorView v) (YiEditorIter i) withMargin mbAlign = return () -- TODO-scrollToIter _ _ _ _ = liftIO $ fail "Mismatching TextEditor types in scrollToIter"-#endif--fontDescription :: Maybe String -> IDEM Gtk.FontDescription-fontDescription mbFontString = liftIO $ do- case mbFontString of- Just str -> do- Gtk.fontDescriptionFromString str- Nothing -> do- f <- Gtk.fontDescriptionNew- Gtk.fontDescriptionSetFamily f "Monospace"- return f--setFont :: EditorView -> Maybe String -> IDEM ()-setFont (GtkEditorView sv) mbFontString = do- fd <- fontDescription mbFontString- liftIO $ Gtk.widgetModifyFont sv (Just fd)-#ifdef LEKSAH_WITH_YI-setFont (YiEditorView v) mbFontString = do- fd <- fontDescription mbFontString- liftIO $ Gtk.layoutSetFontDescription (Yi.layout v) (Just fd)-#endif--setIndentWidth :: EditorView -> Int -> IDEM ()-setIndentWidth (GtkEditorView sv) width = liftIO $ Gtk.sourceViewSetIndentWidth sv width-#ifdef LEKSAH_WITH_YI-setIndentWidth (YiEditorView Yi.View{Yi.viewFBufRef = b}) width =- withYiBuffer' b $ Yi.modifyMode $- \ (mode@Yi.Mode{Yi.modeIndentSettings = mis}) ->- mode{Yi.modeIndentSettings = mis{Yi.shiftWidth = width}}-#endif--setWrapMode :: EditorView -> Bool-> IDEM ()-setWrapMode ev@(GtkEditorView sv) wrapLines = do- sw <- getScrolledWindow ev- if wrapLines- then liftIO $ do- Gtk.textViewSetWrapMode sv Gtk.WrapWord- Gtk.scrolledWindowSetPolicy sw Gtk.PolicyNever Gtk.PolicyAutomatic- else liftIO $ do- Gtk.textViewSetWrapMode sv Gtk.WrapNone- Gtk.scrolledWindowSetPolicy sw Gtk.PolicyAutomatic Gtk.PolicyAutomatic-#ifdef LEKSAH_WITH_YI-setWrapMode (YiEditorView Yi.View{Yi.viewFBufRef = b}) width = return ()-#endif---setRightMargin :: EditorView -> Maybe Int -> IDEM ()-setRightMargin (GtkEditorView sv) mbRightMargin = liftIO $ do- case mbRightMargin of- Just n -> do- Gtk.sourceViewSetShowRightMargin sv True- Gtk.sourceViewSetRightMarginPosition sv (fromIntegral n)- Nothing -> Gtk.sourceViewSetShowRightMargin sv False-#ifdef LEKSAH_WITH_YI-setRightMargin (YiEditorView v) mbRightMargin = return () -- TODO-#endif--setShowLineNumbers :: EditorView -> Bool -> IDEM ()-setShowLineNumbers (GtkEditorView sv) show = liftIO $ Gtk.sourceViewSetShowLineNumbers sv show-#ifdef LEKSAH_WITH_YI-setShowLineNumbers (YiEditorView v) show = return () -- TODO-#endif--setTabWidth :: EditorView -> Int -> IDEM ()-setTabWidth (GtkEditorView sv) width = liftIO $ Gtk.sourceViewSetTabWidth sv width-#ifdef LEKSAH_WITH_YI-setTabWidth (YiEditorView Yi.View{Yi.viewFBufRef = b}) width =- withYiBuffer' b $ Yi.modifyMode $- \ (mode@Yi.Mode{Yi.modeIndentSettings = mis}) ->- mode{Yi.modeIndentSettings = mis{Yi.tabSize = width}}-#endif---- Iterator-transformGtkIter :: Gtk.TextIter -> (Gtk.TextIter -> IO a) -> IDEM EditorIter-transformGtkIter i f = do- new <- liftIO $ Gtk.textIterCopy i- liftIO $ f new- return $ GtkEditorIter new--transformGtkIterMaybe :: Gtk.TextIter -> (Gtk.TextIter -> IO Bool) -> IDEM (Maybe EditorIter)-transformGtkIterMaybe i f = do- new <- liftIO $ Gtk.textIterCopy i- found <- liftIO $ f new- return $ if found- then Just $ GtkEditorIter new- else Nothing--#ifdef LEKSAH_WITH_YI-withYiIter :: Yi.Iter -> Yi.BufferM a -> IDEM a-withYiIter (Yi.Iter b p) f = withYiBuffer' b $ do- Yi.savingPointB $ do- Yi.moveTo p- f--transformYiIter' :: Yi.Iter -> Yi.BufferM Yi.Point -> IDEM EditorIter-transformYiIter' i f = mkYiIter' (Yi.iterFBufRef i) <$> withYiIter i f--transformYiIter :: Yi.Iter -> Yi.BufferM a -> IDEM EditorIter-transformYiIter i f = transformYiIter' i (f >> Yi.pointB)--tryTransformYiIter' :: Yi.Iter -> Yi.BufferM Yi.Point -> IDEM (Maybe EditorIter)-tryTransformYiIter' i@(Yi.Iter b p) f = withYiIter i $ do- newPoint <- f- if p == newPoint- then return Nothing- else return . Just $ mkYiIter' b newPoint--tryTransformYiIter :: Yi.Iter -> Yi.BufferM a -> IDEM (Maybe EditorIter)-tryTransformYiIter i f = tryTransformYiIter' i (f >> Yi.pointB)-#endif--backwardCharC :: EditorIter -> IDEM EditorIter-backwardCharC (GtkEditorIter i) = transformGtkIter i Gtk.textIterBackwardChar-#ifdef LEKSAH_WITH_YI-backwardCharC (YiEditorIter i) = transformYiIter' i Yi.prevPointB-#endif--backwardFindCharC :: EditorIter- -> (Char -> Bool)- -> Maybe EditorIter- -> IDEM (Maybe EditorIter)-backwardFindCharC (GtkEditorIter i) pred mbLimit = transformGtkIterMaybe i $ \x ->- Gtk.textIterBackwardFindChar x pred $- case mbLimit of- Just (GtkEditorIter limit) -> Just limit- Nothing -> Nothing-#ifdef LEKSAH_WITH_YI- _ -> fail "Mismatching TextEditor types in backwardFindChar"-#endif--#ifdef LEKSAH_WITH_YI-backwardFindCharC (YiEditorIter i) pred mbLimit = tryTransformYiIter i $- Yi.doUntilB_ (pred <$> Yi.readB) Yi.leftB-#endif--backwardWordStartC :: EditorIter -> IDEM (Maybe EditorIter)-backwardWordStartC (GtkEditorIter i) = transformGtkIterMaybe i Gtk.textIterBackwardWordStart-#ifdef LEKSAH_WITH_YI-backwardWordStartC (YiEditorIter i@(Yi.Iter b p)) = withYiIter i $ do- Yi.prevWordB- newPoint <- Yi.pointB- if p == newPoint- then return Nothing- else return . Just $ mkYiIter' b newPoint-#endif--backwardToLineStartC :: EditorIter -> IDEM EditorIter-backwardToLineStartC (GtkEditorIter i) = transformGtkIter i $ \new -> do- n <- Gtk.textIterGetLineOffset new- Gtk.textIterBackwardChars new n- return ()-#ifdef LEKSAH_WITH_YI-backwardToLineStartC (YiEditorIter i) = transformYiIter i Yi.moveToSol-#endif--endsWord :: EditorIter -> IDEM Bool-endsWord (GtkEditorIter i) = liftIO $ Gtk.textIterEndsWord i-#ifdef LEKSAH_WITH_YI-endsWord (YiEditorIter i) = withYiIter i $ do- Yi.atBoundaryB Yi.unitWord Yi.Forward-#endif--forwardCharC :: EditorIter -> IDEM EditorIter-forwardCharC (GtkEditorIter i) = transformGtkIter i Gtk.textIterForwardChar-#ifdef LEKSAH_WITH_YI-forwardCharC (YiEditorIter i) = transformYiIter' i Yi.nextPointB-#endif--forwardCharsC :: EditorIter -> Int -> IDEM EditorIter-forwardCharsC (GtkEditorIter i) n = transformGtkIter i $ flip Gtk.textIterForwardChars n-#ifdef LEKSAH_WITH_YI-forwardCharsC (YiEditorIter i) n = transformYiIter i $ Yi.rightN n-#endif--forwardFindCharC :: EditorIter- -> (Char -> Bool)- -> Maybe EditorIter- -> IDEM (Maybe EditorIter)-forwardFindCharC (GtkEditorIter i) pred mbLimit = transformGtkIterMaybe i $ \x ->- Gtk.textIterForwardFindChar x pred $- case mbLimit of- Just (GtkEditorIter limit) -> Just limit- Nothing -> Nothing-#ifdef LEKSAH_WITH_YI- _ -> fail "Mismatching TextEditor types in forwardFindChar"-#endif--#ifdef LEKSAH_WITH_YI-forwardFindCharC (YiEditorIter i) pred mbLimit = tryTransformYiIter i $- Yi.doUntilB_ (pred <$> Yi.readB) Yi.rightB-#endif--forwardSearch :: EditorIter- -> String- -> [Gtk.TextSearchFlags]- -> Maybe EditorIter- -> IDEM (Maybe (EditorIter, EditorIter))-forwardSearch (GtkEditorIter i) str flags mbLimit = liftIO $ do- fmap (fmap (\(start, end) -> (GtkEditorIter start, GtkEditorIter end))) $- Gtk.textIterForwardSearch i str flags $- case mbLimit of- Just (GtkEditorIter limit) -> Just limit- Nothing -> Nothing-#ifdef LEKSAH_WITH_YI- _ -> fail "Mismatching TextEditor types in forwardSearch"-#endif--#ifdef LEKSAH_WITH_YI-forwardSearch (YiEditorIter i) str pred mbLimit = return Nothing -- TODO-#endif--forwardToLineEndC :: EditorIter -> IDEM EditorIter-forwardToLineEndC (GtkEditorIter i) = transformGtkIter i Gtk.textIterForwardToLineEnd-#ifdef LEKSAH_WITH_YI-forwardToLineEndC (YiEditorIter i) = transformYiIter i Yi.moveToEol-#endif--forwardWordEndC :: EditorIter -> IDEM (Maybe EditorIter)-forwardWordEndC (GtkEditorIter i) = transformGtkIterMaybe i Gtk.textIterForwardWordEnd-#ifdef LEKSAH_WITH_YI-forwardWordEndC (YiEditorIter i@(Yi.Iter b p)) = withYiIter i $ do- Yi.nextWordB- newPoint <- Yi.pointB- if p == newPoint- then return Nothing- else return . Just $ mkYiIter' b newPoint-#endif--getChar :: EditorIter -> IDEM (Maybe Char)-getChar (GtkEditorIter i) = liftIO $ Gtk.textIterGetChar i-#ifdef LEKSAH_WITH_YI-getChar (YiEditorIter i) = withYiIter i Yi.readCharB-#endif--getCharsInLine :: EditorIter -> IDEM Int-getCharsInLine (GtkEditorIter i) = liftIO $ Gtk.textIterGetCharsInLine i-#ifdef LEKSAH_WITH_YI-getCharsInLine (YiEditorIter i) = withYiIter i $ length <$> Yi.readLnB-#endif--getLine :: EditorIter -> IDEM Int-getLine (GtkEditorIter i) = liftIO $ Gtk.textIterGetLine i-#ifdef LEKSAH_WITH_YI-getLine (YiEditorIter i) = withYiIter i Yi.curLn-#endif--getLineOffset :: EditorIter -> IDEM Int-getLineOffset (GtkEditorIter i) = liftIO $ Gtk.textIterGetLineOffset i-#ifdef LEKSAH_WITH_YI-getLineOffset (YiEditorIter i) = withYiIter i Yi.curCol-#endif--getOffset :: EditorIter -> IDEM Int-getOffset (GtkEditorIter i) = liftIO $ Gtk.textIterGetOffset i-#ifdef LEKSAH_WITH_YI-getOffset (YiEditorIter (Yi.Iter _ (Yi.Point o))) = return o-#endif--isStart :: EditorIter -> IDEM Bool-isStart (GtkEditorIter i) = liftIO $ Gtk.textIterIsStart i-#ifdef LEKSAH_WITH_YI-isStart (YiEditorIter i) = withYiIter i Yi.atSof-#endif--isEnd :: EditorIter -> IDEM Bool-isEnd (GtkEditorIter i) = liftIO $ Gtk.textIterIsEnd i-#ifdef LEKSAH_WITH_YI-isEnd (YiEditorIter i) = withYiIter i Yi.atEof-#endif--iterEqual :: EditorIter -> EditorIter -> IDEM Bool-iterEqual (GtkEditorIter i1) (GtkEditorIter i2) = liftIO $ Gtk.textIterEqual i1 i2-#ifdef LEKSAH_WITH_YI-iterEqual (YiEditorIter (Yi.Iter _ p1)) (YiEditorIter (Yi.Iter _ p2)) = return $ p1 == p2-iterEqual _ _ = liftIO $ fail "Mismatching TextEditor types in iterEqual"-#endif--startsLine :: EditorIter -> IDEM Bool-startsLine (GtkEditorIter i) = liftIO $ Gtk.textIterStartsLine i-#ifdef LEKSAH_WITH_YI-startsLine (YiEditorIter i) = withYiIter i Yi.atSol-#endif--atEnd :: EditorIter -> IDEM EditorIter-atEnd (GtkEditorIter i) = liftIO $ GtkEditorIter <$> do- buffer <- Gtk.textIterGetBuffer i- Gtk.textBufferGetEndIter buffer-#ifdef LEKSAH_WITH_YI-atEnd (YiEditorIter (Yi.Iter b _)) = iterFromYiBuffer' b Yi.sizeB-#endif--atLine :: EditorIter -> Int -> IDEM EditorIter-atLine (GtkEditorIter i) line = transformGtkIter i $ flip Gtk.textIterSetLine line-#ifdef LEKSAH_WITH_YI-atLine (YiEditorIter i) line = transformYiIter i $ Yi.gotoLn line-#endif--atLineOffset :: EditorIter -> Int -> IDEM EditorIter-atLineOffset (GtkEditorIter i) column = transformGtkIter i $ flip Gtk.textIterSetLineOffset column-#ifdef LEKSAH_WITH_YI-atLineOffset (YiEditorIter i) column = transformYiIter i $ Yi.moveToColB column-#endif--atOffset :: EditorIter -> Int -> IDEM EditorIter-atOffset (GtkEditorIter i) offset = transformGtkIter i $ flip Gtk.textIterSetOffset offset-#ifdef LEKSAH_WITH_YI-atOffset (YiEditorIter (Yi.Iter b _)) offset = return $ YiEditorIter $ Yi.Iter b (Yi.Point offset)-#endif--atStart :: EditorIter -> IDEM EditorIter-atStart (GtkEditorIter i) = liftIO $ GtkEditorIter <$> do- buffer <- Gtk.textIterGetBuffer i- Gtk.textBufferGetEndIter buffer-#ifdef LEKSAH_WITH_YI-atStart (YiEditorIter (Yi.Iter b _)) = return $ mkYiIter' b $ Yi.Point 0-#endif---- Tag Table-newTag :: EditorTagTable -> String -> IDEM EditorTag-newTag (GtkEditorTagTable tt) name = liftIO $ do- t <- Gtk.textTagNew (Just name)- Gtk.textTagTableAdd tt t- return $ GtkEditorTag t-#ifdef LEKSAH_WITH_YI-newTag (YiEditorTagTable) name = return YiEditorTag -- TODO-#endif--lookupTag :: EditorTagTable -> String -> IDEM (Maybe EditorTag)-lookupTag (GtkEditorTagTable tt) name = liftIO $ fmap (fmap GtkEditorTag) $ Gtk.textTagTableLookup tt name-#ifdef LEKSAH_WITH_YI-lookupTag (YiEditorTagTable) name = return Nothing -- TODO-#endif---- Tag-background :: EditorTag -> Gtk.Color -> IDEM ()-background (GtkEditorTag t) color = liftIO $ Gtk.set t [Gtk.textTagBackground := colorHexString color]-#ifdef LEKSAH_WITH_YI-background (YiEditorTag) color = return () -- TODO-#endif--underline :: EditorTag -> Gtk.Underline -> IDEM ()-underline (GtkEditorTag t) value = liftIO $ Gtk.set t [Gtk.textTagUnderline := value]-#ifdef LEKSAH_WITH_YI-underline (YiEditorTag) value = return () -- TODO-#endif---- Events-afterFocusIn :: EditorView -> IDEM () -> IDEM [Connection]-afterFocusIn (GtkEditorView sv) f = do- ideR <- ask- liftIO $ do- id1 <- sv `Gtk.afterFocusIn` \_ -> reflectIDE f ideR >> return False- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-afterFocusIn (YiEditorView v) f = do- ideR <- ask- liftIO $ do- id1 <- (Yi.drawArea v) `Gtk.afterFocusIn` \_ -> reflectIDE f ideR >> return False- return [ConnectC id1]-#endif--afterModifiedChanged :: EditorBuffer -> IDEM () -> IDEM [Connection]-afterModifiedChanged (GtkEditorBuffer sb) f = do- ideR <- ask- liftIO $ do- id1 <- sb `Gtk.afterModifiedChanged` reflectIDE f ideR- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-afterModifiedChanged (YiEditorBuffer b) f = return [] -- TODO-#endif--afterMoveCursor :: EditorView -> IDEM () -> IDEM [Connection]-afterMoveCursor (GtkEditorView sv) f = do- ideR <- ask- GtkEditorBuffer sb <- getBuffer (GtkEditorView sv)- liftIO $ do-#if MIN_VERSION_gtk(0,10,5)- id1 <- sv `Gtk.after` Gtk.moveCursor $ \_ _ _ -> reflectIDE f ideR-#else- id1 <- sv `Gtk.afterMoveCursor` \_ _ _ -> reflectIDE f ideR-#endif- sv `Gtk.widgetAddEvents` [Gtk.ButtonReleaseMask]- id2 <- sv `Gtk.onButtonRelease` \_ -> reflectIDE f ideR >> return False- id3 <- sb `Gtk.afterEndUserAction` reflectIDE f ideR- return [ConnectC id1, ConnectC id2, ConnectC id3]-#ifdef LEKSAH_WITH_YI-afterMoveCursor (YiEditorView v) f = return [] -- TODO-#endif--afterToggleOverwrite :: EditorView -> IDEM () -> IDEM [Connection]-afterToggleOverwrite (GtkEditorView sv) f = do- ideR <- ask- liftIO $ do-#if MIN_VERSION_gtk(0,10,5)- id1 <- sv `Gtk.after` Gtk.toggleOverwrite $ reflectIDE f ideR-#else- id1 <- sv `Gtk.afterToggleOverwrite` reflectIDE f ideR-#endif- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-afterToggleOverwrite (YiEditorView v) f = return [] -- TODO-#endif--onButtonPress :: EditorView- -> (GtkOld.Event -> IDEM Bool)- -> IDEM [Connection]-onButtonPress (GtkEditorView sv) f = do- ideR <- ask- liftIO $ do- id1 <- sv `Gtk.onButtonPress` \event -> reflectIDE (f event) ideR- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-onButtonPress (YiEditorView v) f = do- ideR <- ask- liftIO $ do- id1 <- (Yi.drawArea v) `Gtk.onButtonPress` \event -> reflectIDE (f event) ideR- return [ConnectC id1]-#endif--onButtonRelease :: EditorView- -> (GtkOld.Event -> IDEM Bool)- -> IDEM [Connection]-onButtonRelease (GtkEditorView sv) f = do- ideR <- ask- liftIO $ do- id1 <- sv `Gtk.onButtonRelease` \event -> reflectIDE (f event) ideR- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-onButtonRelease (YiEditorView v) f = do- ideR <- ask- liftIO $ do- id1 <- (Yi.drawArea v) `Gtk.onButtonRelease` \event -> reflectIDE (f event) ideR- return [ConnectC id1]-#endif--onCompletion :: EditorView -> IDEM () -> IDEM () -> IDEM [Connection]-onCompletion (GtkEditorView sv) start cancel = do- ideR <- ask- (GtkEditorBuffer sb) <- getBuffer (GtkEditorView sv)- liftIO $ do- -- when multiple afterBufferInsertText are called quickly,- -- we cancel previous idle action which was not processed,- -- its handler is stored here.- -- Paste operation is example of such sequential events (each word!).- lastHandler <- newIORef Nothing- id1 <- sb `Gtk.afterBufferInsertText` \iter text -> do- mapM_ idleRemove =<< maybeToList <$> readIORef lastHandler- writeIORef lastHandler =<< Just <$> do- (flip idleAdd) priorityDefault $ do- let isIdent a = isAlphaNum a || a == '\'' || a == '_' || a == '.'- let isOp a = isSymbol a || a == ':' || a == '\\' || a == '*' || a == '/' || a == '-'- || a == '!' || a == '@' || a == '%' || a == '&' || a == '?'- if (all isIdent text) || (all isOp text)- then do- hasSel <- Gtk.textBufferHasSelection sb- if not hasSel- then do- (iterC, _) <- Gtk.textBufferGetSelectionBounds sb- atC <- Gtk.textIterEqual iter iterC- when atC $ reflectIDE start ideR- return False- else do- reflectIDE cancel ideR- return False- else do- reflectIDE cancel ideR- return False- return ()-#if MIN_VERSION_gtk(0,10,5)- id2 <- sv `Gtk.on` Gtk.moveCursor $ \_ _ _ -> reflectIDE cancel ideR-#else- id2 <- sv `Gtk.onMoveCursor` \_ _ _ -> reflectIDE cancel ideR-#endif- id3 <- sv `Gtk.onButtonPress` \_ -> reflectIDE cancel ideR >> return False- id4 <- sv `Gtk.onFocusOut` \_ -> reflectIDE cancel ideR >> return False- return [ConnectC id1, ConnectC id2, ConnectC id3, ConnectC id4]-#ifdef LEKSAH_WITH_YI-onCompletion (YiEditorView v) start cancel = return [] -- TODO-#endif--onKeyPress :: EditorView- -> (String -> [Gtk.Modifier] -> Gtk.KeyVal -> IDEM Bool)- -> IDEM [Connection]-onKeyPress (GtkEditorView sv) f = do- ideR <- ask- liftIO $ do- id1 <- sv `Gtk.on` Gtk.keyPressEvent $ do- name <- Gtk.eventKeyName- modifier <- Gtk.eventModifier- keyVal <- Gtk.eventKeyVal- Gtk.liftIO $ reflectIDE (f name modifier keyVal) ideR- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-onKeyPress (YiEditorView v) f = do- ideR <- ask- liftIO $ do- id1 <- (Yi.drawArea v) `Gtk.on` Gtk.keyPressEvent $ do- name <- Gtk.eventKeyName- modifier <- Gtk.eventModifier- keyVal <- Gtk.eventKeyVal- liftIO $ reflectIDE (f name modifier keyVal) ideR- return [ConnectC id1]-#endif--onMotionNotify :: EditorView- -> (Double -> Double -> [Gtk.Modifier] -> IDEM Bool)- -> IDEM [Connection]-onMotionNotify (GtkEditorView sv) f = do- ideR <- ask- liftIO $ do- id1 <- sv `Gtk.on` Gtk.motionNotifyEvent $ do- (ex,ey) <- Gtk.eventCoordinates- modifier <- Gtk.eventModifier- Gtk.liftIO $ reflectIDE (f ex ey modifier) ideR- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-onMotionNotify (YiEditorView v) f = do- ideR <- ask- liftIO $ do- id1 <- (Yi.drawArea v) `Gtk.on` Gtk.motionNotifyEvent $ do- (ex,ey) <- Gtk.eventCoordinates- modifier <- Gtk.eventModifier- liftIO $ reflectIDE (f ex ey modifier) ideR- return [ConnectC id1]-#endif--onLeaveNotify :: EditorView- -> (IDEM Bool)- -> IDEM [Connection]-onLeaveNotify (GtkEditorView sv) f = do- ideR <- ask- liftIO $ do- id1 <- sv `Gtk.on` Gtk.leaveNotifyEvent $ do- Gtk.liftIO $ reflectIDE (f) ideR- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-onLeaveNotify (YiEditorView v) f = do- ideR <- ask- liftIO $ do- id1 <- (Yi.drawArea v) `Gtk.on` Gtk.leaveNotifyEvent $ do- liftIO $ reflectIDE (f) ideR- return [ConnectC id1]-#endif---onKeyRelease :: EditorView- -> (String -> [Gtk.Modifier] -> Gtk.KeyVal -> IDEM Bool)- -> IDEM [Connection]-onKeyRelease (GtkEditorView sv) f = do- ideR <- ask- liftIO $ do- id1 <- sv `Gtk.on` Gtk.keyReleaseEvent $ do- name <- Gtk.eventKeyName- modifier <- Gtk.eventModifier- keyVal <- Gtk.eventKeyVal- Gtk.liftIO $ reflectIDE (f name modifier keyVal) ideR- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-onKeyRelease (YiEditorView v) f = do- ideR <- ask- liftIO $ do- id1 <- (Yi.drawArea v) `Gtk.on` Gtk.keyReleaseEvent $ do- name <- Gtk.eventKeyName- modifier <- Gtk.eventModifier- keyVal <- Gtk.eventKeyVal- liftIO $ reflectIDE (f name modifier keyVal) ideR- return [ConnectC id1]-#endif--onLookupInfo :: EditorView -> IDEM () -> IDEM [Connection]-onLookupInfo (GtkEditorView sv) f = do- ideR <- ask- liftIO $ do- sv `Gtk.widgetAddEvents` [Gtk.ButtonReleaseMask]- id1 <- sv `Gtk.onButtonRelease` \e -> when (controlIsPressed e) (reflectIDE f ideR) >> return False- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-onLookupInfo (YiEditorView v) f = do- ideR <- ask- liftIO $ do- (Yi.drawArea v) `Gtk.widgetAddEvents` [Gtk.ButtonReleaseMask]- id1 <- (Yi.drawArea v) `Gtk.onButtonRelease` \e -> when (controlIsPressed e) (reflectIDE f ideR) >> return False- return [ConnectC id1]-#endif--onPopulatePopup :: EditorView -> (Gtk.Menu -> IDEM ()) -> IDEM [Connection]-onPopulatePopup (GtkEditorView sv) f = do- ideR <- ask- liftIO $ do-#if MIN_VERSION_gtk(0,10,5)- id1 <- sv `Gtk.on` Gtk.populatePopup $ \menu -> reflectIDE (f menu) ideR-#else- id1 <- sv `Gtk.onPopulatePopup` \menu -> reflectIDE (f menu) ideR-#endif- return [ConnectC id1]-#ifdef LEKSAH_WITH_YI-onPopulatePopup (YiEditorView v) f = do- ideR <- ask- liftIO $ do- id1 <- (Yi.drawArea v) `Gtk.onPopupMenu` do- menu <- Gtk.menuNew- reflectIDE (f menu) ideR- Gtk.menuPopup menu Nothing- return [ConnectC id1]-#endif--+ module IDE.TextEditor.Class+ , module IDE.TextEditor.GtkSourceView+ , module IDE.TextEditor.Yi+ , module IDE.TextEditor.CodeMirror++ , TextEditor(..)+ , EditorBuffer(..)+ , EditorView(..)+ , EditorIter(..)+ , EditorMark(..)+ , EditorTag(..)+ , EditorTagTable(..)++ , newDefaultBuffer+#ifndef LEKSAH_WITH_YI+ , newYiBuffer+#endif+#ifndef LEKSAH_WITH_CODE_MIRROR+ , newCMBuffer+#endif+) where++import IDE.TextEditor.Class+import IDE.TextEditor.GtkSourceView+import IDE.TextEditor.Yi+import IDE.TextEditor.CodeMirror++newDefaultBuffer = newGtkBuffer++#ifndef LEKSAH_WITH_YI+newYiBuffer = newDefaultBuffer+#endif++#ifndef LEKSAH_WITH_CODE_MIRROR+newCMBuffer = newDefaultBuffer+#endif
@@ -0,0 +1,205 @@+{-# LANGUAGE TypeFamilies #-}+-----------------------------------------------------------------------------+--+-- Module : IDE.TextEditor.Class+-- Copyright : 2007-2013 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.TextEditor.Class (+ TextEditor(..)+) where++import IDE.Core.Types (IDERef, IDEM)+import Graphics.UI.Editor.Basics (Connection)+import Control.Monad.Reader (ReaderT(..))+import Graphics.UI.Gtk+ (Widget, ECrossing, ScrolledWindow, DrawWindow, Clipboard,+ TextSearchFlags, Menu, EMotion, EKey, EButton, EventM, Rectangle,+ Color, Underline)+import Foreign (Ptr)+import Control.Monad.Reader.Class (MonadReader(..))+import Control.Monad.IO.Class (MonadIO(..))+import System.Glib.Signals (on)+import IDE.Core.Types (IDEEventM)++class TextEditor editor where+ data EditorBuffer editor+ data EditorView editor+ data EditorMark editor+ data EditorIter editor+ data EditorTagTable editor+ data EditorTag editor++ newBuffer :: Maybe FilePath -> String -> IDEM (EditorBuffer editor)+ applyTagByName :: EditorBuffer editor+ -> String+ -> EditorIter editor+ -> EditorIter editor+ -> IDEM ()+ beginNotUndoableAction :: EditorBuffer editor -> IDEM ()+ beginUserAction :: EditorBuffer editor -> IDEM ()+ canRedo :: EditorBuffer editor -> IDEM Bool+ canUndo :: EditorBuffer editor -> IDEM Bool+ copyClipboard :: EditorBuffer editor -> Clipboard -> IDEM ()+ createMark :: EditorBuffer editor+ -> EditorIter editor+ -> Bool+ -> IDEM (EditorMark editor)+ cutClipboard :: EditorBuffer editor -> Clipboard -> Bool -> IDEM ()+ delete :: EditorBuffer editor -> EditorIter editor -> EditorIter editor -> IDEM ()+ deleteSelection :: EditorBuffer editor -> IDEM ()+ endNotUndoableAction :: EditorBuffer editor -> IDEM ()+ endUserAction :: EditorBuffer editor -> IDEM ()+ getEndIter :: EditorBuffer editor -> IDEM (EditorIter editor)+ getInsertMark :: EditorBuffer editor -> IDEM (EditorMark editor)+ getIterAtLine :: EditorBuffer editor -> Int -> IDEM (EditorIter editor)+ getIterAtMark :: EditorBuffer editor -> EditorMark editor -> IDEM (EditorIter editor)+ getIterAtOffset :: EditorBuffer editor -> Int -> IDEM (EditorIter editor)+ getLineCount :: EditorBuffer editor -> IDEM Int+ getModified :: EditorBuffer editor -> IDEM Bool+ getSelectionBoundMark :: EditorBuffer editor -> IDEM (EditorMark editor)+ getSelectionBounds :: EditorBuffer editor -> IDEM (EditorIter editor, EditorIter editor)+ getInsertIter :: EditorBuffer editor -> IDEM (EditorIter editor)+ getSlice :: EditorBuffer editor+ -> EditorIter editor+ -> EditorIter editor+ -> Bool+ -> IDEM String+ getStartIter :: EditorBuffer editor -> IDEM (EditorIter editor)+ getTagTable :: EditorBuffer editor -> IDEM (EditorTagTable editor)+ getText :: EditorBuffer editor+ -> EditorIter editor+ -> EditorIter editor+ -> Bool+ -> IDEM String+ hasSelection :: EditorBuffer editor -> IDEM Bool+ insert :: EditorBuffer editor -> EditorIter editor -> String -> IDEM ()+ newView :: EditorBuffer editor -> Maybe String -> IDEM (EditorView editor)+ pasteClipboard :: EditorBuffer editor+ -> Clipboard+ -> EditorIter editor+ -> Bool+ -> IDEM ()+ placeCursor :: EditorBuffer editor -> EditorIter editor -> IDEM ()+ redo :: EditorBuffer editor -> IDEM ()+ removeTagByName :: EditorBuffer editor+ -> String+ -> IDEM ()+ selectRange :: EditorBuffer editor -> EditorIter editor -> EditorIter editor -> IDEM ()+ setModified :: EditorBuffer editor -> Bool -> IDEM ()+ setStyle :: Bool -> EditorBuffer editor -> Maybe String -> IDEM ()+ setText :: EditorBuffer editor -> String -> IDEM ()+ undo :: EditorBuffer editor -> IDEM ()++ -- Events+ afterModifiedChanged :: EditorBuffer editor -> IDEM () -> IDEM [Connection]++ -- View+ bufferToWindowCoords :: EditorView editor -> (Int, Int) -> IDEM (Int, Int)+ drawTabs :: EditorView editor -> IDEM ()+ getBuffer :: EditorView editor -> IDEM (EditorBuffer editor)+ getWindow :: EditorView editor -> IDEM (Maybe DrawWindow)+ getIterAtLocation :: EditorView editor -> Int -> Int -> IDEM (EditorIter editor)+ getIterLocation :: EditorView editor -> EditorIter editor -> IDEM Rectangle+ getOverwrite :: EditorView editor -> IDEM Bool+ getScrolledWindow :: EditorView editor -> IDEM ScrolledWindow+ getEditorWidget :: EditorView editor -> IDEM Widget+ grabFocus :: EditorView editor -> IDEM ()+ scrollToMark :: EditorView editor+ -> EditorMark editor+ -> Double+ -> Maybe (Double, Double)+ -> IDEM ()+ scrollToIter :: EditorView editor+ -> EditorIter editor+ -> Double+ -> Maybe (Double, Double)+ -> IDEM ()+ setFont :: EditorView editor -> Maybe String -> IDEM ()+ setIndentWidth :: EditorView editor -> Int -> IDEM ()+ setWrapMode :: EditorView editor -> Bool -> IDEM ()+ setRightMargin :: EditorView editor -> Maybe Int -> IDEM ()+ setShowLineNumbers :: EditorView editor -> Bool -> IDEM ()+ setTabWidth :: EditorView editor -> Int -> IDEM ()++ -- Events+ afterFocusIn :: EditorView editor -> IDEM () -> IDEM [Connection]+ afterMoveCursor :: EditorView editor -> IDEM () -> IDEM [Connection]+ afterToggleOverwrite :: EditorView editor -> IDEM () -> IDEM [Connection]+ onButtonPress :: EditorView editor+ -> IDEEventM EButton Bool+ -> IDEM [Connection]+ onButtonRelease :: EditorView editor+ -> IDEEventM EButton Bool+ -> IDEM [Connection]+ onCompletion :: EditorView editor -> IDEM () -> IDEM () -> IDEM [Connection]+ onKeyPress :: EditorView editor+ -> IDEEventM EKey Bool+ -> IDEM [Connection]+ onMotionNotify :: EditorView editor+ -> IDEEventM EMotion Bool+ -> IDEM [Connection]+ onLeaveNotify :: EditorView editor+ -> IDEEventM ECrossing Bool+ -> IDEM [Connection]+ onKeyRelease :: EditorView editor+ -> IDEEventM EKey Bool+ -> IDEM [Connection]+ onLookupInfo :: EditorView editor -> IDEEventM EButton Bool -> IDEM [Connection]+ onMotionNotifyEvent :: EditorView editor -> IDEEventM EMotion Bool -> IDEM [Connection]+ onPopulatePopup :: EditorView editor -> (Menu -> IDEM ()) -> IDEM [Connection]++ -- Iter+ backwardCharC :: EditorIter editor -> IDEM (EditorIter editor)+ backwardFindCharC :: EditorIter editor+ -> (Char -> Bool)+ -> Maybe (EditorIter editor)+ -> IDEM (Maybe (EditorIter editor))+ backwardWordStartC :: EditorIter editor -> IDEM (Maybe (EditorIter editor))+ backwardToLineStartC :: EditorIter editor -> IDEM (EditorIter editor)+ endsWord :: EditorIter editor -> IDEM Bool+ forwardCharC :: EditorIter editor -> IDEM (EditorIter editor)+ forwardCharsC :: EditorIter editor -> Int -> IDEM (EditorIter editor)+ forwardFindCharC :: EditorIter editor+ -> (Char -> Bool)+ -> Maybe (EditorIter editor)+ -> IDEM (Maybe (EditorIter editor))+ forwardSearch :: EditorIter editor+ -> String+ -> [TextSearchFlags]+ -> Maybe (EditorIter editor)+ -> IDEM (Maybe (EditorIter editor, EditorIter editor))+ forwardToLineEndC :: EditorIter editor -> IDEM (EditorIter editor)+ forwardWordEndC :: EditorIter editor -> IDEM (Maybe (EditorIter editor))+ getChar :: EditorIter editor -> IDEM (Maybe Char)+ getCharsInLine :: EditorIter editor -> IDEM Int+ getLine :: EditorIter editor -> IDEM Int+ getLineOffset :: EditorIter editor -> IDEM Int+ getOffset :: EditorIter editor -> IDEM Int+ isStart :: EditorIter editor -> IDEM Bool+ isEnd :: EditorIter editor -> IDEM Bool+ iterEqual :: EditorIter editor -> EditorIter editor -> IDEM Bool+ startsLine :: EditorIter editor -> IDEM Bool+ startsWord :: EditorIter editor -> IDEM Bool+ atEnd :: EditorIter editor -> IDEM (EditorIter editor)+ atLine :: EditorIter editor -> Int -> IDEM (EditorIter editor)+ atLineOffset :: EditorIter editor -> Int -> IDEM (EditorIter editor)+ atOffset :: EditorIter editor -> Int -> IDEM (EditorIter editor)+ atStart :: EditorIter editor -> IDEM (EditorIter editor)++ -- Tag Table+ newTag :: EditorTagTable editor -> String -> IDEM (EditorTag editor)+ lookupTag :: EditorTagTable editor -> String -> IDEM (Maybe (EditorTag editor))++ -- Tag+ background :: EditorTag editor -> Color -> IDEM ()+ underline :: EditorTag editor -> Underline -> IDEM ()+
@@ -0,0 +1,525 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE RankNTypes #-}+-----------------------------------------------------------------------------+--+-- Module : IDE.TextEditor.CodeMirror+-- Copyright : 2007-2013 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.TextEditor.CodeMirror (+ CodeMirror(..)+#ifdef LEKSAH_WITH_CODE_MIRROR+ , TextEditor(..)+ , EditorBuffer(..)+ , EditorView(..)+ , EditorIter(..)+ , EditorMark(..)+ , EditorTag(..)+ , EditorTagTable(..)++ , newCMBuffer+#endif+) where++import Data.Typeable (Typeable)++#ifdef LEKSAH_WITH_CODE_MIRROR+import Control.Monad (unless)+import Data.Text (pack, unpack)+import IDE.TextEditor.Class (TextEditor(..))+import Graphics.UI.Gtk.WebKit.Types (WebView(..))+import Control.Monad.Reader (ReaderT(..))+import Language.Javascript.JSaddle+ (valToObject, (#), JSContextRef, JSObjectRef, jsg, (<#), obj, js2,+ js, JSM, js1, valToText, valToStr, js3, js0, MakeValueRef(..), MakeStringRef(..),+ JSStringRef, JSValueRef, valToBool, strToText, valToNumber, MakeObjectRef)+import Control.Applicative ((<$>))+import Control.Monad.Reader.Class (MonadReader(..))+import Control.Concurrent (putMVar, newEmptyMVar, takeMVar, MVar, tryTakeMVar)+import IDE.Core.Types (IDEM)+import Control.Monad.IO.Class (MonadIO(..))+import Control.Monad.Trans.Class (MonadTrans(..))+import Control.Lens ((^.), IndexPreservingGetter)+import Graphics.UI.Gtk.WebKit.WebView+ (webViewLoadUri, webViewLoadString, webViewGetMainFrame,+ loadFinished, webViewNew)+import qualified GHCJS.CodeMirror as CM (getDataDir)+import System.Glib.Signals (after, on)+import Graphics.UI.Gtk.WebKit.JavaScriptCore.WebFrame+ (webFrameGetGlobalContext)+import Text.Blaze.Html.Renderer.String (renderHtml)+import Text.Hamlet (shamlet)+import Graphics.UI.Gtk+ (ScrolledWindow, menuPopup, menuAttachToWidget, menuNew,+ popupMenuSignal, eventModifier, widgetAddEvents, keyReleaseEvent,+ leaveNotifyEvent, motionNotifyEvent, keyPressEvent,+ buttonReleaseEvent, buttonPressEvent, focusInEvent,+ widgetGrabFocus, widgetGetParent, castToScrolledWindow,+ containerAdd, scrolledWindowNew, Rectangle(..),+ EventMask(..), Modifier(..), ContainerClass, mainIteration,+ castToWidget,+#ifdef MIN_VERSION_gtk3+ widgetGetWindow+#else+ widgetGetDrawWindow+#endif+ )+import Data.Maybe (fromJust)+import IDE.Core.State (onIDE, reflectIDE, leksahOrPackageDir)+import Graphics.UI.Editor.Basics (Connection(..))+import System.Log.Logger (debugM)+#endif++data CodeMirror = CodeMirror deriving( Typeable, Show )++#ifdef LEKSAH_WITH_CODE_MIRROR++data CodeMirrorState = CodeMirrorState {+ cmContext :: JSContextRef+ , cmObject :: JSObjectRef }+type CM = ReaderT (WebView, CodeMirrorState) JSM+webView :: CM WebView+webView = fst <$> ask+codeMirror :: CM JSObjectRef+codeMirror = cmObject . snd <$> ask+runCM :: CodeMirrorRef -> CM a -> IDEM a+runCM (v, mvar) f = liftIO $ do+ s <- guiTakeMVar mvar+ runReaderT (runReaderT f (v, s)) (cmContext s)+ where+ guiTakeMVar mvar = do+ maybeValue <- tryTakeMVar mvar+ case maybeValue of+ Just value -> do+ putMVar mvar value+ return value+ Nothing -> do+ debugM "leksah" "looping"+ s <- loop mvar+ debugM "leksah" "done looping"+ return s+ loop mvar = do+ maybeValue <- tryTakeMVar mvar+ case maybeValue of+ Just value -> do+ putMVar mvar value+ return value+ Nothing -> do+ mainIteration+ loop mvar+type CodeMirrorRef = (WebView, MVar CodeMirrorState)++body = js "body"+value = js "value"+setSize = js2 "setSize"+mode = js "mode"+line = js "line"+ch = js "ch"+left = js "left"+top = js "top"+right = js "right"+bottom = js "bottom"+lastLine = js0 "lastLine"+getRange = js2 "getRange"+setValue = js1 "setValue"+setBookmark = js1 "setBookmark"+setBookmark' = js2 "setBookmark"+insertLeft = js "insertLeft"+find = js0 "find"+from = js "from"+getCursor :: (MakeValueRef a0, MakeObjectRef o) => a0 -> IndexPreservingGetter o (JSM JSValueRef)+getCursor = js1 "getCursor"+isClean = js0 "isClean"+markText = js3 "markText"+className = js "className"+clearHistory = js0 "clearHistory"+callUndo = js0 "undo"+undo' = js "undo"+callRedo = js0 "redo"+redo' = js "redo"+historySize = js0 "historySize"+replaceRange = js3 "replaceRange"+insertAt = js2 "replaceRange"+replaceSelection = js1 "replaceSelection"+posFromIndex = js1 "posFromIndex"+lineCount = js0 "lineCount"+somethingSelected = js0 "somethingSelected"+setSelection = js2 "setSelection"+placeCursorAt = js1 "setSelection"+markClean = js0 "markClean"+coordsChar = js2 "coordsChar"+charCoords = js2 "charCoords"+scrollIntoView = js2 "scrollIntoView"+getAllMarks = js0 "getAllMarks"+indexFromPos = js1 "indexFromPos"+getLineText :: (MakeValueRef a0, MakeObjectRef o) => a0 -> IndexPreservingGetter o (JSM JSValueRef)+getLineText = js1 "getLine"+jsLength = js "length"++cmIter :: CodeMirrorRef -> Int -> Int -> CM (EditorIter CodeMirror)+cmIter cm l c = do+ lift $ do+ i <- obj+ i ^. line <# (fromIntegral l :: Double)+ i ^. ch <# (fromIntegral c :: Double)+ return $ CMIter cm i++newCMBuffer :: Maybe FilePath -> String -> IDEM (EditorBuffer CodeMirror)+newCMBuffer mbFilename contents = do+ ideR <- ask+ liftIO $ do+ debugM "leksah" "newCMBuffer"+ scrolledWindow <- scrolledWindowNew Nothing Nothing+ cmWebView <- webViewNew+ containerAdd scrolledWindow cmWebView+ dataDir <- liftIO $ leksahOrPackageDir "ghcjs-codemirror" CM.getDataDir+ s <- newEmptyMVar+ cmWebView `on` loadFinished $ \ _ -> do+ debugM "leksah" "newCMBuffer loadFinished"+ cmContext <- webViewGetMainFrame cmWebView >>= webFrameGetGlobalContext+ let runjs f = f `runReaderT` cmContext++ runjs $ do+ document <- jsg "document"+ codeMirror <- jsg "CodeMirror"+ code <- obj+ code ^. value <# contents+ code ^. mode <# "haskell"+ cmObject <- codeMirror # (document ^. body, code) >>= valToObject++ cmObject ^. setSize "100%" "100%"+ liftIO $ debugM "leksah" "newCMBuffer loaded"+ liftIO . putMVar s $ CodeMirrorState{..}++ webViewLoadString cmWebView (+ "<html><head>"+ ++ "<script src=\"lib/codemirror.js\">"+ ++ "<link rel=\"stylesheet\" href=\"lib/codemirror.css\">"+ ++ "<script src=\"mode/javascript/javascript.js\">"+ ++ "<script src=\"mode/haskell/haskell.js\">"+ ++ "</head>"+ ++ "<body style=\"margin:0;padding:0 auto;\">"+ ++ "</body></html>"+ ) Nothing Nothing ("file://" ++ dataDir ++ "/codemirror.html")+ debugM "leksah" "newCMBuffer loading"+ return $ CMBuffer (cmWebView, s)++instance TextEditor CodeMirror where+ data EditorBuffer CodeMirror = CMBuffer CodeMirrorRef+ data EditorView CodeMirror = CMView CodeMirrorRef+ data EditorMark CodeMirror = CMMark JSObjectRef | CMCursor JSValueRef+ data EditorIter CodeMirror = CMIter CodeMirrorRef JSObjectRef+ data EditorTagTable CodeMirror = CMTagTable CodeMirrorRef+ data EditorTag CodeMirror = CMTag++ newBuffer = newCMBuffer+ applyTagByName (CMBuffer cm) name (CMIter _ first) (CMIter _ last) = runCM cm $ do+ m <- codeMirror+ lift $ do+ o <- obj+ o ^. className <# name+ m ^. markText first last o+ return ()+ beginNotUndoableAction (CMBuffer cm) = return () -- TODO+ beginUserAction (CMBuffer cm) = return () -- TODO+ canRedo (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ (m ^. historySize ^. redo') >>= valToBool+ canUndo (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ (m ^. historySize ^. undo') >>= valToBool+ copyClipboard (CMBuffer cm) _ = return () -- TODO+ createMark (CMBuffer cm) (CMIter _ i) leftGravity = runCM cm $ do+ m <- codeMirror+ lift $ do+ CMMark <$> if leftGravity+ then m ^. setBookmark i+ else do+ o <- obj+ o ^. insertLeft <# True+ m ^. setBookmark' i o+ cutClipboard (CMBuffer cm) _ _ = return () -- TODO+ delete (CMBuffer cm) (CMIter _ first) (CMIter _ last) = runCM cm $ do+ m <- codeMirror+ lift $ m ^. replaceRange "" first last+ return ()+ deleteSelection (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ m ^. replaceSelection ""+ return ()+ endNotUndoableAction (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ m ^. clearHistory+ return ()+ endUserAction (CMBuffer cm) = return () -- TODO+ getEndIter (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ do+ i <- obj+ l <- m ^. lastLine+ i ^. line <# l+ i ^. ch <# m ^. getLineText l ^. jsLength+ return $ CMIter cm i+ getInsertMark (CMBuffer cm) = runCM cm . lift $ CMCursor <$> makeValueRef "head"+ getIterAtLine (CMBuffer cm) line = runCM cm $ cmIter cm line 0+ getIterAtMark (CMBuffer cm) (CMMark mark) = runCM cm $ do+ lift $ CMIter cm <$> (mark ^. find ^. from >>= valToObject)+ getIterAtMark (CMBuffer cm) (CMCursor c) = runCM cm $ do+ m <- codeMirror+ lift $ CMIter cm <$> ((m ^. getCursor c) >>= valToObject)+ getIterAtOffset (CMBuffer cm) offset = runCM cm $ do+ m <- codeMirror+ lift $ CMIter cm <$> ((m ^. posFromIndex (fromIntegral offset :: Double)) >>= valToObject)+ getLineCount (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ round <$> ((m ^. lineCount) >>= valToNumber)+ getModified (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ not <$> ((m ^. isClean) >>= valToBool)+ getSelectionBoundMark (CMBuffer cm) = runCM cm . lift $ CMCursor <$> makeValueRef "anchor"+ getSelectionBounds (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ do+ start <- (m ^. getCursor "start") >>= valToObject+ end <- (m ^. getCursor "end") >>= valToObject+ return (CMIter cm start, CMIter cm end)+ getInsertIter (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ CMIter cm <$> (m ^. getCursor "head" >>= valToObject)+ getSlice (CMBuffer cm) (CMIter _ first) (CMIter _ last) includeHidenChars = runCM cm $ do+ m <- codeMirror+ lift $ unpack <$> (m ^. getRange first last >>= valToText)+ getStartIter (CMBuffer cm) = runCM cm $ cmIter cm 0 0+ getTagTable (CMBuffer cm) = return $ CMTagTable cm+ getText (CMBuffer cm) (CMIter _ first) (CMIter _ last) includeHidenChars = runCM cm $ do+ m <- codeMirror+ lift $ unpack <$> (m ^. getRange first last >>= valToText)+ hasSelection (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ (m ^. somethingSelected) >>= valToBool+ insert (CMBuffer cm) (CMIter _ p) text = runCM cm $ do+ m <- codeMirror+ lift $ m ^. insertAt text p >> return ()+ newView (CMBuffer cm) mbFontString = return (CMView cm)+ pasteClipboard (CMBuffer cm) clipboard (CMIter _ p) defaultEditable = return () -- TODO+ placeCursor (CMBuffer cm) (CMIter _ i) = runCM cm $ do+ m <- codeMirror+ lift $ m ^. placeCursorAt i >> return ()+ redo (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ m ^. callRedo+ return ()+ removeTagByName (CMBuffer cm) name = runCM cm $ do+ m <- codeMirror+ lift $ do+ marks <- m ^. getAllMarks+ -- TODO+ return ()+ selectRange (CMBuffer cm) (CMIter _ first) (CMIter _ last) = runCM cm $ do+ m <- codeMirror+ lift $ m ^. setSelection first last >> return ()+ setModified (CMBuffer cm) modified = unless modified . runCM cm $ do+ m <- codeMirror+ lift $ m ^. markClean >> return ()+ setStyle preferDark (CMBuffer cm) mbStyle = return () -- TODO+ setText (CMBuffer cm) text = runCM cm $ do+ m <- codeMirror+ lift $ m ^. setValue text+ return ()+ undo (CMBuffer cm) = runCM cm $ do+ m <- codeMirror+ lift $ m ^. callUndo+ return ()+ bufferToWindowCoords (CMView cm) point = return point -- TODO+ drawTabs (CMView _) = return () -- TODO+ getBuffer (CMView cm) = return $ CMBuffer cm+ getWindow (CMView cm) = runCM cm $ do+ v <- webView+#ifdef MIN_VERSION_gtk3+ liftIO $ widgetGetWindow v+#else+ liftIO $ Just <$> widgetGetDrawWindow v+#endif+ getIterAtLocation (CMView cm) x y = runCM cm $ do+ m <- codeMirror+ lift $ do+ pos <- obj+ pos ^. left <# (fromIntegral x :: Double)+ pos ^. top <# (fromIntegral y :: Double)+ CMIter cm <$> (m ^. coordsChar pos "window" >>= valToObject)+ getIterLocation (CMView cm) (CMIter _ i) = runCM cm $ do+ m <- codeMirror+ lift $ do+ rect <- (m ^. charCoords i "window" >>= valToObject)+ l <- rect ^. left >>= valToNumber+ r <- rect ^. right >>= valToNumber+ t <- rect ^. top >>= valToNumber+ b <- rect ^. bottom >>= valToNumber+ return $ Rectangle (round l) (round t) (round $ r - l) (round $ b - t)+ getOverwrite (CMView cm) = return False -- TODO+ getScrolledWindow (CMView (v,_)) = liftIO . fmap (castToScrolledWindow . fromJust) $ widgetGetParent v+ getEditorWidget (CMView (v,_)) = return $ castToWidget v+ grabFocus (CMView cm) = runCM cm $ do+ v <- webView+ liftIO $ widgetGrabFocus v+ scrollToMark (CMView cm) m withMargin mbAlign = do+ i <- getIterAtMark (CMBuffer cm) m+ scrollToIter (CMView cm) i withMargin mbAlign+ scrollToIter (CMView cm) (CMIter _ i) withMargin mbAlign = runCM cm $ do+ m <- codeMirror+ lift $ m ^. scrollIntoView i withMargin >> return ()+ setFont (CMView cm) mbFontString = return () -- TODO+ setIndentWidth (CMView cm) width = return () -- TODO+ setWrapMode (CMView cm) width = return () -- TODO+ setRightMargin (CMView cm) mbRightMargin = return () -- TODO+ setShowLineNumbers (CMView cm) show = return () -- TODO+ setTabWidth (CMView cm) width = return () -- TODO+ backwardCharC (CMIter cm i) = runCM cm $ do+ m <- codeMirror+ lift $ do+ n <- m ^. indexFromPos i >>= valToNumber+ i2 <- m ^. posFromIndex (n - 1)+ return (CMIter cm i2)+ backwardFindCharC (CMIter cm i) pred mbLimit = return Nothing -- TODO+ backwardWordStartC (CMIter cm i) = return Nothing -- TODO+ backwardToLineStartC (CMIter cm i) = runCM cm $ do+ m <- codeMirror+ lift $ do+ i2 <- obj+ i2 ^. line <# i ^. line+ i2 ^. ch <# (0 :: Double)+ return $ CMIter cm i2+ endsWord (CMIter cm i) = return False -- TODO+ forwardCharC (CMIter cm i) = runCM cm $ do+ m <- codeMirror+ lift $ do+ n <- m ^. indexFromPos i >>= valToNumber+ i2 <- m ^. posFromIndex (n + 1)+ return (CMIter cm i2)+ forwardCharsC (CMIter cm i) d = runCM cm $ do+ m <- codeMirror+ lift $ do+ n <- m ^. indexFromPos i >>= valToNumber+ i2 <- m ^. posFromIndex (n + fromIntegral d)+ return (CMIter cm i2)+ forwardFindCharC (CMIter cm i) pred mbLimit = return Nothing -- TODO+ forwardSearch (CMIter cm i) str pred mbLimit = return Nothing -- TODO+ forwardToLineEndC (CMIter cm i) = runCM cm $ do+ m <- codeMirror+ lift $ do+ i2 <- obj+ l <- i ^. line >>= makeValueRef+ i2 ^. line <# l+ i2 ^. ch <# m ^. getLineText l ^. jsLength+ return $ CMIter cm i2+ forwardWordEndC (CMIter cm i) = return Nothing -- TODO+ getChar (CMIter cm i) = return Nothing -- TODO+ getCharsInLine (CMIter cm i) = runCM cm $ do+ m <- codeMirror+ lift $ round <$> (m ^. getLineText (i ^. line) ^. jsLength >>= valToNumber)+ getLine (CMIter cm i) = runCM cm $ do+ lift $ round <$> (i ^. line >>= valToNumber)+ getLineOffset (CMIter cm i) = runCM cm $ do+ lift $ round <$> (i ^. ch >>= valToNumber)+ getOffset (CMIter cm i) = runCM cm $ do+ m <- codeMirror+ lift $ round <$> (m ^. indexFromPos i >>= valToNumber)+ isStart i@(CMIter cm _) = do+ start <- getStartIter (CMBuffer cm)+ iterEqual start i+ isEnd i@(CMIter cm _) = do+ end <- getEndIter (CMBuffer cm)+ iterEqual end i+ iterEqual (CMIter cm i1) (CMIter _ i2) = runCM cm . lift $ do+ l1 <- i1 ^. line >>= valToNumber+ l2 <- i2 ^. line >>= valToNumber+ if l1 /= l2+ then return False+ else do+ c1 <- i1 ^. ch >>= valToNumber+ c2 <- i2 ^. ch >>= valToNumber+ return $ c1 == c2+ startsLine i = (== 0) <$> getLineOffset i+ startsWord (CMIter cm i) = return False -- TODO+ atEnd (CMIter cm _) = getEndIter (CMBuffer cm)+ atLine (CMIter cm _) l = runCM cm $ do+ m <- codeMirror+ lift $ do+ i2 <- obj+ i2 ^. line <# (fromIntegral l :: Double)+ i2 ^. ch <# (0 :: Double)+ return $ CMIter cm i2+ atLineOffset (CMIter cm i) column = runCM cm $ do+ m <- codeMirror+ lift $ do+ i2 <- obj+ i2 ^. line <# i ^. line+ i2 ^. ch <# (fromIntegral column :: Double)+ return $ CMIter cm i2+ atOffset (CMIter cm _ ) offset = getIterAtOffset (CMBuffer cm) offset+ atStart (CMIter cm _) = getStartIter (CMBuffer cm)+ newTag (CMTagTable cm) name = return CMTag -- TODO+ lookupTag (CMTagTable cm) name = return Nothing -- TODO+ background (CMTag) color = return () -- TODO+ underline (CMTag) value = return () -- TODO+ afterFocusIn (CMView (v, _)) f = do+ ideR <- ask+ liftIO $ do+ id1 <- v `after` focusInEvent $ lift $ reflectIDE f ideR >> return False+ return [ConnectC id1]+ afterModifiedChanged (CMBuffer cm) f = return [] -- TODO+ afterMoveCursor (CMView cm) f = return [] -- TODO+ afterToggleOverwrite (CMView cm) f = return [] -- TODO+ onButtonPress (CMView (v, _)) f = do+ id1 <- v `onIDE` buttonPressEvent $ f+ return [ConnectC id1]+ onButtonRelease (CMView (v, _)) f = do+ id1 <- v `onIDE` buttonReleaseEvent $ f+ return [ConnectC id1]+ onCompletion (CMView cm) start cancel = return [] -- TODO+ onKeyPress (CMView (v, _)) f = do+ id1 <- v `onIDE` keyPressEvent $ f+ return [ConnectC id1]+ onMotionNotify (CMView (v, _)) f = do+ id1 <- v `onIDE` motionNotifyEvent $ f+ return [ConnectC id1]+ onLeaveNotify (CMView (v, _)) f = do+ id1 <- v `onIDE` leaveNotifyEvent $ f+ return [ConnectC id1]+ onKeyRelease (CMView (v, _)) f = do+ id1 <- v `onIDE` keyReleaseEvent $ f+ return [ConnectC id1]+ onLookupInfo (CMView (v, _)) f = do+ ideR <- ask+ liftIO $ do+ v `widgetAddEvents` [ButtonReleaseMask]+ id1 <- (`reflectIDE` ideR) $ v `onIDE` buttonReleaseEvent $ do+ mod <- lift $ eventModifier+ case mod of+ [Control] -> f >> return True+ _ -> return False+ return [ConnectC id1]+ onMotionNotifyEvent (CMView cm) f = return [] -- TODO+ onPopulatePopup (CMView (v, _)) f = do+ ideR <- ask+ liftIO $ do+ id1 <- on v popupMenuSignal $ do+ menu <- menuNew+ menuAttachToWidget menu v+ reflectIDE (f menu) ideR+ menuPopup menu Nothing+ return True+ return [ConnectC id1]+#endif+
@@ -0,0 +1,453 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE TypeFamilies #-}+-----------------------------------------------------------------------------+--+-- Module : IDE.TextEditor.GtkSourceView+-- Copyright : 2007-2013 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.TextEditor.GtkSourceView (+ TextEditor(..)+ , EditorBuffer(..)+ , EditorView(..)+ , EditorIter(..)+ , EditorMark(..)+ , EditorTag(..)+ , EditorTagTable(..)++ , GtkSourceView(..)+ , newGtkBuffer+ , simpleGtkBuffer++) where++import IDE.TextEditor.Class (TextEditor(..))+import IDE.Core.Types (colorHexString, Prefs(..), IDE(..), IDEM)+import Control.Monad.IO.Class (MonadIO(..))+import Graphics.UI.Gtk+ (castToWidget, textViewGetIterAtLocation, focusOutEvent,+ focusInEvent, modifiedChanged, textTagUnderline, textTagBackground,+ textTagTableLookup, textTagTableAdd, textTagNew, textIterSetOffset,+ textIterSetLineOffset, textIterSetLine, textIterGetBuffer,+ textIterStartsWord, textIterStartsLine, textIterIsEnd,+ textIterIsStart, textIterGetOffset, textIterGetLine,+ textIterGetCharsInLine, textIterGetChar, textIterForwardWordEnd,+ textIterForwardToLineEnd, textIterForwardSearch,+ textIterForwardFindChar, textIterForwardChars, textIterForwardChar,+ textIterEndsWord, textIterBackwardChars, textIterGetLineOffset,+ textIterBackwardWordStart, textIterBackwardFindChar,+ textIterBackwardChar, populatePopup, eventModifier,+ keyReleaseEvent, leaveNotifyEvent, motionNotifyEvent,+ keyPressEvent, focusOutEvent, textIterEqual, idleAdd,+ bufferInsertText, buttonReleaseEvent, buttonPressEvent,+ toggleOverwrite, endUserAction, widgetAddEvents, moveCursor,+ scrolledWindowSetPolicy, textViewScrollToIter,+ textViewScrollToMark, widgetGrabFocus, widgetGetParent,+ castToScrolledWindow, textViewGetOverwrite,+ textViewGetIterLocation, textViewBuffer,+ textViewBufferToWindowCoords, textBufferSetModified,+ textBufferSelectRange, textBufferRemoveTagByName,+ textBufferPlaceCursor, textBufferPasteClipboard, widgetModifyFont,+ containerAdd, scrolledWindowNew, textViewSetWrapMode,+ textBufferMoveMark, textBufferInsert, textBufferHasSelection,+ textBufferGetText, textBufferGetTagTable, textBufferGetStartIter,+ textBufferGetSlice, textBufferGetSelectionBounds,+ textBufferGetSelectionBound, textBufferGetModified,+ textBufferGetLineCount, textBufferGetIterAtOffset,+ textBufferGetIterAtMark, textBufferGetIterAtLine,+ textBufferGetInsert, textBufferGetEndIter, textBufferEndUserAction,+ textBufferDeleteSelection, textBufferDelete,+ textBufferCutClipboard, textBufferCreateMark,+ textBufferCopyClipboard, textBufferBeginUserAction,+ textBufferApplyTagByName, TextTag, TextTagTable, TextMark,+ textBufferSetText, textIterCopy, TextIter, Modifier(..),+ FontDescription, fontDescriptionFromString, fontDescriptionNew,+ fontDescriptionSetFamily, EventMask(..), after,+#ifdef MIN_VERSION_gtk3+ widgetGetWindow+#else+ widgetGetDrawWindow+#endif+ )+import Data.Typeable (Typeable)+import Control.Applicative ((<$>))+import Graphics.UI.Gtk.SourceView+ (sourceStyleSchemeManagerAppendSearchPath, sourceViewSetTabWidth,+ sourceViewSetShowLineNumbers, sourceViewSetRightMarginPosition,+ sourceViewSetShowRightMargin, sourceViewSetIndentWidth,+ castToSourceBuffer, sourceViewSetDrawSpaces, sourceBufferUndo,+ sourceBufferSetStyleScheme, sourceStyleSchemeManagerGetScheme,+ sourceStyleSchemeManagerGetSchemeIds, sourceStyleSchemeManagerNew,+ sourceBufferRedo, sourceViewSetSmartHomeEnd,+ sourceViewSetAutoIndent, sourceViewSetIndentOnTab,+ sourceViewSetInsertSpacesInsteadOfTabs,+ sourceViewSetHighlightCurrentLine, sourceViewNewWithBuffer,+ sourceBufferGetCanUndo, sourceBufferGetCanRedo, SourceView,+ SourceBuffer, sourceBufferEndNotUndoableAction,+ sourceBufferBeginNotUndoableAction, sourceBufferSetMaxUndoLevels,+ sourceBufferNew, sourceBufferNewWithLanguage,+ sourceLanguageManagerGuessLanguage,+ sourceLanguageManagerSetSearchPath,+ sourceLanguageManagerGetSearchPath, sourceLanguageManagerNew)+import System.FilePath ((</>))+import System.GIO (contentTypeGuess)+import IDE.Core.State (onIDE, reflectIDE, readIDE, getDataDir)+import Graphics.UI.Gtk.SourceView.Enums+ (SourceDrawSpacesFlags(..), SourceSmartHomeEndType(..))+import Graphics.UI.Gtk.General.Enums+ (PolicyType(..), TextWindowType(..), WrapMode(..))+import Control.Monad (when, forM_)+import Control.Monad.Reader.Class (MonadReader(..))+import Graphics.UI.Editor.Basics (Connection(..))+import Data.Maybe (maybeToList, fromJust)+import Data.IORef (writeIORef, readIORef, newIORef)+import System.Glib.MainLoop (priorityDefault, idleRemove)+import Data.Char (isSymbol, isAlphaNum)+import System.Glib.Signals (after, on)+import Control.Monad.Trans.Class (MonadTrans(..))+import System.Glib.Attributes (get, AttrOp(..), set)+import qualified Graphics.UI.Gtk as Gtk (endUserAction)+import IDE.Utils.GUIUtils (fontDescription)++transformGtkIter :: EditorIter GtkSourceView -> (TextIter -> IO a) -> IDEM (EditorIter GtkSourceView)+transformGtkIter (GtkIter i) f = do+ new <- liftIO $ textIterCopy i+ liftIO $ f new+ return (GtkIter new)++transformGtkIterMaybe :: EditorIter GtkSourceView -> (TextIter -> IO Bool) -> IDEM (Maybe (EditorIter GtkSourceView))+transformGtkIterMaybe (GtkIter i) f = do+ new <- liftIO $ textIterCopy i+ found <- liftIO $ f new+ return $ if found+ then Just (GtkIter new)+ else Nothing++data GtkSourceView = GtkSourceView deriving( Typeable, Show )++newGtkBuffer :: Maybe FilePath -> String -> IDEM (EditorBuffer GtkSourceView)+newGtkBuffer mbFilename contents = liftIO $ do+ lm <- sourceLanguageManagerNew+ dataDir <- getDataDir+ oldPath <- sourceLanguageManagerGetSearchPath lm+ sourceLanguageManagerSetSearchPath lm (Just $ (dataDir </> "language-specs") : oldPath)+ mbLang <- case mbFilename of+ Just filename -> do+ guess <- contentTypeGuess filename contents (length contents)+ sourceLanguageManagerGuessLanguage lm (Just filename) $+ case guess of+ (True, _) -> Just "text/x-haskell"+ (False, t) -> Just t+ Nothing -> sourceLanguageManagerGuessLanguage lm Nothing (Just "text/x-haskell")+ mbLang2 <- case mbLang of+ Nothing -> sourceLanguageManagerGuessLanguage lm Nothing (Just "text/x-haskell")+ _ -> return mbLang+ buffer <- case mbLang2 of+ Just sLang -> sourceBufferNewWithLanguage sLang+ Nothing -> sourceBufferNew Nothing+ sourceBufferSetMaxUndoLevels buffer (-1)+ sourceBufferBeginNotUndoableAction buffer+ textBufferSetText buffer contents+ sourceBufferEndNotUndoableAction buffer+ return $ GtkBuffer buffer++instance TextEditor GtkSourceView where+ data EditorBuffer GtkSourceView = GtkBuffer SourceBuffer+ data EditorView GtkSourceView = GtkView SourceView+ data EditorMark GtkSourceView = GtkMark TextMark+ data EditorIter GtkSourceView = GtkIter TextIter+ data EditorTagTable GtkSourceView = GtkTagTable TextTagTable+ data EditorTag GtkSourceView = GtkTag TextTag++ newBuffer = newGtkBuffer+ applyTagByName (GtkBuffer sb) name (GtkIter first) (GtkIter last) = liftIO $+ textBufferApplyTagByName sb name first last+ beginNotUndoableAction (GtkBuffer sb) = liftIO $ sourceBufferBeginNotUndoableAction sb+ beginUserAction (GtkBuffer sb) = liftIO $ textBufferBeginUserAction sb+ canRedo (GtkBuffer sb) = liftIO $ sourceBufferGetCanRedo sb+ canUndo (GtkBuffer sb) = liftIO $ sourceBufferGetCanUndo sb+ copyClipboard (GtkBuffer sb) clipboard = liftIO $ textBufferCopyClipboard sb clipboard+ createMark (GtkBuffer sb) (GtkIter i) leftGravity = liftIO $ GtkMark <$> textBufferCreateMark sb Nothing i leftGravity+ cutClipboard (GtkBuffer sb) clipboard defaultEditable = liftIO $ textBufferCutClipboard sb clipboard defaultEditable+ delete (GtkBuffer sb) (GtkIter first) (GtkIter last) = liftIO $+ textBufferDelete sb first last+ deleteSelection (GtkBuffer sb) = liftIO $+ textBufferDeleteSelection sb True True >> return ()+ endNotUndoableAction (GtkBuffer sb) = liftIO $ sourceBufferEndNotUndoableAction sb+ endUserAction (GtkBuffer sb) = liftIO $ textBufferEndUserAction sb+ getEndIter (GtkBuffer sb) = liftIO $ GtkIter <$> textBufferGetEndIter sb+ getInsertMark (GtkBuffer sb) = liftIO $ GtkMark <$> textBufferGetInsert sb+ getIterAtLine (GtkBuffer sb) line = liftIO $ GtkIter <$> textBufferGetIterAtLine sb line+ getIterAtMark (GtkBuffer sb) (GtkMark m) = liftIO $ GtkIter <$> textBufferGetIterAtMark sb m+ getIterAtOffset (GtkBuffer sb) offset = liftIO $ GtkIter <$> textBufferGetIterAtOffset sb offset+ getLineCount (GtkBuffer sb) = liftIO $ textBufferGetLineCount sb+ getModified (GtkBuffer sb) = liftIO $ textBufferGetModified sb+ getSelectionBoundMark (GtkBuffer sb) = liftIO $ GtkMark <$> textBufferGetSelectionBound sb+ getSelectionBounds (GtkBuffer sb) = liftIO $ (\(a, b) -> (GtkIter a, GtkIter b)) <$>+ textBufferGetSelectionBounds sb+ getInsertIter (GtkBuffer sb) = liftIO $ GtkIter <$> do+ insertMark <- textBufferGetInsert sb+ textBufferGetIterAtMark sb insertMark+ getSlice (GtkBuffer sb) (GtkIter first) (GtkIter last) includeHidenChars = liftIO $+ textBufferGetSlice sb first last includeHidenChars+ getStartIter (GtkBuffer sb) = liftIO $ GtkIter <$> textBufferGetStartIter sb+ getTagTable (GtkBuffer sb) = liftIO $ GtkTagTable <$> textBufferGetTagTable sb+ getText (GtkBuffer sb) (GtkIter first) (GtkIter last) includeHidenChars = liftIO $+ textBufferGetText sb first last includeHidenChars+ hasSelection (GtkBuffer sb) = liftIO $ textBufferHasSelection sb+ insert (GtkBuffer sb) (GtkIter i) text = liftIO $ textBufferInsert sb i text+ newView (GtkBuffer sb) mbFontString = do+ prefs <- readIDE prefs+ fd <- fontDescription mbFontString+ liftIO $ GtkView <$> do+ sv <- sourceViewNewWithBuffer sb+ sourceViewSetHighlightCurrentLine sv True+ sourceViewSetInsertSpacesInsteadOfTabs sv True+ sourceViewSetIndentOnTab sv True+ sourceViewSetAutoIndent sv True+ sourceViewSetSmartHomeEnd sv SourceSmartHomeEndBefore+ if wrapLines prefs+ then textViewSetWrapMode sv WrapWord+ else textViewSetWrapMode sv WrapNone+ sw <- scrolledWindowNew Nothing Nothing+ containerAdd sw sv+ widgetModifyFont sv (Just fd)+ return sv+ pasteClipboard (GtkBuffer sb) clipboard (GtkIter i) defaultEditable = liftIO $+ textBufferPasteClipboard sb clipboard i defaultEditable+ placeCursor (GtkBuffer sb) (GtkIter i) = liftIO $ textBufferPlaceCursor sb i+ redo (GtkBuffer sb) = liftIO $ sourceBufferRedo sb+ removeTagByName (GtkBuffer sb) name = liftIO $ do+ first <- textBufferGetStartIter sb+ last <- textBufferGetEndIter sb+ textBufferRemoveTagByName sb name first last+ selectRange (GtkBuffer sb) (GtkIter first) (GtkIter last) = liftIO $+ textBufferSelectRange sb first last+ setModified (GtkBuffer sb) modified = liftIO $ textBufferSetModified sb modified >> return ()+ setStyle preferDark (GtkBuffer sb) mbStyle = liftIO $ do+ case mbStyle of+ Nothing -> return ()+ Just str -> do+ styleManager <- sourceStyleSchemeManagerNew+ dataDir <- getDataDir+ sourceStyleSchemeManagerAppendSearchPath styleManager $ dataDir </> "data/styles"+ ids <- sourceStyleSchemeManagerGetSchemeIds styleManager+ let preferedNames = if preferDark then [str++"-dark", str] else [str]+ forM_ (take 1 $ filter (flip elem ids) preferedNames) $ \ name -> do+ scheme <- sourceStyleSchemeManagerGetScheme styleManager name+ sourceBufferSetStyleScheme sb (Just scheme)+ setText (GtkBuffer sb) text = liftIO $ textBufferSetText sb text+ undo (GtkBuffer sb) = liftIO $ sourceBufferUndo sb++ afterModifiedChanged (GtkBuffer sb) f = do+ ideR <- ask+ liftIO $ do+ id1 <- sb `after` modifiedChanged $ reflectIDE f ideR+ return [ConnectC id1]++ -- View+ bufferToWindowCoords (GtkView sv) point = liftIO $ textViewBufferToWindowCoords sv TextWindowWidget point+ drawTabs (GtkView sv) = liftIO $ sourceViewSetDrawSpaces sv SourceDrawSpacesTab+ getBuffer (GtkView sv) = liftIO $ (GtkBuffer . castToSourceBuffer) <$> sv `get` textViewBuffer+#ifdef MIN_VERSION_gtk3+ getWindow (GtkView sv) = liftIO $ widgetGetWindow sv+#else+ getWindow (GtkView sv) = liftIO $ Just <$> widgetGetDrawWindow sv+#endif+ getIterAtLocation (GtkView sv) x y = liftIO $ GtkIter <$> textViewGetIterAtLocation sv x y+ getIterLocation (GtkView sv) (GtkIter i) = liftIO $ textViewGetIterLocation sv i+ getOverwrite (GtkView sv) = liftIO $ textViewGetOverwrite sv+ getScrolledWindow (GtkView sv) = liftIO $ fmap (castToScrolledWindow . fromJust) $ widgetGetParent sv+ getEditorWidget (GtkView sv) = return $ castToWidget sv+ grabFocus (GtkView sv) = liftIO $ widgetGrabFocus sv+ scrollToMark (GtkView sv) (GtkMark m) withMargin mbAlign = liftIO $ textViewScrollToMark sv m withMargin mbAlign+ scrollToIter (GtkView sv) (GtkIter i) withMargin mbAlign = liftIO $ textViewScrollToIter sv i withMargin mbAlign >> return ()+ setFont (GtkView sv) mbFontString = do+ fd <- fontDescription mbFontString+ liftIO $ widgetModifyFont sv (Just fd)+ setIndentWidth (GtkView sv) width = liftIO $ sourceViewSetIndentWidth sv width+ setWrapMode v@(GtkView sv) wrapLines = do+ sw <- getScrolledWindow v+ if wrapLines+ then liftIO $ do+ textViewSetWrapMode sv WrapWord+ scrolledWindowSetPolicy sw PolicyNever PolicyAutomatic+ else liftIO $ do+ textViewSetWrapMode sv WrapNone+ scrolledWindowSetPolicy sw PolicyAutomatic PolicyAutomatic+ setRightMargin (GtkView sv) mbRightMargin = liftIO $ do+ case mbRightMargin of+ Just n -> do+ sourceViewSetShowRightMargin sv True+ sourceViewSetRightMarginPosition sv (fromIntegral n)+ Nothing -> sourceViewSetShowRightMargin sv False+ setShowLineNumbers (GtkView sv) show = liftIO $ sourceViewSetShowLineNumbers sv show+ setTabWidth (GtkView sv) width = liftIO $ sourceViewSetTabWidth sv width++ -- Events+ afterFocusIn (GtkView sv) f = do+ ideR <- ask+ liftIO $ do+ id1 <- sv `after` focusInEvent $ lift $ reflectIDE f ideR >> return False+ return [ConnectC id1]+ afterMoveCursor v@(GtkView sv) f = do+ ideR <- ask+ (GtkBuffer sb) <- getBuffer v+ liftIO $ do+ id1 <- sv `after` moveCursor $ \_ _ _ -> reflectIDE f ideR+ sv `widgetAddEvents` [ButtonReleaseMask]+ id2 <- sv `on` buttonReleaseEvent $ lift $ reflectIDE f ideR >> return False+ id3 <- sb `after` Gtk.endUserAction $ reflectIDE f ideR+ return [ConnectC id1, ConnectC id2, ConnectC id3]+ afterToggleOverwrite (GtkView sv) f = do+ ideR <- ask+ liftIO $ do+ id1 <- sv `after` toggleOverwrite $ reflectIDE f ideR+ return [ConnectC id1]+ onButtonPress (GtkView sv) f = do+ id1 <- sv `onIDE` buttonPressEvent $ f+ return [ConnectC id1]+ onButtonRelease (GtkView sv) f = do+ id1 <- sv `onIDE` buttonReleaseEvent $ f+ return [ConnectC id1]+ onCompletion v@(GtkView sv) start cancel = do+ ideR <- ask+ (GtkBuffer sb) <- getBuffer v+ liftIO $ do+ -- when multiple afterBufferInsertText are called quickly,+ -- we cancel previous idle action which was not processed,+ -- its handler is stored here.+ -- Paste operation is example of such sequential events (each word!).+ lastHandler <- newIORef Nothing+ id1 <- after sb bufferInsertText $ \iter text -> do+ mapM_ idleRemove =<< maybeToList <$> readIORef lastHandler+ writeIORef lastHandler =<< Just <$> do+ (flip idleAdd) priorityDefault $ do+ let isIdent a = isAlphaNum a || a == '\'' || a == '_' || a == '.'+ let isOp a = isSymbol a || a == ':' || a == '\\' || a == '*' || a == '/' || a == '-'+ || a == '!' || a == '@' || a == '%' || a == '&' || a == '?'+ if (all isIdent text) || (all isOp text)+ then do+ hasSel <- textBufferHasSelection sb+ if not hasSel+ then do+ (iterC, _) <- textBufferGetSelectionBounds sb+ atC <- textIterEqual iter iterC+ when atC $ reflectIDE start ideR+ return False+ else do+ reflectIDE cancel ideR+ return False+ else do+ reflectIDE cancel ideR+ return False+ return ()+ id2 <- sv `on` moveCursor $ \_ _ _ -> reflectIDE cancel ideR+ id3 <- sv `on` buttonPressEvent $ lift $ reflectIDE cancel ideR >> return False+ id4 <- sv `on` focusOutEvent $ lift $ reflectIDE cancel ideR >> return False+ return [ConnectC id1, ConnectC id2, ConnectC id3, ConnectC id4]+ onKeyPress (GtkView sv) f = do+ id1 <- sv `onIDE` keyPressEvent $ f+ return [ConnectC id1]+ onMotionNotify (GtkView sv) f = do+ id1 <- sv `onIDE` motionNotifyEvent $ f+ return [ConnectC id1]+ onLeaveNotify (GtkView sv) f = do+ id1 <- sv `onIDE` leaveNotifyEvent $ f+ return [ConnectC id1]+ onKeyRelease (GtkView sv) f = do+ id1 <- sv `onIDE` keyReleaseEvent $ f+ return [ConnectC id1]+ onLookupInfo (GtkView sv) f = do+ liftIO $ sv `widgetAddEvents` [ButtonReleaseMask]+ id1 <- sv `onIDE` buttonReleaseEvent $ do+ mod <- lift $ eventModifier+ case mod of+ [Control] -> f >> return True+ _ -> return False+ return [ConnectC id1]+ onMotionNotifyEvent (GtkView sv) handler = do+ liftIO $ widgetAddEvents sv [ButtonMotionMask, Button1MotionMask] -- TODO: this doesn't work yet event gets fired anyways: restrict event to being fired when left mouse button is pressed down+ id1 <- sv `onIDE` motionNotifyEvent $ handler --TODO this is potentially slowing leksah, a better event (if there was any) could be more efficient here+ liftIO $ widgetAddEvents sv [ButtonMotionMask, Button1MotionMask] -- TODO: this doesn't work yet event gets fired anyways: restrict event to being fired when left mouse button is pressed down+ return [ConnectC id1]+ onPopulatePopup (GtkView sv) f = do+ ideR <- ask+ liftIO $ do+ id1 <- sv `on` populatePopup $ \menu -> reflectIDE (f menu) ideR+ return [ConnectC id1]++ -- Iter+ backwardCharC i = transformGtkIter i textIterBackwardChar+ backwardFindCharC i pred mbLimit = transformGtkIterMaybe i $ \x ->+ textIterBackwardFindChar x pred $+ case mbLimit of+ Just (GtkIter limit) -> Just limit+ Nothing -> Nothing+ backwardWordStartC i = transformGtkIterMaybe i textIterBackwardWordStart+ backwardToLineStartC i = transformGtkIter i $ \new -> do+ n <- textIterGetLineOffset new+ textIterBackwardChars new n+ return ()+ endsWord (GtkIter i) = liftIO $ textIterEndsWord i+ forwardCharC i = transformGtkIter i textIterForwardChar+ forwardCharsC i n = transformGtkIter i $ flip textIterForwardChars n+ forwardFindCharC i pred mbLimit = transformGtkIterMaybe i $ \x ->+ textIterForwardFindChar x pred $+ case mbLimit of+ Just (GtkIter limit) -> Just limit+ Nothing -> Nothing+ forwardSearch (GtkIter i) str flags mbLimit = liftIO $ fmap (fmap (\(a, b) -> (GtkIter a, GtkIter b))) $+ textIterForwardSearch i str flags $+ case mbLimit of+ Just (GtkIter limit) -> Just limit+ Nothing -> Nothing+ forwardToLineEndC i = transformGtkIter i textIterForwardToLineEnd+ forwardWordEndC i = transformGtkIterMaybe i textIterForwardWordEnd+ getChar (GtkIter i) = liftIO $ textIterGetChar i+ getCharsInLine (GtkIter i) = liftIO $ textIterGetCharsInLine i+ getLine (GtkIter i) = liftIO $ textIterGetLine i+ getLineOffset (GtkIter i) = liftIO $ textIterGetLineOffset i+ getOffset (GtkIter i) = liftIO $ textIterGetOffset i+ isStart (GtkIter i) = liftIO $ textIterIsStart i+ isEnd (GtkIter i) = liftIO $ textIterIsEnd i+ iterEqual (GtkIter i1) (GtkIter i2) = liftIO $ textIterEqual i1 i2+ startsLine (GtkIter i) = liftIO $ textIterStartsLine i+ startsWord (GtkIter i) = liftIO $ textIterStartsWord i+ atEnd (GtkIter i) = liftIO $ GtkIter <$> do+ buffer <- textIterGetBuffer i+ textBufferGetEndIter buffer+ atLine i line = transformGtkIter i $ flip textIterSetLine line+ atLineOffset i column = transformGtkIter i $ flip textIterSetLineOffset column+ atOffset i offset = transformGtkIter i $ flip textIterSetOffset offset+ atStart (GtkIter i) = liftIO $ GtkIter <$> do+ buffer <- textIterGetBuffer i+ textBufferGetEndIter buffer++ -- Tag Table+ newTag (GtkTagTable tt) name = liftIO $ GtkTag <$> do+ t <- textTagNew (Just name)+ textTagTableAdd tt t+ return t+ lookupTag (GtkTagTable tt) name = liftIO $ fmap GtkTag <$> textTagTableLookup tt name++ -- Tag+ background (GtkTag t) color = liftIO $ set t [textTagBackground := colorHexString color]+ underline (GtkTag t) value = liftIO $ set t [textTagUnderline := value]++simpleGtkBuffer :: String -> IDEM (EditorBuffer GtkSourceView)+simpleGtkBuffer contents = liftIO $ GtkBuffer <$> do+ buffer <- sourceBufferNew Nothing+ textBufferSetText buffer contents+ return buffer++
@@ -0,0 +1,325 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE TypeFamilies #-}+-----------------------------------------------------------------------------+--+-- Module : IDE.TextEditor.Yi+-- Copyright : 2007-2013 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.TextEditor.Yi (+ Yi(..)++#ifdef LEKSAH_WITH_YI+ , TextEditor(..)+ , EditorBuffer(..)+ , EditorView(..)+ , EditorIter(..)+ , EditorMark(..)+ , EditorTag(..)+ , EditorTagTable(..)++ , newYiBuffer+#endif+) where++import Data.Typeable (Typeable)+import Graphics.UI.Gtk (castToWidget)++#ifdef LEKSAH_WITH_YI+import IDE.TextEditor.Class (TextEditor(..))+import IDE.Core.Types (IDEM)+import IDE.Core.State (liftYi, onIDE, reflectIDE, liftYiControl)+import qualified Yi.UI.Pango.Control as Yi+ (getBuffer, setText, newView, getText, newBuffer)+import Yi.UI.Pango.Control+ (Control(..), View(..), iterFBufRef, Iter(..), fBufRef, Buffer(..),+ setBufferMode)+import Yi+ (moveToColB, gotoLn, atSol, atEof, atSof, curCol, curLn, readLnB,+ readCharB, nextWordB, moveToEol, rightB, rightN, nextPointB,+ unitWord, atBoundaryB, moveToSol, prevWordB, leftB, readB,+ doUntilB_, prevPointB, Mode, modifyMode, insertingA, getA, undoB,+ markSavedB, setSelectRegionB, redoB, setMarkPointB, insertNAt,+ regionIsEmpty, regionEnd, regionStart, selMark, isUnchangedBuffer,+ Point(..), MarkValue(..), lineOf, getMarkPointB, pointOfLineColB,+ askMarks, insMark, sizeB, getRawestSelectRegionB, mkRegion,+ deleteRegionB, newMarkB, Mark, pointB, moveTo, savingPointB, Point,+ withGivenBuffer0, liftEditor, BufferM, BufferRef, Mode(..),+ IndentSettings(..))+import Control.Applicative ((<$>))+import Yi.Keymap.Cua (paste, cut, copy)+import Yi.Buffer.Basic (Direction(..))+import Control.Monad.State.Class (gets)+import Control.Monad (unless)+import Control.Monad.IO.Class (MonadIO(..))+import Data.Time (getCurrentTime)+import qualified Graphics.UI.Gtk as Gtk (Modifier(..))+import IDE.Utils.GUIUtils (fontDescription)+import Graphics.UI.Gtk+ (popupMenuSignal, focusInEvent, menuPopup, menuAttachToWidget,+ menuNew, eventModifier, widgetAddEvents, keyReleaseEvent,+ leaveNotifyEvent, motionNotifyEvent, keyPressEvent,+ buttonReleaseEvent, buttonPressEvent, widgetGrabFocus,+ Rectangle(..), layoutSetFontDescription, EventMask(..),+#ifdef MIN_VERSION_gtk3+ widgetGetWindow+#else+ widgetGetDrawWindow+#endif+ )+import Control.Monad.Reader.Class (MonadReader(..))+import Graphics.UI.Editor.Basics (Connection(..))+import Control.Monad.Trans.Class (MonadTrans(..))+import System.Glib.Signals (on, after)+#endif++data Yi = Yi deriving( Typeable, Show )++#ifdef LEKSAH_WITH_YI+newYiBuffer :: Maybe FilePath -> String -> IDEM (EditorBuffer Yi)+newYiBuffer mbFilename contents = do+ liftYiControl $ do+ let (filename, id) = case mbFilename of+ Just fn -> (fn, Right fn)+ Nothing -> ("Unknown.hs", Left "*leksah*")+ buffer <- Yi.newBuffer id contents+ setBufferMode filename buffer+ return $ YiBuffer buffer++withYiBuffer' :: BufferRef -> BufferM a -> IDEM a+withYiBuffer' b f = liftYi $ liftEditor $ withGivenBuffer0 b f++withYiBuffer :: Buffer -> BufferM a -> IDEM a+withYiBuffer b f = withYiBuffer' (fBufRef b) f++mkYiIter' :: BufferRef -> Point -> EditorIter Yi+mkYiIter' b p = YiIter $ Iter b p++mkYiIter :: Buffer -> Point -> EditorIter Yi+mkYiIter b p = mkYiIter' (fBufRef b) p++withYiIter :: Iter -> BufferM a -> IDEM a+withYiIter (Iter b p) f = withYiBuffer' b $ do+ savingPointB $ do+ moveTo p+ f++transformYiIter' :: Iter -> BufferM Point -> IDEM (EditorIter Yi)+transformYiIter' i f = mkYiIter' (iterFBufRef i) <$> withYiIter i f++transformYiIter :: Iter -> BufferM a -> IDEM (EditorIter Yi)+transformYiIter i f = transformYiIter' i (f >> pointB)++tryTransformYiIter' :: Iter -> BufferM Point -> IDEM (Maybe (EditorIter Yi))+tryTransformYiIter' i@(Iter b p) f = withYiIter i $ do+ newPoint <- f+ if p == newPoint+ then return Nothing+ else return . Just $ mkYiIter' b newPoint++tryTransformYiIter :: Iter -> BufferM a -> IDEM (Maybe (EditorIter Yi))+tryTransformYiIter i f = tryTransformYiIter' i (f >> pointB)++iterFromYiBuffer' :: BufferRef -> BufferM Point -> IDEM (EditorIter Yi)+iterFromYiBuffer' b f = mkYiIter' b <$> withYiBuffer' b f++iterFromYiBuffer :: Buffer -> BufferM Point -> IDEM (EditorIter Yi)+iterFromYiBuffer b f = iterFromYiBuffer' (fBufRef b) f++instance TextEditor Yi where+ data EditorBuffer Yi = YiBuffer Buffer+ data EditorView Yi = YiView View+ data EditorMark Yi = YiMark Mark+ data EditorIter Yi = YiIter Iter+ data EditorTagTable Yi = YiTagTable+ data EditorTag Yi = YiTag++ newBuffer = newYiBuffer+ applyTagByName (YiBuffer fb) name (YiIter first) (YiIter last) = return () -- TODO+ beginNotUndoableAction (YiBuffer fb) = return () -- TODO+ beginUserAction (YiBuffer fb) = return () -- TODO+ canRedo (YiBuffer fb) = return True -- TODO+ canUndo (YiBuffer fb) = return True -- TODO+ copyClipboard (YiBuffer fb) _ = liftYi $ liftEditor $ copy+ createMark (YiBuffer b) (YiIter (Iter _ p)) leftGravity = withYiBuffer b $+ YiMark <$> newMarkB (MarkValue p (if leftGravity then Backward else Forward))+ cutClipboard (YiBuffer fb) clipboard defaultEditable = liftYi $ liftEditor $ cut+ delete (YiBuffer b) (YiIter (Iter _ first)) (YiIter (Iter _ last)) =+ withYiBuffer b $ deleteRegionB $ mkRegion first last+ deleteSelection (YiBuffer b) = withYiBuffer b $ do+ region <- getRawestSelectRegionB+ deleteRegionB region -- TODO support flags+ endNotUndoableAction (YiBuffer fb) = return () -- TODO+ endUserAction (YiBuffer fb) = return () -- TODO+ getEndIter (YiBuffer b) = iterFromYiBuffer b sizeB+ getInsertMark (YiBuffer b) = YiMark <$> (withYiBuffer b $ insMark <$> askMarks)+ getIterAtLine (YiBuffer b) line = iterFromYiBuffer b $ pointOfLineColB line 1+ getIterAtMark (YiBuffer b) (YiMark m) = iterFromYiBuffer b $ getMarkPointB m+ getIterAtOffset (YiBuffer b) offset = return $ mkYiIter b $ Point offset+ getLineCount (YiBuffer b) = withYiBuffer b $ sizeB >>= lineOf+ getModified (YiBuffer b) = not <$> (withYiBuffer b $ gets isUnchangedBuffer)+ getSelectionBoundMark (YiBuffer b) = YiMark . selMark <$> (withYiBuffer b $ askMarks)+ getSelectionBounds (YiBuffer b) = withYiBuffer b $ do+ region <- getRawestSelectRegionB+ return (mkYiIter b (regionStart region),+ mkYiIter b (regionEnd region))+ getInsertIter (YiBuffer b) = withYiBuffer b $ do+ insertMark <- insMark <$> askMarks+ mkYiIter b <$> getMarkPointB insertMark+ getSlice (YiBuffer b) (YiIter first) (YiIter last) includeHidenChars = liftYiControl $+ Yi.getText b first last+ getStartIter (YiBuffer b) = return $ mkYiIter b $ Point 0+ getTagTable (YiBuffer b) = return YiTagTable -- TODO+ getText (YiBuffer b) (YiIter first) (YiIter last) includeHidenChars = liftYiControl $+ Yi.getText b first last+ hasSelection (YiBuffer b) = withYiBuffer b $ do+ region <- getRawestSelectRegionB+ return $ not $ regionIsEmpty region+ insert (YiBuffer b) (YiIter (Iter _ p)) text = withYiBuffer b $ insertNAt text p+ newView (YiBuffer b) mbFontString = do+ fd <- fontDescription mbFontString+ liftYiControl $ fmap YiView $ Yi.newView b fd+ pasteClipboard (YiBuffer b) clipboard (YiIter (Iter _ p)) defaultEditable = liftYi $ liftEditor $ paste+ placeCursor (YiBuffer b) (YiIter (Iter _ p)) = withYiBuffer b $ moveTo p+ redo (YiBuffer b) = withYiBuffer b redoB+ removeTagByName (YiBuffer b) name = return () -- TODO+ selectRange (YiBuffer b) (YiIter (Iter _ first)) (YiIter (Iter _ last)) = withYiBuffer b $+ setSelectRegionB $ mkRegion first last+ setModified (YiBuffer b) modified = unless modified $ do+ now <- liftIO $ getCurrentTime+ withYiBuffer b $ markSavedB now+ setStyle preferDark (YiBuffer b) mbStyle = return () -- TODO+ setText (YiBuffer b) text = liftYiControl $ Yi.setText b text+ undo (YiBuffer b) = withYiBuffer b undoB+ bufferToWindowCoords (YiView v) point = return point -- TODO+ drawTabs (YiView _) = return () -- TODO+ getBuffer (YiView v) = return $ YiBuffer $ Yi.getBuffer v+#ifdef MIN_VERSION_gtk3+ getWindow (YiView v) = liftIO $ widgetGetWindow (drawArea v)+#else+ getWindow (YiView v) = liftIO $ Just <$> widgetGetDrawWindow (drawArea v)+#endif+ getIterAtLocation (YiView View{viewFBufRef = b}) x y = return $ mkYiIter' b $ Point 0 -- TODO+ getIterLocation (YiView v) (YiIter i) = return $ Rectangle 0 0 0 0 -- TODO+ getOverwrite (YiView View{viewFBufRef = b}) = withYiBuffer' b $ not <$> getA insertingA+ getScrolledWindow (YiView v) = return $ scrollWin v+ getEditorWidget (YiView v) = return $ castToWidget $ drawArea v+ grabFocus (YiView View{drawArea = da}) = liftIO $ widgetGrabFocus da+ scrollToMark (YiView v) (YiMark m) withMargin mbAlign = return () -- TODO+ scrollToIter (YiView v) (YiIter i) withMargin mbAlign = return () -- TODO+ setFont (YiView v) mbFontString = do+ fd <- fontDescription mbFontString+ liftIO $ layoutSetFontDescription (layout v) (Just fd)+ setIndentWidth (YiView View{viewFBufRef = b}) width =+ withYiBuffer' b $ modifyMode $+ \ (mode@Mode{modeIndentSettings = mis}) ->+ mode{modeIndentSettings = mis{shiftWidth = width}}+ setWrapMode (YiView View{viewFBufRef = b}) width = return ()+ setRightMargin (YiView v) mbRightMargin = return () -- TODO+ setShowLineNumbers (YiView v) show = return () -- TODO+ setTabWidth (YiView View{viewFBufRef = b}) width =+ withYiBuffer' b $ modifyMode $+ \ (mode@Mode{modeIndentSettings = mis}) ->+ mode{modeIndentSettings = mis{tabSize = width}}++ backwardCharC (YiIter i) = transformYiIter' i prevPointB+ backwardFindCharC (YiIter i) pred mbLimit = tryTransformYiIter i $+ doUntilB_ (pred <$> readB) leftB+ backwardWordStartC (YiIter i@(Iter b p)) = withYiIter i $ do+ prevWordB+ newPoint <- pointB+ if p == newPoint+ then return Nothing+ else return . Just $ mkYiIter' b newPoint+ backwardToLineStartC (YiIter i) = transformYiIter i moveToSol+ endsWord (YiIter i) = withYiIter i $ do+ atBoundaryB unitWord Forward+ forwardCharC (YiIter i) = transformYiIter' i nextPointB+ forwardCharsC (YiIter i) n = transformYiIter i $ rightN n+ forwardFindCharC (YiIter i) pred mbLimit = tryTransformYiIter i $+ doUntilB_ (pred <$> readB) rightB+ forwardSearch (YiIter i) str pred mbLimit = return Nothing -- TODO+ forwardToLineEndC (YiIter i) = transformYiIter i moveToEol+ forwardWordEndC (YiIter i@(Iter b p)) = withYiIter i $ do+ nextWordB+ newPoint <- pointB+ if p == newPoint+ then return Nothing+ else return . Just $ mkYiIter' b newPoint+ getChar (YiIter i) = withYiIter i readCharB+ getCharsInLine (YiIter i) = withYiIter i $ length <$> readLnB+ getLine (YiIter i) = withYiIter i curLn+ getLineOffset (YiIter i) = withYiIter i curCol+ getOffset (YiIter (Iter _ (Point o))) = return o+ isStart (YiIter i) = withYiIter i atSof+ isEnd (YiIter i) = withYiIter i atEof+ iterEqual (YiIter (Iter _ p1)) (YiIter (Iter _ p2)) = return $ p1 == p2+ startsLine (YiIter i) = withYiIter i atSol+ startsWord (YiIter i) = withYiIter i atSol -- TODO+ atEnd (YiIter (Iter b _)) = iterFromYiBuffer' b sizeB+ atLine (YiIter i) line = transformYiIter i $ gotoLn line+ atLineOffset (YiIter i) column = transformYiIter i $ moveToColB column+ atOffset (YiIter (Iter b _)) offset = return $ YiIter $ Iter b (Point offset)+ atStart (YiIter (Iter b _)) = return $ mkYiIter' b $ Point 0+ newTag (YiTagTable) name = return YiTag -- TODO+ lookupTag (YiTagTable) name = return Nothing -- TODO+ background (YiTag) color = return () -- TODO+ underline (YiTag) value = return () -- TODO+ afterFocusIn (YiView v) f = do+ ideR <- ask+ liftIO $ do+ id1 <- (drawArea v) `after` focusInEvent $ lift $ reflectIDE f ideR >> return False+ return [ConnectC id1]+ afterModifiedChanged (YiBuffer b) f = return [] -- TODO+ afterMoveCursor (YiView v) f = return [] -- TODO+ afterToggleOverwrite (YiView v) f = return [] -- TODO+ onButtonPress (YiView v) f = do+ id1 <- (drawArea v) `onIDE` buttonPressEvent $ f+ return [ConnectC id1]+ onButtonRelease (YiView v) f = do+ id1 <- (drawArea v) `onIDE` buttonReleaseEvent $ f+ return [ConnectC id1]+ onCompletion (YiView v) start cancel = return [] -- TODO+ onKeyPress (YiView v) f = do+ id1 <- (drawArea v) `onIDE` keyPressEvent $ f+ return [ConnectC id1]+ onMotionNotify (YiView v) f = do+ id1 <- (drawArea v) `onIDE` motionNotifyEvent $ f+ return [ConnectC id1]+ onLeaveNotify (YiView v) f = do+ id1 <- (drawArea v) `onIDE` leaveNotifyEvent $ f+ return [ConnectC id1]+ onKeyRelease (YiView v) f = do+ id1 <- (drawArea v) `onIDE` keyReleaseEvent $ f+ return [ConnectC id1]+ onLookupInfo (YiView v) f = do+ liftIO $ (drawArea v) `widgetAddEvents` [ButtonReleaseMask]+ id1 <- (drawArea v) `onIDE` buttonReleaseEvent $ do+ mod <- lift $ eventModifier+ case mod of+ [Gtk.Control] -> f >> return True+ _ -> return False+ return [ConnectC id1]+ onMotionNotifyEvent (YiView v) f = return [] -- TODO+ onPopulatePopup (YiView v) f = do+ ideR <- ask+ liftIO $ do+ id1 <- (drawArea v) `on` popupMenuSignal $ do+ menu <- menuNew+ menuAttachToWidget menu (drawArea v)+ reflectIDE (f menu) ideR+ menuPopup menu Nothing+ return True+ return [ConnectC id1]++#endif+
@@ -0,0 +1,109 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Utils.Tools+-- Copyright : 2007-2013 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.Utils.ExternalTool (+ runExternalTool'+ , runExternalTool+ , isRunning+ , interruptBuild+) where++import qualified Data.Conduit as C (Sink)+import IDE.Utils.Tool+ (interruptProcessGroupOf, getProcessExitCode, runTool,+ ProcessHandle, ToolOutput(..))+import IDE.Core.State+ (runningTool, modifyIDE_, reflectIDE, useVado, reifyIDE,+ triggerEventIDE, saveAllBeforeBuild, prefs, readIDE, IDEAction,+ IDEM)+import Control.Monad (when)+import IDE.Pane.SourceBuffer (belongsToWorkspace, fileSaveAll)+import IDE.Core.Types (StatusbarCompartment(..), IDEEvent(..))+import Control.Concurrent (forkIO)+import System.Process.Vado (vado, readSettings, getMountPoint)+import Data.Conduit (($$))+import Control.Monad.IO.Class (MonadIO(..))+import Data.Maybe (isNothing)+import Control.Applicative ((<$>))++runExternalTool' :: String+ -> FilePath+ -> [String]+ -> FilePath+ -> C.Sink ToolOutput IDEM ()+ -> IDEAction+runExternalTool' description executable args dir handleOutput = do+ runExternalTool (do+ run <- isRunning+ return (not run))+ (\_ -> return ())+ description+ executable+ args+ dir+ handleOutput+ return()++runExternalTool :: IDEM Bool+ -> (ProcessHandle -> IDEAction)+ -> String+ -> FilePath+ -> [String]+ -> FilePath+ -> C.Sink ToolOutput IDEM ()+ -> IDEAction+runExternalTool runGuard pidHandler description executable args dir handleOutput = do+ prefs <- readIDE prefs+ run <- runGuard+ when run $ do+ when (saveAllBeforeBuild prefs) (do fileSaveAll belongsToWorkspace; return ())+ triggerEventIDE (StatusbarChanged [CompartmentState description, CompartmentBuild True])+ reifyIDE $ \ideR -> forkIO $ do+ -- If vado is enabled then look up the mount point and transform+ -- the execuatble to "ssh" and the arguments+ mountPoint <- if useVado prefs then getMountPoint dir else return $ Right ""+ (executable', args') <- case mountPoint of+ Left mp -> do+ s <- readSettings+ a <- vado mp s dir [] executable args+ return ("ssh", a)+ _ -> return (executable, args)+ -- Run the tool+ (output, pid) <- runTool executable' args' (Just dir)+ reflectIDE (do+ pidHandler pid+ modifyIDE_ (\ide -> ide{runningTool = Just pid})+ output $$ handleOutput) ideR+ return ()++-- ---------------------------------------------------------------------+-- | Handling of Compiler errors+--+isRunning :: IDEM Bool+isRunning = do+ maybeProcess <- readIDE runningTool+ liftIO $ do+ case maybeProcess of+ Just process -> do+ isNothing <$> getProcessExitCode process+ Nothing -> return False++interruptBuild :: IDEAction+interruptBuild = do+ maybeProcess <- readIDE runningTool+ liftIO $ case maybeProcess of+ Just h -> interruptProcessGroupOf h+ _ -> return ()++
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP, ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Utils.GUIUtils@@ -17,9 +17,15 @@ , chooseDir , chooseSaveFile , openBrowser+, showDialog+, showErrorDialog , getCandyState , setCandyState+, getFullScreenState+, setFullScreenState+, getDarkState+, setDarkState , getForgetSession , getBackgroundBuildToggled@@ -33,11 +39,15 @@ , getRecentFiles , getRecentWorkspaces-, controlIsPressed+, getVCS , stockIdFromType , mapControlCommand+, treeViewContextMenu +, __++, fontDescription ) where import Graphics.UI.Gtk@@ -49,14 +59,16 @@ -- (FileChooserAction(..)) --import Graphics.UI.Gtk.General.Structs -- (ResponseId(..))-import qualified Graphics.UI.Gtk.Gdk.Events as G (Event(..))-#if MIN_VERSION_gtk(0,10,5)-import Graphics.UI.Gtk.Gdk.EventM (Modifier(..))-#else-import Graphics.UI.Gtk.Gdk.Enums (Modifier(..))-#endif import Control.Monad.IO.Class (liftIO)+import Control.Exception as E +#ifdef LOCALIZATION++import Text.I18N.GetText+import System.IO.Unsafe (unsafePerformIO)++#endif+ chooseDir :: Window -> String -> Maybe FilePath -> IO (Maybe FilePath) chooseDir window prompt mbFolder = do dialog <- fileChooserDialogNew@@ -131,15 +143,28 @@ widgetDestroy dialog return Nothing ++ openBrowser :: String -> IDEAction openBrowser url = do prefs' <- readIDE prefs- liftIO (catch (do+ liftIO (E.catch (do runProcess (browser prefs') [url] Nothing Nothing Nothing Nothing Nothing return ())- (\ _ -> sysMessage Normal ("Can't find browser executable " ++ browser prefs')))+ (\ (_ :: SomeException) -> sysMessage Normal ("Can't find browser executable " ++ browser prefs'))) return () ++showDialog :: String -> MessageType -> IO ()+showDialog msg msgType = do+ dialog <- messageDialogNew Nothing [] msgType ButtonsOk msg+ _ <- dialogRun dialog+ widgetDestroy dialog+ return ()++showErrorDialog :: String -> IO ()+showErrorDialog msg = showDialog msg MessageError+ -- get widget elements (menu & toolbar) getCandyState :: PaneMonad alpha => alpha Bool@@ -152,6 +177,26 @@ ui <- getUIAction "ui/menubar/_Configuration/Source Candy" castToToggleAction liftIO $toggleActionSetActive ui b +getFullScreenState :: PaneMonad alpha => alpha Bool+getFullScreenState = do+ ui <- getUIAction "ui/menubar/_View/_Full Screen" castToToggleAction+ liftIO $toggleActionGetActive ui++setFullScreenState :: PaneMonad alpha => Bool -> alpha ()+setFullScreenState b = do+ ui <- getUIAction "ui/menubar/_View/_Full Screen" castToToggleAction+ liftIO $toggleActionSetActive ui b++getDarkState :: PaneMonad alpha => alpha Bool+getDarkState = do+ ui <- getUIAction "ui/menubar/_View/Dark" castToToggleAction+ liftIO $toggleActionGetActive ui++setDarkState :: PaneMonad alpha => Bool -> alpha ()+setDarkState b = do+ ui <- getUIAction "ui/menubar/_View/Dark" castToToggleAction+ liftIO $toggleActionSetActive ui b+ getForgetSession :: PaneMonad alpha => alpha (Bool) getForgetSession = do ui <- getUIAction "ui/menubar/_Configuration/Forget Session" castToToggleAction@@ -205,16 +250,12 @@ ui <- getUIAction "ui/toolbar/BuildToolItems/Debug" castToToggleAction liftIO $ toggleActionSetActive ui b -getRecentFiles , getRecentWorkspaces :: IDEM MenuItem+getRecentFiles , getRecentWorkspaces, getVCS :: IDEM MenuItem getRecentFiles = getMenuItem "ui/menubar/_File/Open _Recent" getRecentWorkspaces = getMenuItem "ui/menubar/_Workspace/Open _Recent"-+getVCS = getMenuItem "ui/menubar/Version Con_trol" --this could fail, try returning Menu if it does -- (toolbar) -controlIsPressed :: G.Event -> Bool-controlIsPressed (G.Button _ _ _ _ _ mods _ _ _) | Control `elem` mods = True-controlIsPressed _ = False- stockIdFromType :: DescrType -> StockId stockIdFromType Variable = "ide_function" stockIdFromType Newtype = "ide_newtype"@@ -233,5 +274,62 @@ #endif mapControlCommand a = a +treeViewContextMenu :: TreeViewClass treeView+ => treeView+ -> (Menu -> IO ())+ -> IO (ConnectId treeView, ConnectId treeView)+treeViewContextMenu treeView populateMenu = do+ cid1 <- treeView `on` popupMenuSignal $ showMenu Nothing+ cid2 <- treeView `on` buttonPressEvent $ do+ button <- eventButton+ click <- eventClick+ timestamp <- eventTime+ (x, y) <- eventCoordinates+ case (button, click) of+ (RightButton, SingleClick) -> liftIO $ do+ sel <- treeViewGetSelection treeView+ selCount <- treeSelectionCountSelectedRows sel+ when (selCount <= 1) $ do+ pathInfo <- treeViewGetPathAtPos treeView (floor x, floor y)+ case pathInfo of+ Just (path, _, _) -> do+ treeSelectionUnselectAll sel+ treeSelectionSelectPath sel path+ _ -> return ()+ showMenu (Just (button, timestamp))+ _ -> return False+ return (cid1, cid2)+ where+ showMenu buttonEventDetails = do+ theMenu <- menuNew+ menuAttachToWidget theMenu treeView+ populateMenu theMenu+ menuPopup theMenu buttonEventDetails+ widgetShowAll theMenu+ return True +#ifdef LOCALIZATION++-- | For i18n using hgettext+__ :: String -> String+__ = unsafePerformIO . getText+++#else++-- | For i18n support. Not included in this build.+__ :: String -> String+__ = id++#endif++fontDescription :: Maybe String -> IDEM FontDescription+fontDescription mbFontString = liftIO $ do+ case mbFontString of+ Just str -> do+ fontDescriptionFromString str+ Nothing -> do+ f <- fontDescriptionNew+ fontDescriptionSetFamily f "Monospace"+ return f
@@ -1,4 +1,4 @@-{-# OPTIONS_GHC -XScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- -- Module : IDE.Utils.ServerConnection
@@ -12,7 +12,7 @@ -- | Represents a workspace, a work unit, which can be composed of multiple packages -- ------------------------------------------------------------------------------+{-# LANGUAGE DeriveDataTypeable #-} module IDE.Workspaces ( workspaceNew , workspaceOpen@@ -26,6 +26,7 @@ , workspaceAddPackage' , workspaceRemovePackage , workspacePackageNew+, workspacePackageClone , workspaceTryQuiet , workspaceNewHere , packageTry@@ -33,7 +34,6 @@ , backgroundMake , makePackage- ) where import IDE.Core.State@@ -42,7 +42,7 @@ import Control.Monad (forM_, unless, when, liftM) import Data.Maybe (isJust,fromJust ) import IDE.Utils.GUIUtils- (chooseFile, chooseSaveFile)+ (chooseFile, chooseSaveFile, __) import System.FilePath (takeFileName, (</>), isAbsolute, dropFileName, makeRelative, dropExtension, takeBaseName, addExtension, takeExtension,@@ -60,7 +60,7 @@ (dialogSetDefaultResponse, windowWindowPosition, widgetDestroy, dialogRun, messageDialogNew, dialogAddButton, Window(..), widgetHide, DialogFlags(..))-import IDE.Pane.PackageEditor (packageNew', choosePackageFile, standardSetup)+import IDE.Pane.PackageEditor (packageNew', packageClone, choosePackageFile, standardSetup) import Data.List (delete) import IDE.Package (getModuleTemplate, getPackageDescriptionAndPath, activatePackage,@@ -70,12 +70,8 @@ import System.Time (getClockTime) import Graphics.UI.Gtk.Windows.MessageDialog (ButtonsType(..), MessageType(..))-#if MIN_VERSION_gtk(0,10,5) import Graphics.UI.Gtk.Windows.Dialog (ResponseId(..))-#else-import Graphics.UI.Gtk.General.Structs (ResponseId(..))-#endif-import Control.Exception (SomeException(..))+import qualified Control.Exception as Exc (SomeException(..), throw, Exception) import qualified Data.Map as Map (empty) import IDE.Pane.SourceBuffer (fileOpenThis, fileCheckAll, belongsToPackage) import qualified System.IO.UTF8 as UTF8 (writeFile)@@ -89,55 +85,22 @@ import Control.Monad.Trans.Class (lift) import qualified Data.Set as Set (toList) import Distribution.PackageDescription (hsSourceDirs)--setWorkspace :: Maybe Workspace -> IDEAction-setWorkspace mbWs = do- mbOldWs <- readIDE workspace- modifyIDE_ (\ide -> ide{workspace = mbWs})- let packFile = case mbWs of- Nothing -> Nothing- Just ws -> wsActivePackFile ws- let oldPackFile = case mbOldWs of- Nothing -> Nothing- Just ws -> wsActivePackFile ws- let mbPackages = case mbWs of- Nothing -> Nothing- Just ws -> Just (wsPackages ws)- when (packFile /= oldPackFile) $- case packFile of- Nothing -> deactivatePackage- Just p -> activatePackage (getPackage p (fromJust mbPackages)) >> return ()- mbPack <- readIDE activePack- let wsStr = case mbWs of- Nothing -> ""- Just ws -> wsName ws- let txt = wsStr ++ " > " ++- (case mbPack of- Nothing -> ""- Just p -> packageIdentifierToString (ipdPackageId p))- triggerEventIDE (StatusbarChanged [CompartmentPackage txt])- triggerEventIDE (WorkspaceChanged True True)- triggerEventIDE UpdateWorkspaceInfo- return ()--getPackage :: FilePath -> [IDEPackage] -> Maybe IDEPackage-getPackage fp packages =- case filter (\ p -> ipdCabalFile p == fp) packages of- [p] -> Just p- l -> Nothing---- ------------------------------------------------------------------------ This needs to be incremented, when the workspace format changes----workspaceVersion :: Int-workspaceVersion = 1+import IDE.Command.VCS.Common.Workspaces as VCSWS+import qualified VCSWrapper.Common as VCS+import qualified VCSGui.Common as VCSGUI+import qualified IDE.Workspaces.Writer as Writer+import Text.Printf (printf)+import System.Log.Logger (debugM)+import Data.Maybe (catMaybes)+import IDE.Pane.Log (showDefaultLogLaunch', getLog)+import IDE.LogRef (logOutputDefault) -- | Constructs a new workspace and makes it the current workspace workspaceNew :: IDEAction workspaceNew = do window <- getMainWindow mbFile <- liftIO $ do- chooseSaveFile window "New file for workspace" Nothing+ chooseSaveFile window (__ "New file for workspace") Nothing case mbFile of Nothing -> return () Just filePath -> workspaceNewHere filePath@@ -153,7 +116,7 @@ newWorkspace = emptyWorkspace { wsName = takeBaseName cPath, wsFile = cPath}- liftIO $ writeFields cPath newWorkspace workspaceDescr+ liftIO $ writeFields cPath newWorkspace Writer.workspaceDescr workspaceOpenThis False (Just cPath) return () @@ -169,7 +132,7 @@ maybeWorkspace <- readIDE workspace case maybeWorkspace of Just ws -> runWorkspace f ws- Nothing -> ideMessage Normal "No workspace open"+ Nothing -> ideMessage Normal (__ "No workspace open") workspaceTry :: WorkspaceAction -> IDEAction workspaceTry f = do@@ -182,12 +145,12 @@ resp <- liftIO $ do defaultExists <- doesFileExist defaultWorkspace md <- messageDialogNew (Just mainWindow) [DialogModal] MessageQuestion ButtonsCancel (- "You need to have a workspace open for this to work. "- ++ "Choose ~/leksah.lkshw to "- ++ (if defaultExists then "open workspace " else "create a workspace ")+ (__ "You need to have a workspace open for this to work. ")+ ++ (__ "Choose ~/leksah.lkshw to ")+ ++ (if defaultExists then (__ "open workspace ") else (__ "create a workspace ")) ++ defaultWorkspace)- dialogAddButton md "_New Workspace" (ResponseUser 1)- dialogAddButton md "_Open Workspace" (ResponseUser 2)+ dialogAddButton md (__ "_New Workspace") (ResponseUser 1)+ dialogAddButton md (__ "_Open Workspace") (ResponseUser 2) dialogAddButton md "~/leksah.lkshw" (ResponseUser 3) dialogSetDefaultResponse md (ResponseUser 3) set md [ windowWindowPosition := WinPosCenterOnParent ]@@ -210,13 +173,14 @@ _ -> return () chooseWorkspaceFile :: Window -> IO (Maybe FilePath)-chooseWorkspaceFile window = chooseFile window "Select leksah workspace file (.lkshw)" Nothing+chooseWorkspaceFile window = chooseFile window (__ "Select leksah workspace file (.lkshw)") Nothing workspaceOpenThis :: Bool -> Maybe FilePath -> IDEAction workspaceOpenThis askForSession mbFilePath = case mbFilePath of Nothing -> return () Just filePath -> do+ liftIO . debugM "leksah" $ "workspaceOpenThis " ++ show askForSession ++ " " ++ filePath let spath = dropExtension filePath ++ leksahSessionFileExtension workspaceClose exists <- liftIO $ doesFileExist spath@@ -226,9 +190,9 @@ window <- getMainWindow liftIO $ do md <- messageDialogNew (Just window) [] MessageQuestion ButtonsNone- $ "There are session settings stored with this workspace."- dialogAddButton md "_Ignore Session" ResponseCancel- dialogAddButton md "_Load Session" ResponseYes+ $ (__ "There are session settings stored with this workspace.")+ dialogAddButton md (__ "_Ignore Session") ResponseCancel+ dialogAddButton md (__ "_Load Session") ResponseYes dialogSetDefaultResponse md ResponseYes set md [ windowWindowPosition := WinPosCenterOnParent ] rid <- dialogRun md@@ -243,24 +207,26 @@ ideR <- ask catchIDE (do workspace <- readWorkspace filePath- setWorkspace (Just workspace {wsFile = filePath})- return ())- (\ (e :: SomeException) -> reflectIDE- (ideMessage Normal ("Can't load workspace file " ++ filePath ++ "\n" ++ show e)) ideR)+ Writer.setWorkspace (Just workspace {wsFile = filePath})+ VCSWS.onWorkspaceOpen workspace)+ (\ (e :: Exc.SomeException) -> reflectIDE+ (ideMessage Normal (printf (__ "Can't load workspace file %s\n%s") filePath (show e))) ideR) -- | Closes a workspace workspaceClose :: IDEAction workspaceClose = do+ liftIO $ debugM "leksah" "workspaceClose" oldWorkspace <- readIDE workspace case oldWorkspace of Nothing -> return () Just ws -> do+ VCSWS.onWorkspaceClose let oldActivePackFile = wsActivePackFile ws triggerEventIDE (SaveSession ((dropExtension (wsFile ws)) ++ leksahSessionFileExtension)) addRecentlyUsedWorkspace (wsFile ws)- setWorkspace Nothing+ Writer.setWorkspace Nothing when (isJust oldActivePackFile) $ do triggerEventIDE (Sensitivity [(SensitivityProjectActive, False), (SensitivityWorkspaceOpen, False)])@@ -268,11 +234,12 @@ return () return () + workspacePackageNew :: WorkspaceAction workspacePackageNew = do ws <- ask let path = dropFileName (wsFile ws)- lift $ packageNew' (Just path) (\isNew fp -> do+ lift $ packageNew' path logOutputDefault (\isNew fp -> do window <- getMainWindow workspaceTry $ workspaceAddPackage' fp >> return () when isNew $ do@@ -280,6 +247,15 @@ constructAndOpenMainModule mbPack triggerEventIDE UpdateWorkspaceInfo >> return ()) +workspacePackageClone :: WorkspaceAction+workspacePackageClone = do+ ws <- ask+ let path = dropFileName (wsFile ws)+ lift $ packageClone path logOutputDefault (\fp -> do+ window <- getMainWindow+ workspaceTry $ workspaceAddPackage' fp >> return ()+ triggerEventIDE UpdateWorkspaceInfo >> return ())+ constructAndOpenMainModule :: Maybe IDEPackage -> IDEAction constructAndOpenMainModule Nothing = return () constructAndOpenMainModule (Just idePackage) =@@ -296,7 +272,7 @@ liftIO $ UTF8.writeFile (path </> target) template fileOpenThis (path </> target) _ -> return ()- Nothing -> ideMessage Normal "No package description"+ Nothing -> ideMessage Normal (__ "No package description") workspaceAddPackage :: WorkspaceAction workspaceAddPackage = do@@ -317,15 +293,10 @@ mbPack <- lift $ idePackageFromPath cfp case mbPack of Just pack -> do- let dir = takeDirectory cfp- b1 <- liftIO $ doesFileExist (dir </> "Setup.hs")- b2 <- liftIO $ doesFileExist (dir </> "Setup.lhs")- unless (b1 || b2) $ liftIO $ do- sysMessage Normal "Setup.(l)hs does not exist. Writing Standard"- writeFile (dir </> "Setup.lhs") standardSetup unless (elem cfp (map ipdCabalFile (wsPackages ws))) $ lift $- writeWorkspace $ ws {wsPackages = pack : wsPackages ws,- wsActivePackFile = Just (ipdCabalFile pack)}+ Writer.writeWorkspace $ ws {wsPackages = pack : wsPackages ws,+ wsActivePackFile = Just (ipdCabalFile pack),+ wsActiveExe = Nothing} return (Just pack) Nothing -> return Nothing @@ -334,7 +305,7 @@ maybePackage <- readIDE activePack case maybePackage of Just p -> runPackage f p- Nothing -> ideMessage Normal "No active package"+ Nothing -> ideMessage Normal (__ "No active package") packageTry :: PackageAction -> IDEAction packageTry f = workspaceTry $ do@@ -345,9 +316,9 @@ window <- lift $ getMainWindow resp <- liftIO $ do md <- messageDialogNew (Just window) [] MessageQuestion ButtonsCancel- "You need to have an active package for this to work."- dialogAddButton md "_New Package" (ResponseUser 1)- dialogAddButton md "_Add Package" (ResponseUser 2)+ (__ "You need to have an active package for this to work.")+ dialogAddButton md (__ "_New Package") (ResponseUser 1)+ dialogAddButton md (__ "_Add Package") (ResponseUser 2) dialogSetDefaultResponse md (ResponseUser 2) set md [ windowWindowPosition := WinPosCenterOnParent ] resp <- dialogRun md@@ -366,50 +337,35 @@ workspaceRemovePackage pack = do ws <- ask when (elem pack (wsPackages ws)) $ lift $- writeWorkspace ws {wsPackages = delete pack (wsPackages ws)}+ Writer.writeWorkspace ws {wsPackages = delete pack (wsPackages ws)} return () -workspaceActivatePackage :: IDEPackage -> WorkspaceAction-workspaceActivatePackage pack = do+workspaceActivatePackage :: IDEPackage -> Maybe String -> WorkspaceAction+workspaceActivatePackage pack exe = do ws <- ask- lift $ activatePackage (Just pack)+ lift $ activatePackage (Just (pack, exe)) when (elem pack (wsPackages ws)) $ lift $ do- writeWorkspace ws {wsActivePackFile = Just (ipdCabalFile pack)}+ Writer.writeWorkspace ws {wsActivePackFile = Just (ipdCabalFile pack)+ ,wsActiveExe = exe} return () return () -writeWorkspace :: Workspace -> IDEAction-writeWorkspace ws = do- timeNow <- liftIO getClockTime- let newWs = ws {wsSaveTime = show timeNow,- wsVersion = workspaceVersion,- wsPackagesFiles = map ipdCabalFile (wsPackages ws)}- setWorkspace $ Just newWs- newWs' <- liftIO $ makePathesRelative newWs- liftIO $ writeFields (wsFile newWs') (newWs' {wsFile = ""}) workspaceDescr + readWorkspace :: FilePath -> IDEM Workspace readWorkspace fp = do- ws <- liftIO $ readFields fp workspaceDescr emptyWorkspace- ws' <- liftIO $ makePathesAbsolute ws fp+ liftIO $ debugM "leksah" "readWorkspace"+ ws <- liftIO $ readFields fp Writer.workspaceDescr emptyWorkspace+ ws' <- liftIO $ makePathsAbsolute ws fp packages <- mapM idePackageFromPath (wsPackagesFiles ws')- return ws'{ wsPackages = map fromJust $ filter isJust $ packages}+ --TODO set package vcs here+ return ws'{ wsPackages = catMaybes packages} -makePathesRelative :: Workspace -> IO Workspace-makePathesRelative ws = do- wsFile' <- myCanonicalizePath (wsFile ws)- wsActivePackFile' <- case wsActivePackFile ws of- Nothing -> return Nothing- Just fp -> do- nfp <- liftIO $ myCanonicalizePath fp- return (Just (makeRelative (dropFileName wsFile') nfp))- wsPackagesFiles' <- mapM myCanonicalizePath (wsPackagesFiles ws)- let relativePathes = map (\p -> makeRelative (dropFileName wsFile') p) wsPackagesFiles'- return ws {wsActivePackFile = wsActivePackFile', wsFile = wsFile', wsPackagesFiles = relativePathes} -makePathesAbsolute :: Workspace -> FilePath -> IO Workspace-makePathesAbsolute ws bp = do++makePathsAbsolute :: Workspace -> FilePath -> IO Workspace+makePathsAbsolute ws bp = do wsFile' <- myCanonicalizePath bp wsActivePackFile' <- case wsActivePackFile ws of Nothing -> return Nothing@@ -425,48 +381,18 @@ else myCanonicalizePath (basePath </> relativePath) emptyWorkspace = Workspace {- wsVersion = workspaceVersion+ wsVersion = Writer.workspaceVersion , wsSaveTime = "" , wsName = "" , wsFile = "" , wsPackages = [] , wsPackagesFiles = [] , wsActivePackFile = Nothing+, wsActiveExe = Nothing , wsNobuildPack = []+, packageVcsConf = Map.empty } -workspaceDescr :: [FieldDescriptionS Workspace]-workspaceDescr = [- mkFieldS- (paraName <<<- ParaName "Version of workspace file format" $ emptyParams)- (PP.text . show)- intParser- wsVersion- (\ b a -> a{wsVersion = b})- , mkFieldS- (paraName <<<- ParaName "Time of storage" $ emptyParams)- (PP.text . show)- stringParser- wsSaveTime- (\ b a -> a{wsSaveTime = b})- , mkFieldS- (paraName <<<- ParaName "Name of the workspace" $ emptyParams)- (PP.text . show)- stringParser- wsName- (\ b a -> a{wsName = b})- , mkFieldS- (paraName <<<- ParaName "File paths of contained packages" $ emptyParams)- (PP.text . show)- readParser- wsPackagesFiles- (\b a -> a{wsPackagesFiles = b})- , mkFieldS- (paraName <<<- ParaName "Maybe file path of an active package" $ emptyParams)- (PP.text . show)- readParser- wsActivePackFile- (\fp a -> a{wsActivePackFile = fp})] addRecentlyUsedWorkspace :: FilePath -> IDEAction@@ -500,6 +426,15 @@ return (defaultMakeSettings prefs') makePackages settings (wsPackages ws) MoClean MoClean moNoOp +buildSteps :: Bool -> IDEM [MakeOp]+buildSteps runTests = do+ debug <- isJust <$> readIDE debugState+ return $ case (runTests, debug) of+ (True, True) -> [MoBuild,MoDocu]+ (True, False) -> [MoBuild,MoDocu,MoTest,MoCopy,MoRegister]+ (False, True) -> [MoBuild]+ (False, False) -> [MoBuild,MoCopy,MoRegister]+ workspaceMake :: WorkspaceAction workspaceMake = do ws <- ask@@ -508,16 +443,16 @@ return ((defaultMakeSettings prefs'){ msMakeMode = True, msBackgroundBuild = False})- let steps = if msRunUnitTests settings- then [MoConfigure,MoBuild,MoTest,MoCopy,MoRegister]- else [MoConfigure,MoBuild,MoCopy,MoRegister]- makePackages settings (wsPackages ws) (MoComposed steps) (MoComposed steps) MoMetaInfo+ build <- lift . buildSteps $ msRunUnitTests settings+ let steps = MoComposed (MoConfigure : build)+ makePackages settings (wsPackages ws) steps steps MoMetaInfo backgroundMake :: IDEAction backgroundMake = catchIDE (do ideR <- ask prefs <- readIDE prefs mbPackage <- readIDE activePack+ debug <- isJust <$> readIDE debugState case mbPackage of Nothing -> return () Just package -> do@@ -527,40 +462,37 @@ let isModified = not (null modifiedPacks) when isModified $ do let settings = defaultMakeSettings prefs- if msSingleBuildWithoutLinking settings && not (msMakeMode settings)+ steps <- buildSteps $ msRunUnitTests settings+ if debug || msSingleBuildWithoutLinking settings && not (msMakeMode settings) then workspaceTryQuiet $- makePackages settings modifiedPacks MoBuild (MoComposed []) moNoOp+ makePackages settings modifiedPacks (MoComposed steps) (MoComposed []) moNoOp else do- let steps = if msRunUnitTests settings- then [MoBuild,MoTest,MoCopy,MoRegister]- else [MoBuild,MoCopy,MoRegister] workspaceTryQuiet $ makePackages settings modifiedPacks (MoComposed steps) (MoComposed (MoConfigure:steps)) MoMetaInfo )- (\(e :: SomeException) -> sysMessage Normal (show e))+ (\(e :: Exc.SomeException) -> sysMessage Normal (show e)) makePackage :: PackageAction makePackage = do- p <- ask- (mbWs,settings) <- lift $ do- prefs' <- readIDE prefs- ws <- readIDE workspace- let settings = (defaultMakeSettings prefs'){msBackgroundBuild = False}- return (ws,settings)+ p <- ask+ lift $ do+ getLog >>= liftIO . bringPaneToFront+ showDefaultLogLaunch'+ prefs' <- readIDE prefs+ mbWs <- readIDE workspace+ let settings = (defaultMakeSettings prefs'){msBackgroundBuild = False} case mbWs of- Nothing -> sysMessage Normal "No workspace for build."- Just ws -> lift $- if msSingleBuildWithoutLinking settings && not (msMakeMode settings)+ Nothing -> sysMessage Normal (__ "No workspace for build.")+ Just ws -> do+ debug <- isJust <$> readIDE debugState+ steps <- buildSteps $ msRunUnitTests settings+ if debug || msSingleBuildWithoutLinking settings && not (msMakeMode settings) then runWorkspace- (makePackages settings [p] MoBuild (MoComposed []) moNoOp) ws+ (makePackages settings [p] (MoComposed steps) (MoComposed []) moNoOp) ws else do- let steps = if msRunUnitTests settings- then [MoBuild,MoTest,MoCopy,MoRegister]- else [MoBuild,MoCopy,MoRegister] runWorkspace (makePackages settings [p] (MoComposed steps) (MoComposed (MoConfigure:steps)) MoMetaInfo) ws-
@@ -0,0 +1,162 @@+-----------------------------------------------------------------------------+--+-- Module : IDE.Workspaces.Writer+-- Copyright : 2007-2011 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.Workspaces.Writer (+ writeWorkspace+ ,setWorkspace+ ,workspaceDescr+ ,workspaceVersion+) where++import IDE.Core.Types+import IDE.Core.State+import IDE.Package+ (getModuleTemplate, getPackageDescriptionAndPath, activatePackage,+ deactivatePackage, idePackageFromPath)+import IDE.Utils.FileUtils(myCanonicalizePath)++import Data.Maybe+import Control.Monad (when)+import Control.Monad.Trans (liftIO)+import System.Time (getClockTime)+import Text.PrinterParser+ (readFields,+ writeFields,+ readParser,+ stringParser,+ intParser,+ mkFieldS,+ FieldDescriptionS(..))+import System.FilePath+ (takeFileName, (</>), isAbsolute, dropFileName, makeRelative,+ dropExtension, takeBaseName, addExtension, takeExtension,+ takeDirectory)+import Graphics.UI.Editor.Parameters+ (Parameter(..), (<<<-), paraName, emptyParams)+import qualified Text.PrettyPrint as PP (text)+import System.Log.Logger (debugM)++writeWorkspace :: Workspace -> IDEAction+writeWorkspace ws = do+ timeNow <- liftIO getClockTime+ let newWs = ws {wsSaveTime = show timeNow,+ wsVersion = workspaceVersion,+ wsPackagesFiles = map ipdCabalFile (wsPackages ws)}+ setWorkspace $ Just newWs+ newWs' <- liftIO $ makePathsRelative newWs+ liftIO $ writeFields (wsFile newWs') (newWs' {wsFile = ""}) workspaceDescr++getPackage :: FilePath -> Maybe String -> [IDEPackage] -> Maybe (IDEPackage, Maybe String)+getPackage fp mbExe packages =+ case filter (\ p -> ipdCabalFile p == fp) packages of+ [p] -> Just (p, mbExe)+ l -> Nothing++-- ---------------------------------------------------------------------+-- This needs to be incremented, when the workspace format changes+--+workspaceVersion :: Int+workspaceVersion = 2++setWorkspace :: Maybe Workspace -> IDEAction+setWorkspace mbWs = do+ liftIO $ debugM "leksah" "setWorkspace"+ mbOldWs <- readIDE workspace+ modifyIDE_ (\ide -> ide{workspace = mbWs})+ let packFileAndExe = case mbWs of+ Nothing -> Nothing+ Just ws -> Just (wsActivePackFile ws, wsActiveExe ws)+ let oldPackFileAndExe = case mbOldWs of+ Nothing -> Nothing+ Just ws -> Just (wsActivePackFile ws, wsActiveExe ws)+ let mbPackages = case mbWs of+ Nothing -> Nothing+ Just ws -> Just (wsPackages ws)+ when (packFileAndExe /= oldPackFileAndExe) $+ case packFileAndExe of+ (Just (Just p, mbExe)) -> activatePackage (getPackage p mbExe (fromJust mbPackages)) >> return ()+ _ -> deactivatePackage+ mbPack <- readIDE activePack+ mbExe <- readIDE activeExe+ let wsStr = case mbWs of+ Nothing -> ""+ Just ws -> wsName ws+ let txt = wsStr ++ " "+ ++ (case mbPack of+ Nothing -> ""+ Just p -> packageIdentifierToString (ipdPackageId p))+ ++ (case mbExe of+ Nothing -> ""+ Just exe -> " " ++ exe)+ triggerEventIDE (StatusbarChanged [CompartmentPackage txt])+ triggerEventIDE (WorkspaceChanged True True)+ triggerEventIDE UpdateWorkspaceInfo+ return ()++makePathsRelative :: Workspace -> IO Workspace+makePathsRelative ws = do+ wsFile' <- myCanonicalizePath (wsFile ws)+ wsActivePackFile' <- case wsActivePackFile ws of+ Nothing -> return Nothing+ Just fp -> do+ nfp <- liftIO $ myCanonicalizePath fp+ return (Just (makeRelative (dropFileName wsFile') nfp))+ wsPackagesFiles' <- mapM myCanonicalizePath (wsPackagesFiles ws)+ let relativePathes = map (\p -> makeRelative (dropFileName wsFile') p) wsPackagesFiles'+ return ws {wsActivePackFile = wsActivePackFile', wsFile = wsFile', wsPackagesFiles = relativePathes}++workspaceDescr :: [FieldDescriptionS Workspace]+workspaceDescr = [+ mkFieldS+ (paraName <<<- ParaName "Version of workspace file format" $ emptyParams)+ (PP.text . show)+ intParser+ wsVersion+ (\ b a -> a{wsVersion = b})+ , mkFieldS+ (paraName <<<- ParaName "Time of storage" $ emptyParams)+ (PP.text . show)+ stringParser+ wsSaveTime+ (\ b a -> a{wsSaveTime = b})+ , mkFieldS+ (paraName <<<- ParaName "Name of the workspace" $ emptyParams)+ (PP.text . show)+ stringParser+ wsName+ (\ b a -> a{wsName = b})+ , mkFieldS+ (paraName <<<- ParaName "File paths of contained packages" $ emptyParams)+ (PP.text . show)+ readParser+ wsPackagesFiles+ (\b a -> a{wsPackagesFiles = b})+ , mkFieldS+ (paraName <<<- ParaName "Maybe file path of an active package" $ emptyParams)+ (PP.text . show)+ readParser+ wsActivePackFile+ (\fp a -> a{wsActivePackFile = fp})+ , mkFieldS+ (paraName <<<- ParaName "Maybe name of an active executable" $ emptyParams)+ (PP.text . show)+ readParser+ wsActiveExe+ (\fp a -> a{wsActiveExe = fp})+ , mkFieldS+ (paraName <<<- ParaName "Version Control System configurations for packages" $ emptyParams)+ (PP.text . show)+ readParser+ packageVcsConf+ (\filePath a -> a{packageVcsConf = filePath})]
@@ -0,0 +1,165 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+-----------------------------------------------------------------------------+--+-- Module : IDE.TextEditor.Tests+-- Copyright : 2007-2013 Juergen Nicklisch-Franken, Hamish Mackenzie+-- License : GPL Nothing+--+-- Maintainer : maintainer@leksah.org+-- Stability : provisional+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module IDE.TextEditor.Tests (+ testEditors+) where++import Graphics.UI.Gtk+ (mainQuit, postGUIAsync, windowSetPosition, windowSetDefaultSize,+ mainGUI, widgetShowAll, containerAdd, uiManagerNew, widgetSetName,+ windowNew)+import IDE.TextEditor+ (CodeMirror(..), Yi(..), GtkSourceView(..), TextEditor(..))+import IDE.Core.Types+ (IDEM, KeymapI, Prefs(..), IDE(..), IDEState(..))+import qualified Data.Map as Map (empty)+import Graphics.UI.Frame.Panes+ (PaneLayout(..), FrameState(..))+import IDE.SourceCandy (parseCandy)+import IDE.Utils.FileUtils (getConfigFilePathForLoad)+import IDE.Utils.Utils+ (leksahKeymapFileExtension, leksahCandyFileExtension)+import IDE.Pane.Preferences (defaultPrefs)+import IDE.Keymap (Keymap(..))+import IDE.Command (mkActions)+import qualified IDE.YiConfig as Yi (start)+import IDE.YiConfig (defaultYiConfig)+import Data.IORef (newIORef)+import IDE.Core.State (getDataDir, reflectIDE)+import Control.Monad.IO.Class (MonadIO(..))+import Graphics.UI.Gtk.General.Enums (WindowPosition(..))+import System.Log.Logger (debugM)+import Control.Concurrent (takeMVar, putMVar, newEmptyMVar)+import Test.QuickCheck.Monadic (assert, run, monadicIO)+import Test.QuickCheck.All (quickCheckAll)+import Graphics.UI.Frame.ViewFrame (getWindows)+import Test.QuickCheck (Property)+import Control.Monad.Loops (allM)+import System.IO (stderr, stdout, hFlush)++testEditors :: IO Bool+testEditors = do+ result <- newEmptyMVar+ postGUIAsync $ do+ $quickCheckAll >>= putMVar result+ mainQuit+ mainGUI+ takeMVar result++testIDE :: IDEM Bool -> IO Bool+testIDE f = do+ result <- newEmptyMVar+ Yi.start defaultYiConfig $ \yiControl -> do+ uiManager <- uiManagerNew+ dataDir <- getDataDir+ candyPath <- getConfigFilePathForLoad+ (case sourceCandy defaultPrefs of+ (_,name) -> name ++ leksahCandyFileExtension) Nothing dataDir+ candySt <- parseCandy candyPath+ -- keystrokes+ keysPath <- getConfigFilePathForLoad (keymapName defaultPrefs ++ leksahKeymapFileExtension) Nothing dataDir+ keyMap <- parseKeymap keysPath+ let accelActions = setKeymap (keyMap :: KeymapI) mkActions+ specialKeys <- buildSpecialKeys keyMap accelActions++ win <- windowNew+ windowSetDefaultSize win 900 600+ windowSetPosition win WinPosCenter+ widgetSetName win "Leksah Main Window"+ let fs = FrameState+ { windows = [win]+ , uiManager = uiManager+ , panes = Map.empty+ , activePane = Nothing+ , paneMap = Map.empty+ , layout = TerminalP Map.empty Nothing (-1) Nothing Nothing+ , panePathFromNB = Map.empty+ }+ ide = IDE+ { frameState = fs+ , recentPanes = []+ , specialKeys = specialKeys+ , specialKey = Nothing+ , candy = candySt+ , prefs = defaultPrefs+ , workspace = Nothing+ , activePack = Nothing+ , activeExe = Nothing+ , bufferProjCache = Map.empty+ , allLogRefs = []+ , currentHist = 0+ , currentEBC = (Nothing, Nothing, Nothing)+ , systemInfo = Nothing+ , packageInfo = Nothing+ , workspaceInfo = Nothing+ , workspInfoCache = Map.empty+ , handlers = Map.empty+ , currentState = IsStartingUp+ , guiHistory = (False,[],-1)+ , findbar = (False,Nothing)+ , toolbar = (True,Nothing)+ , recentFiles = []+ , recentWorkspaces = []+ , runningTool = Nothing+ , debugState = Nothing+ , completion = ((750,400),Nothing)+ , yiControl = yiControl+ , server = Nothing+ , vcsData = (Map.empty, Nothing)+ , logLaunches = Map.empty+ , autoCommand = return ()+ }+ ideR <- newIORef ide+ (`reflectIDE` ideR) f >>= putMVar result+ takeMVar result++allEditors :: (forall editor. TextEditor editor+ => ( Maybe FilePath+ -> String+ -> IDEM (EditorBuffer editor))+ -> IDEM Bool)+ -> IO Bool+allEditors test = allM id+ [ doTest GtkSourceView+ , doTest Yi+ , doTest CodeMirror]+ where+ doTest :: forall editor. (TextEditor editor, Show editor) => editor -> IO Bool+ doTest editor = do+ hFlush stdout+ hFlush stderr+ debugM "leksah" $ show editor+ testIDE $ test (newBuffer :: Maybe FilePath -> String -> IDEM (EditorBuffer editor))++prop_test :: String -> Property+prop_test s = monadicIO $ do+ let input = filter (not . flip elem "\NUL\r") s+ result <- run $ allEditors (\buf -> do+ (win:_) <- getWindows+ buffer <- buf Nothing ""+ view <- newView buffer (Just "monospace")+ sw <- getScrolledWindow view+ liftIO $ containerAdd win sw+ setText buffer input+ first <- getStartIter buffer+ last <- getEndIter buffer+ out <- getText buffer first last True+ return $ input == out)+ assert result+
@@ -21,13 +21,21 @@ import Distribution.Package (PackageName(..), PackageIdentifier(..)) import Distribution.Version (Version(..))+import Graphics.UI.Gtk (timeoutAddFull, initGUI)+import IDE.TextEditor.Tests (testEditors)+import System.Log.Logger+ (errorM, setLevel, rootLoggerName, updateGlobalLogger)+import System.Log (Priority(..))+import Control.Concurrent+ (yield, takeMVar, putMVar, newEmptyMVar, threadDelay, forkIO)+import System.Glib.MainLoop (priorityHigh) testString = " Could not find module `Graphics.UI.Gtk':\n" ++ " It is a member of the hidden package `gtk-0.11.0'.\n" ++ " Perhaps you need to add `gtk' to the build-depends in your .cabal file.\n" ++ " Use -v to see a list of the files searched for." -prop_parseHiddenModule = parseHiddenModule testString == Just (HiddenModuleResult {hiddenModule = "Graphics.UI.Gtk", missingPackage = PackageIdentifier {pkgName = PackageName "gtk", pkgVersion = Version {versionBranch = [0,11,0], versionTags = []}}}) +prop_parseHiddenModule = parseHiddenModule testString == Just HiddenModuleResult {hiddenModule = "Graphics.UI.Gtk", missingPackage = PackageIdentifier {pkgName = PackageName "gtk", pkgVersion = Version {versionBranch = [0,11,0], versionTags = []}}} -- At some point the : was removed from this message... testString2 = " Could not find module `Data.Attoparsec.Lazy'\n"@@ -35,8 +43,20 @@ ++ " Perhaps you need to add `attoparsec' to the build-depends in your .cabal file.\n" ++ " Use -v to see a list of the files searched for.\n" -prop_parseHiddenModule2 = parseHiddenModule testString2 == Just (HiddenModuleResult {hiddenModule = "Data.Attoparsec.Lazy", missingPackage = PackageIdentifier {pkgName = PackageName "attoparsec", pkgVersion = Version {versionBranch = [0,10,2,0], versionTags = []}}}) +prop_parseHiddenModule2 = parseHiddenModule testString2 == Just HiddenModuleResult {hiddenModule = "Data.Attoparsec.Lazy", missingPackage = PackageIdentifier {pkgName = PackageName "attoparsec", pkgVersion = Version {versionBranch = [0,10,2,0], versionTags = []}}} main = do- allPass <- $quickCheckAll -- Run QuickCheck on all prop_ functions- unless allPass exitFailure+ result <- newEmptyMVar+ forkIO $ do+ updateGlobalLogger rootLoggerName (setLevel DEBUG)+ allPass <- $quickCheckAll -- Run QuickCheck on all prop_ functions+ initGUI+ timeoutAddFull (yield >> return True) priorityHigh 10+ editorsOk <- testEditors+ putMVar result (allPass && editorsOk)+ forkIO $ do+ threadDelay 60000000+ errorM "leksah tests" "Test took too long to run"+ putMVar result False+ r <- takeMVar result+ unless r exitFailure
@@ -0,0 +1,30 @@+#!/bin/sh + +export PATH='/c/Program Files (x86)/Haskell Platform/2010.2.0.0/bin':$PATH +ghc -V || exit +PATH='/c/Program Files (x86)/Haskell Platform/2011.4.0.0/lib/extralibs/bin':$PATH cabal install haddock-2.8.1 +scripts/gtk2hs.sh ++export PATH='/c/Program Files (x86)/Haskell Platform/2011.2.0.1/bin':$PATH +ghc -V || exit +PATH='/c/Program Files (x86)/Haskell Platform/2011.2.0.1/lib/extralibs/bin':$PATH cabal install haddock-2.9.2 +scripts/gtk2hs.sh ++export PATH='/c/Program Files (x86)/Haskell Platform/2011.4.0.0/bin':$PATH +ghc -V || exit +PATH='/c/Program Files (x86)/Haskell Platform/2011.4.0.0/lib/extralibs/bin':$PATH cabal install haddock-2.9.2 +scripts/gtk2hs.sh ++export PATH='/c/Program Files (x86)/Haskell Platform/2012.2.0.0/bin':$PATH +ghc -V || exit +scripts/gtk2hs.sh ++export PATH='/c/ghc/ghc-7.4.2/bin':$PATH+ghc -V || exit +scripts/gtk2hs.sh ++export PATH='/c/ghc/ghc-7.6.1/bin':$PATH+ghc -V || exit +scripts/gtk2hs.sh + +
@@ -0,0 +1,18 @@+include "../../share/themes/Clearlooks/gtk-2.0/gtkrc"++gtk-icon-theme-name = "Tango"+gtk-enable-mnemonics = 0++style "leksah-close-button-style"+{+ GtkWidget::focus-padding = 0+ GtkWidget::focus-line-width = 0+ xthickness = 0+ ythickness = 0+}+widget "*.leksah-close-button" style "leksah-close-button-style"++# Maybe you wish to uncomment this if the beep is annoying+# gtk-error-bell = 0++
@@ -0,0 +1,27 @@+set PATH=%~dp0\bin;%PATH% + +set XDG_CONFIG_DIRS=%~dp0etc\xdg +set XDG_DATA_DIRS=%~dp0share +set GTK_DATA_PREFIX=%~dp0 +set GTK_EXE_PREFIX=%~dp0 +set GTK_PATH=%~dp0 + +set GTK2_RC_FILES=%~dp0etc\gtk-2.0\gtkrc +set GTK_IM_MODULE_FILE=%~dp0etc\gtk-2.0\gtk.immodules +set GDK_PIXBUF_MODULE_FILE=%~dp0etc\gtk-2.0\gdk-pixbuf.loaders + +set leksah_server_bindir=%~dp0bin +set leksah_server_libdir=%~dp0leksah\ghc-6.12.1 +set leksah_server_datadir=%~dp0leksah +set leksah_server_libexecdir=%~dp0bin + +leksah-server.exe -bos +leksah-server.exe -os +leksah-server.exe -os +leksah-server.exe -os +leksah-server.exe -os +leksah-server.exe -os +leksah-server.exe -os +leksah-server.exe -os + +pause
@@ -0,0 +1,20 @@+set PATH=%~dp0\bin;%PATH% + +set XDG_CONFIG_DIRS=%~dp0etc\xdg +set XDG_DATA_DIRS=%~dp0share +set GTK_DATA_PREFIX=%~dp0 +set GTK_EXE_PREFIX=%~dp0 +set GTK_PATH=%~dp0 + +set GTK2_RC_FILES=%~dp0etc\gtk-2.0\gtkrc +set GTK_IM_MODULE_FILE=%~dp0etc\gtk-2.0\gtk.immodules +set GDK_PIXBUF_MODULE_FILE=%~dp0etc\gtk-2.0\gdk-pixbuf.loaders + +set leksah_server_bindir=%~dp0bin +set leksah_server_libdir=%~dp0leksah\ghc-6.12.1 +set leksah_server_datadir=%~dp0leksah +set leksah_server_libexecdir=%~dp0bin + +leksah-server.exe --server=11111 + +pause
@@ -0,0 +1,30 @@+@echo off +set PATH=%~dp0\bin;%PATH% + +set XDG_CONFIG_DIRS=%~dp0etc\xdg +set XDG_DATA_DIRS=%~dp0share +set GTK_DATA_PREFIX=%~dp0 +set GTK_EXE_PREFIX=%~dp0 +set GTK_PATH=%~dp0 + +set GTK2_RC_FILES=%~dp0etc\gtk-2.0\gtkrc +set GTK_IM_MODULE_FILE=%~dp0etc\gtk-2.0\gtk.immodules +set GDK_PIXBUF_MODULE_FILE=%~dp0etc\gtk-2.0\gdk-pixbuf.loaders + +set leksah_bindir=%~dp0bin +set leksah_libdir=%~dp0leksah\ghc-6.12.1 +set leksah_datadir=%~dp0leksah +set leksah_libexecdir=%~dp0bin + +set leksah_server_bindir=%~dp0bin +set leksah_server_libdir=%~dp0leksah\ghc-6.12.1 +set leksah_server_datadir=%~dp0leksah +set leksah_server_libexecdir=%~dp0bin ++set hlint_datadir=%~dp0hlint +set pretty_show_datadir=%~dp0pretty-show + +leksah.exe + +if errorlevel 1 pause +if not errorlevel 0 pause
binary file changed (absent → 15086 bytes)
@@ -0,0 +1,194 @@+Name "Leksah" + +OutFile "$%LEKSAH_X_X_X_X_GHC_X_X_X%.exe" + +InstallDir C:\Leksah + +InstallDirRegKey HKLM "Software\Leksah" "Install_Dir" + +; Request application privileges for Windows Vista +RequestExecutionLevel admin + +;-------------------------------- + +; Pages + +Page directory +Page instfiles + +UninstPage uninstConfirm +UninstPage instfiles + +;-------------------------------- + +; The stuff to install +Section "Leksah" + + SectionIn RO + + ; Set output path to the installation directory. + SetOutPath $INSTDIR + + ; Put file there + File "leksah.bat" + File "leksah-server.bat" + File "leksah-rebuild-metadata.bat" + File "leksah.ico" + + File /r "$%GTK_PREFIX%\etc" + + SetOutPath $INSTDIR\leksah + File /r "$%LEKSAH_PREFIX%\$%LEKSAH_X_X_X_X%\data" + File /r "$%LEKSAH_PREFIX%\$%LEKSAH_X_X_X_X%\language-specs" + File /r "$%LEKSAH_PREFIX%\$%LEKSAH_X_X_X_X%\pics" + File "$%LEKSAH_PREFIX%\$%LEKSAH_X_X_X_X%\LICENSE" + File "$%LEKSAH_PREFIX%\$%LEKSAH_X_X_X_X%\Readme.md" + + SetOutPath $INSTDIR\hlint + File "$%LEKSAH_PREFIX%\$%HLINT_X_X_X_X%\*" + + SetOutPath $INSTDIR\pretty-show + File /r "$%LEKSAH_PREFIX%\$%PRETTY_SHOW_X_X%\style" + + SetOutPath $INSTDIR\ghcjs-codemirror + File /r "$%LEKSAH_PREFIX%\$%GHCJS_CODEMIRROR_X_X_X_X%\mode" + File /r "$%LEKSAH_PREFIX%\$%GHCJS_CODEMIRROR_X_X_X_X%\lib" + File /r "$%LEKSAH_PREFIX%\$%GHCJS_CODEMIRROR_X_X_X_X%\keymap" + File /r "$%LEKSAH_PREFIX%\$%GHCJS_CODEMIRROR_X_X_X_X%\theme" + + SetOutPath $INSTDIR\bin + File "$%CABAL_USER_BIN%\leksah.exe" + File "$%CABAL_USER_BIN%\vcswrapper.exe" + File "$%CABAL_USER_BIN%\vcsgui.exe" + File "$%CABAL_USER_BIN%\vcsgui-askpass.exe" + File "$%CABAL_USER_BIN%\leksah-server.exe" + File "$%CABAL_USER_BIN%\leksahecho.exe" + File "$%GTK_PREFIX%\bin\iconv.dll" + File "$%GTK_PREFIX%\bin\icudata50.dll" + File "$%GTK_PREFIX%\bin\icui18n50.dll" + File "$%GTK_PREFIX%\bin\icule50.dll" + File "$%GTK_PREFIX%\bin\icuuc50.dll" + File "$%GTK_PREFIX%\bin\libatk-1.0-0.dll" + File "$%GTK_PREFIX%\bin\libbz2-1.dll" + File "$%GTK_PREFIX%\bin\libcairo-2.dll" + File "$%GTK_PREFIX%\bin\libcairo-gobject-2.dll" + File "$%GTK_PREFIX%\bin\libcrypto-10.dll" + File "$%GTK_PREFIX%\bin\libcurl-4.dll" + File "$%GTK_PREFIX%\bin\libenchant.dll" + File "$%GTK_PREFIX%\bin\libexpat-1.dll" + File "$%GTK_PREFIX%\bin\libffi-6.dll" + File "$%GTK_PREFIX%\bin\libfontconfig-1.dll" + File "$%GTK_PREFIX%\bin\libfreetype-6.dll" + File "$%GTK_PREFIX%\bin\libgailutil-3-0.dll" + File "$%GTK_PREFIX%\bin\libgcc_s_sjlj-1.dll" + File "$%GTK_PREFIX%\bin\libgdk-3-0.dll" + File "$%GTK_PREFIX%\bin\libgdk_pixbuf-2.0-0.dll" + File "$%GTK_PREFIX%\bin\libgio-2.0-0.dll" + File "$%GTK_PREFIX%\bin\libglib-2.0-0.dll" + File "$%GTK_PREFIX%\bin\libgmodule-2.0-0.dll" + File "$%GTK_PREFIX%\bin\libgobject-2.0-0.dll" + File "$%GTK_PREFIX%\bin\libgst*-1.0-0.dll" + File "$%GTK_PREFIX%\bin\libgthread-2.0-0.dll" + File "$%GTK_PREFIX%\bin\libgtk-3-0.dll" + File "$%GTK_PREFIX%\bin\libgtksourceview-3.0-1.dll" + File "$%GTK_PREFIX%\bin\libharfbuzz-0.dll" + File "$%GTK_PREFIX%\bin\libharfbuzz-icu-0.dll" + File "$%GTK_PREFIX%\bin\libidn-11.dll" + File "$%GTK_PREFIX%\bin\libintl-8.dll" + File "$%GTK_PREFIX%\bin\libjavascriptcoregtk-3.0-0.dll" + File "$%GTK_PREFIX%\bin\libjpeg-62.dll" + File "$%GTK_PREFIX%\bin\libpango-1.0-0.dll" + File "$%GTK_PREFIX%\bin\libpangocairo-1.0-0.dll" + File "$%GTK_PREFIX%\bin\libpangoft2-1.0-0.dll" + File "$%GTK_PREFIX%\bin\libpangowin32-1.0-0.dll" + File "$%GTK_PREFIX%\bin\libpixman-1-0.dll" + File "$%GTK_PREFIX%\bin\libpng16-16.dll" + File "$%GTK_PREFIX%\bin\libsoup-2.4-1.dll" + File "$%GTK_PREFIX%\bin\libsqlite3-0.dll" + File "$%GTK_PREFIX%\bin\libssh2-1.dll" + File "$%GTK_PREFIX%\bin\libssl-10.dll" + File "$%GTK_PREFIX%\bin\libstdc++-6.dll" + File "$%GTK_PREFIX%\bin\libxml2-2.dll" + File "$%GTK_PREFIX%\bin\libxslt-1.dll" + File "$%GTK_PREFIX%\bin\libwebkitgtk-3.0-0.dll" + File "$%GTK_PREFIX%\bin\libwebp-4.dll" + File "$%GTK_PREFIX%\bin\libwinpthread-1.dll" + File "$%GTK_PREFIX%\bin\zlib1.dll" + + SetOutPath $INSTDIR\share + File /r "$%GTK_PREFIX%\share\themes" + File /r "$%GTK_PREFIX%\share\glib-2.0" + File /r "$%GTK_PREFIX%\share\gtksourceview-3.0" + + SetOutPath $INSTDIR\lib + ; File /r "$%GTK_PREFIX%\lib\gtk-3.0" + ; File /r "$%GTK_PREFIX%\lib\gdk-pixbuf-2.0" + ; File /r "$%GTK_PREFIX%\lib\pango" + ; File /r "$%GTK_PREFIX%\lib\enchant" + ; File /r "$%GTK_PREFIX%\lib\gstreamer-1.0" + + SetOutPath $INSTDIR\libexec + File /r "$%GTK_PREFIX%\libexec\gstreamer-1.0" + + ; Needed to build Gtk2Hs + SetOutPath $INSTDIR\bin + File "$%GTK_PREFIX%\bin\pkg-config.exe" + + ; SetOutPath $INSTDIR\lib + ; File /r "$%GTK_PREFIX%\lib\pkgconfig" + + SetOutPath $INSTDIR + File /r "$%GTK_PREFIX%\include" + File /r "$%GTK_PREFIX%\lib" + + ; Write the installation path into the registry + WriteRegStr HKLM SOFTWARE\Leksah "Install_Dir" "$INSTDIR" + + ; Write the uninstall keys for Windows + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Leksah" "DisplayName" "Leksah" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Leksah" "UninstallString" '"$INSTDIR\uninstall.exe"' + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Leksah" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Leksah" "NoRepair" 1 + WriteUninstaller "uninstall.exe" + +SectionEnd + +; Optional section (can be disabled by the user) +Section "Start Menu Shortcuts" + + CreateDirectory "$SMPROGRAMS\Leksah" + CreateShortCut "$SMPROGRAMS\Leksah\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + CreateShortCut "$SMPROGRAMS\Leksah\Server.lnk" "$INSTDIR\leksah-server.bat" "" "$INSTDIR\leksah.ico" 0 + CreateShortCut "$SMPROGRAMS\Leksah\Rebuild Metadata.lnk" "$INSTDIR\leksah-rebuild-metadata.bat" "" "$INSTDIR\leksah.ico" 0 + CreateShortCut "$SMPROGRAMS\Leksah\Leksah.lnk" "$INSTDIR\bin\leksah.exe" "" "$INSTDIR\leksah.ico" 0 SW_SHOWMINIMIZED + +SectionEnd + +;-------------------------------- + +; Uninstaller + +Section "Uninstall" + + ; Remove registry keys + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Leksah" + DeleteRegKey HKLM SOFTWARE\Leksah + + ; Remove files and uninstaller + Delete $INSTDIR\leksah*.bat + Delete $INSTDIR\leksah.ico + RMDir /r $INSTDIR\leksah + RMDir /r $INSTDIR\bin + RMDir /r $INSTDIR\lib + RMDir /r $INSTDIR\etc + RMDir /r $INSTDIR\share + Delete $INSTDIR\uninstall.exe + + ; Remove shortcuts, if any + Delete "$SMPROGRAMS\Leksah\*.*" + + ; Remove directories used + RMDir "$SMPROGRAMS\Leksah" + RMDir "$INSTDIR" + +SectionEnd
@@ -0,0 +1,119 @@+#!/bin/sh++. scripts/stage.sh || exit++export CABAL_USER_BIN=$HOME/AppData/Roaming/cabal/bin+export GHC_USER_PREFIX=$HOME/AppData/Roaming/cabal/i386-windows-ghc-`ghc$GHCVERSION --numeric-version`+export LEKSAH_PREFIX=$GHC_USER_PREFIX+export LEKSAH_SERVER_PREFIX=$GHC_USER_PREFIX+export HLINT_X_X_X_X=`ghc-pkg$GHCVERSION list |grep '^ *hlint-' | tail -n1 | tr -d ' \n'`+export PRETTY_SHOW_X_X=`ghc-pkg$GHCVERSION list |grep '^ *pretty-show-' | tail -n1 | tr -d ' \n'`+export GHCJS_CODEMIRROR_X_X_X_X=`ghc-pkg$GHCVERSION list |grep '^ *ghcjs-codemirror-' | tail -n1 | tr -d ' \n'`++sed 's|\<ctrl\>q|\<alt\>F4|' <data/keymap.lkshk >"$LEKSAH_PREFIX/$LEKSAH_X_X_X_X/data/keymap.lkshk" || exit++cd win32 || exit++export CURL_PREFIX=`pkg-config --libs-only-L libcurl | sed 's|^-L||' | sed 's|/lib *$||'`+export MINGW_BIN=`cmd //C echo \`dirname \\\`which gcc\\\`\``+export PATH=$PATH:/c/Program\ Files\ \(x86\)/NSIS:/c/Program\ Files/NSIS+#makensis leksah.nsi++export PATH=$PATH:/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.8/bin:/c/Program\ Files/WiX\ Toolset\ v3.8/bin+mkdir -p SourceDir+cp -ru leksah.bat SourceDir+cp -ru leksah-server.bat SourceDir+cp -ru leksah-rebuild-metadata.bat SourceDir+cp -ru "$GTK_PREFIX"/etc SourceDir+mkdir -p SourceDir/leksah+cp -ru "$LEKSAH_PREFIX/$LEKSAH_X_X_X_X"/data SourceDir/leksah+cp -ru "$LEKSAH_PREFIX/$LEKSAH_X_X_X_X"/language-specs SourceDir/leksah+cp -ru "$LEKSAH_PREFIX/$LEKSAH_X_X_X_X"/pics SourceDir/leksah+cp -u "$LEKSAH_PREFIX/$LEKSAH_X_X_X_X"/LICENSE SourceDir/leksah+cp -u "$LEKSAH_PREFIX/$LEKSAH_X_X_X_X"/Readme.md SourceDir/leksah+mkdir -p SourceDir/hlint+cp -u "$LEKSAH_PREFIX/$HLINT_X_X_X_X"/* SourceDir/hlint+mkdir -p SourceDir/pretty-show+cp -ru "$LEKSAH_PREFIX/$PRETTY_SHOW_X_X"/style SourceDir/pretty-show+mkdir -p SourceDir/ghcjs-codemirror+cp -ru "$LEKSAH_PREFIX/$GHCJS_CODEMIRROR_X_X_X_X"/mode SourceDir/ghcjs-codemirror+cp -ru "$LEKSAH_PREFIX/$GHCJS_CODEMIRROR_X_X_X_X"/lib SourceDir/ghcjs-codemirror+cp -ru "$LEKSAH_PREFIX/$GHCJS_CODEMIRROR_X_X_X_X"/keymap SourceDir/ghcjs-codemirror+cp -ru "$LEKSAH_PREFIX/$GHCJS_CODEMIRROR_X_X_X_X"/theme SourceDir/ghcjs-codemirror+mkdir -p SourceDir/bin+cp -u "$CABAL_USER_BIN"/leksah.exe SourceDir/bin +cp -u "$CABAL_USER_BIN"/vcswrapper.exe SourceDir/bin +cp -u "$CABAL_USER_BIN"/vcsgui.exe SourceDir/bin +cp -u "$CABAL_USER_BIN"/vcsgui-askpass.exe SourceDir/bin +cp -u "$CABAL_USER_BIN"/leksah-server.exe SourceDir/bin +cp -u "$CABAL_USER_BIN"/leksahecho.exe SourceDir/bin +cp -u "$GTK_PREFIX"/bin/iconv.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/icudata50.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/icui18n50.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/icule50.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/icuuc50.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libatk-1.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libbz2-1.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libcairo-2.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libcairo-gobject-2.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libcrypto-10.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libcurl-4.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libenchant.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libexpat-1.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libffi-6.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libfontconfig-1.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libfreetype-6.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgailutil-3-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgcc_s_sjlj-1.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgdk-3-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgdk_pixbuf-2.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgio-2.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libglib-2.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgmodule-2.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgobject-2.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgst*-1.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgthread-2.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgtk-3-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libgtksourceview-3.0-1.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libharfbuzz-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libharfbuzz-icu-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libidn-11.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libintl-8.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libjavascriptcoregtk-3.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libjpeg-62.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libpango-1.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libpangocairo-1.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libpangoft2-1.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libpangowin32-1.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libpixman-1-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libpng16-16.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libsoup-2.4-1.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libsqlite3-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libssh2-1.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libssl-10.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libstdc++-6.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libxml2-2.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libxslt-1.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libwebkitgtk-3.0-0.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libwebp-4.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/libwinpthread-1.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/zlib1.dll SourceDir/bin +cp -u "$GTK_PREFIX"/bin/pkg-config.exe SourceDir/bin +mkdir -p SourceDir/share+cp -ru "$GTK_PREFIX"/share/themes SourceDir/share +cp -ru "$GTK_PREFIX"/share/glib-2.0 SourceDir/share +cp -ru "$GTK_PREFIX"/share/gtksourceview-3.0 SourceDir/share +mkdir -p SourceDir/libexec+cp -ru "$GTK_PREFIX"/libexec/gstreamer-1.0 SourceDir/libexec ++cp -ru "$GTK_PREFIX"/include SourceDir +cp -ru "$GTK_PREFIX"/lib SourceDir ++# mkdir -p SourceDir/fonts+# cp -ru /c/Windows/Fonts/DejaVuS*.ttf SourceDir ++heat dir SourceDir -srd -gg -sfrag -template fragment -out heat.wxs -cg Leksah -dr INSTALLDIR -sreg suppress registry harvesting || exit+candle heat.wxs || exit+candle leksah.wxs || exit+light -ext WixUIExtension heat.wixobj leksah.wixobj -out $LEKSAH_X_X_X_X.msi || exit+
@@ -0,0 +1,35 @@+#!/bin/sh++#export PATH='/c/Program Files (x86)/Haskell Platform/2010.2.0.0/bin':$PATH+#ghc -V || exit+#scripts/clean.sh+#PATH='/c/Program Files (x86)/Haskell Platform/2011.4.0.0/lib/extralibs/bin':$PATH cabal install haddock-2.8.1+#win32/makeinstaller.sh || exit++export PATH='/c/Program Files (x86)/Haskell Platform/2011.2.0.1/bin':$PATH+ghc -V || exit+scripts/clean.sh+PATH='/c/Program Files (x86)/Haskell Platform/2011.2.0.1/lib/extralibs/bin':$PATH cabal install haddock-2.9.2+win32/makeinstaller.sh || exit++export PATH='/c/Program Files (x86)/Haskell Platform/2011.4.0.0/bin':$PATH+ghc -V || exit+scripts/clean.sh+PATH='/c/Program Files (x86)/Haskell Platform/2011.4.0.0/lib/extralibs/bin':$PATH cabal install haddock-2.9.2+win32/makeinstaller.sh || exit++export PATH='/c/Program Files (x86)/Haskell Platform/2012.2.0.0/bin':$PATH+ghc -V || exit+scripts/clean.sh+win32/makeinstaller.sh || exit++export PATH='/c/Program Files (x86)/Haskell Platform/2012.4.0.0/bin':$PATH+ghc -V || exit+scripts/clean.sh+win32/makeinstaller.sh || exit++export PATH='/c/Program Files (x86)/Haskell Platform/2013.2.0.0/bin':$PATH+ghc -V || exit+scripts/clean.sh+win32/makeinstaller.sh || exit+
@@ -0,0 +1,17 @@+#!/bin/sh + +# This is just a handy script to run after blowing away your ~/AppData/Roaming/ghc directory. +# On Vista and later you will need to be admin. + +export PATH='/C/Program Files (x86)/Haskell Platform/2010.2.0.0/bin':$PATH +ghc -V +ghc-pkg recache + +export PATH='/C/Program Files (x86)/Haskell Platform/2011.2.0.1/bin':$PATH +ghc -V +ghc-pkg recache + +export PATH='/C/Program Files (x86)/Haskell Platform/2011.4.0.0/bin':$PATH +ghc -V +ghc-pkg recache +