Pokitext: text editor on pokitto


#1

(requested for Lua and lil file editing)

Designs for keyboard layouts I’m considering:

*. Reduced Ascii table on a grid
*. Dpad map, think of a virtual cellphone numpad a and b scroll back and forth, c button swaps from input to cursor mode
*. Intelligent input, a dictionary of commands in a list (language specific)


Lua on Pokitto
#2

I’ve been doodling the layouts with GIMP, I’ll post if I get some meaningful one.

At first I started redrawing my keyboard, but quickly scratched it because you get into QWERTY vs QWERTZ vs whatever, plus unaligned keys, plus layout optimized for hand typing.

So better have a regular ABC grid, with multiple pages, because there’s too many to fit on a single screen without taking too much space. One page can be lowercase, one uppercase, plus some special symbols on each.

I think there should be also special keys like arrows and shift for text selection so that you’re able to do most things with just the keyboard and not switch between the keyboard and some other mode.

Also advanced features like fast accessible most frequent characters or word completion (dictionary made from words in currently opened document?).


#3

The extra features might be nice but don’t forget our input is limited to 7 buttons


#4

Does anywhere even use QWERTZ?
I thought most of the world used a variant of QWERTY.
Or at the very least, most of the major european countries, the US and Japan.

I’d be more concerned about printing accented letters and currency symbols (e.g. the standard US layout doesn’t have the € sign*, most non-Japanese keyboards don’t have a yen sign) and the differences in placement between double quote and the at sign.

Personally I quite like the 3DS’s approach to the keyboard.
This is a modded version so some of the symbols are different,
but it gets the idea across:


* In case it wasn’t obvious, the standard UK layout does.


I think step 1 ought to be to define an interface for sending and receiving characters,
so multiple backends can be used (e.g. bluetooth keyboard, wifi keyboard, serial keyboard).

That should be relatively simple:

class CharInput
{
public:
	virtual bool hasCharAvailable(void) const = 0;
	virtual std::size_t charsAvailable(void) const = 0;
	virtual char32_t peekUnicodeChar(void) const = 0;
	virtual char32_t readUnicodeChar(void) = 0;
};

class CharOutput
{
public:
	virtual std::size_t charsRemaining(void) const = 0;
	virtual bool sendUnicodeChar(char32_t c) = 0;
};

#5

Germany is qwertz, I’m using azerty actually (its a pain playing games who don’t let you remap keys)
Problem with key maping is it’s very language specific, you don’t have to have ç or œ in English so there not on the top level. Anyway programing locks us in a little more and we can go for a qwerty layout also with Lua we can omit or but them on the second level characters that aren’t used like ; isn’t necessary in Lua same for €$£Ç%


#6

I do :smile: It’s default where I live.


#7

