This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
H4X0RZ's profile picture

Optimized Key Layout

Started by H4X0RZ, 07 November 2015 - 08:00 PM
H4X0RZ #1
Posted 07 November 2015 - 09:00 PM
tl;dr These scripts will generate a keyboard layout by sorting a giving piece of code and arranging the keys by how often the given char appears in the code.

I were bored today so I started this little "project". It isn't anything special, it just allows you to generate a keyboard layout (for CC) which will/should fit your needs. It consists out of two programs. One that analyzes a given file (which should contain code) and the other one takes the output from the first and converts that into an executable layout. When generating it will sort the characters of the given file by how often they appear and then gives them places according to their "worth". (the most used keys get a more centralized place on the keyboard. G is the key worth the most, then it goes to the left and right from G (alternating) and then the other two "layers" of keys. Then the same happens with capitalized (shift) keys). This method *should* give you the most optimized layout (according to the code provided)

Using it is easy:
download 2BiacX78 and EFVX27ye (I have saved them as "analyze" and "generate" but you can decide for yourself)
then choose some big file containing code (maybe one you wrote. I were using the minified code from Howl) and enter
analyze <file name>
This will save a dump of the appearing chars (and their probability) into "output". After that enter
generate output
This will generate the finished executable which will set your computer up for the new layout. I'm using a simplified version of my event remapper for that (it is included at the top of the layout).

The "Howl layout" looks like this for example:
Spoiler

-----------------------------------------
--		  Custom Key Layout		  --
-----------------------------------------
----------------Remapper------------------
local map = {}
local function addRemap(expected, modifier)
  map[expected] = modifier
end
function os.pullEvent(filter)
local evt = {os.pullEventRaw(filter or nil)}
if(evt[1] == "char") then
   for k,v in pairs(map) do
	 if(k[2] == evt[2]) then
	   e = v(evt)
	   return unpack(e)
	 end
   end
end
return unpack(evt)
end
------------------------------------------
addRemap({'char',"m"},function(evt) return {'char',"'"} end)
addRemap({'char',"l"},function(evt) return {'char',"i"} end)
addRemap({'char',"o"},function(evt) return {'char',")"} end)
addRemap({'char',"n"},function(evt) return {'char',"\""} end)
addRemap({'char',"q"},function(evt) return {'char',"("} end)
addRemap({'char',"p"},function(evt) return {'char',"c"} end)
addRemap({'char',"s"},function(evt) return {'char',"o"} end)
addRemap({'char',"r"},function(evt) return {'char',"s"} end)
addRemap({'char',"u"},function(evt) return {'char',"="} end)
addRemap({'char',"1"},function(evt) return {'char',"P"} end)
addRemap({'char',"w"},function(evt) return {'char',"f"} end)
addRemap({'char',"v"},function(evt) return {'char',","} end)
addRemap({'char',"y"},function(evt) return {'char',"h"} end)
addRemap({'char',"x"},function(evt) return {'char'," "} end)
addRemap({'char',"2"},function(evt) return {'char',"z"} end)
addRemap({'char',"3"},function(evt) return {'char',"N"} end)
addRemap({'char',"4"},function(evt) return {'char',"R"} end)
addRemap({'char',"5"},function(evt) return {'char',"F"} end)
addRemap({'char',"6"},function(evt) return {'char',"w"} end)
addRemap({'char',"7"},function(evt) return {'char',"1"} end)
addRemap({'char',"8"},function(evt) return {'char',"H"} end)
addRemap({'char',"9"},function(evt) return {'char',"M"} end)
addRemap({'char',"0"},function(evt) return {'char',"W"} end)
addRemap({'char',"A"},function(evt) return {'char',";"} end)
addRemap({'char',"C"},function(evt) return {'char',"_"} end)
addRemap({'char',"B"},function(evt) return {'char',"x"} end)
addRemap({'char',"E"},function(evt) return {'char',"}"} end)
addRemap({'char',"D"},function(evt) return {'char',":"} end)
addRemap({'char',"G"},function(evt) return {'char',"p"} end)
addRemap({'char',"F"},function(evt) return {'char',"m"} end)
addRemap({'char',"I"},function(evt) return {'char',"{"} end)
addRemap({'char',"H"},function(evt) return {'char',"T"} end)
addRemap({'char',"K"},function(evt) return {'char',"E"} end)
addRemap({'char',"J"},function(evt) return {'char',"C"} end)
addRemap({'char',"M"},function(evt) return {'char',"k"} end)
addRemap({'char',"L"},function(evt) return {'char',"y"} end)
addRemap({'char',"O"},function(evt) return {'char',"["} end)
addRemap({'char',"N"},function(evt) return {'char',"I"} end)
addRemap({'char',"Q"},function(evt) return {'char',"]"} end)
addRemap({'char',"P"},function(evt) return {'char',"D"} end)
addRemap({'char',"S"},function(evt) return {'char',"b"} end)
addRemap({'char',"R"},function(evt) return {'char',"U"} end)
addRemap({'char',"U"},function(evt) return {'char',"A"} end)
addRemap({'char',"W"},function(evt) return {'char',"S"} end)
addRemap({'char',"V"},function(evt) return {'char',"g"} end)
addRemap({'char',"Y"},function(evt) return {'char',"O"} end)
addRemap({'char',"X"},function(evt) return {'char',"L"} end)
addRemap({'char',"a"},function(evt) return {'char',"a"} end)
addRemap({'char',"c"},function(evt) return {'char',"u"} end)
addRemap({'char',"b"},function(evt) return {'char',"\n"} end)
addRemap({'char',"e"},function(evt) return {'char',"."} end)
addRemap({'char',"d"},function(evt) return {'char',"t"} end)
addRemap({'char',"g"},function(evt) return {'char',"e"} end)
addRemap({'char',"f"},function(evt) return {'char'," "} end)
addRemap({'char',"i"},function(evt) return {'char',"d"} end)
addRemap({'char',"h"},function(evt) return {'char',"n"} end)
addRemap({'char',"k"},function(evt) return {'char',"r"} end)
addRemap({'char',"j"},function(evt) return {'char',"l"} end)
With this layout "f" would act as spacebar (but the normal spacebar could still be used), "g" becomes "e", "h" becomes "n" etc. Sometimes if brackets are used strange (idk if that is even possible in Lua) it could happen that an opening/closing bracket is available from the normal keyboard but for it's counterpart you need shift so look out for that.

