Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Half-QWERTY: One-handed Typing


  • Please log in to reply
175 replies to this topic
  • Guests
  • Last active:
  • Joined: --
do any of you guys use this on a consistent basis? how is it please let me know!

wisp (guest)
  • Guests
  • Last active:
  • Joined: --
I would still like to be able to write one-handedly without having to press modifiers.

I still think it would be easy using dictionaries, like cell phones do (the good old T9 thingy).

Adding dictionaries easily would great!

I can't program. So if someone does it, please, let me know. ^_^

cesa.
facundo
@gmail
.com

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007

I would still like to be able to write one-handedly without having to press modifiers.

I don't see how? Any suggestions?

I still think it would be easy using dictionaries, like cell phones do (the good old T9 thingy).

Look at typing aid here <!-- m -->http://www.autohotke...pic.php?t=53630<!-- m -->

senseful
  • Members
  • 13 posts
  • Last active: Jul 26 2010 08:20 AM
  • Joined: 26 Nov 2009

I would still like to be able to write one-handedly without having to press modifiers.

I still think it would be easy using dictionaries, like cell phones do (the good old T9 thingy).

Adding dictionaries easily would great!


I made a simple script, which follows enguneer's idea:

it seems feasible

1. make a script with words as hotstrings (parse a dictionary website to get the words?)

:*:word::word
:*:another::another

2. loop read the file and parse each line to turn it into (using the mirror list)
:*:wwrd::word
:*:abwtger::another

3. Run the parsed script

4. Profit!


How to use it:

[*:gc91wjxl]Download a dictionary text file where each word is on its own line. (A good one I found is the 2of12 dictionary which is a part of the 12Dicts pakage. Simply scroll down to the "Official 12Dicts Package" section, download the zip file, then extract it. Use any of the dictionaries you want. View the readme for explanations about the differences between them).
[*:gc91wjxl]Run this AutoHotkey script I created (code is at the end of this post).
[*:gc91wjxl]When it asks for a dictionary file immediately after you launch it, select one of the text file dictionaries you want to use.
[*:gc91wjxl]Wait until it is done processing, it can take up to 5 minutes for a 40K word dictionary. You can check the progress by opening up the script and viewing "Variables and their contents". You should see a variable called gHotstringCount, which should be roughly twice the amount of words in the dictionary so about 80K for a 40K word dictionary. You can press F5 to refresh it.
[*:gc91wjxl]Once it is done, an .ahk file will be generated with a similar name in the same folder (e.g. C:\Dictionary.txt will generate C:\Dictionary-Half.ahk).
[*:gc91wjxl]Run this generated .ahk file which contains all the hotstrings.
[*:gc91wjxl]Type a word with only half of the keyboard and it should be converted after you press space. (For example, type "yhil" and it will convert it to "this", type "tges" and it will also be converted to "this".)
There are several issues which I didn't have time to fix:

