Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stdout option for the tools that directly write to the file #26

Open
aminya opened this issue Mar 15, 2023 · 9 comments
Open

stdout option for the tools that directly write to the file #26

aminya opened this issue Mar 15, 2023 · 9 comments

Comments

@aminya
Copy link

aminya commented Mar 15, 2023

Some formatter tools like black from Python have no option for printing to the stdout. There should be an option so that those tools can directly write to the file without warnings.

@han-tyumi
Copy link

I'm also facing this with F#'s Fantomas.

@adaliszk
Copy link

adaliszk commented Sep 9, 2024

Similar with PHP's PHP-CS-Fixer

@RafaelKr
Copy link

RafaelKr commented Nov 21, 2024

In my Symfony project (PHP) I built a little wrapper script to overcome this limitation. It's not nice, but it works for now.

I created the file bin/dprint-stdout-wrapper.sh

#!/usr/bin/env bash

# Currently dprint doesn't provide a way to use commands which modify the
# file directly instead of printing the result to stdout
# see https://github.com/dprint/dprint-plugin-exec/issues/26
#
# Therefore we use this little wrapper script which we can call like this
# bin/dprint-stdout-wrapper.sh vendor/bin/php-cs-fixer fix {{file_path}}
#
# The last argument MUST BE the file path as it first calls the command and
# then uses cat to print that path to a file

# https://unix.stackexchange.com/a/612122
FILE_PATH="${!#}"  # see man bash, search for "indirect expansion"

# this "pops" the file path from the argument list which we use via $@
set -- "${@:1:$#-1}"

$@ $FILE_PATH >&2 && cat $FILE_PATH

Now I can use the following config in my dprint.json to run PHP-CS-Fixer and Twig-CS-Fixer:

{
    // ...
    "markup": {
        "associations": [
            "!**/*.twig"
        ]
    },
    "exec": {
        "cwd": "${configDir}",

        "commands": [
            {
                "command": "bin/dprint-stdout-wrapper.sh vendor/bin/php-cs-fixer fix {{file_path}}",
                "exts": ["php"]
            },
            {
                "command": "bin/dprint-stdout-wrapper.sh vendor/bin/twig-cs-fixer lint --report null --fix {{file_path}}",
                "exts": ["twig"]
            }
        ]
    },
    "excludes": [
        "**/node_modules",
        "**/*-lock.json",
        "assets/vendor/*",
        "assets/**/controllers.json",
        "composer.json",
        "public/assets/*",
        "package.json",
        "README.md"
    ],
    "plugins": [
        // ...
        "https://plugins.dprint.dev/exec-0.5.0.json@8d9972eee71fa1590e04873540421f3eda7674d0f1aae3d7c788615e7b7413d0"
    ]
}

Edit: added twig-cs-fixer command

Edit 2: >&2 was required to pipe stdout to stderr

@RafaelKr
Copy link

@adaliszk I just updated my comment. See "Edit 2"

@RafaelKr
Copy link

I just noticed one downside: When running dprint fmt the fix is still applied to the file.

So we also would need dprint-plugin-exec to provide us with the current mode, maybe via a command template {{mode}}.
Then in our script we can decide if we want to use fix or check (or --dry-run, etc)

@adaliszk
Copy link

adaliszk commented Nov 22, 2024

Yeah, I was thinking about making a wrapper like that, but the issue is that there would be two separate reads and writes for the same file.
At the moment, I am exploring the option of changing the PHP-CS-Fixer and, in extension, Laravel Pint to have a print mode instead.

Luckily, the stdin option is already there, so it's easy to argue for a stdout mode to let any external tool handle the filesystem.

@RafaelKr
Copy link

