talonhub / community

Voice command set for Talon, community-supported.
MIT License
646 stars 782 forks source link

Discussion: Improve code operators #1597

Open AndreasArvidsson opened 1 week ago

AndreasArvidsson commented 1 week ago

The problem

Implementing operators in a programming language today is very verbose. This is due to the fact that each operator is its own action. This creates a lot of boiler plate and there is no easy overview of the operators in a particular language.

eg 97 lines in java : https://github.com/talonhub/community/blob/c5f32adef6db9a722e949423f2203cb7d474594f/lang/java/java.py#L93-L190

My implementation - Talon list with typed class

My solution to this is to use a Talon list. The benefit with this is that operators that is not supported by the language is not speakable and its implementation is quite compact. I even added a class so I could get typed operators in my list.

eg 23 lines in java: https://github.com/AndreasArvidsson/andreas-talon/blob/ab634074d15197eca86f7bff5c0fb549799faa46/languages/java/java.py#L12-L35

Pros

Cons

The middle ground solution

One way to do it would be to keep the community Talon files but instead of each operator calling a separate action we just have a single code_operator(id: str) that is used by all the operators. We would then per language have something very similar to the operator's class in my example that just defines each operator's value but don't assign them to a Talon list. Instead the class is used by an action. eg: (op | logical | bitwise) (ex | exclusive) or: user.code_operator("bitwise_exclusive_or")

Pros

Cons

Summary

I'm very happy with my implementation for my own needs, but for community I think the middle ground solution is the best. That would basically involve:

  1. Create a dict/class for each programming language with its operators
  2. Implement the new operator's action
  3. Replace all the old calls to the operator's actions in the Talon files with the new action

Any opinions? @phillco @knausj85 @nriley

AndreasArvidsson commented 14 hours ago

After a discussion with @phillco I now have a new suggestion:

  1. Keep the existing operator tags: code_operators_array, code_operators_assignment, etc.
  2. For each operator tag: create a talon-list file that maps spoken forms to identifiers. eg:
    list: user.code_operators_math
    tag: user.code_operators_math
    -
    subtract: SUBTRACT
  3. Create a single operators.talon file that utilizes each list.
    op {user.code_operators_math}: user.code_operator(code_operators_math)
    op {user.code_operators_assignment}: user.code_operator(code_operators_assignment)
    • If a tag is not defined then that list is just empty and the entire command is not speakable.
  4. For each programming language defined a action that returns a dictionary with all the operators for that language.
    operators = {
    "SUBTRACT": " - "
    }

I think this is quite a clean solution but it does have a limitation compared to today's implementation. All operators must be definable as a string so we can't do anything like today's subscript: https://github.com/talonhub/community/blob/b85932a6aa2372f553ff7be988aeae6d7127dcaa/lang/java/java.py#L96-L97

We also have the consideration that since we're moving to Talon list files we're probably going to deprecate a lot off the optional parts of the command grammars. For example I can't see us supporting this in a Talon list file: https://github.com/talonhub/community/blob/b85932a6aa2372f553ff7be988aeae6d7127dcaa/lang/tags/operators_assignment.talon#L25-L26 Deprecating commands are fine but does that mean we need to migrate all programming languages at once? Otherwise some commands should be deprecated in specific languages and not in other.