From fd28eab179a65f17780ba611b56c1c7e8233f2cc Mon Sep 17 00:00:00 2001
From: Peter Johanson <peter@peterjohanson.com>
Date: Mon, 5 Aug 2024 16:50:35 -0600
Subject: [PATCH] feat: Add the ability to keep/omit behaviors for a given
 build.

* Use defines to keep either all behaviors with omits, or selective behaviors with
  explicit kept behavior, before including `behavior.dtsi` in keymaps.
* Default ZMK_BEHAVIORS_KEEP_ALL when building with the studio RPC
  endpoint snippet.
---
 app/boards/native_posix_64.overlay                  |  2 +-
 .../minivan_studio_tester.keymap                    |  2 ++
 app/dts/behaviors/backlight.dtsi                    |  7 ++++++-
 app/dts/behaviors/bluetooth.dtsi                    |  7 ++++++-
 app/dts/behaviors/caps_word.dtsi                    |  6 +++++-
 app/dts/behaviors/gresc.dtsi                        |  7 ++++++-
 app/dts/behaviors/key_press.dtsi                    |  8 ++++++--
 app/dts/behaviors/key_repeat.dtsi                   |  6 +++++-
 app/dts/behaviors/key_toggle.dtsi                   |  7 ++++++-
 app/dts/behaviors/layer_tap.dtsi                    |  7 ++++++-
 app/dts/behaviors/mod_tap.dtsi                      |  7 ++++++-
 app/dts/behaviors/momentary_layer.dtsi              |  7 ++++++-
 app/dts/behaviors/mouse_key_press.dtsi              | 13 ++++++++++++-
 app/dts/behaviors/none.dtsi                         |  7 ++++++-
 app/dts/behaviors/outputs.dtsi                      |  7 ++++++-
 app/dts/behaviors/soft_off.dtsi                     |  7 ++++++-
 app/dts/behaviors/sticky_key.dtsi                   | 12 ++++++++++--
 app/dts/behaviors/to_layer.dtsi                     |  7 ++++++-
 app/dts/behaviors/toggle_layer.dtsi                 |  7 ++++++-
 app/dts/behaviors/transparent.dtsi                  |  7 ++++++-
 app/include/dt-bindings/zmk/behaviors.h             |  9 +++++++++
 app/snippets/studio-rpc-usb-uart/snippet.yml        |  1 +
 22 files changed, 129 insertions(+), 21 deletions(-)
 create mode 100644 app/include/dt-bindings/zmk/behaviors.h

diff --git a/app/boards/native_posix_64.overlay b/app/boards/native_posix_64.overlay
index d0526ca3..2e571c4b 100644
--- a/app/boards/native_posix_64.overlay
+++ b/app/boards/native_posix_64.overlay
@@ -1,4 +1,4 @@
-#include <behaviors.dtsi>
+
 #include <dt-bindings/zmk/keys.h>
 #include <dt-bindings/zmk/kscan_mock.h>
 
diff --git a/app/boards/shields/minivan_studio_tester/minivan_studio_tester.keymap b/app/boards/shields/minivan_studio_tester/minivan_studio_tester.keymap
index 531d8e0c..a9a77260 100644
--- a/app/boards/shields/minivan_studio_tester/minivan_studio_tester.keymap
+++ b/app/boards/shields/minivan_studio_tester/minivan_studio_tester.keymap
@@ -4,6 +4,8 @@
  * SPDX-License-Identifier: MIT
  */
 
+#define ZMK_BEHAVIORS_KEEP_ALL
+
 #include <behaviors.dtsi>
 #include <dt-bindings/zmk/keys.h>
 