Yes, that's really not very elegant, just a workaround.
Also I now used a similar wrapper for Twig-CS-Fixer and then running prettier with the Plugin for Tailwind automatic class sorting on the file (https://github.com/ttskch/prettier-plugin-tailwindcss-anywhere)

After also adding https://daisyui.com/ it was writing log output from daisyUI to my twig files. I now set an env var in my script which disables logging from the tailwind.config.js – also not very nice.

@RafaelKr
Copy link

RafaelKr commented Nov 25, 2024

Okay, my colleague had issues in VS Code because the command wrote to the file multiple times. I now updated my wrapper script to use a temporary file instead.

bin/dprint-stdout-wrapper.sh

#!/usr/bin/env bash

# Currently dprint doesn't provide a way to use commands which modify the
# file directly instead of printing the result to stdout
# see https://github.com/dprint/dprint-plugin-exec/issues/26
#
# Therefore we use this little wrapper script which we can call like this
# bin/dprint-stdout-wrapper.sh vendor/bin/php-cs-fixer fix
#
# dprint passes the input via stdin which we write to a temporary file.
# Then we apply the formatting to the temporary file and write the result
# to stdout. dprint then writes the output back to the input file.

TEMP_FILE=$(mktemp)

# read stdin to temporary file
cat - > $TEMP_FILE

function cleanup {
  rm "$TEMP_FILE"
}
# make sure the temporary file is removed on exit, even in error cases
trap cleanup EXIT

$@ $TEMP_FILE >&2 && cat $TEMP_FILE

To make it work for twig files in VS Code my workaround is even worse, but works now:

bin/fix-twig.sh

#!/usr/bin/env bash

# Currently dprint doesn't provide a way to use commands which modify the
# file directly instead of printing the result to stdout
# see https://github.com/dprint/dprint-plugin-exec/issues/26
#
# Therefore we use this little wrapper script which we can call like this
# bin/fix-twig.sh {{file_path}}
#
# dprint passes the input via stdin which we write to a temporary file.
# Then we apply the formatting to the temporary file and write the result
# to stdout. dprint then writes the output back to the input file.

# We use the file path for prettier to determine the correct parser
# https://prettier.io/docs/en/options.html#file-path
FILE_PATH="$1"

TEMP_FILE=$(mktemp)
# read stdin to temporary file
cat - > $TEMP_FILE

function cleanup {
    rm -f "$TEMP_FILE"
}
# make sure the temporary file is removed on exit, even in error cases
trap cleanup EXIT

CURRENT_SCRIPT_DIR_NAME=$(dirname "${BASH_SOURCE[0]}")

vendor/bin/twig-cs-fixer lint --report null --fix $TEMP_FILE

if [[ $FILE_PATH != *.html.twig ]]; then
  cat $TEMP_FILE
  exit
fi

cat $TEMP_FILE | \
  DISABLE_DAISY_LOGS=1 node_modules/.bin/prettier \
    --config "$CURRENT_SCRIPT_DIR_NAME/.prettierrc" \
    --stdin-filepath "$FILE_PATH"

The .prettierrc file is taken from https://github.com/ttskch/prettier-plugin-tailwindcss-anywhere?tab=readme-ov-file#usage

My dprint.json looks like:

{
    // ...
    "markup": {
        "associations": [
            "!**/*.twig"
        ]
    },
    "exec": {
        "cwd": "${configDir}",

        "commands": [
            {
                "command": "bin/dprint-stdout-wrapper.sh vendor/bin/php-cs-fixer fix",
                "exts": ["php"]
            },
            {
                "command": "bin/fix-twig.sh {{file_path}}",
                "exts": ["twig"]
            }
        ]
    },
    "excludes": [
        "**/node_modules",
        "**/*-lock.json",
        "assets/vendor/*",
        "assets/**/controllers.json",
        "composer.json",
        "public/assets/*",
        "package.json"
    ],
    "plugins": [
        // ...
        "https://plugins.dprint.dev/exec-0.5.0.json@8d9972eee71fa1590e04873540421f3eda7674d0f1aae3d7c788615e7b7413d0"
    ]
}

Edit: simplified bin/fix-twig.sh as ttskch/prettier-plugin-tailwindcss-anywhere#2 got fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants