# Macro that translates marlin params to klipper params

**URL:** <https://klipper.discourse.group/t/macro-that-translates-marlin-params-to-klipper-params/10886>\
**Category:** Macros\
**Created:** [October 9, 2023, 8:34am UTC](https://klipper.discourse.group/t/macro-that-translates-marlin-params-to-klipper-params/10886 "2023-10-09T08:34:52Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Luro02](https://yyz2.discourse-cdn.com/free1/user_avatar/klipper.discourse.group/luro02/32/7510_2.png) [@Luro02](https://klipper.discourse.group/u/Luro02)\
**Post date:** [October 9, 2023, 8:34am UTC](https://klipper.discourse.group/t/macro-that-translates-marlin-params-to-klipper-params/10886/1 "2023-10-09T08:34:52Z")

</div>

In the example for the M117 macro, the raw params are parsed in the macro itself to remove comments.

I did not want to parse arguments for every single marlin macro, so I wrote one that does the parsing:

````python
# Translates marlin gcode arguments into klipper arguments.
#
# Usage:
# _PARSE_MARLIN_PARAMS TARGET=[<macro>] ARGS='{rawparams}'
# Parameters:
# [<macro>] The name of the macro that should be called with the parsed arguments 
#
# Examples:
# ```
# [gcode_macro _T123]
# gcode:
# { action_respond_info("_T123 called with: params={}, rawparams={}".format(params, rawparams)) }
#
# [gcode_macro T123]
# gcode:
# _PARSE_MARLIN_PARAMS TARGET=_T123 ARGS='{rawparams}'
# ```
#
# Note:
# Klipper gcode_macros expect key value arguments like 'MY_MACRO KEY=VALUE'.
#
# The traditional gcode style 'MY_MACRO H123 B C' is not allowed for all macros.
# If 'MY_MACRO' does not have the correct format, klipper will complain about "malformed command".
# 
# The following must be satisfied (based on the current source code):
# - Starts with a character 'c' for which the python expression 'c.upper().isupper()' is True
# (all characters 'A-Z' and 'a-z' satisfy this, numbers or special characters like '_' do not)
# - After that a number must follow
# - The format must be '<letter><float>' where <float> must start with a number and the python
# expression 'float("<float>"")' must not fail
#
# I recommend that your macro has a name in the format '<letter><number>' like for example 'T123'.
#
# There is no boolean filter in jinja, so you can not write
# {% set FLAG = params.F|default(false)|boolean %}
#
# As a workaround, I recommend writing this instead:
# {% set FLAG = params.F|default(false)|lower == "true" %}
[gcode_macro _PARSE_MARLIN_PARAMS]
description: Translates marlin params into klipper params
gcode:
    {% set TARGET = params.TARGET|string %}
    {% set ARGS = params.ARGS|default("")|string %}

    # This parses the rawparams by first removing trailing comments with ; and '\x23' = '#', then splitting
    # the result by whitespace (to obtain a list of arguments)
    {% set parsed_params = ARGS.split(';', 1)[0].split('\x23', 1)[0].lower().split() %}

    # { action_respond_info("ARGS: {}, parsed: {}".format(ARGS, parsed_params)) }

    {% set macro_command = [TARGET] %}
    {% for x in parsed_params %}
        {% if x|length > 1 %}
            {% set _ = macro_command.append("{}={}".format(x[0:1], x[1:])) %}
        {% else %}
            # Flags are set to true
            {% set _ = macro_command.append("{}=true".format(x)) %}
        {% endif %}
    {% endfor %}

    # { action_respond_info("Command: {}".format(macro_command|join(' '))) }
    { macro_command|join(' ') }

````

This is especially useful for macros where an argument has a value like `H<number>`.

For example the gcode G12 accepts the following arguments

> `G12 [P<0|1|2>] [R<radius>] [S<count>] [T<count>] [X] [Y] [Z]`

> **[Clean the Nozzle](https://marlinfw.org/docs/gcode/G012.html)**
>
> Start the nozzle cleaning process. Three types of cleaning patterns are supported: straight strokes, zigzags and circles. This feature requires a dedicated cleaning area on or outside the bed, but within reach of the nozzle. The pattern may be...

```python
[gcode_macro _G12]
gcode:
    { action_respond_info("_G12 called with: params={}, rawparams={}".format(params, rawparams)) }
    # G12 [P<0|1|2>] [R<radius>] [S<count>] [T<count>] [X] [Y] [Z]

    {% set P = params.P|default(0)|int %}
    {% set R = params.R|default(0)|float %}
    {% set T = params.T|default(0)|int %}
    {% set S = params.S|default(0)|int %}

    {% set X = params.X|default(false)|lower == "true" %}
    {% set Y = params.Y|default(false)|lower == "true" %}
    {% set Z = params.Z|default(false)|lower == "true" %}

    { action_respond_info("_G12 P={} R={} T={} S={} X={} Y={} Z={}".format(P, R, T, S, X, Y, Z)) }

[gcode_macro G12]
gcode:
    _PARSE_MARLIN_PARAMS TARGET=_G12 ARGS='{rawparams}'

```

```auto
$ G12 P1 R2.1 T3 S5 X Y
_G12 called with: params={'P': '1', 'R': '2.1', 'T': '3', 'S': '5', 'X': 'true', 'Y': 'true'}, rawparams=p=1 r=2.1 t=3 s=5 x=true y=true
_G12 P=1 R=2.1 T=3 S=5 X=True Y=True Z=False

$ G12
_G12 called with: params={}, rawparams=
_G12 P=0 R=0.0 T=0 S=0 X=False Y=False Z=False

```

Not having a `boolean` filter is a bit of a pain (especially when some might use 0 or 1 to indicate true/false). Jinja supports creating custom filters, but not inside templates: [python - Embed custom filter definition into jinja2 template? - Stack Overflow](https://stackoverflow.com/a/25450294)

This would require a PR against the Klipper Repo, which I would be willing to do if it will be merged.
