bash-my-aws / bash-my-aws

Bash-my-AWS provides simple but powerful CLI commands for managing AWS resources

Home Page:https://bash-my-aws.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tool to format awscli commands

mbailey opened this issue · comments

I edit with vim. Life would be easier with a command to format an AWSCLI to fit the standard pattern that has evolved for this project.

aws s3api copy-object                                        \
  --copy-source "${example/release-$BUILD_NUMBER/index.html" \
  --bucket "${DEPLOYMENT_BUCKET}"                            \                  
  --key "search/"                                            \
  --content-type text/html                                   \
  --cache-control public,max-age=60,s-maxage=60              \
  --metadata-directive REPLACE

Lint-my-Bash-my-AWS

This would be a nice tool to check out. If it works as expected, it could be used as a pre-commit hook so new contributions would be formatted correctly.

https://github.com/mvdan/sh

This would be a nice tool to check out. If it works as expected, it could be used as a pre-commit hook so new contributions would be formatted correctly.

https://github.com/mvdan/sh

I would be curious to see the output of the formatter on this codebase...

For a chuckle, here's an imperfect bashy solution:

# Load up an example variable
str='aws s3api copy-object --copy-source "${example}/release-$BUILD_NUMBER/index.html" --bucket "${DEPLOYMENT_BUCKET}" --key "search/" --content-type text/html --cache-control public,max-age=60,s-maxage=60 --metadata-directive REPLACE'

# Search for a leading space and a dash, to capture ` -a` and `--arg` style options
# Replace with a newline and two space indentation, slurp each line into an array
mapfile -t < <(sed 's/ -/\n  -/g' <<< "$str")

# Get the length of the longest line
right_bound=$(for element in "${MAPFILE[@]}"; do printf -- '%d\n' "${#element}"; done | sort -n | tail -n 1)

# Pad it
right_bound=$(( right_bound + 2 ))

# Behold, the mighty printf!
for element in "${MAPFILE[@]}"; do printf -- '%s%*s%s\n' "${element}" $(( right_bound - "${#element}" )) '\'; done
aws s3api copy-object                                         \
  --copy-source "${example}/release-$BUILD_NUMBER/index.html" \
  --bucket "${DEPLOYMENT_BUCKET}"                             \
  --key "search/"                                             \
  --content-type text/html                                    \
  --cache-control public,max-age=60,s-maxage=60               \
  --metadata-directive REPLACE                                \

To get that last line to behave might require something a little more involved e.g.

for (( i=0; i<"${#MAPFILE[@]}"; i++ )); do
  if (( i == ("${#MAPFILE[@]}" - 1) )); then
    printf -- '%s\n' "${MAPFILE[i]}"
  else
    printf -- '%s%*s%s\n' "${MAPFILE[i]}" $(( right_bound - "${#MAPFILE[i]}" )) '\'
  fi    
done

Result:

aws s3api copy-object                                         \
  --copy-source "${example}/release-$BUILD_NUMBER/index.html" \
  --bucket "${DEPLOYMENT_BUCKET}"                             \
  --key "search/"                                             \
  --content-type text/html                                    \
  --cache-control public,max-age=60,s-maxage=60               \
  --metadata-directive REPLACE

If we throw all of that into a function:

code_block() {
  # Search for a leading space and a dash, to capture ` -a` and `--arg` style options
  # Replace with a newline and two space indentation, slurp each line into an array
  mapfile -t < <(sed 's/ -/\n  -/g' <<< "${*}")

  # Get the length of the longest line
  right_bound=$(for element in "${MAPFILE[@]}"; do printf -- '%d\n' "${#element}"; done | sort -n | tail -n 1)

  # Pad it
  right_bound=$(( right_bound + 2 ))

  # Generate our output
  for (( i=0; i<"${#MAPFILE[@]}"; i++ )); do
    if (( i == ("${#MAPFILE[@]}" - 1) )); then
      printf -- '%s\n' "${MAPFILE[i]}"
    else
      printf -- '%s%*s%s\n' "${MAPFILE[i]}" $(( right_bound - "${#MAPFILE[i]}" )) '\'
    fi    
  done
}

We get behaviour like this:

$ code_block 'aws s3api copy-object --copy-source "${example}/release-$BUILD_NUMBER/index.html" --bucket "${DEPLOYMENT_BUCKET}" --key "search/" --content-type text/html --cache-control public,max-age=60,s-maxage=60 --metadata-directive REPLACE'
aws s3api copy-object                                         \
  --copy-source "${example}/release-$BUILD_NUMBER/index.html" \
  --bucket "${DEPLOYMENT_BUCKET}"                             \
  --key "search/"                                             \
  --content-type text/html                                    \
  --cache-control public,max-age=60,s-maxage=60               \
  --metadata-directive REPLACE

$ code_block 'ssh -t -i "${BMA_SSH_DIR:-~/.ssh}/${keyname}" -o LogLevel=error -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -l "${ssh_user}" "${private_ip}"'
ssh                                      \
  -t                                     \
  -i "${BMA_SSH_DIR:-~/.ssh}/${keyname}" \
  -o LogLevel=error                      \
  -o StrictHostKeyChecking=no            \
  -o UserKnownHostsFile=/dev/null        \
  -l "${ssh_user}" "${private_ip}"

Noting the single quotes to keep it all literal.