Cthulhu is no longer a fork. Now it is a screen reader written in Golang.
This commit is contained in:
1 parent
a998fe67de
commit
069fc674dc
708 files changed
+112482
-532
No files matched your search
@@ -0,0 +1,105 @@
|
||||
// Cthulhu screen reader.
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// Authors: Storm Dragon, Angus Kola
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation, either version 3 of the License, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
// more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along with
|
||||
// this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
|
||||
"git.stormux.org/storm/cthulhu/internal/input"
|
||||
"git.stormux.org/storm/cthulhu/internal/presentation"
|
||||
"git.stormux.org/storm/cthulhu/internal/review"
|
||||
)
|
||||
|
||||
func flatReviewCommand(command input.Command) (review.FlatUnit, int) {
|
||||
switch command {
|
||||
case input.ReviewWindowStart:
|
||||
return review.WindowStart, 0
|
||||
case input.ReviewWindowEnd:
|
||||
return review.WindowEnd, 0
|
||||
case input.ReviewPreviousLine:
|
||||
return review.Line, -1
|
||||
case input.ReviewCurrentLine:
|
||||
return review.Line, 0
|
||||
case input.ReviewNextLine:
|
||||
return review.Line, 1
|
||||
case input.ReviewPreviousWord:
|
||||
return review.Word, -1
|
||||
case input.ReviewCurrentWord, input.ReviewSpellWord, input.ReviewPhoneticWord:
|
||||
return review.Word, 0
|
||||
case input.ReviewNextWord:
|
||||
return review.Word, 1
|
||||
case input.ReviewPreviousCharacter:
|
||||
return review.Character, -1
|
||||
case input.ReviewCurrentCharacter, input.ReviewPhoneticCharacter:
|
||||
return review.Character, 0
|
||||
case input.ReviewNextCharacter:
|
||||
return review.Character, 1
|
||||
case input.ReviewWordAbove:
|
||||
return review.WordAbove, 0
|
||||
case input.ReviewWordBelow:
|
||||
return review.WordBelow, 0
|
||||
case input.ReviewLineEnd:
|
||||
return review.LineEnd, 0
|
||||
default:
|
||||
return 0, 0
|
||||
}
|
||||
}
|
||||
|
||||
func presentFlatReviewResult(logger *slog.Logger, speech speechEnqueuer, result review.Result) {
|
||||
text := ""
|
||||
if result.Err != nil {
|
||||
logger.Warn("flat review failed", "error", result.Err)
|
||||
switch {
|
||||
case errors.Is(result.Err, review.ErrLimitedReview):
|
||||
text = "This window exceeds the current flat review text limit."
|
||||
case errors.Is(result.Err, review.ErrNoReviewContent):
|
||||
text = "No visible content."
|
||||
default:
|
||||
text = "Could not find current location."
|
||||
}
|
||||
} else if !result.Moved && (result.FlatStep != 0 || result.FlatUnit == review.WordAbove || result.FlatUnit == review.WordBelow) {
|
||||
// Python's sequential review stops silently at window boundaries.
|
||||
return
|
||||
} else {
|
||||
text = presentation.FlatReviewText(result.FlatPosition.Text, result.FlatUnit == review.Character || result.FlatUnit == review.LineEnd)
|
||||
}
|
||||
speech.Interrupt()
|
||||
request := speechRequest{Text: text, Role: "text", Cause: "flat-review", Character: result.Err == nil && (result.FlatUnit == review.Character || result.FlatUnit == review.LineEnd)}
|
||||
if result.Err == nil && result.FlatUnit == review.Line {
|
||||
request.Line = &speechLine{Object: result.FlatPosition.Object, Raw: result.FlatPosition.Text}
|
||||
}
|
||||
if result.Err == nil {
|
||||
set_review_spelling(&request, result.FlatPosition.Text, result.FlatSpeech)
|
||||
}
|
||||
speech.Enqueue(request)
|
||||
if logger.Enabled(context.Background(), slog.LevelDebug) {
|
||||
logger.Debug("queued flat review presentation",
|
||||
"speech_text", request.Text, "spelling", request.Spelling, "speech_style", result.FlatSpeech,
|
||||
"unit", result.FlatUnit,
|
||||
"moved", result.Moved,
|
||||
"bus", result.FlatPosition.Object.BusName,
|
||||
"object_path", result.FlatPosition.Object.Path,
|
||||
"offset", result.FlatPosition.Offset,
|
||||
"has_offset", result.FlatPosition.HasOffset,
|
||||
"capture_duration", result.CaptureDuration,
|
||||
"capture_reason", result.CaptureReason,
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user