diff --git a/app/dts/behaviors/backlight.dtsi b/app/dts/behaviors/backlight.dtsi
index dd045eff..9b6162e1 100644
--- a/app/dts/behaviors/backlight.dtsi
+++ b/app/dts/behaviors/backlight.dtsi
@@ -4,10 +4,15 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
  / {
     behaviors {
+#if ZMK_BEHAVIOR_OMIT(BL)
+        /omit-if-no-ref/
+#endif
         // Behavior can be invoked on peripherals, so name must be <= 8 characters.
-        /omit-if-no-ref/ bl: bcklight {
+        bl: bcklight {
             compatible = "zmk,behavior-backlight";
             #binding-cells = <2>;
             display-name = "Backlight";
diff --git a/app/dts/behaviors/bluetooth.dtsi b/app/dts/behaviors/bluetooth.dtsi
index bece156f..29fed4ce 100644
--- a/app/dts/behaviors/bluetooth.dtsi
+++ b/app/dts/behaviors/bluetooth.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ bt: bluetooth {
+#if ZMK_BEHAVIOR_OMIT(BT)
+        /omit-if-no-ref/
+#endif
+        bt: bluetooth {
             compatible = "zmk,behavior-bluetooth";
             #binding-cells = <2>;
             display-name = "Bluetooth";
diff --git a/app/dts/behaviors/caps_word.dtsi b/app/dts/behaviors/caps_word.dtsi
index 05431bd8..99354f42 100644
--- a/app/dts/behaviors/caps_word.dtsi
+++ b/app/dts/behaviors/caps_word.dtsi
@@ -4,11 +4,15 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
 #include <dt-bindings/zmk/keys.h>
 
 / {
     behaviors {
-        /omit-if-no-ref/ caps_word: caps_word {
+#if ZMK_BEHAVIOR_OMIT(CAPS_WORD)
+        /omit-if-no-ref/
+#endif
+        caps_word: caps_word {
             compatible = "zmk,behavior-caps-word";
             #binding-cells = <0>;
             continue-list = <UNDERSCORE BACKSPACE DELETE>;
diff --git a/app/dts/behaviors/gresc.dtsi b/app/dts/behaviors/gresc.dtsi
index 2643a383..e3e0935f 100644
--- a/app/dts/behaviors/gresc.dtsi
+++ b/app/dts/behaviors/gresc.dtsi
@@ -4,11 +4,16 @@
  * SPDX-License-Identifier: MIT
  */
 
+
+#include <dt-bindings/zmk/behaviors.h>
 #include <dt-bindings/zmk/keys.h>
 
 / {
     behaviors {
-        /omit-if-no-ref/ gresc: grave_escape {
+#if ZMK_BEHAVIOR_OMIT(GRESC)
+        /omit-if-no-ref/
+#endif
+        gresc: grave_escape {
             compatible = "zmk,behavior-mod-morph";
             #binding-cells = <0>;
             bindings = <&kp ESC>, <&kp GRAVE>;
diff --git a/app/dts/behaviors/key_press.dtsi b/app/dts/behaviors/key_press.dtsi
index 2435699b..08adbf79 100644
--- a/app/dts/behaviors/key_press.dtsi
+++ b/app/dts/behaviors/key_press.dtsi
@@ -4,10 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /* DEPRECATED: `cp` will be removed in the future */
-        /omit-if-no-ref/ cp: kp: key_press {
+#if ZMK_BEHAVIOR_OMIT(KP)
+    /omit-if-no-ref/
+#endif
+        kp: key_press {
             compatible = "zmk,behavior-key-press";
             #binding-cells = <1>;
             display-name = "Key Press";
diff --git a/app/dts/behaviors/key_repeat.dtsi b/app/dts/behaviors/key_repeat.dtsi
index cd5d3771..d2144699 100644
--- a/app/dts/behaviors/key_repeat.dtsi
+++ b/app/dts/behaviors/key_repeat.dtsi
@@ -4,11 +4,15 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
 #include <dt-bindings/zmk/keys.h>
 
 / {
     behaviors {
-        /omit-if-no-ref/ key_repeat: key_repeat {
+#if ZMK_BEHAVIOR_OMIT(KEY_REPEAT)
+    /omit-if-no-ref/
+#endif
+        key_repeat: key_repeat {
             compatible = "zmk,behavior-key-repeat";
             #binding-cells = <0>;
             usage-pages = <HID_USAGE_KEY>;
diff --git a/app/dts/behaviors/key_toggle.dtsi b/app/dts/behaviors/key_toggle.dtsi
index a7b66aab..cd43c592 100644
--- a/app/dts/behaviors/key_toggle.dtsi
+++ b/app/dts/behaviors/key_toggle.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ kt: key_toggle {
+#if ZMK_BEHAVIOR_OMIT(KT)
+    /omit-if-no-ref/
+#endif
+        kt: key_toggle {
             compatible = "zmk,behavior-key-toggle";
             #binding-cells = <1>;
             display-name = "Key Toggle";
diff --git a/app/dts/behaviors/layer_tap.dtsi b/app/dts/behaviors/layer_tap.dtsi
index 2858bf17..9c1bea1a 100644
--- a/app/dts/behaviors/layer_tap.dtsi
+++ b/app/dts/behaviors/layer_tap.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ lt: layer_tap {
+#if ZMK_BEHAVIOR_OMIT(LT)
+        /omit-if-no-ref/
+#endif
+        lt: layer_tap {
             compatible = "zmk,behavior-hold-tap";
             #binding-cells = <2>;
             flavor = "tap-preferred";
diff --git a/app/dts/behaviors/mod_tap.dtsi b/app/dts/behaviors/mod_tap.dtsi
index 0b46f77e..b5e52e66 100644
--- a/app/dts/behaviors/mod_tap.dtsi
+++ b/app/dts/behaviors/mod_tap.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ mt: mod_tap {
+#if ZMK_BEHAVIOR_OMIT(MT)
+        /omit-if-no-ref/
+#endif
+        mt: mod_tap {
             compatible = "zmk,behavior-hold-tap";
             #binding-cells = <2>;
             flavor = "hold-preferred";
diff --git a/app/dts/behaviors/momentary_layer.dtsi b/app/dts/behaviors/momentary_layer.dtsi
index cae08d5f..c263ef10 100644
--- a/app/dts/behaviors/momentary_layer.dtsi
+++ b/app/dts/behaviors/momentary_layer.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ mo: momentary_layer {
+#if ZMK_BEHAVIOR_OMIT(MO)
+        /omit-if-no-ref/
+#endif
+        mo: momentary_layer {
             compatible = "zmk,behavior-momentary-layer";
             #binding-cells = <1>;
             display-name = "Momentary Layer";
diff --git a/app/dts/behaviors/mouse_key_press.dtsi b/app/dts/behaviors/mouse_key_press.dtsi
index 975c24aa..4fbc2eb4 100644
--- a/app/dts/behaviors/mouse_key_press.dtsi
+++ b/app/dts/behaviors/mouse_key_press.dtsi
@@ -1,6 +1,17 @@
+/*
+ * Copyright (c) 2023 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+ #include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ mkp: mouse_key_press {
+#if ZMK_BEHAVIOR_OMIT(MKP)
+        /omit-if-no-ref/
+#endif
+        mkp: mouse_key_press {
             compatible = "zmk,behavior-mouse-key-press";
             #binding-cells = <1>;
         };
diff --git a/app/dts/behaviors/none.dtsi b/app/dts/behaviors/none.dtsi
index a9a820c3..5ac55438 100644
--- a/app/dts/behaviors/none.dtsi
+++ b/app/dts/behaviors/none.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ none: none {
+#if ZMK_BEHAVIOR_OMIT(NONE)
+        /omit-if-no-ref/
+#endif
+        none: none {
             compatible = "zmk,behavior-none";
             #binding-cells = <0>;
             display-name = "None";
diff --git a/app/dts/behaviors/outputs.dtsi b/app/dts/behaviors/outputs.dtsi
index 3047852a..6071dcbd 100644
--- a/app/dts/behaviors/outputs.dtsi
+++ b/app/dts/behaviors/outputs.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ out: outputs {
+#if ZMK_BEHAVIOR_OMIT(OUT)
+        /omit-if-no-ref/
+#endif
+        out: outputs {
             compatible = "zmk,behavior-outputs";
             #binding-cells = <1>;
             display-name = "Output Selection";
diff --git a/app/dts/behaviors/soft_off.dtsi b/app/dts/behaviors/soft_off.dtsi
index a5c9d255..68dce9c9 100644
--- a/app/dts/behaviors/soft_off.dtsi
+++ b/app/dts/behaviors/soft_off.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ soft_off: z_so_off {
+#if ZMK_BEHAVIOR_OMIT(SOFT_OFF)
+        /omit-if-no-ref/
+#endif
+        soft_off: z_so_off {
             compatible = "zmk,behavior-soft-off";
             #binding-cells = <0>;
             split-peripheral-off-on-press;
diff --git a/app/dts/behaviors/sticky_key.dtsi b/app/dts/behaviors/sticky_key.dtsi
index 382a7254..4429ffc4 100644
--- a/app/dts/behaviors/sticky_key.dtsi
+++ b/app/dts/behaviors/sticky_key.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ sk: sticky_key {
+#if ZMK_BEHAVIOR_OMIT(SK)
+        /omit-if-no-ref/
+#endif
+        sk: sticky_key {
             compatible = "zmk,behavior-sticky-key";
             #binding-cells = <1>;
             release-after-ms = <1000>;
@@ -14,7 +19,10 @@
             ignore-modifiers;
             display-name = "Sticky Key";
         };
-        /omit-if-no-ref/ sl: sticky_layer {
+#if ZMK_BEHAVIOR_OMIT(STICKY_LAYER)
+        /omit-if-no-ref/
+#endif
+        sl: sticky_layer {
             compatible = "zmk,behavior-sticky-key";
             #binding-cells = <1>;
             release-after-ms = <1000>;
diff --git a/app/dts/behaviors/to_layer.dtsi b/app/dts/behaviors/to_layer.dtsi
index 3c740209..532636a6 100644
--- a/app/dts/behaviors/to_layer.dtsi
+++ b/app/dts/behaviors/to_layer.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ to: to_layer {
+#if ZMK_BEHAVIOR_OMIT(TO)
+        /omit-if-no-ref/
+#endif
+        to: to_layer {
             compatible = "zmk,behavior-to-layer";
             #binding-cells = <1>;
             display-name = "To Layer";
diff --git a/app/dts/behaviors/toggle_layer.dtsi b/app/dts/behaviors/toggle_layer.dtsi
index ea9b25b7..81846e77 100644
--- a/app/dts/behaviors/toggle_layer.dtsi
+++ b/app/dts/behaviors/toggle_layer.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ tog: toggle_layer {
+#if ZMK_BEHAVIOR_OMIT(TOG)
+        /omit-if-no-ref/
+#endif
+        tog: toggle_layer {
             compatible = "zmk,behavior-toggle-layer";
             #binding-cells = <1>;
             display-name = "Toggle Layer";
diff --git a/app/dts/behaviors/transparent.dtsi b/app/dts/behaviors/transparent.dtsi
index 03ec36a6..09d29a4a 100644
--- a/app/dts/behaviors/transparent.dtsi
+++ b/app/dts/behaviors/transparent.dtsi
@@ -4,9 +4,14 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <dt-bindings/zmk/behaviors.h>
+
 / {
     behaviors {
-        /omit-if-no-ref/ trans: transparent {
+#if ZMK_BEHAVIOR_OMIT(TRANS)
+        /omit-if-no-ref/
+#endif
+        trans: transparent {
             compatible = "zmk,behavior-transparent";
             #binding-cells = <0>;
             display-name = "Transparent";
diff --git a/app/include/dt-bindings/zmk/behaviors.h b/app/include/dt-bindings/zmk/behaviors.h
new file mode 100644
index 00000000..abfb91f4
--- /dev/null
+++ b/app/include/dt-bindings/zmk/behaviors.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2024 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define ZMK_BEHAVIOR_OMIT(_name)                                                                   \
+    !(defined(ZMK_BEHAVIORS_KEEP_##_name) ||                                                       \
+      (defined(ZMK_BEHAVIORS_KEEP_ALL) && !defined(ZMK_BEHAVIORS_OMIT_##_name)))
\ No newline at end of file
diff --git a/app/snippets/studio-rpc-usb-uart/snippet.yml b/app/snippets/studio-rpc-usb-uart/snippet.yml
index e0e334de..ea5a17b2 100644
--- a/app/snippets/studio-rpc-usb-uart/snippet.yml
+++ b/app/snippets/studio-rpc-usb-uart/snippet.yml
@@ -3,5 +3,6 @@
 
 name: studio-rpc-usb-uart
 append:
+  DTS_EXTRA_CPPFLAGS: -DZMK_BEHAVIORS_KEEP_ALL
   EXTRA_DTC_OVERLAY_FILE: studio-rpc-usb-uart.overlay
   EXTRA_CONF_FILE: studio-rpc-usb-uart.conf