[*:gc91wjxl]Words that contain an "a", "z", "x" or "c" will not work correctly since they use the chars ";", "/", ".", and "," respectively, all of which are hotstring end chars (see #Hotstring in the help). I tried a quick and dirty solution by remapping the keys to different ones that aren't end chars, but I couldn't get it to work in my first attempt. The code I tried using will be at the end of the post.
[*:gc91wjxl]If you use the backspace key while typing a hotstring, it won't convert the hotstring due to how hotstrings are implemented in autohotkey.
[*:gc91wjxl]You will run into conflicts where the same hotstring will be needed for multiple words. Currently it just takes the first one and the second one is ignored and presented to you at the end letting you which words were ignored. You can either modify the dictionary to not have these duplicated words, or move the one you want to use to the top of the file. When I ran it on a 40K word list, I got about 1K conflicts.
Hopefully this can be a starting point for a useful script. Feel free to modify the code and improve it.

Here's the code:
; Convert Dictionary to Half Qwerty hotstrings
; v1.0 by Senseful (http://sensefulsolutions.blogspot.com/)

gHotstringsCreated_ := "" ; store a hash table of all hotstrings created to detect duplicates
gDuplicateHotstrings := "" ; store all duplicated hotstrings, to then show the user so they can fix the dictionary
gHotstringCount := 0 ; store the amount of hotstrings generated

CreateHalfDictionary()
CreateHalfDictionary() {
  ; e.g. inputDictionaryFile = C:\Dictionary.txt
  FileSelectFile, inputDictionaryFile, 1, , Select a Dictionary to Convert
  if ErrorLevel
    ExitApp
    
  ; e.g. outputDictionaryFile = C:\Dictionary-Half.ahk
  SplitPath, inputDictionaryFile, , fileDir, , fileName
  outputDictionaryFile := fileDir . "" . fileName . "-Half.ahk"

  if (FileExist(outputDictionaryFile)) {
    ; 52 = 4 (Yes/No) + 48 (Exclamation)
    MsgBox, 52, , The file %outputDictionaryFile% already exists do you want to overwrite it? 
    okToOverwrite := false
    IfMsgBox Yes
      okToOverwrite := true
    if (!okToOverwrite)
      ExitApp
  }
  FileDelete, %outputDictionaryFile%

  leftHandChars :=  "12345qwertasdfgzxcvb"
  rightHandChars := "67890poiuy;lkjh/.,mn"

  Loop, Read, %inputDictionaryFile%, %outputDictionaryFile%
  {
    word := A_LoopReadLine  
    AddHotstring(word, leftHandChars, rightHandChars)
    AddHotstring(word, rightHandChars, leftHandChars)
  }
  
  global gDuplicateHotstrings
  if (gDuplicateHotstrings != "") {
    ; there were duplicate hotstrings
    MsgBox, % "The following hotstrings were duplicates, and were not created:`n`n" . gDuplicateHotstrings
  }
  
  global gHotstringCount
  MsgBox, The dictionary was successfully created with %gHotstringCount% hotstrings. The file is located at: %outputDictionaryFile%
}

AddHotstring(word, fromChars, toChars) {
  global
  local hotstring := ""
  Loop, parse, word
  {
    local char := A_LoopField 
    local replacementCharIndex := InStr(fromChars, char)
    local newChar
    if (replacementCharIndex > 0) {
      newChar := SubStr(toChars, replacementCharIndex, 1)
    } else {
      newChar := char
    }
    hotstring .= newChar
  }
  
  ; words like "x-ray" contain a dash (-) which cannot be a variable name, so replace it with an underscore (_)
  local hotstringHash := RegExReplace(hotstring, "\W", "_")
  if (gHotstringsCreated_%hotstringHash%) {
    ; duplicate hotstring found
    gDuplicateHotstrings .= hotstring . "`n"
    return
  }
  gHotstringsCreated_%hotstringHash% := 1
  
  if (hotstring == word) {
    ; the entire word can be written with one hand (e.g. junk), so instead of 
    ; adding a hotstring "::junk::junk", just skip it
    return
  }
 
  gHotstringCount++
  local line := "::" . hotstring . "::" . word . "`n"
  FileAppend, %line%
}

Here's my first attempt at a fix which didn't work:
; The following are considered characters that end a hotstring: -()[]{}:;'"/\,.?!`n `t
  ; that means the following characters are the only non alphanumeric 
  ; characters which can be a part of a hotstring: ``[email protected]#$%^&*_+=|<>
  ; ; (a) will send ~ instead
  ; , (c) will send < instead
  ; . (x) will send > instead
  ; / (z) will send | instead

  ; setup the hotkeys that will switch these characters
  ; also make it so if they are pressed twice, it will send the actual punctuation character
  FileAppend, `;::~`n, %outputDictionaryFile%
  FileAppend, ::`~`~::`;`n, %outputDictionaryFile%
  FileAppend, ::aa::`;`n, %outputDictionaryFile%
  
  FileAppend, ,::<`n, %outputDictionaryFile%
  FileAppend, ::`<`<::,`n, %outputDictionaryFile%
  FileAppend, ::cc::,`n, %outputDictionaryFile%
  
  FileAppend, .::>`n, %outputDictionaryFile%
  FileAppend, ::`>`>::.`n, %outputDictionaryFile%
  FileAppend, ::xx::.`n, %outputDictionaryFile%
  
  FileAppend, /::|`n, %outputDictionaryFile%
  FileAppend, ::||::/`n, %outputDictionaryFile%
  FileAppend, ::zz::/`n, %outputDictionaryFile%
  
  leftHandChars :=  "12345qwertasdfgzxcvb"
  rightHandChars := "67890poiuy~lkjh|><mn" ; "67890poiuy;lkjh/.,mn"


Arion
  • Members
  • 7 posts
  • Last active: Mar 17 2012 01:58 AM
  • Joined: 21 Oct 2008
Great script!

Here's my little contribuition:

; Initialize variables
mirror_1 = 0
mirror_2 = 9
mirror_3 = 8
mirror_4 = 7
mirror_5 = 6
mirror_q = p
mirror_w = o
mirror_e = i
mirror_r = u
mirror_t = y
mirror_a = `;
mirror_s = l
mirror_d = k
mirror_f = j
mirror_g = h
mirror_z = /
mirror_x = .
mirror_c = ,
mirror_v = m
mirror_b = n

Return


; Declare useful hotkeys
Space & '::        Send, {Delete}
Space & Tab::      Send, {BackSpace}
Space & CapsLock:: Send, {Enter}
Shift & Space::    Send, %A_Space% ; To repeat several spaces without having to press multiple times


; Declare main hotkeys
Space:: Send, {Space}

Space & 1::
Space & 2::
Space & 3::
Space & 4::
space & 5::
Space & q::
Space & w::
Space & e::
Space & r::
Space & t::
Space & a::
Space & s::
Space & d::
Space & f::
Space & g::
Space & z::
Space & x::
Space & c::
Space & v::
Space & b::


; This is genial! Congratulations!
StringRight, thisKey, A_ThisHotkey, 1
StringTrimRight, mirrorKey, mirror_%thisKey%, 0


;  Utilizing the elegant ternary operator to get modifiers' state
modifiers :=   (GetKeyState("Ctrl") ? "^" : "")
             . (GetKeyState("Alt") ? "!" : "")
             . (GetKeyState("LWin") || GetKeyState("RWin") ? "#" : "")
             . (GetKeyState("Shift") ? "+" : "")


; Sends the resulting keys
Send %modifiers%{%mirrorKey%}

Return


#Esc::
Reload


I am writing this using only my left hand. It is still a little difficult and slow, but I am getting used to it.

Great work!

fredthedeadhead
  • Members
  • 1 posts
  • Last active: May 06 2010 08:18 PM
  • Joined: 03 May 2010
What a great script :)

I was wondering if it were possible for Autohotkey to ignore when LAlt and space were pressed together though? I use Launchy, a keystroke launcher, but since this script uses the space bar, it breaks Launchy. Thanks very much.

(Sorry for the necro bump, I didn't think starting an entirely new topic would be better.)

DreymaR
  • Members
  • 89 posts
  • Last active: Jun 19 2013 08:03 AM
  • Joined: 24 May 2009
Using the space bar as a mirroring trigger isn't the best idea in my opinion. For the left hand, I used CapsLock and I think it worked okay. For the right hand, Enter should similarly work but it's a bit further away. Maybe RShift, but that'd lead to some rearranging.

The better idea is of course to rig a pedal to send, e.g., the F24 keystroke. Takes some skills to pull off though.
Better burden you cannot carry than man-wisdom much -- Hávamál

gigamatrix
  • Guests
  • Last active:
  • Joined: --
hi, I'm from Poland, and here we have letters like "ą" and "ę" etc. We write it using alt + letter (a, e, s etc). I'would like use script for one handed keyboard, but I can't write script for these letters.
I tried write

; Declare main hotkeys
Space & lalt:: Send {ralt}

But it doesn't work...

Can you help me? :)

DreymaR
  • Members
  • 89 posts
  • Last active: Jun 19 2013 08:03 AM
  • Joined: 24 May 2009
You need to work with scan codes I think. Also know that RAlt isn't the same as AltGr - which may be emulated by LCtrl+RAlt (or <^>! if you speak AHKese). Not entirely sure it'll always work...
Better burden you cannot carry than man-wisdom much -- Hávamál

auto
  • Guests
  • Last active:
  • Joined: --
I'm using half-querty ahk file.
When I press a space bar with any other key a little bit longer, it closes a window.
So, for example, I can't type a capital K with one hand.
(Space bar + pressing long 'd' or Shift + Space bar + d)
Either way doesn't work.
Is there anyone who can solve this problem?
Or am I doing something wrong?

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007

I'm using half-querty ahk file.
When I press a space bar with any other key a little bit longer, it closes a window.
So, for example, I can't type a capital K with one hand.
(Space bar + pressing long 'd' or Shift + Space bar + d)
Either way doesn't work.
Is there anyone who can solve this problem?
Or am I doing something wrong?

There are various versions of the script here in the thread, which one are you using?

You can find a link to a specific post by RIGHT clicking on the small "page" icon before "Posted Image Posted: date ... Post subject: ...." and copy the link.

auto
  • Guests
  • Last active:
  • Joined: --
Thank your for your quick reply, hugov.

Below is the script I'm using now.



#SingleInstance

; HalfKeyboard invented by Matias Corporation between 1992 and 1996
; Originally coded in AutoHotkey by jonny in 2004
; Many thanks to Chris for helping him out with this script.
; Capslock hacks and `~ remap to '" by Watcher
; This implementation was done by mbirth in 2007
;
; mixed with "Capitalize letters after 1 second hold" at request of Calibran
; http://www.autohotke...311.html#228311
; just tested very briefly so try at your own peril :-)
;
;
; This code is again a little bit modified by a Korean user in May.09.

KeyIsDown = 0
UpperDelay = 1000
UpperDelay *= -1


Menu Tray, Tip, HalfKeyboard modified



RegRead KLang, HKEY_CURRENT_USER, Keyboard Layout\Preload, 1
StringRight KLang, KLang, 4
If (!KLang)
KLang := A_Language

If (KLang = "0407") {
; 0407 DE_de QWERTZ mirror set
original := "^12345qwertasdfgyxcvb"
mirrored := "ß09876poiuzolkjh-.,mn"
} Else If (KLang = "040c" || KLang = "040C") {
; 040c FR_fr AZERTY mirror set
original := "²&e" . """" . "'(azertqsdfgwxcvb" ; split up string for better
mirrored := ")ac" . "_" . "e-poiuymlkjh!:;,n" ; human readability
} Else {
; 0409 US_us QWERTY mirror set
original := "``" . "12345qwertasdfgzxcvb" ; split up string for better
mirrored := "'" . "09876poiuy;lkjh/.,mn" ; human readability
}


; Now define all hotkeys
Loop % StrLen(original)
{
c1 := SubStr(original, A_Index, 1)
c2 := SubStr(mirrored, A_Index, 1)
Hotkey Space & %c1%, DoHotkey
Hotkey Space & %c2%, DoHotkey
Hotkey %c1%, KeyDown
Hotkey %c1% UP, KeyUP
}

return


; This key may help, as the space-on-up may get annoying, especially if you type fast.
Control & Space::Suspend

; Not exactly mirror but as close as we can get, Capslock enter, Tab backspace.
Space & CapsLock::Send {Enter}
Space & Tab::Send {Backspace}

; If spacebar didn't modify anything, send a real space keystroke upon release.
+Space::Send {Space}
Space::Send {Space}

; Define special key combos here (took them from RG's mod):
^1::Send {Home}
^2::Send {End}
^3::Send {Del}

; General purpose
DoHotkey:
StartTime := A_TickCount
StringRight ThisKey, A_ThisHotkey, 1
i1 := InStr(original, ThisKey)
i2 := InStr(mirrored, ThisKey)
If (i1+i2 = 0) {
MirrorKey := ThisKey
} Else If (i1 > 0) {
MirrorKey := SubStr(mirrored, i1, 1)
} Else {
MirrorKey := SubStr(original, i2, 1)
}

Modifiers := ""
If (GetKeyState("LWin") || GetKeyState("RWin")) {
Modifiers .= "#"
}
If (GetKeyState("Control")) {
Modifiers .= "^"
}
If (GetKeyState("Alt")) {
Modifiers .= "!"
}
If (GetKeyState("Shift") + GetKeyState("CapsLock", "T") = 1) {
; only add if Shift is held OR CapsLock is on (XOR) (both held down would result in value of 2)
Modifiers .= "+"
}

/*
KeyWait, %ThisKey%, T1
Send %Modifiers%{%MirrorKey%}
If (A_TickCount - StartTime >= 1000)
{
StringUpper, MirrorKey, MirrorKey
Send {Backspace}+%MirrorKey%
*/

If (KeyIsDown < 1 or ThisKey <> LastKey)
{
KeyIsDown := True
LastKey := ThisKey
Send %Modifiers%{%MirrorKey%}
SetKeyDelay, 65535
SetTimer, ReplaceWithUpperMirror, %UpperDelay%
}

Return


MenuExit:
ExitApp
Return

KeyDown:
Key:=A_ThisHotkey
If (KeyIsDown < 1 or Key <> LastKey)
{
KeyIsDown := True
LastKey := Key
Send %Key%
SetKeyDelay, 65535
SetTimer, ReplaceWithUpper, %UpperDelay%
}
Return

KeyUp:
Key:=A_ThisHotkey
SetTimer, ReplaceWithUpper, Off
SetTimer, ReplaceWithUpperMirror, Off
KeyIsDown := False
Return

ReplaceWithUpper:
SetKeyDelay, -1
Send {Backspace}+%LastKey%
Return

ReplaceWithUpperMirror:
SetKeyDelay, -1
Send {Backspace}+%MirrorKey%
Return

auto
  • Guests
  • Last active:
  • Joined: --
By the way, you guys don't have this kind of problem?

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
A) Why didn't you link, and B) why didn't you use code tags
[code][/code]
It looks 'my edit3' at first glance, and no I don't experience that problem.

xrzok
  • Members
  • 1 posts
  • Last active: Jun 22 2010 06:42 PM
  • Joined: 22 Jun 2010
This script is just what I've been looking for, thank you very much.

I'm however having a few issues with it (I'm using the script in the first post). First off, the space-depressed state seems to lock from time to time and so I have to disable and enable the script again to get it working using ctrl+space. I'm still trying to learn this Autohotkey program, so I can't figure out where in the script this irritating feature resides.

Second, is it possible to use the Alt-key as the main modifier instead? My keyboard features a quite a large Alt-key, so I believe it would work as well as the Space. I'd like to use the Alt-key because it wouldn't interfere with my normal typing and I wouldn't have to constantly turn the script on and off.

Thank you for the answers in advance.