Update offsetsGtk.hs

This commit is contained in:
千住柱間 2025-03-04 03:32:30 +00:00
commit 7d284d8dcd

View file

@ -1,6 +1,15 @@
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE OverloadedStrings #-}
{-
this is a prototype of a hakurei-like tokenizer, where the sentence is clickable.
the function must accept a list of strings, because xcdat works that way.
also, you must FIX the current problem of just getting what's next to the cursor
-}
module Main where
import qualified GI.Gtk as Gtk
@ -9,53 +18,66 @@ import qualified Data.Text as T
import Data.Text (Text)
import Data.Maybe (fromMaybe)
import Control.Monad (void)
import Data.Int (Int32)
-- | 'getWordAtOffset' takes a list of words and an offset (index)
-- and returns the word at that offset if it exists.
getWordAtOffset :: [Text] -> Int -> Maybe Text
getWordAtOffset wordsList offset =
if offset >= 0 && offset < length wordsList
then Just (wordsList !! offset)
else Nothing
-- | Given a list of tokens and a character offset (into the concatenated text),
-- 'findTokenAtOffset' returns the index and token that covers that offset.
findTokenAtOffset :: [Text] -> Int -> Maybe (Int, Text)
findTokenAtOffset tokens offset = go tokens 0 0
where
go [] _ _ = Nothing
go (t:ts) idx start =
let tokenLength = T.length t
in if offset < start + tokenLength
then Just (idx, t)
else go ts (idx + 1) (start + tokenLength)
main :: IO ()
main = do
-- Create a new GTK application with a unique application ID.
app <- Gtk.applicationNew (Just "com.example.HaskellGiExample") []
-- Connect to the application's "activate" signal.
void $ Gio.onApplicationActivate app $ do
-- Create an application window (GTK 4 style).
window <- Gtk.applicationWindowNew app
-- Create a text view widget.
window <- Gtk.applicationWindowNew app
textView <- Gtk.textViewNew
-- Define some sample text.
let sampleText = "Haskell GI makes GUI programming and text processing elegant"
-- Assume these are the tokens from a tokenizer.
let tokens = ["これ", "", "日本語", "", "文章", "です"]
sampleText = T.concat tokens -- Concatenate tokens without spaces.
-- Set the sample text in the text view's buffer.
buffer <- Gtk.textViewGetBuffer textView
Gtk.textBufferSetText buffer sampleText (-1)
-- Process the text: split into words and retrieve the word at a given offset.
let wordsList = T.words sampleText
offset = 3 -- For example, get the 4th word (zero-indexed)
wordAtOffset = fromMaybe "No word found" (getWordAtOffset wordsList offset)
-- Add a click gesture to the text view.
gesture <- Gtk.gestureClickNew
Gtk.widgetAddController textView gesture
putStrLn $ "The word at offset " ++ show offset ++ " is: " ++ T.unpack wordAtOffset
-- When the user clicks, get the text iterator at that location.
void $ Gtk.onGestureClickPressed gesture $ \_ x y -> do
-- Convert the x and y coordinates (Double) to Int32 as required.
let ix = fromIntegral (round x) :: Int32
iy = fromIntegral (round y) :: Int32
(success, iter) <- Gtk.textViewGetIterAtLocation textView ix iy
if success
then do
offset32 <- Gtk.textIterGetOffset iter
let offset = fromIntegral offset32 :: Int
tokenInfo = findTokenAtOffset tokens offset
case tokenInfo of
Just (i, token) ->
putStrLn $ "Clicked token " ++ show i ++ ": " ++ T.unpack token
Nothing ->
putStrLn "Clicked outside any token."
else putStrLn "Could not determine text position."
-- Set the text view as the sole child of the window (wrap in Just).
-- Set the text view as the sole child of the window.
Gtk.windowSetChild window (Just textView)
-- Connect the window's close-request signal to quit the application.
void $ Gtk.on window #closeRequest $ do
Gio.applicationQuit app
return False
-- Show the window.
Gtk.widgetShow window
-- Run the application (which handles initialization and the main loop).
_ <- Gio.applicationRun app Nothing
return ()