Po niekoľkých hodinách strávených snahou prinútiť zreťazené metódy v PHP zoradiť sa pekne pod seba, som napokon našiel riešenie. Inými slovami, pri uložení súboru som chcel prejsť z tohto:

$this->user->account->organizations()->saveMany(Organization::factory(5)
->make())->first()->update(['name' => 'A Big Brand Name']);

Na niečo, čo vyzerá takto:

$this->user->account
    ->organizations()
    ->saveMany(Organization::factory(5)->make())
    ->first()
    ->update(['name' => 'A Big Brand Name']);

Druhá verzia je jednoznačne čitateľnejšia, a teda trvá kratšie pochopiť, čo kód robí.

Čo mi nefungovalo #

Tu je niekoľko rôznych, možno nesúvisiacich metód na riešenie tohto problému, ktoré mi nefungovali, v náhodnom poradí.

coc-prettier #

Vo svojom aktuálnom nastavení neovim používam coc-prettier, najmä pre jeho jednoduchosť pri práci s Markdownom (prose-wrap, že?) a JavaScriptom. PHP však prettier nepodporuje natívne a je dostupný ako komunitný plugin prettier/plugin-php.

Momentálne to vyzerá tak, že tieto dva spolu nevychádzajú. Odpoveď je celkom čerstvá a určite existuje potenciál pre prettier pluginy v rámci coc-prettier, no žiaľ, viac som na túto tému nenašiel.

Intelephense v coc-phpls s coc-prettier #

Spolu s coc-prettier dokáže coc-phpls tiež formátovať PHP pri uložení, a to pomocou týchto dvoch relevantných nastavení v :CocConfig:

"intelephense.format.enable": true,
"coc.preferences.formatOnSaveFiletypes": ["php"]

Žiaľ, v čase písania je jedinou konfiguračnou možnosťou formátovača intelephense.format.braces. Toto nastavenie nemá žiadny vplyv na zarovnávanie zreťazených PHP metód. Navyše sa akosi dostáva do konfliktu s tabWidth z prettiera, ak sa napevno zakódovaná hodnota Intelephense líši. Nakoniec som obe vyššie uvedené nastavenia odstranil/vypol.

vim-phpfmt #

S pluginom vim-phpfmt som mal čo sa týka zarovnávania zreťazených metód v PHP absolútnu smolu. Čakalo sa to, keďže plugin nebol aktualizovaný viac ako 5 rokov.

Využíva phpcbf, čiže PHP Code Beautifier and Fixer z balíka PHP CodeSniffer, ktorý je aktívne vyvíjaný. Verím, že tento prístup by mohol fungovať, no nie som si istý, ako dlho by trvalo, kým by to celé nachodilo.

inotifywait skript #

V jednom momente som skúšal využiť skript na sledovanie testov tak, že som na zmenený súbor spustil globálne nainštalovaný prettier, keďže som ho mal aj tak spustený:

#!/bin/bash
while true; do
  FILE=$(inotifywait --recursive \
    --exclude=".*.*sw*" --exclude="4913" \
    ./watch_this_folder --format "%w%f" -e close_write)
  && clear
  && prettier --parser=php -w "$FILE"
done

Mal som však s týmto prístupom množstvo problémov - od oneskorených testov, cez to, že vim neprekreslil reformatovaný súbor, až po náhodné formátovanie súborov alebo aj celých priečinkov, takže som touto cestou nešiel ďalej.

Čo funguje #

Našiel som dve riešenia, ktoré pre zarovnávanie zreťazených metód v PHP fungujú rozumne dobre. Obe sa opierajú o prettier.

prettier/plugin-php vimscript #

Upravený vimscript, o ktorom som písal včera fungoval a myslel som si, že pri ňom zostanem. Choďte sa pozrieť tam na viac podrobností o tomto prístupe.

vim-prettier #

S komplikovaným riešením uvedeným v #119 pre vim-prettier, ktoré je momentálne odkazované v dokumentácii, som nemal šťastie. Tiež mi prišlo čudné mať nainštalovaný ako vim plugin súčasne vim-prettier aj coc-prettier.

Keď som to však všetko dokumentoval, náhodou som objavil poklad v #263. Pokiaľ viem, riešenie vyžaduje len pár krokov. Nainštalujte plugin-php ako závislosť projektu:

npm install -D @prettier/plugin-php

Potom upravte súbor vimrc:

call plug#begin('~/.vim/plugged')
  Plug 'prettier/vim-prettier', { 'do': 'npm install', 'for': ['php'] }
call plug#end()

autocmd BufWritePre *.php PrettierAsync

Spustite :PlugInstall a môžete ísť. Ako vidíme, vim-prettier je povolený len pre PHP súbory, ostatné rieši coc-prettier v mojom nastavení. Keď som videl, že tieto dva naozaj fungujú vedľa seba bez problémov, bol som s týmto nastavením spokojnejší a moja neochota ustúpila.

Na tomto nastavení sa mi naozaj páči jeho jednoduchosť a tiež to, že rešpektuje projektový súbor .prettierrc, presne podľa môjho vkusu, napríklad:

{
  "tabWidth": 4,
  "semi": false,
  "singleQuote": true,
  "trailingComma": "es5",
  "trailingCommaPHP": true,
  "proseWrap": "always",
  "arrowParens": "avoid",
  "bracketSpacing": true,
  "phpVersion": "8.0",
  "braceStyle": "1tbs"
}

Štandardné možnosti prettiera aj tie z konfigurácie plugin-php pekne na jednom mieste. Nevýhodou je, že ak chcete rôznu hodnotu tabWidth pre rôzne typy súborov v rámci projektu, týmto spôsobom to presne nejde. No tak by to trochu odporovalo filozofii prettiera, ktorý je zámerene jednoznačný a konzistentný.

Žeľ, že som toto riešenie nenašiel hneď na začiatku - no lepšie neskôr ako nikdy. Príjemné písanie!