phoityne 0.0.4.0 → 0.0.5.0
raw patch · 9 files changed
+759/−379 lines, 9 files
Files
- Changelog.md +16/−0
- README.md +1/−80
- app/Phoityne/IO/GUI/Control.hs +238/−142
- app/Phoityne/IO/GUI/GTK/Constant.hs +5/−0
- app/Phoityne/IO/GUI/GTK/Interface.hs +27/−12
- app/Phoityne/IO/GUI/GTK/SearchResultTable.hs +60/−5
- app/Phoityne/IO/GUI/GTK/TextEditor.hs +149/−37
- conf/Phoityne.glade +260/−100
- phoityne.cabal +3/−3
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-[](https://www.youtube.com/watch?v=MKMEgb0sFsI)--### Demo Video2-[](https://www.youtube.com/watch?v=T10wWCmWHaA)---## Document----------------------+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