The way it is done right now has to leave some characters out because I only have a german keyboard so I could only write a full "priority list" for the normal german layout (QWERTZ). If anyone want's to write a "priority list" for the standard english layout please do so.

Greetings,
~H4X0RZ
Edited on 07 November 2015 - 08:13 PM
Creator #2
Posted 07 November 2015 - 09:25 PM
So why exactly should the first file be code? Can't it be a text file?
H4X0RZ #3
Posted 07 November 2015 - 10:00 PM
So why exactly should the first file be code? Can't it be a text file?
It can be anything but a code file "teaches" the layout more about the appearance of characters in a Lua file.
SquidDev #4
Posted 08 November 2015 - 11:22 AM
This is kinda cool, (though I'm not sure I see the point). Also, it uses Howl so I have to approve :P/>.

One thing though: You might want to delegate to the os.pullEvent method rather than os.pullEventRaw - otherwise you won't catch terminate events.
H4X0RZ #5
Posted 08 November 2015 - 01:51 PM
This is kinda cool, (though I'm not sure I see the point). Also, it uses Howl so I have to approve :P/>.

One thing though: You might want to delegate to the os.pullEvent method rather than os.pullEventRaw - otherwise you won't catch terminate events.

TBH, there is no point in using this :P/> All it does is remap your keyboard so the most used characters (that's why you should do it with a *large* file of *code*) are more centralized.

There are some points which make it completely unusable:
  1. Shifting doesn't do the same as for a "normal" keyboard. On a "normal" kb it reveals the capitalized counterparts of the keys. My generator will just sort by the appearance of the characters so capitalized/not-capitalized characters are mixed on both "layers" (shifted and "normal") and they aren't on the same keys. For example the "Howl layout": "a" is equal to "a" (lol) and "U" is equal to "A".
  2. It's extremely hard to recognize the position of every key unless you have some magic keyboard.
Thanks for telling me to switch from pullEventRaw to pullEvent, haven't thought about that!

//Off-Topic
Maybe I'm going to write something that works like ASETNIOP because I'm really interested in how that works (writing text using chords)