Also automatic closing brackets? Hit (,{ or [ to get the closing version after the cursor?


#8

Depends – is it supposed to be a general plaintext editor, or a programming editor?

I’d just try to make a text editor for start, but make it extendable so that this can be added.


If we go for the language layouts, there will have to be a possibility to configure them, switch them and so on. I’d like to avoid this and simply go for ABC. These layouts exist for optimized hand (or even pen) typing anyway, so we don’t gain anything. I think simpler is better here.


I would also try to avoid caring about accents/language specifics – these won’t be used in programming, and can be avoided in things like note taking and so on. We could add a possibility to insert a character by numeric code just in case and that’s it. The rendering would then depend on the compiled font, which you could change if needed.


#9

I don’t know how bad t9 would be for programing?
(9 key Predictive text)


#10

I really don’t know, we’ll have to try it out :slight_smile:


#11

…some ideas here:


#12

Interesting approach, though hard to get your head around, you have to be very intentional with your key presses, I personally prefer a more soft lock to navigate
But will definitely keep it in mind


#13

I have that problem even in QWERTY because I don’t like the WASD layout.

No, but I can type áéíóú by using AltGr.
I wish there were more, I find them handy.
Sometimes I want to speak French.
I have a Japanese IME installed because 日本語がすごい!

No, but I suspect many people will want to use it for clarity reasons.

Actually Lua uses % as its modulo operator,
and I suspect other languages do too.

Strange.

I concur.

Personally I find automatic insertion like that more of a hindrance than a help.
I’m used to writing code in a non-assisting editor and on paper, so the IDE trying to ‘help’ me usually causes me more problems.

I disagree.
People get used to a certain layout and they’re usually quicker at using that layout.
If you throw ABC at someone then they suddenly struggle with trying to find where the characters that they want are.

I quite like the idea of a wheel-based thing, but I don’t know how easy it would be to use:

Predictive text would be good for programming because you can load all the language keywords in and possibly maintain a list of all the words that have already appeared in the text, thus making common identifiers faster to reuse.
(Notepad++ does this.)

I’m not so sure about using a 9-key system like a phone though.

(To be honest, a bluetooth keyboard connected via bluetooth hat would solve a lot of these problems.)


The more I think it over, the more I see how important it will be to make things like the input method and the text assist features modular.

Here’s a revision of my earlier idea for a part of the interface:

class CharInput
{
public:
	// Number of chars in the read buffer
	virtual std::size_t charsAvailable(void) const = 0;
	
	// View the next char without removing it
	virtual char32_t peekUnicodeChar(void) const = 0;
	
	// Remove a char from the read buffer
	virtual char32_t readUnicodeChar(void) = 0;
	
	virtual bool hasCharAvailable(void) const
	{
		return (this->charsAvailable() > 0);
	}
};

class CharOutput
{
public:
	// Number of chars waiting to be sent over the network
	virtual std::size_t charsPending(void) const = 0;
	
	// Send a char, returns false if the send buffer is full
	virtual bool sendUnicodeChar(char32_t c) = 0;
	
	// Attempt to flush the send buffer, returns false if flush failed
	virtual bool flush(void) = 0;
};

This allows the backend to be a screen keyboard, bluetooth, USART etc.
I think the virtuality is important here, because it allows the implementation to be swapped at runtime.
That way, if the hypothetical bluetooth/serial keyboard runs out of power or gets disconnected, the on-screen keyboard can be used as a fallback, and different implementations of an on-screen keyboard can be registered.

Also note that although the interface treats each char as a UTF32 char, the implementation is free to convert between UTF32 and UTF7, UTF8 or UTF16 to reduce the amount of memory used.
This allows for maximum flexibility and provides a simpler interface that’s capable of handling both common and exotic characters.


#14

Maybe I’d see the keyboard as a stream of commands rather than chars? (If it has arrow keys and things like that. It could also e.g. switch to insert mode.) One of the commands would be put char X.


About the layouts: ABC is a universal layout that no one will get lost in… if they know the alphabet that is :slight_smile: But let’s not guess, we better try both and see what feels better.


#15

Hrm, fair point, I forgot the arrow keys.

Although that creates the problem of keycodes, I’m not sure if those are standardised or not.
I know SDL solves that by having virtual keycodes and actual keycodes and then remapping them.

enum class Keycode
{
	Nop,
	Print,
	Left, Right, Up, Down,
	Insert,
	Home, End,
	PageUp, PageDown,
	Backspace, Delete,
	Enter,
};

struct Command
{
	Keycode keycode = Nop;
	char32_t character = '\0';
	
	constepxr Command(void) = default;
	constexpr Command(Keycode keycode) : keycode(keycode), character() {}
	constexpr Command(Keycode keycode, char32_t character) : keycode(keycode), character(character) {}
};

class CommandInput
{
public:
	// Number of commands in the read buffer
	virtual std::size_t commandsAvailable(void) const = 0;
	
	// View the next command without removing it
	virtual Command peekCommand(void) const = 0;
	
	// Remove a command from the read buffer
	virtual Command readCommand(void) = 0;
	
	virtual bool hasCommandAvailable(void) const
	{
		return (this->commandsAvailable() > 0);
	}
};

class CommandOutput
{
public:
	// Number of commands waiting to be sent over the network
	virtual std::size_t commandsPending(void) const = 0;
	
	// Send a command, returns false if the send buffer is full
	virtual bool sendCommand(Command command) = 0;
	
	// Attempt to flush the send buffer, returns false if flush failed
	virtual bool flush(void) = 0;
};

I’m not entirely sure nobody will get lost.
It’s probably just best to provide both as standard and as more as they get requested.

In fact, if you just number the keys it should be easy enough to map the key number to the symbol that needs to be printed on it/the symbol that it generates.


#16

oh that must be new for me then, it dident used to work and you had to call math.mod() function for it

true and the esp32 could surve that purpose, but due to concerns bout power draw wen using wireless stuff we stopped development on that hat :S, theres also the silly idea of using IR and using a tv remote to add buttons (not sure if thats a better typing experience)

i get the impression the key map has to be modular, changable. maybe a silly idea but this might be something to push on the eeprom? cus im sure a decent onscreen keyboard thats personalized to your liking could be reused in other games?


#17

Sure, definitely make this moddable at the source code level, I just wouldn’t want to dive into runtime configurations of the keyboard, saving it to EEPROM, making menus for that etc. The main problem I have with the national layouts is that they’re not a regular grid (EDIT: and also the fact that they use rows of 10, 9, 7 keys, while I’d like to have it as rectangular as possible, like 9, 9, 8) – you can align it anyway, but then it’ll become just confusing because it’s different. As far as I remember, I never had any problems with ABC in Gameboy games, at least to me it was always intuitive. But as long as the layouts don’t mess with grid alignment, I’m all for allowing compile-time configuration of the layout, I know people have vastly different preferences.


Anyway, as I see it now, we need 3 things:

  • A keyboard – a reusable thing that interacts with the user and gives out “commands” – mostly characters, but also cursor operations, mode changes and so on.
  • A text widget – also reusable, a “window” that renders text from given buffer along with a cursor and can do things like scroll, highlight selection and so on.
  • An editor to glue these two together, handle saving/loading, copy/paste, configuration, extensions and so on.

Also, what font? :slight_smile: Will any of the present ones do the job?


And also, keys I think we’ll need, these need to be somehow fit into the grid(s):

characters:
  0123456789
  ABCDEFGHIJKLMNOPQRSTUVWXYZ
  abcdefghijklmnopqrstuvwxyz
  .,;:!?"'`^
  ()[]{}
  <>=-+*~/\_|
  #$%&@
  ⎵     SPACE
  ↦     TAB
  ⏎     NEWLINE

special:
  ⇦     BACKSPACE (delete backwards)
  ⇨     DEL (delete forward -- need this or not?)
  ⨯     ESCAPE/CANCEL (cancel selection?)
  ✓     OK/RETURN (need this or not? could be the same as NEWLINE)
  ↪     SHIFT (for text selection?)
  △     CTRL (for copy/paste -- need this or not?)
  ⇆     SWITCH_KEYBOARD_PAGE
  ⌑     SPECIAL (super/win/... for "special" needs of the program -- need this or not?)
  ←↑→↓  ARROWS (for moving the cursor)

Maybe like this? (includes all the above keys except )

page1:
  ⨯0123456789⇦⇨<>
  ↦ABCDEFGHIJ⏎&+-
  ↪KLMNOPQRST↑@=*
  △UVWXYZ⎵_⇆←↓→/\

page2:
  ⨯.,;:!?"'`^⇦⇨()
  ↦abcdefghij⏎%[]
  ↪klmnopqrst↑${}
  △uvwxyz⎵#⇆←↓→~|

#18

Think of this as a data structure problem: Getting to a key on a grid using the directionals to navigate is sort of like doing a search on a (quadrupally-) linked list. As an example, if it were a QWERTY grid: to get from A to L, you have to go through S, D, F, G, H, J, K.
The faster algorithm is to use a tree instead of a list. Since there are few buttons, making them chorded would help flatten the tree, so you press a direction to select a branch and A/B/C/A+B/A+C to select a leaf. It might sound complicated, but with just two actions you can select any letter/number, move the cursor, etc.

To clarify:
keyboard
Up+Left+A+B = I
Right+C+A = V
Left+B = E
etc.


#19

I agree with what @adekto said above – these systems are really smart and I am sure will be effective if you learn to use them, but they’re totally unfamiliar to most people, and difficult to learn (as in be able to use this without much effort in order to actually be able to think about what’s being written) – and since this is basically a toy, I am afraid no one would want to put the energy into learning to type like this. It’s like vim/emacs – they’re effective tools, but most people give up just because of that huge unfamiliarity when they first see it. So we can try this as an alternative, but I’d still like to stick to the good old keyboard as default.

Anyway, don’t stop posting these though :slight_smile: they’re interesting and could make for a great alternative.


#20

I agree that it’s unfamiliar, but is it really that difficult to learn? The labels and the buttons they correspond to are right there on the screen.
If the idea is to make a keyboard for short texts (Type in your initials for a Highscore list), then yes, the grid is fine. For a notepad-like application, the grid is going to be painful, especially if there isn’t an autocomplete.