LoginSignup
1
1

More than 1 year has passed since last update.

[Looker] lkmlfmtでLookMLのフォーマットを統一する

Last updated at Posted at 2023-04-16

概要

開発中のlkmlfmtというフォーマッタがある程度使える段階になったので紹介する。GitHubのREADMEに書かなかった開発動機や実装方針の話も書き残しておく。

背景

Lookerのショートカット一覧を見るとCtrl+Shift+Fでファイルをフォーマットできると書いてあるが、それだけじゃあ足りないのだよ。sql: ;;html: ;;で埋め込まれたコードまでフォーマットする手段がほしい...しかもliquidテンプレートもいい感じに扱ってほしい...そんな動機で開発し始めたのがlkmlfmt。

実装方針

ゼロから自前で実装するのはしんどいので、可能な限り他力本願を貫く。

  • 大枠のLookMLのフォーマットだけ自前で実装する
    • といっても構文解析にはlarkを使ったりとなるべく楽をする
  • sql: ;;で埋め込まれたコードはsqlfmtでフォーマットする
    • jinjaまじりのsqlをフォーマットできるので、liquid ↔ jinjaの変換だけ手伝えばSQLのフォーマットを丸投げできる
  • html: ;;で埋め込まれたコードはDjHTMLでフォーマットする
    • jinjaまじりのhtmlをフォーマットできるので、liquid ↔ jinjaの変換だけ手伝えばHTMLのフォーマットを丸投げできる
    • djLintもよさそうだったが、今回の目的だとやや使いにくい1ので不採用
    • Prettierのplugin(prettier-plugin-liquid)を使えばliquidまじりのhtmlをフォーマットできそうだが、ここだけJavaScriptで実装するのも面倒なので不採用

DjHTMLに依存する機能はv0.0.7で本体から切り出してpluginとした2

使い方

local

Pythonに慣れた人には同じみのpipコマンドでインストールする。

pip install lkmlfmt

lkmlfmtというコマンドが利用可能になるので、引数として対象ファイル(複数あってもよいしディレクトリでもよい)を指定するだけ。

cat > ./temp.lkml << EOF
view: view_name {
derived_table: {
sql: with cte as (select column_name from tablename where ts between current_date()-7 and current_date()) select column_name from cte ;;
}
dimension: column_name {
html:
{% if value == "foo" %}
<img src="https://example.com/foo"/>
{% else %}
<img src="https://example.com/bar"/>
{% endif %} ;;
}}
EOF

lkmlfmt ./temp.lkml

cat ./temp.lkml
# view: view_name {
#   derived_table: {
#     sql:
#       with
#         cte as (
#           select column_name
#           from tablename
#           where ts between current_date() - 7 and current_date()
#         )
#       select column_name
#       from cte
#     ;;
#   }
#   dimension: column_name {
#     html:
#       {% if value == "foo" %}
#         <img src="https://example.com/foo"/>
#       {% else %}
#         <img src="https://example.com/bar"/>
#       {% endif %}
#     ;;
#   }
# }

フォーマッタあるあるだけれど、--checkオプションを付けるとフォーマット済みかどうかの確認だけ行う。そのほか細かいオプションはlkmlfmt --helpで確認できる。

GitHub Actions

LookMLをlocalで書くことは少ないだろうから、GitHubActionsで動くようにしておくと多分便利。Pull Requstがフォーマット済みか確認するならこんな感じ。

.github/workflows/fmt-check.yaml
on: [pull_request]
jobs:
  format-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11' # '>=3.11' is required
      - run: pip install lkmlfmt
      - run: lkmlfmt --check path/to/lookml/file/or/directory

特定のbranchに対してシュッとフォーマットのPull Requestを出すならこんな感じ。事前にSettings > Actions > GeneralからPull Requestの作成を許可する必要がある。
image.png

.github/workflows/fmt-pr.yaml
on: [workflow_dispatch]
jobs:
  format-pr:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11' # '>=3.11' is required
      - run: pip install lkmlfmt
      - run: lkmlfmt path/to/lookml/file/or/directory
      - uses: peter-evans/create-pull-request@v5
        with:
          branch: format/${{ github.ref_name }}

もっとちゃんと運用するなら、依存packageを含めてversionを固定したり、installしたpackageをcacheしたりしておきたい。その場合requirements.txtをproject直下においてsetup-pythonの部分を以下のようにするとよいはず3

      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'
          cache: 'pip' # 追記

今後

以下はまだできていないのでやっていく。

  • liquidテンプレートの内側({%%}とかで囲まれた部分)はまだフォーマットできない4のでやっていく
  • docstringをちゃんと書いたり、Pull Requestを受け付ける準備をする

バグも随時直すので、もし見つけたらこの記事のコメント欄やGitHubのIssueで報告してもらえるとありがたいです。

  1. 文字列として与えたhtmlをフォーマットするAPIがあれば文句なしだったが、htmlはファイルで与える実装方針に見えた。

  2. 本体のLICENSEを使いやすく保つため。

  3. pipenvやpoetryを使いたい人はactions/setup-pythonREADMEを見るべし。

  4. 現状だと、どんなに余分な空白があったりしてもそのまま放置する。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1