Re: [dev] [sandy] Additional key tests

From: Markus Teich <markus.teich_AT_stusta.mhn.de>
Date: Fri, 1 Aug 2014 22:19:25 +0200

Silvan Jegen wrote:
> http://sillymon.ch/data/funcfsm.png
> (source: http://sillymon.ch/data/funcfsm.dot )

Heyho Silvan,

this seems to be way too complex.

> To simplify the states I assume that a count ([0-9]+) can only occur before
> the movement command (jklhw etc.) and not before the operator (ydc). That
> means that "d3w" is valid but "3dw" isn't.

What about "5s", "3x" or "10p"? This is just another prefix. In vim if you type
"2d3w" the amounts get multiplied and you delete 6 words.

> The fsm_* functions would need to read input to decide on the transitions (i.
> e. functions to call; to extract the count argument for move(), fsm_move would
> have to read in a loop). I think maybe passing a function pointer to these
> functions would make sense. The passed function pointer would then determine
> whether the next input is read from stdin or a buffer (useful for macros?) or
> from wherever.

So you have to synchronously wait for input in these functions? o.O

> I have not written one line of code yet because I am not sure this is the best
> approach. Do you see issues with this proposal or do you have a better
> idea/implementation in mind?

I would rather propose a much simpler, but generic FSM/DFA for parsing keyboard
commands:

http://fs.tum.de/~teichm/sandy_keys.png

We should implement a global state something like this:

struct action {
        int amount;
        union {
                enum op o;
                enum preop po;
        } cmd;
        union {
                struct {
                        int inner;
                        enum textobj o;
                } to;
                enum movement mov;
        } m;
};

text-objects would have a mandatory prefix either 'i' for inner or 'a' for
outer.

The enum could contain the following values:
preop: a i o p r s v x
textobj: w s p " ' ` [ ] { } < > { } t
movement: b e h j k l n w
op: c d y

for example resulting in:
enum op {
        OP_CHANGE = 'c',
        OP_DELETE = 'd',
        OP_YANK = 'y',
};

Then we could just collect the information through a state dependent function
table:

int (*q0_transitions[256])(char input) = {
        ['0'] = transition_number,
        …
        [PREOP_PASTE] = transition_preop,
        …
        [MOV_WORD] = transition_mov,
        …
        [OP_CHANGE] = transition_op,
        …
};

The transition_number(char input) function would just do
action.amount *= 10;
action.amount += input - '0';

After we reach an end-state, we have collected all the info in our struct
action, can execute the apropriate commands (again through a function table),
reset the action struct and the state to q0.

I feel this is much easier to manage and even extend with custom mappings within
config.h. What do you think?

--Markus
Received on Fri Aug 01 2014 - 22:19:25 CEST

This archive was generated by hypermail 2.3.0 : Fri Aug 01 2014 - 22:24:13 CEST