packages feed

phoityne 0.0.4.0 → 0.0.5.0

raw patch · 9 files changed

+759/−379 lines, 9 files

Files

Changelog.md view
@@ -1,4 +1,15 @@+20160501 phoityne-0.0.5.0++  * [Change] Ctrl+PageUp、Ctrl+PageDownでテキストエディッタのタブを移動するように変更した。+  * [Change] 検索において、大文字と小文字を区別するオプションを追加した。+  * [Info] ghc-8.0.1に対応した。+  * [Add] 検索結果をハイライトするように変更した。+  * [Add] F3 + Shiftショートカットキーで検索を逆にたどるように変更した。+  * [Add] 置換において選択範囲のみ置換できるように変更した。++ 20160301 phoityne-0.0.4.0+   * [Change] ブレークせずに実行が終了した場合は、デバッグ終了状態に遷移するように変更した。   * [Change] stack buildの起動引数を「--test --no-run-tests」に変更した。   * [Change] ghciの起動引数を「--test --no-build --no-load」に変更した。@@ -6,6 +17,7 @@   * [Fix] ファイルを再オープンした際は、エディッタにおいてファイル先頭に移動しないように修正した。   * [Add] システムフォントの名前とサイズを設定ファイルで指定するように変更した。 + 20160201 phoityne-0.0.3.0    * [Fix] phoityne終了時にghciを停止するように修正した。@@ -15,17 +27,21 @@   * [Add] タイトルにプロジェクトフォルダパスを表示するように変更した。   * [Add] ghci起動/終了のショートカットキーを追加した。(F8, Shift+F8) + 20160101 phoityne-0.0.2.0    * [Add] 参照先情報を取得する機能を追加した(:info)。   * [Add] ファイル保存時にghci上でファイルをロードする機能を追加した。   * [Add] print source file path on statusbar. + 20151223 phoityne-0.0.1.1    * [Add] README.md, Changelog.md + 20151220 phoityne-0.0.1.0    * [Info] Initial release.+ 
README.md view
@@ -1,83 +1,4 @@ # Phoityne -Phoityne is a ghci debug viewer with simple editor.-(on Windows)--## Install---### Setup GTK3-Download the all in package of gtk from [here](http://win32builder.gnome.org/ "GTK3").-Extract it and set path to bin and lib folder, set install directory to prefix of  lib/pkgconfig/*.pc files.---### Start stack project--    % stack new project-      . . . . .-    %-    % cd project-    % stack install phoityne-      . . . . .-    %-    % C:\Users\username\AppData\Roaming\local\bin\phoityne.exe-    %--## Keyboard shortcuts---### Build, Debug-* F5 : start debug / jump to next break point-* Shift+F5 : end debug-* F7 : build-* Shift+F7 : rebuild (stack clean; stack build)-* F9 : put on/off break point-* F10 : step over-* F11 : step in--### File, Search-* Ctrl+S : save all-* Ctrl+F : search-* F3 : jump to next search result-* Ctrl+R : replace--### Folder Tree-* Left :  collapse folder-* Right :  expand folder-* Up :  go up-* Down :  go down---## Demo Videos--### Demo Video1-[![Demo Video1](http://img.youtube.com/vi/MKMEgb0sFsI/0.jpg)](https://www.youtube.com/watch?v=MKMEgb0sFsI)--### Demo Video2-[![Demo Video2](http://img.youtube.com/vi/T10wWCmWHaA/0.jpg)](https://www.youtube.com/watch?v=T10wWCmWHaA)---## Document-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド1.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド2.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド3.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド4.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド5.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド6.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド7.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド8.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド9.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド10.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド11.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド12.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド13.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド14.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド15.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド16.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド17.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド18.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド19.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド20.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド21.PNG)-![Document](https://sites.google.com/site/phoityne/doc_jp/スライド22.PNG)+Deprecated - use phoityne-vscode package instead. 
app/Phoityne/IO/GUI/Control.hs view
@@ -12,6 +12,7 @@ , DebugCommandData(..) ) where + -- モジュール import Phoityne.Constant import Phoityne.Utility@@ -183,6 +184,7 @@   IF.setupMainWindow builder ("Phoityne [" ++ (IF.getPathFromNodeData rootNode) ++ "]") systemFont     (mainWindowCloseEventHanlder mvarGUI cmdData)     (mainWindowKeyPressEventHandler mvarGUI cmdData)+    (textEditorSwitchPageEventHandler mvarGUI cmdData)    IF.setupToolButton builder     (toolBTdebugStartHandler mvarGUI cmdData)@@ -206,7 +208,7 @@     (folderTreeCreateFileAction     mvarGUI cmdData)     (folderTreeRenameAction         mvarGUI)     (folderTreeDeleteAction         mvarGUI)-    (folderTreeSearchAction         mvarGUI)+    (folderTreeSearchAction         mvarGUI cmdData)     (folderTreeReplaceAction        mvarGUI cmdData)     (folderTreeKeyPressEventHandler mvarGUI cmdData)     (folderTreeStartupAction        mvarGUI cmdData)@@ -377,51 +379,71 @@     withEditor (nodeData, editor) = do       guiData <- readMVar mvarGUI       let builder = widgetStoreMVarGUIData guiData+          store   = searchResultListStoreMVarGUIData guiData        defaultStr <- IF.getSelectedText editor       IF.getSearchKeyBySearchDialog builder defaultStr >>= \case-        Nothing  -> return True-        Just key -> do-          clearSearchResultTable mvarGUI-          activateSearchResultTab mvarGUI-          setSearchFiles mvarGUI [nodeData]-          keywordLineSearch [nodeData] key (searchResultHandler mvarGUI)-          +        (Nothing, _)  -> return True+        (Just key, isLower) -> do+          runSearch mvarGUI cmdDat [nodeData] (key, isLower)+                   (lineNo, _) <- IF.getCodeTextLineNumber editor-          activateTextEditorWithSearchResult mvarGUI cmdDat $ Just (IF.getPathFromNodeData nodeData, lineNo+2)+          IF.nextCurrentSearchResult builder store $ Just (IF.getPathFromNodeData nodeData, lineNo+2)++          updateSearchResultTag mvarGUI cmdDat (IF.getPathFromNodeData nodeData) editor+          activateTextEditorWithSearchResult mvarGUI cmdDat+           return True -mainWindowKeyPressEventHandler mvarGUI cmdDat "r" _ True =findCurrentTextEditor mvarGUI >>= \case+mainWindowKeyPressEventHandler mvarGUI cmdDat "r" _ True = findCurrentTextEditor mvarGUI >>= \case   Nothing -> errorM _LOG_NAME "[mainWindowKeyPressEventHandler] invalid text editor." >> return True   Just a -> withEditor a   where     withEditor (nodeData, editor) = do       guiData <- readMVar mvarGUI       let builder   = widgetStoreMVarGUIData guiData+          store     = searchResultListStoreMVarGUIData guiData           nodeDatas = [nodeData] -      IF.getReplaceByReplaceDialog builder >>= \case+      rangeMay <- IF.getSelectedRange editor+      +      IF.getReplaceByReplaceDialog builder (getRangeInfo rangeMay) >>= \case         Nothing -> return True         Just (key, rep) -> do           saveAll mvarGUI cmdDat-          replaceFiles nodeDatas key rep+          replaceFiles nodeDatas rangeMay key rep           reloadAll mvarGUI     -          -- search-          clearSearchResultTable mvarGUI-          activateSearchResultTab mvarGUI-          setSearchFiles mvarGUI nodeDatas-          keywordLineSearch nodeDatas rep (searchResultHandler mvarGUI)+          runSearch mvarGUI cmdDat nodeDatas (rep, False)                      (lineNo, _) <- IF.getCodeTextLineNumber editor-          activateTextEditorWithSearchResult mvarGUI cmdDat $ Just (IF.getPathFromNodeData nodeData, lineNo+2)+          IF.nextCurrentSearchResult builder store $ Just (IF.getPathFromNodeData nodeData, lineNo+2)++          updateSearchResultTag mvarGUI cmdDat (IF.getPathFromNodeData nodeData) editor+          activateTextEditorWithSearchResult mvarGUI cmdDat+           return True +    getRangeInfo Nothing = "ALL"+    getRangeInfo (Just (s, e)) = "L" ++ show (s+1) ++ " - L" ++ show (e+1) -mainWindowKeyPressEventHandler mvarGUI cmdDat "F3" False _ = do-  activateTextEditorWithSearchResult mvarGUI cmdDat Nothing+++mainWindowKeyPressEventHandler mvarGUI cmdDat "F3" isShift _ = do+  autoSearch mvarGUI cmdDat++  guiData <- readMVar mvarGUI+  let builder = widgetStoreMVarGUIData guiData+      store   = searchResultListStoreMVarGUIData guiData++  if True == isShift then IF.prevCurrentSearchResult builder store+    else  IF.nextCurrentSearchResult builder store Nothing++  activateTextEditorWithSearchResult mvarGUI cmdDat+   return True + mainWindowKeyPressEventHandler _ _ _ _ _ = return False  @@ -1141,23 +1163,26 @@ -- | --  Event Handler ---folderTreeSearchAction :: MVar MVarGUIData -> IF.FolderTreeSearchAction-folderTreeSearchAction mvarGUI = do+folderTreeSearchAction :: MVar MVarGUIData -> DebugCommandData -> IF.FolderTreeSearchAction+folderTreeSearchAction mvarGUI cmdDat = do   guiData <- readMVar mvarGUI   let builder   = widgetStoreMVarGUIData guiData       treeStore = folderTreeMVarGUIData guiData -  IF.getSelectedFolderTreeAllNodeData builder treeStore >>= withNodeDatas builder-    +  IF.getSelectedFolderTreeNodeData builder treeStore >>= \case+    Nothing -> errorM _LOG_NAME "invalid tree folder status."+    Just (IF.FolderNodeData _ _ _) -> IF.getSelectedFolderTreeAllNodeData builder treeStore >>= withNodeDatas builder+    Just (IF.FileNodeData _ _ _) -> do+      folderTreeKeyPressEventHandler mvarGUI cmdDat "Return" False False+      mainWindowKeyPressEventHandler mvarGUI cmdDat "f" False True+      return ()+   where     withNodeDatas _ [] = errorM _LOG_NAME "invalid node data."     withNodeDatas builder nodeDatas = do-      keyMay <- IF.getSearchKeyBySearchDialog builder ""+      (keyMay, isLower) <- IF.getSearchKeyBySearchDialog builder ""       when (isJust keyMay) $ do-        clearSearchResultTable mvarGUI-        activateSearchResultTab mvarGUI-        setSearchFiles mvarGUI nodeDatas-        keywordLineSearch nodeDatas (fromJust keyMay) (searchResultHandler mvarGUI)+        runSearch mvarGUI cmdDat nodeDatas (fromJust keyMay, isLower)  -- | --  Event Handler@@ -1168,23 +1193,25 @@   let builder   = widgetStoreMVarGUIData guiData       treeStore = folderTreeMVarGUIData guiData -  IF.getSelectedFolderTreeAllNodeData builder treeStore >>= withNodeDatas builder+  IF.getSelectedFolderTreeNodeData builder treeStore >>= \case+    Nothing -> errorM _LOG_NAME "invalid tree folder status."+    Just (IF.FolderNodeData _ _ _) -> IF.getSelectedFolderTreeAllNodeData builder treeStore >>= withNodeDatas builder+    Just (IF.FileNodeData _ _ _) -> do+      folderTreeKeyPressEventHandler mvarGUI cmdDat "Return" False False+      mainWindowKeyPressEventHandler mvarGUI cmdDat "r" False True+      return ()    where     withNodeDatas _ [] = errorM _LOG_NAME "invalid node data."     withNodeDatas builder nodeDatas = do-      IF.getReplaceByReplaceDialog builder >>= \case+      IF.getReplaceByReplaceDialog builder "ALL" >>= \case         Nothing -> return ()         Just (key, rep) -> do           saveAll mvarGUI cmdDat-          replaceFiles nodeDatas key rep+          replaceFiles nodeDatas Nothing key rep           reloadAll mvarGUI     -          -- search-          clearSearchResultTable mvarGUI-          activateSearchResultTab mvarGUI-          setSearchFiles mvarGUI nodeDatas-          keywordLineSearch nodeDatas rep (searchResultHandler mvarGUI)+          runSearch mvarGUI cmdDat nodeDatas (rep, False)      -- | --  イベントハンドラ@@ -1472,46 +1499,9 @@   infoM _LOG_NAME "ctrl g called. not yet implemented."   return True -codeTextKeyPressEventHandler mvarGUI cmdData "F4" _ _ _ _ = findCurrentTextEditor mvarGUI >>= \case-  Nothing -> errorM _LOG_NAME "[codeTextKeyPressEventHandler] invalid text editor." >> return True-  Just a -> withEditor a-  where-    withEditor (nodeDat, editor) = do-      key <- IF.getSelectedText editor-      withKey key $ IF.getPathFromNodeData nodeDat--    withKey key path-      | null key  = return True-      | otherwise = autoRunGHCi mvarGUI cmdData >>= \case-          False -> errorM _LOG_NAME "run ghci failed." >> return True-          True -> do-            guiData <- readMVar mvarGUI-            let builder = widgetStoreMVarGUIData guiData-            res <- IF.isDebugStarted builder-            debugStarted key path res--    debugStarted key path True = fileLoaded key path True-    debugStarted key path False = loadHsFile mvarGUI cmdData path >>= fileLoaded key path--    fileLoaded _ path False = errorM _LOG_NAME ("load hs file fail." ++ path) >> return True-    fileLoaded key _ True = do-      guiData <- readMVar mvarGUI-      let builder   = widgetStoreMVarGUIData guiData-          info      = infoDebugCommandData cmdData-          getResult = readDebugCommandData cmdData-      -      cmdStr <- info key-      IF.putStrLnConsole builder cmdStr--      cmdStr <- getResult-      IF.putStrConsole builder cmdStr-      -      case getDefinedTextRangeData cmdStr of-        Right pos -> activateTextEditor mvarGUI cmdData pos-        Left err  -> infoM _LOG_NAME $ "[codeTextKeyPressEventHandler]" ++ show err--      return True+codeTextKeyPressEventHandler mvarGUI cmdData "F4" _ _ _ _ = jumpToCodeDefinition mvarGUI cmdData >> return True +codeTextKeyPressEventHandler mvarGUI cmdData "F12" _ _ _ _ = jumpToCodeDefinition mvarGUI cmdData >> return True  codeTextKeyPressEventHandler mvarGUI cmdDat "z" False True _ _ = do   guiData <- takeMVar mvarGUI@@ -1609,20 +1599,83 @@       return ()      +codeTextKeyPressEventHandler mvarGUI cmdDat "Page_Up" False True _ _ = do+  guiData <- readMVar mvarGUI+  let builder = widgetStoreMVarGUIData guiData++  IF.pageUpTextEditor builder++  return True++codeTextKeyPressEventHandler mvarGUI cmdDat "Page_Down" False True _ _ = do+  guiData <- readMVar mvarGUI+  let builder = widgetStoreMVarGUIData guiData++  IF.pageDownTextEditor builder++  return True+ codeTextKeyPressEventHandler _ _ _ _ _ _ _ = return False   -- |---  イベントハンドラ+-- -- -codeBufferChangedEventHandler :: MVar MVarGUIData -> IO ()-codeBufferChangedEventHandler _ = return ()+jumpToCodeDefinition :: MVar MVarGUIData -> DebugCommandData -> IO ()+jumpToCodeDefinition mvarGUI cmdData = findCurrentTextEditor mvarGUI >>= \case+  Nothing -> errorM _LOG_NAME "[codeTextKeyPressEventHandler] invalid text editor."+  Just a  -> withEditor a+  where+    withEditor (nodeDat, editor) = do+      key <- IF.getSelectedText editor+      withKey key $ IF.getPathFromNodeData nodeDat +    withKey key path+      | null key  = return ()+      | otherwise = autoRunGHCi mvarGUI cmdData >>= \case+          False -> errorM _LOG_NAME "run ghci failed."+          True -> do+            guiData <- readMVar mvarGUI+            let builder = widgetStoreMVarGUIData guiData+            res <- IF.isDebugStarted builder+            debugStarted key path res +    debugStarted key path True = fileLoaded key path True+    debugStarted key path False = loadHsFile mvarGUI cmdData path >>= fileLoaded key path +    fileLoaded _ path False = errorM _LOG_NAME ("load hs file fail." ++ path)+    fileLoaded key _ True = do+      guiData <- readMVar mvarGUI+      let builder   = widgetStoreMVarGUIData guiData+          info      = infoDebugCommandData cmdData+          getResult = readDebugCommandData cmdData+      +      cmdStr <- info key+      IF.putStrLnConsole builder cmdStr++      cmdStr <- getResult+      IF.putStrConsole builder cmdStr+      +      case getDefinedTextRangeData cmdStr of+        Right pos -> activateTextEditor mvarGUI cmdData pos+        Left err  -> infoM _LOG_NAME $ "[codeTextKeyPressEventHandler]" ++ show err++ -- | --  イベントハンドラ -- +codeBufferChangedEventHandler :: MVar MVarGUIData -> IO ()+codeBufferChangedEventHandler mvarGUI = findCurrentTextEditor mvarGUI >>= \case+  Nothing -> errorM _LOG_NAME "[codeBufferChangedEventHandler] invalid text editor."+  Just (_, editor) -> do+    IF.clearSearchResultTag editor+    clearSearchResultTable mvarGUI+    setSearchFiles mvarGUI []++    +-- |+--  イベントハンドラ+--  codeBufferDeleteRangeEventHandler :: MVar MVarGUIData -> (Int, Int) -> (Int, Int) -> String -> IO () codeBufferDeleteRangeEventHandler mvarGUI (siLineNo, siColNo) (eiLineNo, eiColNo) str = findCurrentTextEditor mvarGUI >>= \case   Nothing -> errorM _LOG_NAME "[codeBufferDeleteRangeEventHandler] invalid text editor."@@ -1637,10 +1690,10 @@       let delDat = DeleteRangeUndoRedoData {                      filePathDeleteRangeUndoRedoData = IF.getPathFromNodeData nodeDat                    , startLineNoDeleteRangeUndoRedoData = siLineNo-                   , startColNoDeleteRangeUndoRedoData = siColNo-                   , endLineNoDeleteRangeUndoRedoData = eiLineNo-                   , endColNoDeleteRangeUndoRedoData = eiColNo-                   , textDeleteRangeUndoRedoData = str+                   , startColNoDeleteRangeUndoRedoData  = siColNo+                   , endLineNoDeleteRangeUndoRedoData   = eiLineNo+                   , endColNoDeleteRangeUndoRedoData    = eiColNo+                   , textDeleteRangeUndoRedoData        = str                    }                       @@ -1811,7 +1864,52 @@ --  検索 -- +runSearch :: MVar MVarGUIData -> DebugCommandData -> [IF.NodeData]  -> (String, Bool) -> IO ()+runSearch mvarGUI cmdDat targets info@(key, isLower)  = do++  guiData <- readMVar mvarGUI+  let builder = widgetStoreMVarGUIData guiData++  clearSearchResultTable mvarGUI+  setSearchFiles mvarGUI targets++  saveAll mvarGUI cmdDat+  keywordLineSearch targets info (searchResultHandler mvarGUI)++  activateSearchResultTab mvarGUI++ -- |+--   F3が押された際に、検索キーが設定されているが、検索未実施のソースファイルが+--   テキストエディッタに表示されている場合に、検索を自動実行する。+--+autoSearch :: MVar MVarGUIData -> DebugCommandData -> IO ()+autoSearch mvarGUI cmdDat = findCurrentTextEditor mvarGUI >>= \case+  Nothing -> errorM _LOG_NAME "[autoSearch] invalid text editor"+  Just a -> withEditor a+  where+    withEditor curEditor@(nodeDat, _) = do+      guiData <- readMVar mvarGUI+      let files = searchFilesMVarGUIData guiData+    +      hasSearched curEditor $ L.elem (IF.getPathFromNodeData nodeDat) files+    +    hasSearched _ True = return ()+    hasSearched curEditor False = do+      guiData <- readMVar mvarGUI+      let builder = widgetStoreMVarGUIData guiData++      key <- IF.getSearchKeyFromSearchDialog builder+      isSearchKey curEditor key++    isSearchKey (nodeData, editor) info@(key, _) +      | null key  = mainWindowKeyPressEventHandler mvarGUI cmdDat "f" False True >> return ()+      | otherwise = do+          runSearch mvarGUI cmdDat [nodeData] info+          updateSearchResultTag mvarGUI cmdDat (IF.getPathFromNodeData nodeData) editor+++-- | --   検索対象となったファイル群を共有データに保存する。 --  setSearchFiles :: MVar MVarGUIData -> [IF.NodeData] -> IO ()@@ -1850,7 +1948,7 @@ -- | --  複数ファイルにおいて、行単位のキーワード検索を行う ---keywordLineSearch :: [IF.NodeData] -> String -> (FilePath -> Int -> Int -> Int -> String -> IO ()) -> IO ()+keywordLineSearch :: [IF.NodeData]  -> (String, Bool) -> (FilePath -> Int -> Int -> Int -> String -> IO ()) -> IO () keywordLineSearch [] _ _ = return () keywordLineSearch ((IF.FolderNodeData _ _ _):xs) key hdl = keywordLineSearch xs key hdl keywordLineSearch ((IF.FileNodeData _ _ path):xs) key hdl = searchFile path key hdl >> keywordLineSearch xs key hdl@@ -1859,20 +1957,20 @@     -- |     --     ---    searchFile :: FilePath -> String -> (FilePath -> Int -> Int -> Int -> String -> IO ()) -> IO ()-    searchFile path key hdl = do+    searchFile :: FilePath -> (String, Bool) -> (FilePath -> Int -> Int -> Int -> String -> IO ()) -> IO ()+    searchFile path (key, isLower) hdl = do       bs <- loadFile path-      searchLine (TE.pack key) (hdl path) 1 $ TE.lines $ TE.decodeUtf8 bs+      searchLine (TE.pack key) isLower (hdl path) 1 $ TE.lines $ TE.decodeUtf8 bs               -- |     --     ---    searchLine :: TE.Text -> (Int -> Int -> Int -> String -> IO ()) -> Int -> [TE.Text] -> IO ()-    searchLine _ _ _ [] = return ()-    searchLine key hdl lineNo (line:lines) = do-      mapM_ go $ TE.breakOnAll key line-      searchLine key hdl (lineNo+1) lines+    searchLine :: TE.Text -> Bool -> (Int -> Int -> Int -> String -> IO ()) -> Int -> [TE.Text] -> IO ()+    searchLine _ _ _ _ [] = return ()+    searchLine key isLower hdl lineNo (line:lines) = do+      mapM_ go $ TE.breakOnAll (if isLower then TE.toLower key else key) (if isLower then TE.toLower line else line)+      searchLine key isLower hdl (lineNo+1) lines       where         go (prior, _) = hdl lineNo (colIdx prior) (colIdx prior + TE.length key - 1) (TE.unpack line)         colIdx txt = (TE.length txt) + 1@@ -1894,17 +1992,26 @@ -- | --   行単位の置換を行う ---replaceFiles :: [IF.NodeData] -> String -> String -> IO ()-replaceFiles [] _ _ = return ()-replaceFiles ((IF.FolderNodeData _ _ _):xs) key rep = replaceFiles xs key rep-replaceFiles ((IF.FileNodeData _ _ path):xs) key rep = replaceFile path key rep >> replaceFiles xs key rep+replaceFiles :: [IF.NodeData] -> Maybe (Int, Int) -> String -> String -> IO ()+replaceFiles [] _ _ _ = return ()+replaceFiles ((IF.FolderNodeData _ _ _):xs) rangeMay key rep = replaceFiles xs rangeMay key rep+replaceFiles ((IF.FileNodeData _ _ path):xs) rangeMay key rep = replaceFile path rangeMay key rep >> replaceFiles xs rangeMay key rep   where-    replaceFile :: FilePath -> String -> String -> IO ()-    replaceFile path key rep = do+    replaceFile :: FilePath -> Maybe (Int, Int) -> String -> String -> IO ()+    replaceFile path Nothing key rep = do       bs <- loadFile path       let res = TE.replace (TE.pack key) (TE.pack rep) $ TE.decodeUtf8 bs       saveFile path $ TE.encodeUtf8 res +    replaceFile path (Just (sl, el)) key rep = do+      bs <- loadFile path+      let conts   = TE.lines . TE.decodeUtf8 $ bs+          prefix  = TE.unlines$ take sl conts+          targets = take (el - sl + 1) $ drop sl conts+          suffix  = TE.unlines $ drop (el+1) conts+          repls   = TE.replace (TE.pack key) (TE.pack rep) $ TE.unlines targets+          res     = TE.append prefix $ TE.append repls suffix+      saveFile path $ TE.encodeUtf8 res  -- |===================================================================== --  Utility@@ -2162,53 +2269,18 @@ -- | --  -- -activateTextEditorWithSearchResult :: MVar MVarGUIData -> DebugCommandData -> Maybe IF.SearchResultOffset -> IO ()-activateTextEditorWithSearchResult mvarGUI cmdDat offset = findCurrentTextEditor mvarGUI >>= \case-  Nothing -> errorM _LOG_NAME "[activateTextEditorWithSearchResult] invalid text editor"-  Just a -> withEditor a-  where-    withEditor curEditor@(nodeDat, _) = do-      guiData <- readMVar mvarGUI-      let files   = searchFilesMVarGUIData guiData-    -      hasSearched curEditor $ L.elem (IF.getPathFromNodeData nodeDat) files-    -    hasSearched _ True = do-      guiData <- readMVar mvarGUI-      let builder = widgetStoreMVarGUIData guiData-          store   = searchResultListStoreMVarGUIData guiData-      IF.nextCurrentSearchResult builder store offset+activateTextEditorWithSearchResult :: MVar MVarGUIData -> DebugCommandData -> IO ()+activateTextEditorWithSearchResult mvarGUI cmdDat = do+  guiData <- readMVar mvarGUI+  let builder = widgetStoreMVarGUIData guiData+      store   = searchResultListStoreMVarGUIData guiData -      activateTextEditorWithCurrentSearchResult mvarGUI cmdDat+  IF.getCurrentSearchResult builder store >>= \case+    Nothing -> return ()+    Just (IF.SearchResultData filePath lineNo startCol endCol _) -> do+      activateTextEditor mvarGUI cmdDat $ HighlightTextRangeData filePath lineNo startCol lineNo endCol -    hasSearched curEditor False = do-      guiData <- readMVar mvarGUI-      let builder = widgetStoreMVarGUIData guiData-      key <- IF.getSearchKeyFromSearchDialog builder-      isSearchKey curEditor key -    isSearchKey (nodeData, editor) key -      | null key  = mainWindowKeyPressEventHandler mvarGUI cmdDat "f" False True >> return ()-      | otherwise = do-          clearSearchResultTable mvarGUI-          activateSearchResultTab mvarGUI-          setSearchFiles mvarGUI [nodeData]-          keywordLineSearch [nodeData] key (searchResultHandler mvarGUI)-          -          (lineNo, _) <- IF.getCodeTextLineNumber editor-          activateTextEditorWithSearchResult mvarGUI cmdDat $ Just (IF.getPathFromNodeData nodeData, lineNo+2)--    activateTextEditorWithCurrentSearchResult :: MVar MVarGUIData -> DebugCommandData -> IO ()-    activateTextEditorWithCurrentSearchResult mvarGUI cmdData = do-      guiData <- readMVar mvarGUI-      let builder = widgetStoreMVarGUIData guiData-          store   = searchResultListStoreMVarGUIData guiData-    -      IF.getCurrentSearchResult builder store >>= \case-        Nothing -> return ()-        Just (IF.SearchResultData filePath lineNo startCol endCol _) -> do-          activateTextEditor mvarGUI cmdData $ HighlightTextRangeData filePath lineNo startCol lineNo endCol- -- | -- --@@ -2242,6 +2314,30 @@         True  -> return $ Just (n, e)         False -> findCurrent builder xs ++-- |+--+--+updateSearchResultTag :: MVar MVarGUIData -> DebugCommandData -> FilePath -> IF.TextEditorData -> IO ()+updateSearchResultTag mvarGUI cmdData path editor = do+  guiData <- readMVar mvarGUI+  let store = searchResultListStoreMVarGUIData guiData++  searchDatas <- IF.getSearchResultDataByFilePath store path+  +  IF.updateSearchResultTag editor $ map go searchDatas++  where+    go (IF.SearchResultData _ lineNo startCol endCol _) = IF.SearchResultTagInfo (lineNo-1) (startCol-1) (endCol-1)+++-- |+--+--+textEditorSwitchPageEventHandler :: MVar MVarGUIData -> DebugCommandData -> FilePath -> IO ()+textEditorSwitchPageEventHandler mvarGUI cmdData path = findTextEditorByPath mvarGUI path >>= \case+  Nothing -> errorM _LOG_NAME $ "[textEditorSwitchPageEventHandler]invalid text editor."+  Just editor -> updateSearchResultTag mvarGUI cmdData path editor   -- |=====================================================================
app/Phoityne/IO/GUI/GTK/Constant.hs view
@@ -58,6 +58,9 @@ _NAME_CODE_NOTE :: String _NAME_CODE_NOTE = "CodeNote" +_NAME_HASKELL_LOGO :: String+_NAME_HASKELL_LOGO = "HaskellLogo"+ _NAME_MAIN_PANED :: String _NAME_MAIN_PANED = "MainPaned" @@ -127,6 +130,8 @@ _BREAK_POINT_HIGHLIGHT_TAG :: T.Text _BREAK_POINT_HIGHLIGHT_TAG = T.pack "BreakPointHighlightTag" +_SEARCH_RESULT_HIGHLIGHT_TAG :: T.Text+_SEARCH_RESULT_HIGHLIGHT_TAG = T.pack "SearchResultHighlightTag"  _NAME_STATUS_BAR :: String _NAME_STATUS_BAR = "StatusBar"
app/Phoityne/IO/GUI/GTK/Interface.hs view
@@ -108,6 +108,8 @@  type StopGHCiBTClickedEventHandler = IO () +type TextEditorSwitchPageEventHandler = FilePath -> IO ()+ -- | -- --@@ -179,8 +181,9 @@                 -> (String, Int)                 -> MainWindowCloseEventHandler                 -> MainWindowKeyPressEventHandler+                -> TextEditorSwitchPageEventHandler                 -> IO ()-setupMainWindow builder title systemFont closeEvt keyEvt = do+setupMainWindow builder title systemFont closeEvt keyEvt swEvt = do    settings <- fromJust <$> settingsGetDefault   settingsSetStringProperty settings "gtk-font-name" fontDesc ""@@ -200,7 +203,7 @@   panedSetPosition codePaned 350    note <- builderGetObject builder castToNotebook _NAME_CODE_NOTE-  on note switchPage $ switchPageEventHandler note builder+  on note switchPage $ switchPageEventHandler note builder swEvt    return () @@ -290,13 +293,13 @@ -- | -- ---switchPageEventHandler :: Notebook -> Builder -> Int -> IO ()-switchPageEventHandler note builder pageId = do+switchPageEventHandler :: Notebook -> Builder -> TextEditorSwitchPageEventHandler -> Int -> IO ()+switchPageEventHandler note builder swEvt pageId = do   path <- notebookGetNthPage note pageId >>= \case     Nothing -> return "[ERROR] text editor not found."     Just child -> notebookGetMenuLabelText note child >>= \case-      Nothing -> return "[ERROR] text editor not found."-      Just a  -> return a    +      Nothing -> return "[INFO] This is Phoityne welcome page."+      Just a  -> swEvt a >> return a          putStrStatusBar builder path @@ -358,11 +361,13 @@ -- | -- ---getSearchKeyBySearchDialog :: Builder -> String -> IO (Maybe String)+getSearchKeyBySearchDialog :: Builder -> String -> IO (Maybe String, Bool) getSearchKeyBySearchDialog builder defaultStr = do   dialog <- builderGetObject builder castToDialog "SearchDialog"   entry  <- builderGetObject builder castToEntry "SearchDialogEntry"+  chkBox <- builderGetObject builder castToToggleButton  "SearchCheckBox"   entrySetText entry defaultStr+  toggleButtonSetActive chkBox False    widgetGrabFocus entry   res <- dialogRun dialog >>= \case@@ -373,25 +378,35 @@    widgetHide dialog -  return res+  isOn <- toggleButtonGetActive chkBox +  return (res, not isOn)+ -- | -- ---getSearchKeyFromSearchDialog :: Builder -> IO String+getSearchKeyFromSearchDialog :: Builder -> IO (String, Bool) getSearchKeyFromSearchDialog builder = do   entry  <- builderGetObject builder castToEntry "SearchDialogEntry"-  entryGetText entry+  key <- entryGetText entry +  chkBox <- builderGetObject builder castToToggleButton  "SearchCheckBox"+  isOn <- toggleButtonGetActive chkBox++  return (key, not isOn)+ -- | -- ---getReplaceByReplaceDialog :: Builder  -> IO (Maybe (String, String))-getReplaceByReplaceDialog builder = do+getReplaceByReplaceDialog :: Builder  -> String -> IO (Maybe (String, String))+getReplaceByReplaceDialog builder info = do   initReplaceDialog builder   dialog <- builderGetObject builder castToDialog "ReplaceDialog"   searchEntry  <- builderGetObject builder castToEntry "ReplaceDialogSearchEntry"   replaceEntry <- builderGetObject builder castToEntry "ReplaceDialogReplaceEntry"+  replaceLabel <- builderGetObject builder castToLabel "ReplaceRangeInfo"++  labelSetText replaceLabel info    res <- dialogRun dialog >>= \case     ResponseUser 0 -> do
app/Phoityne/IO/GUI/GTK/SearchResultTable.hs view
@@ -19,6 +19,7 @@ , prevCurrentSearchResult , nextCurrentSearchResult , getCurrentSearchResult+, getSearchResultDataByFilePath ) where  -- モジュール@@ -153,10 +154,7 @@ -- -- delSearchBTClickedEventHandler :: Builder -> ListStore SearchResultData -> IO ()-delSearchBTClickedEventHandler _ store = do-  -- initSearchDialog builder-  -- initReplaceDialog builder-  clearSearchResultTable store+delSearchBTClickedEventHandler _ store = clearSearchResultTable store  -- | --@@ -185,11 +183,58 @@ --   --  prevCurrentSearchResult :: Builder -> ListStore SearchResultData -> IO ()-prevCurrentSearchResult = undefined+prevCurrentSearchResult builder store = do+  treeView <- builderGetObject builder castToTreeView "SearchResultTreeView"+  modelMay <- treeViewGetModel treeView+  prevCurrentSearchResultWithModel treeView store modelMay + -- | --   -- +prevCurrentSearchResultWithModel :: TreeView -> ListStore SearchResultData -> Maybe TreeModel -> IO ()+prevCurrentSearchResultWithModel _ _ Nothing = errorM _LOG_NAME $ "[nextCurrentSearchResultWithModel] invalid search result tree view."+prevCurrentSearchResultWithModel treeView _ (Just model) = do+  sel <- treeViewGetSelection treeView+  treeSelectionGetSelected sel >>= \case+    Nothing -> treeModelGetIterEnd model >>= \case+      Nothing -> return () -- table is empty+      Just iter -> selectRow model sel iter+  +    Just iter -> treeModelIterPrev model iter >>= \case+      Nothing -> treeModelGetIterEnd model >>= \case+        Nothing -> return ()  -- table is empty+        Just iter -> selectRow model sel iter+      Just iter -> selectRow model sel iter++  where+    selectRow model sel iter = do      +      treeSelectionSelectIter sel iter+      treePath <- treeModelGetPath model iter+      treeViewScrollToCell treeView (Just treePath) Nothing Nothing++-- |+--  +-- +treeModelIterPrev :: TreeModel -> TreeIter -> IO (Maybe TreeIter)+treeModelIterPrev model iter = treeModelGetPath model iter >>= \case+  [] -> return Nothing+  xs -> if 0 == head xs then return Nothing+          else treeModelIterNthChild model Nothing $ (head xs) - 1++-- |+--  +-- +treeModelGetIterEnd :: TreeModel -> IO (Maybe TreeIter)+treeModelGetIterEnd model = do+  count <- treeModelIterNChildren model Nothing+  treeModelIterNthChild model Nothing $ count - 1++++-- |+--  +--  nextCurrentSearchResult :: Builder -> ListStore SearchResultData -> Maybe SearchResultOffset -> IO () nextCurrentSearchResult builder store offset = do   treeView <- builderGetObject builder castToTreeView "SearchResultTreeView"@@ -272,4 +317,14 @@       Just firstIter -> do         treeSelectionSelectIter sel firstIter         return $ Just firstIter+++-- |+--+--+getSearchResultDataByFilePath :: SearchResultListStore -> FilePath -> IO [SearchResultData]+getSearchResultDataByFilePath store path = do+  datas <- listStoreToList store+  return $ filter ((path ==) . filePathSearchResultData) datas+ 
app/Phoityne/IO/GUI/GTK/TextEditor.hs view
@@ -8,6 +8,7 @@  module Phoityne.IO.GUI.GTK.TextEditor (   TextEditorData(..)+, SearchResultTagInfo(..) , LineTextDoubleClickedHandler , CodeNoteCloseEventHandler , CodeTextKeyPressEventHandler@@ -36,6 +37,11 @@ , deleteBreakPointTagAtLine , updateBreakPointTag , searchEndIter+, pageUpTextEditor+, pageDownTextEditor+, updateSearchResultTag+, clearSearchResultTag+, getSelectedRange ) where  -- モジュール@@ -83,7 +89,17 @@   , tabLabelTextEditorData :: Label   } deriving (Eq) + -- |+--  +-- +data SearchResultTagInfo = SearchResultTagInfo {+    lineNoSearchResultTagInfo   :: Int+  , startColSearchResultTagInfo :: Int+  , endColSearchResultTagInfo   :: Int+  } deriving (Show, Read, Eq, Ord)++-- | -- -- type CodeTextKeyPressEventHandler = String -> Bool -> Bool -> Bool -> Int -> IO Bool@@ -195,6 +211,14 @@       set tag [textTagBackground := "blue", textTagForeground := "white", textTagBackgroundSet := True]       textTagTableAdd tagTable tag +  textTagTableLookup tagTable (T.unpack _SEARCH_RESULT_HIGHLIGHT_TAG) >>= \case+    Just _  -> return ()+    Nothing -> do+      tag <- textTagNew (Just _SEARCH_RESULT_HIGHLIGHT_TAG)+      set tag [textTagBackground := "yellow", textTagBackgroundSet := True]+      textTagTableAdd tagTable tag++   box <- hBoxNew False 0    lineScroll <- scrolledWindowNew Nothing Nothing@@ -216,6 +240,7 @@   textViewSetBorderWindowSize lineTextView TextWindowBottom 5   --textViewSetBorderWindowSize lineTextView TextWindowLeft 10   --textViewSetBorderWindowSize lineTextView TextWindowRight 5+   textViewSetEditable lineTextView False   textViewSetCursorVisible lineTextView False   textViewSetJustification lineTextView JustifyRight@@ -280,10 +305,11 @@           labelSetText label $ str ++ (" *"::String)           widgetSetSensitive saveBt True -    codeTextBufferChangedHandler lineBuf codeBuf _ = do+    codeTextBufferChangedHandler lineBuf codeBuf bufEVH = do       ll <- textBufferGetLineCount lineBuf       cl <- textBufferGetLineCount codeBuf       updateLineNo lineBuf codeBuf ll cl+      bufEVH      updateLineNo lineBuf _ ll cl       | ll == cl = return ()@@ -350,6 +376,7 @@      widgetGrabFocus codeTextView + -- | --  Event Handler -- @@ -388,54 +415,41 @@   iter <- textBufferGetIterAtLine buf line   addBreakPointTagAtIter self iter + -- | -- -- addBreakPointTagAtIter :: TextView -> TextIter -> IO () addBreakPointTagAtIter self startIter = do   textBuf <- textIterGetBuffer startIter-  tagTable <- textBufferGetTagTable textBuf -  tag <- textTagNew Nothing-  set tag [textTagBackground := "blue", textTagForeground := "white", textTagBackgroundSet := True]-  textTagTableAdd tagTable tag-    endIter <- textIterCopy startIter   _ <- textViewForwardDisplayLineEnd self endIter -  textBufferApplyTag textBuf tag startIter endIter+  textBufferApplyTagByName textBuf _BREAK_POINT_HIGHLIGHT_TAG startIter endIter   -- |+--+--+deleteBreakPointTag :: TextEditorData -> Int -> IO ()+deleteBreakPointTag (TextEditorData lineView _ _ _) = deleteBreakPointTagAtLine lineView+++-- | --  指定行についているタグをすべて削除する -- deleteBreakPointTagAtLine :: TextView -> Int -> IO () deleteBreakPointTagAtLine textView line = do-  buf  <- textViewGetBuffer textView-  iter <- textBufferGetIterAtLine buf line-  deleteBreakPointTagAtIter iter+  textBuf  <- textViewGetBuffer textView+  startIter <- textBufferGetIterAtLine textBuf line --- |---  TextIterの位置についているタグをすべて削除する----deleteBreakPointTagAtIter :: TextIter -> IO ()-deleteBreakPointTagAtIter iter = do-  textBuf  <- textIterGetBuffer iter-  tagTable <- textBufferGetTagTable textBuf-  tags     <- textIterGetTags iter-  mapM_ (textTagTableRemove tagTable) tags+  endIter <- textIterCopy startIter+  _ <- textViewForwardDisplayLineEnd textView endIter --- |-------deleteBreakPointTag :: TextEditorData -> Int -> IO ()-deleteBreakPointTag (TextEditorData lineView _ _ _) lineNo = do-  textBuf  <- textViewGetBuffer lineView-  tagTable <- textBufferGetTagTable textBuf-  iter     <- textBufferGetIterAtLine textBuf (lineNo - 1)-  tags     <- textIterGetTags iter-  mapM_ (textTagTableRemove tagTable) tags+  textBufferRemoveTagByName textBuf _BREAK_POINT_HIGHLIGHT_TAG startIter endIter + -- | --   --@@ -678,22 +692,31 @@           str <- textBufferGetText buf iter endIter False           if startswith _COMMENT_TAG (strip str) then return (True, length (head (split _COMMENT_TAG str)))             else return (False, length (takeWhile (== ' ') str))- ++ -- | -- ---getSelectedLineNumbers :: TextEditorData -> IO (Int, Int)-getSelectedLineNumbers te@(TextEditorData _ codeView _ _) = do+getSelectedRange :: TextEditorData -> IO (Maybe (Int, Int))+getSelectedRange (TextEditorData _ codeView _ _) = do   buf  <- textViewGetBuffer codeView   textBufferHasSelection buf >>= \case-    True -> do+    False  -> return Nothing+    True   -> do       (startIter, endIter) <- textBufferGetSelectionBounds buf        s <- textIterGetLine startIter       e <- textIterGetLine endIter-      return (s, e)-    False  -> do-      (l, _) <- getCodeTextLineNumber te-      return (l, l)+      return $ Just (s, e)+ +-- |+--+--+getSelectedLineNumbers :: TextEditorData -> IO (Int, Int)+getSelectedLineNumbers te = getSelectedRange te >>= \case+  Just range -> return range+  Nothing -> do+    (l, _) <- getCodeTextLineNumber te+    return (l, l)  -- | --@@ -773,3 +796,92 @@   return $ (startNo < lineNo) && (lineNo < endNo)  +-- |+--  +--+pageUpTextEditor :: Builder -> IO ()+pageUpTextEditor builder = do+  note <- builderGetObject builder castToNotebook _NAME_CODE_NOTE+  logo <- builderGetObject builder castToWidget _NAME_HASKELL_LOGO+  +  logoIdx <- notebookPageNum note logo+  pageNum <- notebookGetNPages note+  curPage <- notebookGetCurrentPage note++  withLogoIdx note logoIdx pageNum curPage++  where+    withLogoIdx _ Nothing _ _ = criticalM _LOG_NAME "haskell logo tab not found."+    withLogoIdx _ _ _ (-1)    = criticalM _LOG_NAME "invalid code note."+    withLogoIdx note (Just logoIdx) pageNum curPage+      | (curPage + 1) == logoIdx = withPageNums note pageNum logoIdx+      | otherwise = withPageNums note pageNum curPage++    withPageNums note pageNum curPage+      | 1 > pageNum  = criticalM _LOG_NAME "invalid code note."+      | 1 == pageNum = return ()+      | curPage == (pageNum -1) = notebookSetCurrentPage note 0+      | otherwise = notebookNextPage note++-- |+--  +--+pageDownTextEditor :: Builder -> IO ()+pageDownTextEditor builder = do+  note <- builderGetObject builder castToNotebook _NAME_CODE_NOTE+  logo <- builderGetObject builder castToWidget _NAME_HASKELL_LOGO+  +  logoIdx <- notebookPageNum note logo+  pageNum <- notebookGetNPages note+  curPage <- notebookGetCurrentPage note++  withLogoIdx note logoIdx pageNum curPage+ +  where+    withLogoIdx _ Nothing _ _ = criticalM _LOG_NAME "haskell logo tab not found."+    withLogoIdx _ _ _ (-1)    = criticalM _LOG_NAME "invalid code note."+    withLogoIdx note (Just logoIdx) pageNum curPage+      | (0 == curPage) && ((pageNum -1) == logoIdx) = withPageNums note pageNum logoIdx+      | (curPage - 1) == logoIdx = withPageNums note pageNum logoIdx+      | otherwise = withPageNums note pageNum curPage++    withPageNums note pageNum curPage+      | 1 > pageNum  = criticalM _LOG_NAME "invalid code note."+      | 1 == pageNum = return ()+      | 0 == curPage = notebookSetCurrentPage note (pageNum - 1)+      | otherwise = notebookSetCurrentPage note (curPage - 1)+++-- |+--  +--+updateSearchResultTag :: TextEditorData -> [SearchResultTagInfo] -> IO ()+updateSearchResultTag editor@(TextEditorData _ view _ _) datas = do+  clearSearchResultTag editor++  buf <- textViewGetBuffer view+  mapM_ (go buf) datas++  where+    go buf (SearchResultTagInfo lineNo startCol endCol) = do+      startIter <- textBufferGetIterAtLineOffset buf lineNo startCol+      endIter   <- textBufferGetIterAtLineOffset buf lineNo (endCol + 1)++      textBufferApplyTagByName buf _SEARCH_RESULT_HIGHLIGHT_TAG startIter endIter+++-- |+--  +--+clearSearchResultTag :: TextEditorData -> IO ()+clearSearchResultTag (TextEditorData _ view _ _) = do+  buf <- textViewGetBuffer view+  +  startIter <- textBufferGetStartIter buf+  endIter <- textBufferGetEndIter buf+  textBufferRemoveTagByName buf _SEARCH_RESULT_HIGHLIGHT_TAG startIter endIter+++++    
conf/Phoityne.glade view
@@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- Generated with glade 3.19.0 --> <interface>-  <requires lib="gtk+" version="3.0"/>+  <requires lib="gtk+" version="3.16"/>   <object class="GtkLabel" id="BindingsCol1Label">     <property name="visible">True</property>     <property name="can_focus">False</property>@@ -38,6 +38,80 @@     <property name="label" translatable="yes">Condition</property>   </object>   <object class="GtkTextTagTable" id="CodeTextTagTable"/>+  <object class="GtkDialog" id="GoDialog">+    <property name="can_focus">False</property>+    <property name="type_hint">dialog</property>+    <child internal-child="vbox">+      <object class="GtkBox" id="GoDialogVBox">+        <property name="can_focus">False</property>+        <property name="orientation">vertical</property>+        <property name="spacing">2</property>+        <child internal-child="action_area">+          <object class="GtkButtonBox" id="GoDialogAction">+            <property name="can_focus">False</property>+            <property name="layout_style">end</property>+            <child>+              <object class="GtkButton" id="button1">+                <property name="label">gtk-ok</property>+                <property name="visible">True</property>+                <property name="can_focus">True</property>+                <property name="receives_default">True</property>+                <property name="use_stock">True</property>+              </object>+              <packing>+                <property name="expand">True</property>+                <property name="fill">True</property>+                <property name="position">0</property>+              </packing>+            </child>+            <child>+              <object class="GtkButton" id="button2">+                <property name="label">gtk-cancel</property>+                <property name="visible">True</property>+                <property name="can_focus">True</property>+                <property name="receives_default">True</property>+                <property name="use_stock">True</property>+              </object>+              <packing>+                <property name="expand">True</property>+                <property name="fill">True</property>+                <property name="position">1</property>+              </packing>+            </child>+          </object>+          <packing>+            <property name="expand">False</property>+            <property name="fill">False</property>+            <property name="position">2</property>+          </packing>+        </child>+        <child>+          <object class="GtkLabel" id="GoDialogLabel">+            <property name="visible">True</property>+            <property name="can_focus">False</property>+            <property name="halign">start</property>+            <property name="label" translatable="yes">Input line number.</property>+          </object>+          <packing>+            <property name="expand">False</property>+            <property name="fill">True</property>+            <property name="position">0</property>+          </packing>+        </child>+        <child>+          <object class="GtkEntry" id="GoDialogEntry">+            <property name="visible">True</property>+            <property name="can_focus">True</property>+          </object>+          <packing>+            <property name="expand">False</property>+            <property name="fill">True</property>+            <property name="position">1</property>+          </packing>+        </child>+      </object>+    </child>+  </object>   <object class="GtkDialog" id="ReplaceDialog">     <property name="can_focus">False</property>     <property name="border_width">5</property>@@ -87,32 +161,20 @@             <property name="expand">False</property>             <property name="fill">True</property>             <property name="pack_type">end</property>-            <property name="position">1</property>-          </packing>-        </child>-        <child>-          <object class="GtkLabel" id="ReplaceDialogLabel">-            <property name="visible">True</property>-            <property name="can_focus">False</property>-            <property name="halign">start</property>-            <property name="label" translatable="yes">Input replacement</property>-          </object>-          <packing>-            <property name="expand">False</property>-            <property name="fill">True</property>-            <property name="position">0</property>+            <property name="position">2</property>           </packing>         </child>         <child>-          <object class="GtkGrid" id="grid1">+          <object class="GtkGrid" id="ReplaceGrid">             <property name="visible">True</property>             <property name="can_focus">False</property>+            <property name="column_spacing">5</property>             <property name="row_homogeneous">True</property>             <child>               <object class="GtkLabel" id="ReplaceDialogSearchKeyLabel">                 <property name="visible">True</property>                 <property name="can_focus">False</property>-                <property name="label" translatable="yes">Search</property>+                <property name="label" translatable="yes">Keyword</property>               </object>               <packing>                 <property name="left_attach">0</property>@@ -152,14 +214,74 @@                 <property name="top_attach">0</property>               </packing>             </child>+            <child>+              <object class="GtkLabel" id="ReplaceRangeLabel">+                <property name="visible">True</property>+                <property name="can_focus">False</property>+                <property name="label" translatable="yes">Range</property>+              </object>+              <packing>+                <property name="left_attach">0</property>+                <property name="top_attach">2</property>+              </packing>+            </child>+            <child>+              <object class="GtkLabel" id="ReplaceRangeInfo">+                <property name="visible">True</property>+                <property name="can_focus">False</property>+                <property name="halign">start</property>+                <property name="label" translatable="yes">ALL</property>+                <property name="angle">0.050000000000000003</property>+              </object>+              <packing>+                <property name="left_attach">1</property>+                <property name="top_attach">2</property>+              </packing>+            </child>           </object>           <packing>-            <property name="expand">True</property>+            <property name="expand">False</property>             <property name="fill">True</property>-            <property name="padding">2</property>-            <property name="position">2</property>+            <property name="position">0</property>           </packing>         </child>+        <child>+          <object class="GtkBox" id="ReplaceCautionBox">+            <property name="visible">True</property>+            <property name="can_focus">False</property>+            <property name="spacing">5</property>+            <child>+              <object class="GtkImage" id="image1">+                <property name="visible">True</property>+                <property name="can_focus">False</property>+                <property name="stock">gtk-dialog-warning</property>+              </object>+              <packing>+                <property name="expand">False</property>+                <property name="fill">True</property>+                <property name="position">0</property>+              </packing>+            </child>+            <child>+              <object class="GtkLabel" id="ReplaceCautionLabel">+                <property name="visible">True</property>+                <property name="can_focus">False</property>+                <property name="label" translatable="yes">Save files automatically.</property>+              </object>+              <packing>+                <property name="expand">False</property>+                <property name="fill">True</property>+                <property name="position">1</property>+              </packing>+            </child>+          </object>+          <packing>+            <property name="expand">False</property>+            <property name="fill">True</property>+            <property name="padding">10</property>+            <property name="position">1</property>+          </packing>+        </child>       </object>     </child>     <action-widgets>@@ -171,14 +293,16 @@     <property name="can_focus">False</property>     <property name="border_width">5</property>     <property name="title" translatable="yes">Search</property>+    <property name="modal">True</property>     <property name="window_position">center-always</property>+    <property name="destroy_with_parent">True</property>     <property name="icon">h.ico</property>     <property name="type_hint">dialog</property>     <child internal-child="vbox">       <object class="GtkBox" id="SearchDialogBox">         <property name="can_focus">False</property>         <property name="orientation">vertical</property>-        <property name="spacing">2</property>+        <property name="spacing">5</property>         <child internal-child="action_area">           <object class="GtkButtonBox" id="SearchDialogActionArea">             <property name="can_focus">False</property>@@ -222,11 +346,33 @@           </packing>         </child>         <child>-          <object class="GtkLabel" id="SearchDialogLabel">+          <object class="GtkGrid" id="SearchGrid">             <property name="visible">True</property>             <property name="can_focus">False</property>-            <property name="halign">start</property>-            <property name="label" translatable="yes">Input keyword</property>+            <property name="column_spacing">5</property>+            <child>+              <object class="GtkLabel" id="SearchLabel">+                <property name="visible">True</property>+                <property name="can_focus">False</property>+                <property name="label" translatable="yes">Keyword</property>+              </object>+              <packing>+                <property name="left_attach">0</property>+                <property name="top_attach">0</property>+              </packing>+            </child>+            <child>+              <object class="GtkEntry" id="SearchDialogEntry">+                <property name="visible">True</property>+                <property name="can_focus">True</property>+                <property name="invisible_char">●</property>+                <property name="activates_default">True</property>+              </object>+              <packing>+                <property name="left_attach">1</property>+                <property name="top_attach">0</property>+              </packing>+            </child>           </object>           <packing>             <property name="expand">False</property>@@ -235,11 +381,14 @@           </packing>         </child>         <child>-          <object class="GtkEntry" id="SearchDialogEntry">+          <object class="GtkCheckButton" id="SearchCheckBox">+            <property name="label" translatable="yes">case sensitive</property>             <property name="visible">True</property>             <property name="can_focus">True</property>-            <property name="invisible_char">●</property>-            <property name="activates_default">True</property>+            <property name="receives_default">False</property>+            <property name="xalign">0.039999999105930328</property>+            <property name="yalign">0.4699999988079071</property>+            <property name="draw_indicator">True</property>           </object>           <packing>             <property name="expand">False</property>@@ -247,6 +396,43 @@             <property name="position">2</property>           </packing>         </child>+        <child>+          <object class="GtkBox" id="SearchCautionBox">+            <property name="visible">True</property>+            <property name="can_focus">False</property>+            <property name="spacing">5</property>+            <child>+              <object class="GtkImage" id="SearchCautionIcon">+                <property name="visible">True</property>+                <property name="can_focus">False</property>+                <property name="stock">gtk-dialog-warning</property>+              </object>+              <packing>+                <property name="expand">False</property>+                <property name="fill">True</property>+                <property name="position">0</property>+              </packing>+            </child>+            <child>+              <object class="GtkLabel" id="SearchCautionLabel">+                <property name="visible">True</property>+                <property name="can_focus">False</property>+                <property name="label" translatable="yes">Save files automatically.</property>+              </object>+              <packing>+                <property name="expand">False</property>+                <property name="fill">True</property>+                <property name="position">1</property>+              </packing>+            </child>+          </object>+          <packing>+            <property name="expand">False</property>+            <property name="fill">True</property>+            <property name="padding">10</property>+            <property name="position">3</property>+          </packing>+        </child>       </object>     </child>     <action-widgets>@@ -682,14 +868,24 @@                     <property name="scrollable">True</property>                     <property name="enable_popup">True</property>                     <child>-                      <object class="GtkImage" id="image1">+                      <object class="GtkBox" id="WelcomeBox">                         <property name="visible">True</property>                         <property name="can_focus">False</property>-                        <property name="pixbuf">HaskellLogoStyPreview-1.png</property>+                        <property name="orientation">vertical</property>+                        <property name="homogeneous">True</property>+                        <child>+                          <object class="GtkImage" id="HaskellLogo">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="pixbuf">HaskellLogoStyPreview-1.png</property>+                          </object>+                          <packing>+                            <property name="expand">False</property>+                            <property name="fill">True</property>+                            <property name="position">0</property>+                          </packing>+                        </child>                       </object>-                      <packing>-                        <property name="reorderable">True</property>-                      </packing>                     </child>                     <child type="tab">                       <object class="GtkLabel" id="WelcomeLabel">@@ -994,6 +1190,36 @@                             <property name="visible">True</property>                             <property name="can_focus">False</property>                             <child>+                              <object class="GtkToolbar" id="SearchResultToolbar">+                                <property name="visible">True</property>+                                <property name="can_focus">False</property>+                                <property name="orientation">vertical</property>+                                <property name="toolbar_style">icons</property>+                                <property name="icon_size">1</property>+                                <child>+                                  <object class="GtkToolButton" id="SearchResultDeleteBT">+                                    <property name="visible">True</property>+                                    <property name="can_focus">False</property>+                                    <property name="tooltip_text" translatable="yes">Delete search result</property>+                                    <property name="is_important">True</property>+                                    <property name="label" translatable="yes">SearchResultDeleteLabel</property>+                                    <property name="use_underline">True</property>+                                    <property name="stock_id">gtk-delete</property>+                                  </object>+                                  <packing>+                                    <property name="expand">False</property>+                                    <property name="homogeneous">True</property>+                                  </packing>+                                </child>+                              </object>+                              <packing>+                                <property name="expand">False</property>+                                <property name="fill">True</property>+                                <property name="pack_type">end</property>+                                <property name="position">0</property>+                              </packing>+                            </child>+                            <child>                               <object class="GtkScrolledWindow" id="SearchResultScrolledWindow">                                 <property name="visible">True</property>                                 <property name="can_focus">True</property>@@ -1043,36 +1269,7 @@                               <packing>                                 <property name="expand">True</property>                                 <property name="fill">True</property>-                                <property name="position">0</property>-                              </packing>-                            </child>-                            <child>-                              <object class="GtkToolbar" id="SearchResultToolbar">-                                <property name="visible">True</property>-                                <property name="can_focus">False</property>-                                <property name="orientation">vertical</property>-                                <property name="toolbar_style">icons</property>-                                <property name="icon_size">1</property>-                                <child>-                                  <object class="GtkToolButton" id="SearchResultDeleteBT">-                                    <property name="visible">True</property>-                                    <property name="can_focus">False</property>-                                    <property name="tooltip_text" translatable="yes">Delete search result</property>-                                    <property name="is_important">True</property>-                                    <property name="label" translatable="yes">SearchResultDeleteLabel</property>-                                    <property name="use_underline">True</property>-                                    <property name="stock_id">gtk-delete</property>-                                  </object>-                                  <packing>-                                    <property name="expand">False</property>-                                    <property name="homogeneous">True</property>-                                  </packing>-                                </child>-                              </object>-                              <packing>-                                <property name="expand">False</property>-                                <property name="fill">True</property>-                                <property name="position">2</property>+                                <property name="position">1</property>                               </packing>                             </child>                           </object>@@ -1191,6 +1388,7 @@             <property name="can_focus">False</property>             <property name="halign">start</property>             <property name="label" translatable="yes">Input folder name.</property>+            <property name="angle">2.2351741811588166e-010</property>           </object>           <packing>             <property name="expand">False</property>@@ -1306,44 +1504,6 @@         <property name="margin_top">1</property>         <property name="margin_bottom">1</property>         <property name="label" translatable="yes">Create File</property>-      </object>-    </child>-    <child>-      <object class="GtkSeparatorMenuItem" id="TreeViewPopupMenuSep1">-        <property name="visible">True</property>-        <property name="can_focus">False</property>-        <property name="margin_top">1</property>-        <property name="margin_bottom">1</property>-      </object>-    </child>-    <child>-      <object class="GtkMenuItem" id="TreeViewPopupMenuRenameItem">-        <property name="use_action_appearance">False</property>-        <property name="related_action">TreeViewPopupRenameAction</property>-        <property name="visible">True</property>-        <property name="can_focus">False</property>-        <property name="margin_top">1</property>-        <property name="margin_bottom">1</property>-        <property name="label" translatable="yes">Rename</property>-      </object>-    </child>-    <child>-      <object class="GtkSeparatorMenuItem" id="TreeViewPopupMenuSep2">-        <property name="visible">True</property>-        <property name="can_focus">False</property>-        <property name="margin_top">1</property>-        <property name="margin_bottom">1</property>-      </object>-    </child>-    <child>-      <object class="GtkMenuItem" id="TreeViewPopupMenuDeleteItem">-        <property name="use_action_appearance">False</property>-        <property name="related_action">TreeViewPopupDeleteAction</property>-        <property name="visible">True</property>-        <property name="can_focus">False</property>-        <property name="margin_top">1</property>-        <property name="margin_bottom">1</property>-        <property name="label" translatable="yes">Delete</property>       </object>     </child>   </object>
phoityne.cabal view
@@ -1,7 +1,7 @@ name:                phoityne-version:             0.0.4.0-synopsis:            ghci debug viewer with simple editor.-description:         Phoityne is a ghci debug viewer with simple editor.+version:             0.0.5.0+synopsis:            Deprecated - ghci debug viewer with simple editor.+description:         Deprecated - use phoityne-vscode package instead. license:             BSD3 license-file:        LICENSE author:              phoityne_hs