Skip to content

Instantly share code, notes, and snippets.

@4z3
Created March 24, 2021 00:12
Show Gist options
  • Save 4z3/e477cfbedb05b560940d26fbd80b01ab to your computer and use it in GitHub Desktop.
Save 4z3/e477cfbedb05b560940d26fbd80b01ab to your computer and use it in GitHub Desktop.
elm-format-wrapper that allows to ignore blocks of code
{ pkgs }:
pkgs.symlinkJoin {
name = "elm-format-wrapper";
paths = [
(pkgs.writers.writeDashBin "elm-format" ''
# elm-format-wrapper 1.0.0
#
# Usage:
# elm-format [--help] [--action=ACTION] PATH...
#
# Description:
# Format paths like elm-format, but allow ignoring blocks of code:
#
# --elm-format-ignore-begin
# don't format code here...
# --elm-format-ignore-end
#
# Available options:
# --action=format (this is the default action)
# reformat each file
#
# --action=diff
# show patch that would be applied if action would be "format"
# instead of formating the files.
#
# -h, --help
# show this help :)
#
# --output=PATH
# --output PATH
# write formatted file to PATH.
# If multiple files are formatted, then the last one will end up in
# the output path. This option is mainly for compatibility with
# elm-format.
#
# --yes
# ignored; this option is for compatibility with elm-format
#
set -efu
help() {
${pkgs.gnused}/bin/sed -rn '
0,/^$/{
/#!/d
s/^# ?//p
}
' "$0"
}
action=format
output=
for arg; do
shift
case $arg in
--action=*)
action=''${arg#*=}
case $action in
diff) continue;;
format) continue;;
esac
echo "error: bad action: $action" >&2
exit 1
;;
--output)
output=$1
shift
continue
;;
--output=*)
output=''${arg#*=}
continue
;;
--yes)
continue
;;
-h|--help)
help
exit
;;
-*)
echo "error: bad argument: $arg" >&2
help >&2
exit 1
esac
set -- "$@" "$arg"
done
action_format() {(
old=$1
new=$2
if test -n "$output"; then
${pkgs.coreutils}/bin/cp "$new" "$output"
else
${pkgs.coreutils}/bin/cp "$new" "$old"
fi
)}
action_diff() {(
old=$1
new=$2
${pkgs.diffutils}/bin/diff -u --color "$old" "$new"
if test -n "$output"; then
${pkgs.coreutils}/bin/cp "$new" "$output"
fi
)}
temp=$(${pkgs.coreutils}/bin/mktemp -t elm-format-wrapper.XXXXXXXX)
clean() {
${pkgs.coreutils}/bin/rm "$temp"
}
trap clean EXIT
${pkgs.coreutils}/bin/yes n |
${pkgs.elmPackages.elm-format}/bin/elm-format "$@" |
${pkgs.gnused}/bin/sed -rn '
/^This will overwrite the following files to use Elm.s preferred style:$/,/^This cannot be undone!/{
s/^\s*(\S+)$/\1/p
}
' |
while IFS= read -r path; do
${pkgs.coreutils}/bin/cat "$path" |
${pkgs.gnused}/bin/sed -r '
/^--elm-format-ignore-begin$/,/^--elm-format-ignore-end$/{
s/^/--@/
}
' |
${pkgs.elmPackages.elm-format}/bin/elm-format --stdin > "$temp"
${pkgs.gnused}/bin/sed -ir '
/^--@--elm-format-ignore-begin$/,/^--@--elm-format-ignore-end$/{
s/^--@//
}
' "$temp"
action_"$action" "$path" "$temp"
done
'')
];
}
@4z3
Copy link
Author

4z3 commented Mar 24, 2021

The above Nix package can be used to create a shell providing a wrapped elm-format, e.g. like so:

$ nix-shell -p '
  (import <nixpkgs> {}).callPackage (builtins.fetchurl {
    url = https://gist.githubusercontent.com/4z3/e477cfbedb05b560940d26fbd80b01ab/raw/53e79fdabcd956cb797b7671959cf65b6e6d44c1/elm-format-wrapper.nix;
 }) {}
'

(Only tested with nixpkgs 20.09, so YMMV)

@Janiczek
Copy link

wrapper by itself:

#!/usr/bin/env bash

# elm-format-wrapper 1.0.0
#
# Usage:
#   elm-format-wrapper [--help] [--action=ACTION] PATH...
#
# Description:
#   Format paths like elm-format, but allow ignoring blocks of code:
#
#     --elm-format-ignore-begin
#     don't format code here...
#     --elm-format-ignore-end
#
# Available options:
#   --action=format (this is the default action)
#       reformat each file
#
#   --action=diff
#       show patch that would be applied if action would be "format"
#       instead of formating the files.
#
#   -h, --help
#       show this help :)
#
#   --output=PATH
#   --output PATH
#       write formatted file to PATH.
#       If multiple files are formatted, then the last one will end up in
#       the output path.  This option is mainly for compatibility with
#       elm-format.
#
#   --yes
#       ignored; this option is for compatibility with elm-format
#     
set -efu
help() {
  gsed -rn '
    0,/^$/{
      /#!/d
      s/^# ?//p
    }
  ' "$0"
}
action=format
output=
for arg; do
  shift
  case $arg in
    --action=*)
      action=''${arg#*=}
      case $action in
        diff) continue;;
        format) continue;;
      esac
      echo "error: bad action: $action" >&2
      exit 1
      ;;
    --output)
      output=$1
      shift
      continue
      ;;
    --output=*)
      output=''${arg#*=}
      continue
      ;;
    --yes)
      continue
      ;;
    -h|--help)
      help
      exit
      ;;
    -*)
      echo "error: bad argument: $arg" >&2
      help >&2
      exit 1
  esac
  set -- "$@" "$arg"
done
action_format() {(
  old=$1
  new=$2
  if test -n "$output"; then
    cp "$new" "$output"
  else
    cp "$new" "$old"
  fi
)}
action_diff() {(
  old=$1
  new=$2
  diff -u --color "$old" "$new"
  if test -n "$output"; then
    cp "$new" "$output"
  fi
)}
temp=$(mktemp -t elm-format-wrapper.XXXXXXXX)
clean() {
  rm "$temp"
}
trap clean EXIT
yes n |
elm-format "$@" |
gsed -rn '
  /^This will overwrite the following files to use Elm.s preferred style:$/,/^This cannot be undone!/{
    s/^\s*(\S+)$/\1/p
  }
' |
while IFS= read -r path; do
  cat "$path" |
  gsed -r '
    /^--elm-format-ignore-begin$/,/^--elm-format-ignore-end$/{
      s/^/--@/
    }
  ' |
  elm-format --stdin > "$temp"
  gsed -ir '
    /^--@--elm-format-ignore-begin$/,/^--@--elm-format-ignore-end$/{
      s/^--@//
    }
  ' "$temp"
  action_"$action" "$path" "$temp"
done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment