Release v0.6.13: correct words across punctuation keys
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
project(KSwitcher VERSION 0.6.12 LANGUAGES CXX RC)
|
||||
project(KSwitcher VERSION 0.6.13 LANGUAGES CXX RC)
|
||||
if(NOT WIN32)
|
||||
message(FATAL_ERROR "KSwitcher uses native Windows APIs")
|
||||
endif()
|
||||
|
||||
Binary file not shown.
+5
-7
@@ -1,16 +1,14 @@
|
||||
# Latest Windows release
|
||||
|
||||
## v0.6.12 — 2026-10-30
|
||||
## v0.6.13 — 2026-10-30
|
||||
|
||||
## Changes
|
||||
- Start automatic layout correction immediately after Space and preserve subsequent typing while the correction runs.
|
||||
- Accept identical corrected words shared by multiple selected languages; use the selected language order to choose the target layout. Different valid spellings remain ambiguous.
|
||||
- Run the log viewer in the configurator process, separate from the resident input hooks. Clearing logs remains coordinated with the resident process.
|
||||
- Keep the native four-column ListView. Resize the table with its window, anchor the footer and Close button, and make Details fill the remaining width.
|
||||
- Exclude copied diagnostic rows from clipboard history.
|
||||
- Correct words containing punctuation keys that become letters in the target layout, such as `hj,bnm` → `робить`. Validate letters and capitalization after conversion so personal dictionary entries can match.
|
||||
- Extend automatic word selection across internal punctuation only while the selected text matches a suffix of the tracked input. Verify the complete tracked word before replacing it.
|
||||
- Give the fixed-layout automatic-correction settings dialog a fixed window size, retaining scrolling on small displays instead of allowing empty space when resized.
|
||||
|
||||
## Validation
|
||||
Native and input regression suites, screenshot UI and updater checks, log-viewer integration, continuous-typing integration, and isolated configurator/log process checks. Manual development-build checks covered window dragging and automatic Details column width.
|
||||
220 native regression checks, 466 input/UI checks, screenshot editor and notification registration checks, 45 updater checks and updater progress checks passed. Native editor integration verified continuous typing during correction and complete selection/conversion of `hj,bnm` to `робить`. The correction was also confirmed in the user's editor.
|
||||
|
||||
**Upgrade:** choose Update in the tray menu. Legacy v0.3.0–v0.4.1 clients first receive the v0.4.2 compatibility bridge, then the current full release. v0.2.3 and earlier require manual installation.
|
||||
For manual installation, exit KSwitcher and extract the entire ZIP into its installation folder. Keep personal `data/` and customized dictionaries.
|
||||
|
||||
@@ -1 +1 @@
|
||||
866de2d1d6fe121a7845760519f934bf0bd7820bbd11734a14c454b69a6bb8ad KSwitcher-win-x64.zip
|
||||
eae70031520882cc6a798e11a640fa101df01db12aeba4e6c96d8aa90037ae1e KSwitcher-win-x64.zip
|
||||
|
||||
+3
-3
@@ -9,8 +9,8 @@ IDC_SCREENSHOT_PENCIL CURSOR "icons/lucide/pencil.cur"
|
||||
1 RT_MANIFEST "app.manifest"
|
||||
201 RCDATA "update.ps1"
|
||||
1 VERSIONINFO
|
||||
FILEVERSION 0,6,12,0
|
||||
PRODUCTVERSION 0,6,12,0
|
||||
FILEVERSION 0,6,13,0
|
||||
PRODUCTVERSION 0,6,13,0
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
BEGIN
|
||||
@@ -20,7 +20,7 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "FileDescription", "KSwitcher — native keyboard and clipboard utility"
|
||||
VALUE "ProductName", "KSwitcher"
|
||||
VALUE "FileVersion", "0.6.12"
|
||||
VALUE "FileVersion", "0.6.13"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
+7
-3
@@ -940,6 +940,7 @@ void App::transform(int command, int snippet)
|
||||
std::wstring predicted;
|
||||
for (wchar_t key : recent.keys)
|
||||
predicted += key == L' ' ? L' ' : available[hint].at(physicalLayout().code(key));
|
||||
expected = predicted;
|
||||
if (!autoCorrector.suggest(predicted, hint, available, config) ||
|
||||
!autoCorrectionAllowed(target, config) || !valid())
|
||||
return;
|
||||
@@ -979,9 +980,12 @@ void App::transform(int command, int snippet)
|
||||
autoSelected = true;
|
||||
Sleep(25);
|
||||
text = tx.copy();
|
||||
// Some editors first select only ") ". Extend by whole-word
|
||||
// boundaries, then still verify against the complete tracked run.
|
||||
for (int i = 0; i < 3 && autoClosingSelection(text, config) && tx.valid(); ++i)
|
||||
// Editors may split hj,bnm at the comma. Extend only a verified
|
||||
// suffix of the tracked input, and still require a complete match.
|
||||
for (int i = 0; i < 3 && tx.valid() &&
|
||||
matchAutoInput(recent, text, available, physicalLayout(), config) < 0 &&
|
||||
(autoClosingSelection(text, config) ||
|
||||
(!text.empty() && text.size() < expected.size() && expected.ends_with(text))); ++i)
|
||||
{
|
||||
if (!chord(VK_LEFT, MOD_CONTROL | MOD_SHIFT))
|
||||
break;
|
||||
|
||||
+5
-1
@@ -152,7 +152,11 @@ std::optional<AutoSuggestion> AutoCorrector::suggest(const std::wstring &typed,
|
||||
suffix.insert(suffix.begin(), word.back());
|
||||
word.pop_back();
|
||||
}
|
||||
if (!safeAutoWord(word, settings.autoMinLength) || suffix.size() > 6 || rejected.contains(lower(word)))
|
||||
// Punctuation keys can be letters in the target layout (for example ',' -> 'б').
|
||||
// Validate letters and capitalization after conversion, not before it.
|
||||
if (settings.autoMinLength < 1 || settings.autoMinLength > 32 ||
|
||||
word.size() < (size_t)settings.autoMinLength || word.size() > 32 ||
|
||||
suffix.size() > 6 || rejected.contains(lower(word)))
|
||||
return {};
|
||||
for (auto &never : settings.autoNever)
|
||||
if (lower(never) == lower(word))
|
||||
|
||||
+1
-1
@@ -1072,7 +1072,7 @@ LRESULT CALLBACK autoOptionsProc(HWND w, UINT msg, WPARAM wp, LPARAM lp)
|
||||
void showAutoOptions(HWND parent, SettingsView *v)
|
||||
{
|
||||
HWND w = makeWindow(*v->app, L"KSwitcher.AutoOptions", L"Automatic layout correction", autoOptionsProc,
|
||||
560, 680);
|
||||
560, 680, 0, false);
|
||||
SetWindowLongPtrW(w, GWLP_HWNDPARENT, (LONG_PTR)parent);
|
||||
SetWindowLongPtrW(w, GWLP_USERDATA, (LONG_PTR) new AutoOptionsView{parent, v});
|
||||
label(w, L"Offline dictionaries (only layouts in your cycle are used)", 18, 16, 525);
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#include "platform.h"
|
||||
namespace ks
|
||||
{
|
||||
inline constexpr wchar_t AppVersion[] = L"0.6.12";
|
||||
inline constexpr wchar_t AppVersion[] = L"0.6.13";
|
||||
inline constexpr UINT UpdateMessage = WM_APP + 7;
|
||||
inline constexpr UINT UpdateCheckIntervalMs = 6 * 60 * 60 * 1000;
|
||||
inline constexpr UINT UpdateNotificationRetryMs = 5 * 60 * 1000;
|
||||
|
||||
@@ -334,7 +334,25 @@ LRESULT CALLBACK procedure(HWND w, UINT msg, WPARAM wp, LPARAM lp)
|
||||
stage = 21;
|
||||
break;
|
||||
case 21:
|
||||
{
|
||||
require(text() == L"привет а", "automatic correction preserves immediate next-word typing without a pause");
|
||||
auto uk = std::find_if(app->layouts.begin(), app->layouts.end(), [](const auto &layout) {
|
||||
return ks::layoutLanguage(layout) == L"uk";
|
||||
});
|
||||
require(uk != app->layouts.end(), "Ukrainian layout available for punctuation-key regression");
|
||||
app->settings.autoLanguages = {L"en", L"uk"};
|
||||
app->settings.cycle = {app->layouts[en].id, uk->id};
|
||||
app->settings.autoWords[L"uk"] = {L"робить"};
|
||||
app->autoCorrector = ks::AutoCorrector{};
|
||||
ActivateKeyboardLayout(app->layouts[en].handle, 0);
|
||||
prepare(L"hj,bnm ", false);
|
||||
record(L"hj,bnm ");
|
||||
app->transform(ks::AutoCorrect);
|
||||
stage = 22;
|
||||
break;
|
||||
}
|
||||
case 22:
|
||||
require(text() == L"робить ", "automatic correction selects and converts the whole word across an internal comma");
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -276,6 +276,15 @@ int main(int argc, char **argv)
|
||||
require(!supplemental.suggest(L"релызик ", 1, layouts, options),
|
||||
"never-correct list takes precedence over personal word");
|
||||
options.autoNever.clear();
|
||||
options.autoWords[L"uk"].push_back(L"робить");
|
||||
auto commaWord = supplemental.suggest(L"hj,bnm ", 0, layouts, options);
|
||||
require(commaWord && commaWord->text == L"робить " && commaWord->target == 2,
|
||||
"personal Ukrainian word accepts a punctuation key that maps to a letter");
|
||||
require(!supplemental.suggest(L"hj,bnm123 ", 0, layouts, options),
|
||||
"punctuation-key correction still rejects digits");
|
||||
options.autoMinLength = 1;
|
||||
require(!supplemental.suggest(L"ye ", 0, layouts, options),
|
||||
"known English ye remains protected at minimum length one");
|
||||
options.cycle = {L"en", L"ru"};
|
||||
require(!supplemental.suggest(L"релызик ", 1, layouts, options),
|
||||
"personal dictionary respects disabled target layouts");
|
||||
|
||||
Reference in New Issue
Block a user