Print more readable usage information for boot script

#!/bin/sh

set -e

# Set VERBOSE to enable verbose logging of the boot script
#VERBOSE=true
if [ ! -z $DEBUG_BOOT ]; then
    set -x
fi;

my_readlink_f() {
    TARGET_FILE="$1"
    cd $(dirname "$TARGET_FILE")
    TARGET_FILE=$(basename "$TARGET_FILE")

    # Iterate down a (possible) chain of symlinks
    while [ -L "$TARGET_FILE" ]
    do
        TARGET_FILE=$(readlink "$TARGET_FILE")
        cd $(dirname "$TARGET_FILE")
        TARGET_FILE=$(basename "$TARGET_FILE")
    done
    # Compute the canonicalized name by finding the physical path
    # for the directory we're in and appending the target file.
    PHYS_DIR=$(pwd -P)
    RESULT="$PHYS_DIR/$TARGET_FILE"
    echo "$RESULT"
}

# Path to this script
if uname | grep -q 'Darwin'; then
  # on OSX, best to install coreutils from homebrew or similar
  # to get greadlink
  if command -v greadlink >/dev/null 2>&1; then
    SCRIPT="${SCRIPT:-$(greadlink -f "$0")}"
  else
    SCRIPT="${SCRIPT:-$(my_readlink_f "$0")}"
  fi
else
  SCRIPT="${SCRIPT:-$(readlink -f "$0" )}"
fi

# Parent directory of this script
SCRIPT_DIR="${SCRIPT_DIR:-$(dirname "${SCRIPT}")}"
# Root directory of all releases
RELEASE_ROOT_DIR="${RELEASE_ROOT_DIR:-$(dirname $(dirname ${SCRIPT_DIR}))}"

# Disable flow control for run_erl
# Flow control can cause several problems. On Linux, if you
# accidentally hit Ctrl-S (instead of Ctrl-D to detach) and
# then some other key, the entire beam process will hang when
# attempting to write to stdout. On Solaris, the beam process
# will hang on writing if ScrollLock is on.
RUN_ERL_DISABLE_FLOWCNTRL="${RUN_ERL_DISABLE_FLOWCNTRL:-true}"
# Name of the release
REL_NAME="${REL_NAME:-<%= release_name %>}"
# Current version of the release
REL_VSN="${REL_VSN:-<%= release_version %>}"
# Current version of ERTS being used
# If this is not present/unset, it will be detected
<%= if ((is_binary(include_erts) or include_erts) and not is_nil(erts_vsn)) do %>ERTS_VSN="${ERTS_VSN:-<%= erts_vsn %>}"<% end %>
# VM code loading mode, embedded by default, can also be interactive
# See http://erlang.org/doc/man/code.html
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
# Path to start_erl.data
START_ERL_DATA="${START_ERL_DATA:-$RELEASE_ROOT_DIR/releases/start_erl.data}"
# Directory containing the current version of this release
REL_DIR="${REL_DIR:-$RELEASE_ROOT_DIR/releases/$REL_VSN}"
# The lib directory for this release
REL_LIB_DIR="${REL_LIB_DIR:-$RELEASE_ROOT_DIR/lib}"
# Options passed to erl
ERL_OPTS="${ERL_OPTS:-<%= release.profile.erl_opts %>}"
# When stdout is piped to a file, this is the directory those files will
# be stored in. defaults to /log in the release root directory

# RELEASE_MUTABLE_DIR
RELEASE_MUTABLE_DIR="${RELEASE_MUTABLE_DIR:-$RELEASE_ROOT_DIR/var}"

RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_MUTABLE_DIR/log}"
# A string of extra options to pass to erl, here for plugins
EXTRA_OPTS="${EXTRA_OPTS:-}"

# Pre-start/stop event hook paths
PRE_START_HOOKS="$REL_DIR/hooks/pre_start.d"
POST_START_HOOKS="$REL_DIR/hooks/post_start.d"
PRE_STOP_HOOKS="$REL_DIR/hooks/pre_stop.d"
POST_STOP_HOOKS="$REL_DIR/hooks/post_stop.d"
PRE_UPGRADE_HOOKS="$REL_DIR/hooks/pre_upgrade.d"
POST_UPGRADE_HOOKS="$REL_DIR/hooks/post_upgrade.d"

# Get node pid
get_pid() {
    if output="$(nodetool rpcterms os getpid)"
    then
        echo "$output" | sed -e 's/"//g'
        return 0
    else
        echo "$output"
        return 1
    fi
}

# Generate a unique nodename
gen_nodename() {
    id="longname$(gen_id)-${NAME}"
    "$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
}

# Generate a random id
gen_id() {
    od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}

# Control a node
# Use like `nodetool "ping"`
nodetool() {
    command="$1"; shift
    name=${PEERNAME:-$NAME}
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$name" \
                            -setcookie "$COOKIE" "$command" $@
}

# Run an escript in the node's environment
# Use like `escript "path/to/escript"`
escript() {
    shift; scriptpath="$1"; shift
    export RELEASE_ROOT_DIR

    "$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" $@
}

# Private. Load target cookie, either from vm.args or $HOME/.cookie
_load_cookie() {
    COOKIE_ARG="$(grep '^-setcookie' "$VMARGS_PATH" || true)"
    DEFAULT_COOKIE_FILE="$HOME/.erlang.cookie"
    if [ -z "$COOKIE_ARG" ]; then
        if [ -f "$DEFAULT_COOKIE_FILE" ]; then
            COOKIE="$(cat "$DEFAULT_COOKIE_FILE")"
        fi
    else
        # Extract cookie name from COOKIE_ARG
        COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
    fi
}

# Private. Ensure that cookie is set.
_check_cookie() {
    # Attempt reloading cookie in case it has been set in a hook
    if [ -z "$COOKIE" ]; then
        _load_cookie
    fi
    # Die if cookie is still not set, as connecting via distribution will fail
    if [ -z "$COOKIE" ]; then
        printf "a secret cookie must be provided in one of the following ways:\n  - with vm.args using the -setcookie parameter,\n  or\n  by writing the cookie to '$DEFAULT_COOKIE_FILE', with permissions set to 0400"
        exit 1
    fi
}

# Private. For determining the version of ERTS available to the release
# This is only ever called if ERTS_VSN is not set
_detect_erts_vsn() {
    set +e # temporarily disable so we can display a nice error message to the user
    __erl="$(which erl)"
    set -e
    if [ -z "${__erl}"  ]; then
        echo 'erlang runtime not found. If erlang is installed check your $PATH. aborting.'
        exit 1
    fi
    "$__erl" -boot start_clean -eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver]), halt()' -noshell
}

# Private. Gets a list of code paths for this release
_get_code_paths() {
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/release_utils.escript" "get_code_paths" "$ROOTDIR" "$ERTS_DIR" "$REL_NAME" "$REL_VSN"
}

# Private. For setting ERTS_DIR and ROOTDIR
_find_erts_dir() {
    __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
    if [ -d "$__erts_dir" ]; then
        ERTS_DIR="$__erts_dir";
        ROOTDIR="$RELEASE_ROOT_DIR"
    else
        set +e # temporarily disable so we can display a nice error message to the user
        __erl="$(which erl)"
        set -e
        if [ -z "${__erl}"  ]; then
          echo 'erlang runtime not found. If erlang is installed check your $PATH. aborting.'
          exit 1
        fi
        code="io:format(\"~s\", [code:root_dir()]), halt()."
        __erl_root="$("$__erl" -noshell -eval "$code")"
        ERTS_DIR="$__erl_root/erts-$ERTS_VSN"
        ROOTDIR="$__erl_root"
    fi
}

# Private. Open a shell on a remote node
_rem_sh() {
    # Generate a unique id used to allow multiple remsh to the same node
    # transparently
    id="remsh$(gen_id)-${NAME}"

    # Get the node's ticktime so that we use the same thing.
    TICKTIME="$(nodetool rpcterms net_kernel get_net_ticktime)"

    # Setup remote shell command to control node
    if [ ! -z "$USE_ERL_SHELL" ]; then
        exec "$BINDIR/erl" \
            -hidden \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            "$NAME_TYPE" "$id" -remsh "$NAME" -setcookie "$COOKIE"
    else
        __code_paths=$(_get_code_paths)
        exec "$BINDIR/erl" \
            -pa "$CONSOLIDATED_DIR" \
            ${__code_paths} \
            -hidden -noshell \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            -user Elixir.IEx.CLI "$NAME_TYPE" "$id" -setcookie "$COOKIE" \
            -extra --no-halt +iex -"$NAME_TYPE" "$id" --cookie "$COOKIE" --remsh "$NAME"
    fi
}

# Output a start command for the last argument of run_erl
_start_command() {
    printf "exec \"%s\" \"%s\" -- %s %s" "$RELEASE_ROOT_DIR/bin/$REL_NAME" \
           "$START_OPTION" "${ARGS}" "${EXTRA_OPTS}"
}

# Do a textual replacement of ${VAR} occurrences in $1 and pipe to $2
_replace_os_vars() {
    awk '
        function escape(s) {
            gsub(/'\&'/, "\\\\&", s);
            return s;
        }
        {
            while(match($0,"[$]{[^}]*}")) {
                var=substr($0,RSTART+2,RLENGTH-3);
                gsub("[$]{"var"}", escape(ENVIRON[var]))
            }
        }1' < "$1" > "$1.bak"
    mv -- "$1.bak" "$1"
}

# Private. Run hooks from directory.
_run_hooks_from_dir() {
   if [ -d "$1" ]; then
      for file in $1/[0-9a-zA-Z]*.sh; do
        [ -f "$file" ] || continue
        . "$file"
      done
   fi
}

# If TERM is not set, set it to xterm
if [ -z "$TERM" ]; then
    export TERM=xterm
fi

# If ERTS_VSN is not set, detect it
if [ -z "$ERTS_VSN" ]; then
    export ERTS_VSN="$(_detect_erts_vsn)"
    echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"
fi

# Allow override of where to read configuration from
# By default it's RELEASE_ROOT_DIR
if [ -z "$RELEASE_CONFIG_DIR" ]; then
    export RELEASE_CONFIG_DIR="$RELEASE_ROOT_DIR"
fi

# Make sure directories exist
mkdir -p "$RELEASE_MUTABLE_DIR"
echo "Files in this directory are regenerated frequently, edits will be lost" \
    > "$RELEASE_MUTABLE_DIR/WARNING_README"
mkdir -p "$RUNNER_LOG_DIR"

# Set VMARGS_PATH, the path to the vm.args file to use
# Use $RELEASE_CONFIG_DIR/vm.args if exists, otherwise releases/VSN/vm.args
if [ -z "$VMARGS_PATH" ]; then
    if [ -f "$RELEASE_CONFIG_DIR/vm.args" ]; then
        export VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
    else
        export VMARGS_PATH="$REL_DIR/vm.args"
    fi
fi
if [ "$VMARGS_PATH" != "$RELEASE_MUTABLE_DIR/vm.args" ]; then
    echo "#### Generated - edit/create $RELEASE_CONFIG_DIR/vm.args instead." \
        >  "$RELEASE_MUTABLE_DIR/vm.args"
    cat  "$VMARGS_PATH"                              \
        >> "$RELEASE_MUTABLE_DIR/vm.args"
    export VMARGS_PATH=$RELEASE_MUTABLE_DIR/vm.args
fi
if [ $REPLACE_OS_VARS ]; then
    _replace_os_vars "$VMARGS_PATH"
fi

# Set SYS_CONFIG_PATH, the path to the sys.config file to use
# Use $RELEASE_CONFIG_DIR/sys.config if exists, otherwise releases/VSN/sys.config
if [ -z "$SYS_CONFIG_PATH" ]; then
    if [ -f "$RELEASE_CONFIG_DIR/sys.config" ]; then
        export SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
    else
        export SYS_CONFIG_PATH="$REL_DIR/sys.config"
    fi
fi
if [ "$SYS_CONFIG_PATH" != "$RELEASE_MUTABLE_DIR/sys.config" ]; then
    (echo "%% Generated - edit/create $RELEASE_CONFIG_DIR/sys.config instead."; \
    cat  "$SYS_CONFIG_PATH")                              \
        > "$RELEASE_MUTABLE_DIR/sys.config"
    export SYS_CONFIG_PATH=$RELEASE_MUTABLE_DIR/sys.config
fi
if [ $REPLACE_OS_VARS ]; then
    _replace_os_vars "$SYS_CONFIG_PATH"
fi

# Extract the target node name from node.args
# Should be `-sname somename` or `-name somename@somehost`
export NAME_ARG="$(egrep '^-s?name' "$VMARGS_PATH" || true)"
if [ -z "$NAME_ARG" ]; then
    echo "vm.args needs to have either -name or -sname parameter."
    exit 1
fi

# Extract the name type and name from the NAME_ARG for REMSH
# NAME_TYPE should be -name or -sname
export NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
# NAME will be either `somename` or `somename@somehost`
export NAME="$(echo "$NAME_ARG" | awk '{print $2}')"

# Where the pipe will be stored when using `start`
# This is used so you can attach the running application to the current
# shell using `attach`
PIPE_DIR="${PIPE_DIR:-$RELEASE_MUTABLE_DIR/erl_pipes/$NAME/}"

# Extract the target cookie
_load_cookie

_find_erts_dir
export ROOTDIR="$RELEASE_ROOT_DIR"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
ERTS_LIB_DIR="$ERTS_DIR/../lib"
CONSOLIDATED_DIR="$ROOTDIR/lib/${REL_NAME}-${REL_VSN}/consolidated"

cd "$ROOTDIR"

# User can specify an sname without @hostname
# This will fail when creating remote shell
# So here we check for @ and add @hostname if missing
case $NAME in
    *@*)
        # Nothing to do
        ;;
    *)
        NAME=$NAME@$(gen_nodename)
        ;;
esac

# For Elixir runtime
export DISTILLERY_TASK="$1"

# Check the first argument for instructions
case "$1" in
    start|start_boot)

        # Make sure there is not already a node running
        #RES=`$NODETOOL ping`
        #if [ "$RES" = "pong" ]; then
        #    echo "Node is already running!"
        #    exit 1
        #fi
        # Save this for later.
        CMD=$1
        case "$1" in
            start)
                shift
                START_OPTION="console"
                HEART_OPTION="start"
                ;;
            start_boot)
                shift
                START_OPTION="console_boot"
                HEART_OPTION="start_boot"
                ;;
        esac
        ARGS="$@"
        RUN_PARAM="$@"

        _check_cookie
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Set arguments for the heart command
        set -- "$SCRIPT_DIR/$REL_NAME" "$HEART_OPTION"
        [ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"

        # Export the HEART_COMMAND
        HEART_COMMAND="$RELEASE_ROOT_DIR/bin/$REL_NAME $CMD"
        export HEART_COMMAND

        mkdir -p "$PIPE_DIR"

        "$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
                          "$(_start_command)"

        _run_hooks_from_dir "$POST_START_HOOKS"
        ;;

    stop)
        _check_cookie
        _run_hooks_from_dir "$PRE_STOP_HOOKS"
        # Wait for the node to completely stop...
        PID="$(get_pid)"
        if ! nodetool "stop"; then
            exit 1
        fi
        while $(kill -s 0 "$PID" 2>/dev/null);
        do
            sleep 1
        done
        _run_hooks_from_dir "$POST_STOP_HOOKS"
        ;;

    restart)
        _check_cookie
        _run_hooks_from_dir "$PRE_START_HOOKS"
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        _check_cookie
        _run_hooks_from_dir "$PRE_START_HOOKS"
        ## Restart the VM completely (uses heart to restart it)
        if ! nodetool "reboot"; then
            exit 1
        fi
        ;;

    pid)
        ## Get the VM's pid
        _check_cookie
        if ! get_pid; then
            exit 1
        fi
        ;;

    ping)
        _check_cookie
        ## See if the VM is alive
        if ! nodetool "ping"; then
            exit 1
        fi
        ;;

    pingpeer)
        PEERNAME=$2 nodetool "ping"
        exit_status=$?
        if [ "$exit_status" -ne 0 ]; then
            exit $exit_status
        fi
        ;;

    escript)
        _check_cookie
        ## Run an escript under the node's environment
        if ! escript $@; then
            exit 1
        fi
        ;;

    attach)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        exec "$BINDIR/to_erl" "$PIPE_DIR"
        ;;

    remote_console)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        _rem_sh
        ;;

    upgrade|downgrade|install)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        SOURCE_VERSION="$REL_VSN"
        TARGET_VERSION="$2"

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        _run_hooks_from_dir "$PRE_UPGRADE_HOOKS"

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "install_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        _run_hooks_from_dir "$POST_UPGRADE_HOOKS"

        ;;
    unpack)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        exec "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    console|console_clean|console_boot)
        # .boot file typically just $REL_NAME (ie, the app name)
        # however, for debugging, sometimes start_clean.boot is useful.
        # For e.g. 'setup', one may even want to name another boot script.
        case "$1" in
            console)
                if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
                  BOOTFILE="$REL_DIR/$REL_NAME"
                else
                  BOOTFILE="$REL_DIR/start"
                fi
                ;;
            console_clean)
                BOOTFILE="$ROOTDIR/bin/start_clean"
                __code_paths=$(_get_code_paths)
                EXTRA_CODE_PATHS=${__code_paths}
                ;;
            console_boot)
                shift
                BOOTFILE="$1"
                shift
                ;;
        esac
        # Setup beam-required vars
        EMU="beam"
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        _check_cookie

        # Start the VM, executing pre_start hook along
        # the way. We can't run the post_start hook because
        # the console will crash with no TTY attached
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" \
            -boot "$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            ${EXTRA_CODE_PATHS} \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -user Elixir.IEx.CLI \
            -extra --no-halt +iex

        # Dump environment info for logging purposes
        if [ ! -z $VERBOSE ]; then
            echo "Exec: $@" -- ${1+$ARGS} ${EXTRA_OPTS}
            echo "Root: $ROOTDIR"

            # Log the startup
            echo "$RELEASE_ROOT_DIR"
        fi;

        logger -t "$REL_NAME[$$]" "Starting up"

        exec "$@" -- ${1+$ARGS} ${EXTRA_OPTS}
        ;;

    foreground)
        # start up the release in the foreground for use by runit
        # or other supervision services

        [ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
        FOREGROUNDOPTIONS="-noshell -noinput +Bd"

        # Setup beam-required vars
        EMU=beam
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        _check_cookie

        # Start the VM, executing pre and post start hooks
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
            -boot "$REL_DIR/$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -extra ${EXTRA_OPTS}

        # Dump environment info for logging purposes
        if [ ! -z $VERBOSE ]; then
            echo "Exec: $@" -- ${1+$ARGS}
            echo "Root: $ROOTDIR"
        fi;

        "$@" -- ${1+$ARGS} &
        __bg_pid=$!
        _run_hooks_from_dir "$POST_START_HOOKS"
        wait $__bg_pid
        ;;
    rpc)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpc $@
        ;;
    rpcterms)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpcterms $@
        ;;
    eval)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        nodetool "eval" $@
        ;;
    command)
        # Execute as command-line utility
        #
        # Like the escript command, this does not start the OTP application.
        # If your command depends on a running OTP application,
        # use
        #
        #     {:ok, _} = Application.ensure_all_started(:your_app)

        _check_cookie

        shift
        MODULE="$1"; shift
        FUNCTION="$1"; shift

        # Save extra arguments
        ARGS="$@"

        # Build arguments for erlexec
        __code_paths=$(_get_code_paths)
        set -- "$ERL_OPTS"
        [ "$SYS_CONFIG_PATH" ] && set -- "$@" -config "$SYS_CONFIG_PATH"
        set -- "$@" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR"
        set -- "$@" -noshell
        set -- "$@" -boot start_clean
        set -- "$@" -pa "$CONSOLIDATED_DIR"
        set -- "$@" ${__code_paths}
        set -- "$@" -s "$MODULE" "$FUNCTION"

        $BINDIR/erlexec $@ -extra $ARGS
        exit "$?"
        ;;
    describe)
        ## Print a summary of information about this release
        echo "$REL_NAME-$REL_VSN\n"
        echo "erts:       $ERTS_VSN"
        echo "path:       $REL_DIR"
        echo "sys.config: $SYS_CONFIG_PATH"
        echo "vm.args:    $VMARGS_PATH"
        echo "name:       $NAME"
        echo "cookie:     $COOKIE"
        echo "erl_opts:   ${ERL_OPTS:-none provided}"
        echo ""
        echo "hooks:"
        __has_hooks=0
        for hook in "$REL_DIR"/hooks/*.d/[0-9a-zA-Z]*.sh; do
            [ -f "$hook" ] || continue
            __has_hooks=1
            echo "$hook"
        done
        if [ $__has_hooks -eq 0 ]; then
            echo "No custom hooks found."
        fi
        echo ""
        echo "commands:"
        __has_commands=0
        for command in "$REL_DIR"/commands/*.sh; do
            [ -f "$command" ] || continue
            __has_commands=1
            echo "$command"
        done
        if [ $__has_commands -eq 0 ]; then
            echo "No custom commands found."
        fi
        exit 0
        ;;
    *)
        __command_path="$REL_DIR/commands/$1"
        if [ -f "$__command_path" ]; then
            _check_cookie
            . "$__command_path"
        else
            echo "Usage: $REL_NAME <task>"
            echo
            echo "Service Control"
            echo "======================="
            echo "start                          # start $REL_NAME as a daemon"
            echo "start_boot <file>              # start $REL_NAME as a daemon, but supply a custom .boot file"
            echo "foreground                     # start $REL_NAME in the foreground"
            echo "console                        # start $REL_NAME with a console attached"
            echo "console_clean                  # start a console with code paths set but no apps loaded/started"
            echo "console_boot <file>            # start $REL_NAME with a console attached, but supply a custom .boot file"
            echo "stop                           # stop the $REL_NAME daemon"
            echo "restart                        # restart the $REL_NAME daemon without shutting down the VM"
            echo "reboot                         # restart the $REL_NAME daemon"
            echo
            echo "Upgrades"
            echo "======================="
            echo "upgrade <version>              # upgrade $REL_NAME to <version>"
            echo "downgrade <version>            # downgrade $REL_NAME to <version>"
            echo "install <version>              # install the $REL_NAME-<version> release, but do not upgrade to it"
            echo
            echo "Utilities"
            echo "======================="
            echo "attach                         # attach the current TTY to $REL_NAME's console"
            echo "remote_console                 # remote shell to $REL_NAME's console"
            echo "pid                            # get the pid of the running $REL_NAME instance"
            echo "ping                           # checks if $REL_NAME is running, pong is returned if successful"
            echo "pingpeer <peer>                # check if a peer node is running, pong is returned if successful"
            echo "escript <file>                 # execute an escript"
            echo "rpc <mod> <fun> [<args..>]     # execute an RPC call using the given MFA"
            echo "rpcterms <mod> <fun> [<expr>]  # execute an RPC call using the given Erlang expression for args"
            echo "eval <expr>                    # execute the given Erlang expression on the running node"
            echo "command <mod> <fun> [<args..>] # execute the given MFA"
            echo "describe                       # print useful information about the $REL_NAME release"
            echo
            echo "Custom Commands"
            echo "======================="
            __has_commands=0
            for command in "$REL_DIR"/commands/*.sh; do
                [ -f "$command" ] || continue
                __has_commands=1
                echo "$command"
            done
            if [ $__has_commands -eq 0 ]; then
                echo "No custom commands found."
            fi
            echo ""
            exit 1
        fi
        ;;
esac

exit 0

#!/bin/sh

set -e

# Set VERBOSE to enable verbose logging of the boot script
#VERBOSE=true
if [ ! -z $DEBUG_BOOT ]; then
    set -x
fi;

my_readlink_f() {
    TARGET_FILE="$1"
    cd $(dirname "$TARGET_FILE")
    TARGET_FILE=$(basename "$TARGET_FILE")

    # Iterate down a (possible) chain of symlinks
    while [ -L "$TARGET_FILE" ]
    do
        TARGET_FILE=$(readlink "$TARGET_FILE")
        cd $(dirname "$TARGET_FILE")
        TARGET_FILE=$(basename "$TARGET_FILE")
    done
    # Compute the canonicalized name by finding the physical path
    # for the directory we're in and appending the target file.
    PHYS_DIR=$(pwd -P)
    RESULT="$PHYS_DIR/$TARGET_FILE"
    echo "$RESULT"
}

# Path to this script
if uname | grep -q 'Darwin'; then
  # on OSX, best to install coreutils from homebrew or similar
  # to get greadlink
  if command -v greadlink >/dev/null 2>&1; then
    SCRIPT="${SCRIPT:-$(greadlink -f "$0")}"
  else
    SCRIPT="${SCRIPT:-$(my_readlink_f "$0")}"
  fi
else
  SCRIPT="${SCRIPT:-$(readlink -f "$0" )}"
fi

# Parent directory of this script
SCRIPT_DIR="${SCRIPT_DIR:-$(dirname "${SCRIPT}")}"
# Root directory of all releases
RELEASE_ROOT_DIR="${RELEASE_ROOT_DIR:-$(dirname $(dirname ${SCRIPT_DIR}))}"

# Disable flow control for run_erl
# Flow control can cause several problems. On Linux, if you
# accidentally hit Ctrl-S (instead of Ctrl-D to detach) and
# then some other key, the entire beam process will hang when
# attempting to write to stdout. On Solaris, the beam process
# will hang on writing if ScrollLock is on.
RUN_ERL_DISABLE_FLOWCNTRL="${RUN_ERL_DISABLE_FLOWCNTRL:-true}"
# Name of the release
REL_NAME="${REL_NAME:-<%= release_name %>}"
# Current version of the release
REL_VSN="${REL_VSN:-<%= release_version %>}"
# Current version of ERTS being used
# If this is not present/unset, it will be detected
<%= if ((is_binary(include_erts) or include_erts) and not is_nil(erts_vsn)) do %>ERTS_VSN="${ERTS_VSN:-<%= erts_vsn %>}"<% end %>
# VM code loading mode, embedded by default, can also be interactive
# See http://erlang.org/doc/man/code.html
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
# Path to start_erl.data
START_ERL_DATA="${START_ERL_DATA:-$RELEASE_ROOT_DIR/releases/start_erl.data}"
# Directory containing the current version of this release
REL_DIR="${REL_DIR:-$RELEASE_ROOT_DIR/releases/$REL_VSN}"
# The lib directory for this release
REL_LIB_DIR="${REL_LIB_DIR:-$RELEASE_ROOT_DIR/lib}"
# Options passed to erl
ERL_OPTS="${ERL_OPTS:-<%= release.profile.erl_opts %>}"
# When stdout is piped to a file, this is the directory those files will
# be stored in. defaults to /log in the release root directory

# RELEASE_MUTABLE_DIR
RELEASE_MUTABLE_DIR="${RELEASE_MUTABLE_DIR:-$RELEASE_ROOT_DIR/var}"

RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_MUTABLE_DIR/log}"
# A string of extra options to pass to erl, here for plugins
EXTRA_OPTS="${EXTRA_OPTS:-}"

# Pre-start/stop event hook paths
PRE_START_HOOKS="$REL_DIR/hooks/pre_start.d"
POST_START_HOOKS="$REL_DIR/hooks/post_start.d"
PRE_STOP_HOOKS="$REL_DIR/hooks/pre_stop.d"
POST_STOP_HOOKS="$REL_DIR/hooks/post_stop.d"
PRE_UPGRADE_HOOKS="$REL_DIR/hooks/pre_upgrade.d"
POST_UPGRADE_HOOKS="$REL_DIR/hooks/post_upgrade.d"

# Get node pid
get_pid() {
    if output="$(nodetool rpcterms os getpid)"
    then
        echo "$output" | sed -e 's/"//g'
        return 0
    else
        echo "$output"
        return 1
    fi
}

# Generate a unique nodename
gen_nodename() {
    id="longname$(gen_id)-${NAME}"
    "$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
}

# Generate a random id
gen_id() {
    od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}

# Control a node
# Use like `nodetool "ping"`
nodetool() {
    command="$1"; shift
    name=${PEERNAME:-$NAME}
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$name" \
                            -setcookie "$COOKIE" "$command" $@
}

# Run an escript in the node's environment
# Use like `escript "path/to/escript"`
escript() {
    shift; scriptpath="$1"; shift
    export RELEASE_ROOT_DIR

    "$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" $@
}

# Private. Load target cookie, either from vm.args or $HOME/.cookie
_load_cookie() {
    COOKIE_ARG="$(grep '^-setcookie' "$VMARGS_PATH" || true)"
    DEFAULT_COOKIE_FILE="$HOME/.erlang.cookie"
    if [ -z "$COOKIE_ARG" ]; then
        if [ -f "$DEFAULT_COOKIE_FILE" ]; then
            COOKIE="$(cat "$DEFAULT_COOKIE_FILE")"
        fi
    else
        # Extract cookie name from COOKIE_ARG
        COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
    fi
}

# Private. Ensure that cookie is set.
_check_cookie() {
    # Attempt reloading cookie in case it has been set in a hook
    if [ -z "$COOKIE" ]; then
        _load_cookie
    fi
    # Die if cookie is still not set, as connecting via distribution will fail
    if [ -z "$COOKIE" ]; then
        printf "a secret cookie must be provided in one of the following ways:\n  - with vm.args using the -setcookie parameter,\n  or\n  by writing the cookie to '$DEFAULT_COOKIE_FILE', with permissions set to 0400"
        exit 1
    fi
}

# Private. For determining the version of ERTS available to the release
# This is only ever called if ERTS_VSN is not set
_detect_erts_vsn() {
    set +e # temporarily disable so we can display a nice error message to the user
    __erl="$(which erl)"
    set -e
    if [ -z "${__erl}"  ]; then
        echo 'erlang runtime not found. If erlang is installed check your $PATH. aborting.'
        exit 1
    fi
    "$__erl" -boot start_clean -eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver]), halt()' -noshell
}

# Private. Gets a list of code paths for this release
_get_code_paths() {
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/release_utils.escript" "get_code_paths" "$ROOTDIR" "$ERTS_DIR" "$REL_NAME" "$REL_VSN"
}

# Private. For setting ERTS_DIR and ROOTDIR
_find_erts_dir() {
    __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
    if [ -d "$__erts_dir" ]; then
        ERTS_DIR="$__erts_dir";
        ROOTDIR="$RELEASE_ROOT_DIR"
    else
        set +e # temporarily disable so we can display a nice error message to the user
        __erl="$(which erl)"
        set -e
        if [ -z "${__erl}"  ]; then
          echo 'erlang runtime not found. If erlang is installed check your $PATH. aborting.'
          exit 1
        fi
        code="io:format(\"~s\", [code:root_dir()]), halt()."
        __erl_root="$("$__erl" -noshell -eval "$code")"
        ERTS_DIR="$__erl_root/erts-$ERTS_VSN"
        ROOTDIR="$__erl_root"
    fi
}

# Private. Open a shell on a remote node
_rem_sh() {
    # Generate a unique id used to allow multiple remsh to the same node
    # transparently
    id="remsh$(gen_id)-${NAME}"

    # Get the node's ticktime so that we use the same thing.
    TICKTIME="$(nodetool rpcterms net_kernel get_net_ticktime)"

    # Setup remote shell command to control node
    if [ ! -z "$USE_ERL_SHELL" ]; then
        exec "$BINDIR/erl" \
            -hidden \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            "$NAME_TYPE" "$id" -remsh "$NAME" -setcookie "$COOKIE"
    else
        __code_paths=$(_get_code_paths)
        exec "$BINDIR/erl" \
            -pa "$CONSOLIDATED_DIR" \
            ${__code_paths} \
            -hidden -noshell \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            -user Elixir.IEx.CLI "$NAME_TYPE" "$id" -setcookie "$COOKIE" \
            -extra --no-halt +iex -"$NAME_TYPE" "$id" --cookie "$COOKIE" --remsh "$NAME"
    fi
}

# Output a start command for the last argument of run_erl
_start_command() {
    printf "exec \"%s\" \"%s\" -- %s %s" "$RELEASE_ROOT_DIR/bin/$REL_NAME" \
           "$START_OPTION" "${ARGS}" "${EXTRA_OPTS}"
}

# Do a textual replacement of ${VAR} occurrences in $1 and pipe to $2
_replace_os_vars() {
    awk '
        function escape(s) {
            gsub(/'\&'/, "\\\\&", s);
            return s;
        }
        {
            while(match($0,"[$]{[^}]*}")) {
                var=substr($0,RSTART+2,RLENGTH-3);
                gsub("[$]{"var"}", escape(ENVIRON[var]))
            }
        }1' < "$1" > "$1.bak"
    mv -- "$1.bak" "$1"
}

# Private. Run hooks from directory.
_run_hooks_from_dir() {
   if [ -d "$1" ]; then
      for file in $1/[0-9a-zA-Z]*.sh; do
        [ -f "$file" ] || continue
        . "$file"
      done
   fi
}

# If TERM is not set, set it to xterm
if [ -z "$TERM" ]; then
    export TERM=xterm
fi

# If ERTS_VSN is not set, detect it
if [ -z "$ERTS_VSN" ]; then
    export ERTS_VSN="$(_detect_erts_vsn)"
    echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"
fi

# Allow override of where to read configuration from
# By default it's RELEASE_ROOT_DIR
if [ -z "$RELEASE_CONFIG_DIR" ]; then
    export RELEASE_CONFIG_DIR="$RELEASE_ROOT_DIR"
fi

# Make sure directories exist
mkdir -p "$RELEASE_MUTABLE_DIR"
echo "Files in this directory are regenerated frequently, edits will be lost" \
    > "$RELEASE_MUTABLE_DIR/WARNING_README"
mkdir -p "$RUNNER_LOG_DIR"

# Set VMARGS_PATH, the path to the vm.args file to use
# Use $RELEASE_CONFIG_DIR/vm.args if exists, otherwise releases/VSN/vm.args
if [ -z "$VMARGS_PATH" ]; then
    if [ -f "$RELEASE_CONFIG_DIR/vm.args" ]; then
        export VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
    else
        export VMARGS_PATH="$REL_DIR/vm.args"
    fi
fi
if [ "$VMARGS_PATH" != "$RELEASE_MUTABLE_DIR/vm.args" ]; then
    echo "#### Generated - edit/create $RELEASE_CONFIG_DIR/vm.args instead." \
        >  "$RELEASE_MUTABLE_DIR/vm.args"
    cat  "$VMARGS_PATH"                              \
        >> "$RELEASE_MUTABLE_DIR/vm.args"
    export VMARGS_PATH=$RELEASE_MUTABLE_DIR/vm.args
fi
if [ $REPLACE_OS_VARS ]; then
    _replace_os_vars "$VMARGS_PATH"
fi

# Set SYS_CONFIG_PATH, the path to the sys.config file to use
# Use $RELEASE_CONFIG_DIR/sys.config if exists, otherwise releases/VSN/sys.config
if [ -z "$SYS_CONFIG_PATH" ]; then
    if [ -f "$RELEASE_CONFIG_DIR/sys.config" ]; then
        export SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
    else
        export SYS_CONFIG_PATH="$REL_DIR/sys.config"
    fi
fi
if [ "$SYS_CONFIG_PATH" != "$RELEASE_MUTABLE_DIR/sys.config" ]; then
    (echo "%% Generated - edit/create $RELEASE_CONFIG_DIR/sys.config instead."; \
    cat  "$SYS_CONFIG_PATH")                              \
        > "$RELEASE_MUTABLE_DIR/sys.config"
    export SYS_CONFIG_PATH=$RELEASE_MUTABLE_DIR/sys.config
fi
if [ $REPLACE_OS_VARS ]; then
    _replace_os_vars "$SYS_CONFIG_PATH"
fi

# Extract the target node name from node.args
# Should be `-sname somename` or `-name somename@somehost`
export NAME_ARG="$(egrep '^-s?name' "$VMARGS_PATH" || true)"
if [ -z "$NAME_ARG" ]; then
    echo "vm.args needs to have either -name or -sname parameter."
    exit 1
fi

# Extract the name type and name from the NAME_ARG for REMSH
# NAME_TYPE should be -name or -sname
export NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
# NAME will be either `somename` or `somename@somehost`
export NAME="$(echo "$NAME_ARG" | awk '{print $2}')"

# Where the pipe will be stored when using `start`
# This is used so you can attach the running application to the current
# shell using `attach`
PIPE_DIR="${PIPE_DIR:-$RELEASE_MUTABLE_DIR/erl_pipes/$NAME/}"

# Extract the target cookie
_load_cookie

_find_erts_dir
export ROOTDIR="$RELEASE_ROOT_DIR"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
ERTS_LIB_DIR="$ERTS_DIR/../lib"
CONSOLIDATED_DIR="$ROOTDIR/lib/${REL_NAME}-${REL_VSN}/consolidated"

cd "$ROOTDIR"

# User can specify an sname without @hostname
# This will fail when creating remote shell
# So here we check for @ and add @hostname if missing
case $NAME in
    *@*)
        # Nothing to do
        ;;
    *)
        NAME=$NAME@$(gen_nodename)
        ;;
esac

# For Elixir runtime
export DISTILLERY_TASK="$1"

# Check the first argument for instructions
case "$1" in
    start|start_boot)

        # Make sure there is not already a node running
        #RES=`$NODETOOL ping`
        #if [ "$RES" = "pong" ]; then
        #    echo "Node is already running!"
        #    exit 1
        #fi
        # Save this for later.
        CMD=$1
        case "$1" in
            start)
                shift
                START_OPTION="console"
                HEART_OPTION="start"
                ;;
            start_boot)
                shift
                START_OPTION="console_boot"
                HEART_OPTION="start_boot"
                ;;
        esac
        ARGS="$@"
        RUN_PARAM="$@"

        _check_cookie
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Set arguments for the heart command
        set -- "$SCRIPT_DIR/$REL_NAME" "$HEART_OPTION"
        [ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"

        # Export the HEART_COMMAND
        HEART_COMMAND="$RELEASE_ROOT_DIR/bin/$REL_NAME $CMD"
        export HEART_COMMAND

        mkdir -p "$PIPE_DIR"

        "$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
                          "$(_start_command)"

        _run_hooks_from_dir "$POST_START_HOOKS"
        ;;

    stop)
        _check_cookie
        _run_hooks_from_dir "$PRE_STOP_HOOKS"
        # Wait for the node to completely stop...
        PID="$(get_pid)"
        if ! nodetool "stop"; then
            exit 1
        fi
        while $(kill -s 0 "$PID" 2>/dev/null);
        do
            sleep 1
        done
        _run_hooks_from_dir "$POST_STOP_HOOKS"
        ;;

    restart)
        _check_cookie
        _run_hooks_from_dir "$PRE_START_HOOKS"
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        _check_cookie
        _run_hooks_from_dir "$PRE_START_HOOKS"
        ## Restart the VM completely (uses heart to restart it)
        if ! nodetool "reboot"; then
            exit 1
        fi
        ;;

    pid)
        ## Get the VM's pid
        _check_cookie
        if ! get_pid; then
            exit 1
        fi
        ;;

    ping)
        _check_cookie
        ## See if the VM is alive
        if ! nodetool "ping"; then
            exit 1
        fi
        ;;

    pingpeer)
        PEERNAME=$2 nodetool "ping"
        exit_status=$?
        if [ "$exit_status" -ne 0 ]; then
            exit $exit_status
        fi
        ;;

    escript)
        _check_cookie
        ## Run an escript under the node's environment
        if ! escript $@; then
            exit 1
        fi
        ;;

    attach)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        exec "$BINDIR/to_erl" "$PIPE_DIR"
        ;;

    remote_console)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        _rem_sh
        ;;

    upgrade|downgrade|install)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        SOURCE_VERSION="$REL_VSN"
        TARGET_VERSION="$2"

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        _run_hooks_from_dir "$PRE_UPGRADE_HOOKS"

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "install_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        _run_hooks_from_dir "$POST_UPGRADE_HOOKS"

        ;;
    unpack)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        exec "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    console|console_clean|console_boot)
        # .boot file typically just $REL_NAME (ie, the app name)
        # however, for debugging, sometimes start_clean.boot is useful.
        # For e.g. 'setup', one may even want to name another boot script.
        case "$1" in
            console)
                if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
                  BOOTFILE="$REL_DIR/$REL_NAME"
                else
                  BOOTFILE="$REL_DIR/start"
                fi
                ;;
            console_clean)
                BOOTFILE="$ROOTDIR/bin/start_clean"
                __code_paths=$(_get_code_paths)
                EXTRA_CODE_PATHS=${__code_paths}
                ;;
            console_boot)
                shift
                BOOTFILE="$1"
                shift
                ;;
        esac
        # Setup beam-required vars
        EMU="beam"
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        _check_cookie

        # Start the VM, executing pre_start hook along
        # the way. We can't run the post_start hook because
        # the console will crash with no TTY attached
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" \
            -boot "$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            ${EXTRA_CODE_PATHS} \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -user Elixir.IEx.CLI \
            -extra --no-halt +iex

        # Dump environment info for logging purposes
        if [ ! -z $VERBOSE ]; then
            echo "Exec: $@" -- ${1+$ARGS} ${EXTRA_OPTS}
            echo "Root: $ROOTDIR"

            # Log the startup
            echo "$RELEASE_ROOT_DIR"
        fi;

        logger -t "$REL_NAME[$$]" "Starting up"

        exec "$@" -- ${1+$ARGS} ${EXTRA_OPTS}
        ;;

    foreground)
        # start up the release in the foreground for use by runit
        # or other supervision services

        [ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
        FOREGROUNDOPTIONS="-noshell -noinput +Bd"

        # Setup beam-required vars
        EMU=beam
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        _check_cookie

        # Start the VM, executing pre and post start hooks
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
            -boot "$REL_DIR/$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -extra ${EXTRA_OPTS}

        # Dump environment info for logging purposes
        if [ ! -z $VERBOSE ]; then
            echo "Exec: $@" -- ${1+$ARGS}
            echo "Root: $ROOTDIR"
        fi;

        "$@" -- ${1+$ARGS} &
        __bg_pid=$!
        _run_hooks_from_dir "$POST_START_HOOKS"
        wait $__bg_pid
        ;;
    rpc)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpc $@
        ;;
    rpcterms)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpcterms $@
        ;;
    eval)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        nodetool "eval" $@
        ;;
    command)
        # Execute as command-line utility
        #
        # Like the escript command, this does not start the OTP application.
        # If your command depends on a running OTP application,
        # use
        #
        #     {:ok, _} = Application.ensure_all_started(:your_app)

        _check_cookie

        shift
        MODULE="$1"; shift
        FUNCTION="$1"; shift

        # Save extra arguments
        ARGS="$@"

        # Build arguments for erlexec
        __code_paths=$(_get_code_paths)
        set -- "$ERL_OPTS"
        [ "$SYS_CONFIG_PATH" ] && set -- "$@" -config "$SYS_CONFIG_PATH"
        set -- "$@" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR"
        set -- "$@" -noshell
        set -- "$@" -boot start_clean
        set -- "$@" -pa "$CONSOLIDATED_DIR"
        set -- "$@" ${__code_paths}
        set -- "$@" -s "$MODULE" "$FUNCTION"

        $BINDIR/erlexec $@ -extra $ARGS
        exit "$?"
        ;;
    describe)
        ## Print a summary of information about this release
        echo "$REL_NAME-$REL_VSN\n"
        echo "erts:       $ERTS_VSN"
        echo "path:       $REL_DIR"
        echo "sys.config: $SYS_CONFIG_PATH"
        echo "vm.args:    $VMARGS_PATH"
        echo "name:       $NAME"
        echo "cookie:     $COOKIE"
        echo "erl_opts:   ${ERL_OPTS:-none provided}"
        echo ""
        echo "hooks:"
        __has_hooks=0
        for hook in "$REL_DIR"/hooks/*.d/[0-9a-zA-Z]*.sh; do
            [ -f "$hook" ] || continue
            __has_hooks=1
            echo "$hook"
        done
        if [ $__has_hooks -eq 0 ]; then
            echo "No custom hooks found."
        fi
        echo ""
        echo "commands:"
        __has_commands=0
        for command in "$REL_DIR"/commands/*.sh; do
            [ -f "$command" ] || continue
            __has_commands=1
            echo "$command"
        done
        if [ $__has_commands -eq 0 ]; then
            echo "No custom commands found."
        fi
        exit 0
        ;;
    *)
        __command_path="$REL_DIR/commands/$1"
        if [ -f "$__command_path" ]; then
            _check_cookie
            . "$__command_path"
        else
            echo "Usage: $REL_NAME {start|start_boot <file>|foreground|stop|restart|reboot|pid|ping|pingpeer|console|console_clean|console_boot <file>|attach|remote_console|upgrade|downgrade|install|escript|rpc|rpcterms|eval|command <module> <function> <args>}|describe"
            exit 1
        fi
        ;;
esac

exit 0


Added default favicon

Added default favicon

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="ricardo@codeloveandboards.com">

    <title>Phoenix Toggl</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
    <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,600|Ropa+Sans" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
    <link id="favicon" rel="icon" type="image/png" href="<%= static_path(@conn, "/images/favicon.png") %>"/>
  </head>

  <body>
    <main id="main_wrapper" role="main"></main>
    <script src="<%= static_path(@conn, "/js/app.js") %>"></script>
  </body>
</html>

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="ricardo@codeloveandboards.com">

    <title>Phoenix Toggl</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
    <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,600|Ropa+Sans" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
  </head>

  <body>
    <main id="main_wrapper" role="main"></main>
    <script src="<%= static_path(@conn, "/js/app.js") %>"></script>
  </body>
</html>


Made navbar backlink point to the index lists

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Hello CoursePlanner!</title>
    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700" type="text/css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

          <%= if length(@conn.path_info) > 1 do %>
            <a
              href="/<%= Enum.at(@conn.path_info, 0) %>"
              class="mdl-button mdl-js-button mdl-button--icon layout-backlink"
            >
              

          <% end %>

            <%= @view_module.page_title %>

            <%= @conn.assigns.current_user.name %>
            <%= @conn.assigns.current_user.family_name %>
            <button id="profile_dropdown"
                    class="profile-bubble__button"
            >
              <img
                class="profile-bubble__image"
                src="<%= CoursePlanner.SharedView.get_gravatar_url( @conn.assigns.current_user.email ) %>"
              />
            </button>

                <%= link "Edit profile", to: user_path(@conn, :edit, @conn.assigns.current_user) %>

                <%= CoursePlanner.Coherence.ViewHelpers.signout_link(@conn, "Sign out") %>

      <%= CoursePlanner.SharedView.navbar "Course Planner" do %>
        <%= CoursePlanner.SharedView.navbar_item "Dashboard", @conn, dashboard_path(@conn, :show) %>
        <%= CoursePlanner.SharedView.navbar_separator %>
        <%= CoursePlanner.SharedView.navbar_item "Coordinators", @conn, coordinator_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Students", @conn, student_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Teachers", @conn, teacher_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Volunteers", @conn, volunteer_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "All users", @conn, user_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_separator %>
        <%= CoursePlanner.SharedView.navbar_item "Courses", @conn, course_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Terms", @conn, term_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_separator %>
        <%= CoursePlanner.SharedView.navbar_item "Offered Courses", @conn, offered_course_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Classes", @conn, class_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Attendances", @conn, attendance_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Tasks", @conn, task_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Settings", @conn, setting_path(@conn, :show) %>
      <% end %>

            <%= render @view_module, @view_template, assigns %>

      <button class="mdl-snackbar__action" type="button"></button>

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Hello CoursePlanner!</title>
    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700" type="text/css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

          <%= if length(@conn.path_info) > 1 do %>

              

          <% end %>

            <%= @view_module.page_title %>

            <%= @conn.assigns.current_user.name %>
            <%= @conn.assigns.current_user.family_name %>
            <button id="profile_dropdown"
                    class="profile-bubble__button"
            >
              <img
                class="profile-bubble__image"
                src="<%= CoursePlanner.SharedView.get_gravatar_url( @conn.assigns.current_user.email ) %>"
              />
            </button>

                <%= link "Edit profile", to: user_path(@conn, :edit, @conn.assigns.current_user) %>

                <%= CoursePlanner.Coherence.ViewHelpers.signout_link(@conn, "Sign out") %>

      <%= CoursePlanner.SharedView.navbar "Course Planner" do %>
        <%= CoursePlanner.SharedView.navbar_item "Dashboard", @conn, dashboard_path(@conn, :show) %>
        <%= CoursePlanner.SharedView.navbar_separator %>
        <%= CoursePlanner.SharedView.navbar_item "Coordinators", @conn, coordinator_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Students", @conn, student_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Teachers", @conn, teacher_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Volunteers", @conn, volunteer_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "All users", @conn, user_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_separator %>
        <%= CoursePlanner.SharedView.navbar_item "Courses", @conn, course_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Terms", @conn, term_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_separator %>
        <%= CoursePlanner.SharedView.navbar_item "Offered Courses", @conn, offered_course_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Classes", @conn, class_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Attendances", @conn, attendance_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Tasks", @conn, task_path(@conn, :index) %>
        <%= CoursePlanner.SharedView.navbar_item "Settings", @conn, setting_path(@conn, :show) %>
      <% end %>

            <%= render @view_module, @view_template, assigns %>

      <button class="mdl-snackbar__action" type="button"></button>


Amazon Fire Stick Ad

Amazon Fire Stick Ad

  <%= gettext("Ad") %>

Fire TV Stick

Mit einer riesigen Auswahl an Filmen und Serienepisoden.

EUR 39,99

  https://www.amazon.de

  <%= gettext("Ad") %>

Wunder wirken Wunder: Wie Medizin und Magie uns heilen

von Dr. med. Eckart von Hirschhausen

Ein heilsamer Blick auf die Wunderwelt der Heilkunst
Die Wissenschaft hat die Magie aus der Medizin vertrieben, aber nicht aus uns Menschen.

  amazon.de


removing local scope for non posix compatible shells; making hostname return correctly for solaris

#!/bin/sh

set -e

readlink_f() {
  cd "$(dirname "$1")" > /dev/null

  filename="$(basename "$1")"

  if [ -h "$filename" ]; then
    readlink_f "$(readlink "$filename")"
  else
    echo "`pwd -P`/$filename"
  fi
}

SELF=$(readlink_f "$0")
SCRIPT_PATH=$(dirname "$SELF")
RELEASE_PATH=$(dirname "$SCRIPT_PATH")

APP=<%= app %>
if [ `uname -s` = 'SunOS' ]; then
  HOSTNAME=`hostname`
else
  HOSTNAME=`hostname -f`
fi
SERVER_NODE=$APP@$HOSTNAME
CONTROL_NODE=$APP$$@$HOSTNAME

alive() {
  $SCRIPT_PATH/elixir --name $CONTROL_NODE -e 'Pogo.alive! :"'$SERVER_NODE'"'

  return $?
}

start() {
  if alive; then
    echo "$APP is already running"
    exit 0
  fi

  if [ -f "$RELEASE_PATH/etc/$APP.config" ]; then
    export ELIXIR_ERL_OPTS="-config $RELEASE_PATH/etc/$APP.config"
  fi

  if [ "$#" != 0 ]; then
    export ELIXIR_ERL_OPTS="$ELIXIR_ERL_OPTS $@"
  fi

  $SCRIPT_PATH/elixir --name $SERVER_NODE --app $APP --no-halt --detached

  if alive; then
    echo "$APP started as $SERVER_NODE";
  else
    echo "$APP failed to start"
  fi
}

stop() {
  if ! alive; then
    echo "$APP is not running (or not reachable)"
    exit 0
  fi

  $SCRIPT_PATH/elixir --name $CONTROL_NODE -e 'Pogo.stop :"'$SERVER_NODE'"'

  if [ $? ]; then
    echo "$APP has stopped"
  else
    echo "$APP did not stop"
  fi
}

restart() {
  if ! alive; then
    echo "$APP is unreachable"
    exit 1
  fi

  $SCRIPT_PATH/elixir --name $CONTROL_NODE -e 'Pogo.restart :"'$SERVER_NODE'"'
}

reboot() {
  if ! alive; then
    echo "$APP is unreachable"
    exit 1
  fi

  $SCRIPT_PATH/elixir --name $CONTROL_NODE -e 'Pogo.reboot :"'$SERVER_NODE'"'
}

console() {
  if alive; then
    echo "$APP is already running"
    exit 0
  fi

  if [ -f "$RELEASE_PATH/etc/$APP.config" ]; then
    export ELIXIR_ERL_OPTS="-config $RELEASE_PATH/etc/$APP.config"
  fi

  if [ "$#" != 0 ]; then
    export ELIXIR_ERL_OPTS="$@"
  fi

  exec $SCRIPT_PATH/iex --name $SERVER_NODE --app $APP
}

attach() {
  if ! alive; then
    echo "$APP is unreachable"
    exit 1
  fi

  exec $SCRIPT_PATH/iex --remsh $SERVER_NODE --name $CONTROL_NODE
}

status() {
  if alive; then
    echo "$APP is running"
    exit 0
  else
    echo "$APP could not be reached"
    exit 1
  fi
}

case "$1" in
  start)
    shift
    start $@
    ;;
  stop)
    stop
    ;;
  restart)
    restart
    ;;
  reboot)
    reboot
    ;;
  console)
    shift
    console $@
    ;;
  attach)
    attach
    ;;
  status)
    status
    ;;
  *)
    echo "Usage: $0 (start|stop|restart|reboot|console|attach|status)"
    exit 1
esac

exit $?

#!/bin/sh

set -e

readlink_f() {
  cd "$(dirname "$1")" > /dev/null

  local filename="$(basename "$1")"

  if [ -h "$filename" ]; then
    readlink_f "$(readlink "$filename")"
  else
    echo "`pwd -P`/$filename"
  fi
}

SELF=$(readlink_f "$0")
SCRIPT_PATH=$(dirname "$SELF")
RELEASE_PATH=$(dirname "$SCRIPT_PATH")

APP=<%= app %>
HOSTNAME=`hostname -f`
SERVER_NODE=$APP@$HOSTNAME
CONTROL_NODE=$APP$$@$HOSTNAME

alive() {
  $SCRIPT_PATH/elixir --name $CONTROL_NODE -e 'Pogo.alive! :"'$SERVER_NODE'"'

  return $?
}

start() {
  if alive; then
    echo "$APP is already running"
    exit 0
  fi

  if [ -f "$RELEASE_PATH/etc/$APP.config" ]; then
    export ELIXIR_ERL_OPTS="-config $RELEASE_PATH/etc/$APP.config"
  fi

  if [ "$#" != 0 ]; then
    export ELIXIR_ERL_OPTS="$ELIXIR_ERL_OPTS $@"
  fi

  $SCRIPT_PATH/elixir --name $SERVER_NODE --app $APP --no-halt --detached

  if alive; then
    echo "$APP started as $SERVER_NODE";
  else
    echo "$APP failed to start"
  fi
}

stop() {
  if ! alive; then
    echo "$APP is not running (or not reachable)"
    exit 0
  fi

  $SCRIPT_PATH/elixir --name $CONTROL_NODE -e 'Pogo.stop :"'$SERVER_NODE'"'

  if [ $? ]; then
    echo "$APP has stopped"
  else
    echo "$APP did not stop"
  fi
}

restart() {
  if ! alive; then
    echo "$APP is unreachable"
    exit 1
  fi

  $SCRIPT_PATH/elixir --name $CONTROL_NODE -e 'Pogo.restart :"'$SERVER_NODE'"'
}

reboot() {
  if ! alive; then
    echo "$APP is unreachable"
    exit 1
  fi

  $SCRIPT_PATH/elixir --name $CONTROL_NODE -e 'Pogo.reboot :"'$SERVER_NODE'"'
}

console() {
  if alive; then
    echo "$APP is already running"
    exit 0
  fi

  if [ -f "$RELEASE_PATH/etc/$APP.config" ]; then
    export ELIXIR_ERL_OPTS="-config $RELEASE_PATH/etc/$APP.config"
  fi

  if [ "$#" != 0 ]; then
    export ELIXIR_ERL_OPTS="$@"
  fi

  exec $SCRIPT_PATH/iex --name $SERVER_NODE --app $APP
}

attach() {
  if ! alive; then
    echo "$APP is unreachable"
    exit 1
  fi

  exec $SCRIPT_PATH/iex --remsh $SERVER_NODE --name $CONTROL_NODE
}

status() {
  if alive; then
    echo "$APP is running"
    exit 0
  else
    echo "$APP could not be reached"
    exit 1
  fi
}

case "$1" in
  start)
    shift
    start $@
    ;;
  stop)
    stop
    ;;
  restart)
    restart
    ;;
  reboot)
    reboot
    ;;
  console)
    shift
    console $@
    ;;
  attach)
    attach
    ;;
  status)
    status
    ;;
  *)
    echo "Usage: $0 (start|stop|restart|reboot|console|attach|status)"
    exit 1
esac

exit $?


Remove favicon HTML, not actually needed

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Marc Addeo's blog about code, learning, and rambling.">
    <meta name="author" content="Marc Addeo">

  <%= if assigns[:title] do %>
    <title><%= @title %> | marc.cx</title>
  <% else %>
    <title>marc.cx</title>
  <% end %>
    <link href="http://fonts.googleapis.com/css?family=Inconsolata:400,700|Open+Sans:300italic,400italic,700,300,800,400" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

  <%= if Mix.env == :prod do %>

  <% end %>

              <%= for item <- navigation(@conn) do %>
                <li role="presentation" <%= if item.active do %>class="active"<% end %>>
                  <a <%= if item[:target] do %>target="<%= item.target %>" <% end %>href="<%= item.href %>"><%= item.text %>

              <% end %>

            <a href="<%= page_path(@conn, :index) %>" class="title text-muted">marc.cx

      <%= @inner %>

              <img width="32" src="<%= static_path(@conn, "/images/kopimi.svg") %>" />

            hi@marc.cx

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Marc Addeo's blog about code, learning, and rambling.">
    <meta name="author" content="Marc Addeo">

  <%= if assigns[:title] do %>
    <title><%= @title %> | marc.cx</title>
  <% else %>
    <title>marc.cx</title>
  <% end %>
    <link rel="icon" type="image/png" href="favicon.ico" />
    <link href="http://fonts.googleapis.com/css?family=Inconsolata:400,700|Open+Sans:300italic,400italic,700,300,800,400" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

  <%= if Mix.env == :prod do %>

  <% end %>

              <%= for item <- navigation(@conn) do %>
                <li role="presentation" <%= if item.active do %>class="active"<% end %>>
                  <a <%= if item[:target] do %>target="<%= item.target %>" <% end %>href="<%= item.href %>"><%= item.text %>

              <% end %>

            <a href="<%= page_path(@conn, :index) %>" class="title text-muted">marc.cx

      <%= @inner %>

              <img width="32" src="<%= static_path(@conn, "/images/kopimi.svg") %>" />

            hi@marc.cx


Limits the size of the how it works container

<%= gettext "Step 1" %>

<%= gettext "Find a great article" %>

      <%= gettext "Virtual DOM in the Netscape Navigator Web browser without page. Four is not include any state container for graphic applications using AMD. Metalsmith is a library for a NoSQL database. Universal is a simple examples of common host environment in the user-interface logic is a framework originally created and variables from Node." %>

<%= gettext "Step 2" %>

<%= gettext "Add it to your list" %>

      <%= gettext "It is supported by modular programming, in a JavaScript and display animated 3D content production; the goal of deployment-ready files from HTML pages hosted on innovative features and browsing activities to JavaScript CommonJS is supported by Nitobi. The Rhino engine is a way of referencing variables from Node. Because JavaScript for dynamic web framework that are not available in 2D or for apps. React Native development." %>

<%= gettext "Step 3" %>

<%= gettext "Enjoy it on the go!" %>

      <%= gettext "Hoisting is another common host objects. On the Module Pattern is a swiss army knife, focusing on data fetching. Memoize is a HTML5 mobile application more responsive. XHR is a fast, small, and Cordova. Hoisting is a fast and more responsive." %>


better header font on jd

better header font on jd

<%
  background_color = case @brand do
    "bnc" -> "none"
    "jd" -> "#5B919F"
  end
%>

<header class="header" style="background-color: <%= background_color %>">

    <a href="https://<%= homepage(@brand) %>">
      <%= if @brand == "jd" do %>

        <%= if @mobile do %>
          <img class="mobile" src="<%= static_path(@conn, "/images/horizontal-logo-jd.png")%>" />
        <% else %>
          <img class="desktop" src="<%= static_path(@conn, "/images/horizontal-logo-jd.png")%>" />
        <% end %>

      <% else %>

        <%= if @mobile do %>
          <img class="mobile" src="<%= static_path(@conn, "/images/horizontal-logo-smaller-bnc.png")%>" />
        <% else %>
          <img class="desktop" src="<%= static_path(@conn, "/images/horizontal-logo-bnc.png")%>" />
        <% end %>

      <% end %>

    <%= if (not @mobile) do %>
      <a class="donate-link" target="_blank" href="https://<%= homepage(@brand) %>/donate">
        Support <%= abbr(@brand) %>

    <% end %>

<%= if @mobile do %>

<% else %>

<% end %>


Quote action name to fix deprecation

Quote action name to fix deprecation


Improve generated index template styling

Listing <%= plural %>

<%= for {k, _} <- attrs do %>      <%= Phoenix.Naming.camelize(k) %>
<% end %>

<%= "<%=" %> for <%= singular %> <- @<%= plural %> do <%= "%\>" %>

<%= for {k, _} <- attrs do %>      <%= "<%=" %> <%= singular %>.<%= k %> <%= "%\>" %>
<% end %>

        <%= "<%=" %> link "Show", to: <%= singular %>_path(@conn, :show, <%= singular %>), class: "btn btn-default btn-xs" <%= "%\>" %>
        <%= "<%=" %> link "Edit", to: <%= singular %>_path(@conn, :edit, <%= singular %>), class: "btn btn-default btn-xs" <%= "%\>" %>
        <%= "<%=" %> link "Delete", to: <%= singular %>_path(@conn, :delete, <%= singular %>), method: :delete, class: "btn btn-danger btn-xs" <%= "%\>" %>

<%% end %>

<%= "<%=" %> link "New <%= singular %>", to: <%= singular %>_path(@conn, :new), class: "btn btn-primary" <%= "%\>" %>


Add placeholders

Add placeholders

<%= form_for @changeset, post_path(@conn, :create), fn f -> %>

      <%= label f, :title %>

      <%= text_input f, :title, placeholder: "Enter title..." %>

      <%= label f, :body %>

      <%= text_input f, :body, placeholder: "Enter body..." %>

      <%= label f, :channel_id, "Channel" %>

      <%= select f, :channel_id, @channels %>

  <%= submit "Submit" %>
  <%= link("cancel", to: "/") %>
<% end %>

<%= form_for @changeset, post_path(@conn, :create), fn f -> %>

      <%= label f, :title %>

      <%= text_input f, :title %>

      <%= label f, :body %>

      <%= text_input f, :body %>

      <%= label f, :channel_id, "Channel" %>

      <%= select f, :channel_id, @channels %>

  <%= submit "Submit" %>
  <%= link("cancel", to: "/") %>
<% end %>


Update google analytics link

Update google analytics link

Analytics

  <%= link to: analytics_path(@conn, :index, users: true), class: "w-50 no-underline dark-blue dib pa2 dim border-box" do %>

Users

  <% end %>
  <%= link to: analytics_path(@conn, :index, answers: true), class: "w-50 no-underline dark-red dib pa2 dim border-box" do %>

Answers

  <% end %>

Google Analytics

Mailgun Analytics


Update the ad.

Update the ad.

  <%= gettext("Ad") %>

Wunder wirken Wunder: Wie Medizin und Magie uns heilen

von Dr. med. Eckart von Hirschhausen

Ein heilsamer Blick auf die Wunderwelt der Heilkunst
Die Wissenschaft hat die Magie aus der Medizin vertrieben, aber nicht aus uns Menschen.

  amazon.de

  <%= gettext("Ad") %>

Fire HD 6 ab nur 74,99 €

15,2 cm (6 Zoll), HD-Display. 30 € Rabatt auf Fire HD 6 (Limone)

  amazon.de


embed bigger font

embed bigger font

<title>Liquio Inline</title>

<div class="area" style="background: <%= score_color(@poll) %>;">

			<%= if @poll.choice_type == "time_quantity" do %>

					<%= if Enum.empty?(@poll.results.by_datetime) do %>
						?
					<% else %>
						<%= render "chart.html", points: @poll.results.by_datetime |> Enum.map(& {&1.datetime, &1.mean, &1.turnout_ratio}), tooltips: false %>
					<% end %>

			<% else %>
				<%= if @poll.results.mean != nil do %>
					<%= if @poll.choice_type == "probability" do %>
						<%= round(@poll.results.mean * 100) %>%
					<% else %>
						<%= number_format(@poll.results.mean) %>
					<% end %>
				<% else %>
					?
				<% end %>

				<%= round(@poll.results.turnout_ratio * 100) %>% turnout
			<% end %>


Page title

Page title

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Gomoku</title>
    <link rel="stylesheet" href="/css/phoenix.css">
    <link rel="stylesheet" href="/css/app.css">

Gomoku

      <%= @inner %>

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Hello Phoenix!</title>
    <link rel="stylesheet" href="/css/phoenix.css">
    <link rel="stylesheet" href="/css/app.css">

Gomoku

      <%= @inner %>


adding rudex

adding rudex

<!DOCTYPE html>

	<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
	<meta content="width=device-width, initial-scale=1" name="viewport">
	<meta content="BeyondBOINC displays the recently created content from a curated list of Steemit authors on the topics of cryptocurrency, distributed computing and technology." name="description">
	<meta content="Gridcoin, Bitshares, Steemit, Cryptocurrency, Blog, Aggregator, Glasnost, BOINC, BeyondBitcoin, BeyondBOINC, Distributed Computing, Cloud computing, Science, Peerplays, Blockchain, Decentralization, money, science, technology, crypto" name="keywords">
	<meta content="Customminer aka @cm-steem" name="author">
	<meta content="index, follow" name="robots">
	<meta content="1 days" name="revisit-after">

	<link rel="apple-touch-icon" sizes="57x57" href="/images/apple-icon-57x57.png">
	<link rel="apple-touch-icon" sizes="60x60" href="/images/apple-icon-60x60.png">
	<link rel="apple-touch-icon" sizes="72x72" href="/images/apple-icon-72x72.png">
	<link rel="apple-touch-icon" sizes="76x76" href="/images/apple-icon-76x76.png">
	<link rel="apple-touch-icon" sizes="114x114" href="/images/apple-icon-114x114.png">
	<link rel="apple-touch-icon" sizes="120x120" href="/images/apple-icon-120x120.png">
	<link rel="apple-touch-icon" sizes="144x144" href="/images/apple-icon-144x144.png">
	<link rel="apple-touch-icon" sizes="152x152" href="/images/apple-icon-152x152.png">
	<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-icon-180x180.png">
	<link rel="icon" type="image/png" sizes="192x192"  href="/images/android-icon-192x192.png">
	<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
	<link rel="icon" type="image/png" sizes="96x96" href="/images/favicon-96x96.png">
	<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
	<link rel="manifest" href="/images/manifest.json">
	<meta name="msapplication-TileColor" content="#ffffff">
	<meta name="msapplication-TileImage" content="/images/ms-icon-144x144.png">
	<meta name="theme-color" content="#ffffff">

	<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

	<link href="https://beyondboinc.net" rel="canonical">
	<title>BeyondBOINC: <%= naive_translate("head title", @conn.assigns[:lang])%></title>
 	<link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
 	<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/semantic.css" rel="stylesheet">

          			<img class="logo" src="/images/<%=naive_image_chooser("logo", @conn.assigns[:lang])%>">
          			BeyondBOINC

	        	<a href="/authors/<%=@conn.assigns[:about_blog_author]%>/<%=@conn.assigns[:about_blog_permlink]%>" class="item"><%=naive_translate("about", @conn.assigns[:lang])%>

					Trade GRC

							 Decentralized Exchanges

									BitSquare

									OpenLedger

									Rudex

									BTSABC

								<civ class="item">
									FreedomLedger
								</civ>

									BTSBOTS

									Bitshares-Light

							 Centralized Exchanges

									HolyTransactions

									Poloniex

									C-Cex

									Bittrex

							 Explorers

									GridcoinStats

									GridResearchCorp

									Explorer.Gridcoin.Asia

									HolyTransactions

							 Exchange Stats

									CoinMarketCap

									CoinGecko

									CoinCap

					BOINC links

							 Official

									BOINC Website

									BOINC Forums

									GitHub

							 Services

									FormulaBOINC

									User of the day

									Desktop Grid Federation

									Boincstats

									Statsbzh

									DC-Vault

									Free-DC

							 Team Forums

									Rechenkraft

									SETI Germany

									SETI USA

									Free-DC

									Czech national team

									L'Alliance Francophone

									Overclock.Net

									Planet3DNow

					BOINC Projects

							 Physical Science

ATLAS@Home

Cosmology@Home

LHC@Home

theSkyNet POGS

Universe@home

Asteroids@home

Einstein@home

Milkyway@home

SETI@home

							 Multiple Applications

Citizen Science Grid

SZTAKI Desktop Grid

World Community Grid

yoyo@home

							 Mathematics and Computing

Enigma@Home

NFS@Home

NumberFields@home

SRBase

VGTU

YAFU

Amicable Numbers

Collatz Conjecture

Moo! Wrapper

PrimeGrid

							 Earth Sciences

Leiden Classical

							 Biology and Medicine

Rosetta@Home

GPUgrid

					Community links

							 Gridcoin

									Official Website

									Forums

									GitHub

									Twitter

									Steemit

									Telegram

									Reddit

									IRC

									GRC MediaWiki

									GRC @ Wikipedia

							 Bitshares

									Official website

									Forums

									Telegram

									Explorer

							 Peerplays

									Official website

									Telegram

									Peerplays.chat

									GitHub

							 Steemit

									Official website

									Telegram

									Steemit.Chat

									GitHub

									Applications

									Explorer

				  <input placeholder="Search..." type="text" id="Search">
				  <button class="ui icon button" id="Button">

				  </button>

				<%= if get_flash(@conn, :info) do %>

						<%= get_flash(@conn, :info) %>

				<%end %>
				<%= if get_flash(@conn, :error) do %>

						<%= get_flash(@conn, :error) %>

				<%end %>

			<%= render @view_module, @view_template, assigns %>

Promoted Tags

	            Gridcoin
	            BOINC
	            Bitshares
	            BeyondBitcoin
	            Cryptocurrency

Promoted Authors

	            @CM-Steem
	            @OfficialFuzzy
	            @Erkan
	            @SC-Steemit
	            @moisesmcardona

Affiliate links

	            Vultr
	            Namecheap
	            NordVPN
	            Purse.IO
	            CoinPayments

About

BeyondBOINC is a Steemit backed blog, powered by the  Glasnost  library & is actively maintained by @CM-STEEM.

Want to be a featured author? Join the BeyondBOINC Telegram Chat to apply.

GRC Address: SCyjzkycFPZ1pgR2WP4xvk9o5AD5kArWfX

	      <img class="ui centered mini image" src="/images/<%=naive_image_chooser("logo", @conn.assigns[:lang])%>">

	        Home
	        Site Map
	        BeyondBOINC Telegram Chat

<!DOCTYPE html>

	<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
	<meta content="width=device-width, initial-scale=1" name="viewport">
	<meta content="BeyondBOINC displays the recently created content from a curated list of Steemit authors on the topics of cryptocurrency, distributed computing and technology." name="description">
	<meta content="Gridcoin, Bitshares, Steemit, Cryptocurrency, Blog, Aggregator, Glasnost, BOINC, BeyondBitcoin, BeyondBOINC, Distributed Computing, Cloud computing, Science, Peerplays, Blockchain, Decentralization, money, science, technology, crypto" name="keywords">
	<meta content="Customminer aka @cm-steem" name="author">
	<meta content="index, follow" name="robots">
	<meta content="1 days" name="revisit-after">

	<link rel="apple-touch-icon" sizes="57x57" href="/images/apple-icon-57x57.png">
	<link rel="apple-touch-icon" sizes="60x60" href="/images/apple-icon-60x60.png">
	<link rel="apple-touch-icon" sizes="72x72" href="/images/apple-icon-72x72.png">
	<link rel="apple-touch-icon" sizes="76x76" href="/images/apple-icon-76x76.png">
	<link rel="apple-touch-icon" sizes="114x114" href="/images/apple-icon-114x114.png">
	<link rel="apple-touch-icon" sizes="120x120" href="/images/apple-icon-120x120.png">
	<link rel="apple-touch-icon" sizes="144x144" href="/images/apple-icon-144x144.png">
	<link rel="apple-touch-icon" sizes="152x152" href="/images/apple-icon-152x152.png">
	<link rel="apple-touch-icon" sizes="180x180" href="/images/apple-icon-180x180.png">
	<link rel="icon" type="image/png" sizes="192x192"  href="/images/android-icon-192x192.png">
	<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
	<link rel="icon" type="image/png" sizes="96x96" href="/images/favicon-96x96.png">
	<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
	<link rel="manifest" href="/images/manifest.json">
	<meta name="msapplication-TileColor" content="#ffffff">
	<meta name="msapplication-TileImage" content="/images/ms-icon-144x144.png">
	<meta name="theme-color" content="#ffffff">

	<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

	<link href="https://beyondboinc.net" rel="canonical">
	<title>BeyondBOINC: <%= naive_translate("head title", @conn.assigns[:lang])%></title>
 	<link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
 	<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.10/semantic.css" rel="stylesheet">

          			<img class="logo" src="/images/<%=naive_image_chooser("logo", @conn.assigns[:lang])%>">
          			BeyondBOINC

	        	<a href="/authors/<%=@conn.assigns[:about_blog_author]%>/<%=@conn.assigns[:about_blog_permlink]%>" class="item"><%=naive_translate("about", @conn.assigns[:lang])%>

					Trade GRC

							 Decentralized Exchanges

									BitSquare

									OpenLedger

									BTSABC

								<civ class="item">
									FreedomLedger
								</civ>

									BTSBOTS

									Bitshares-Light

							 Centralized Exchanges

									HolyTransactions

									Poloniex

									C-Cex

									Bittrex

							 Explorers

									GridcoinStats

									GridResearchCorp

									Explorer.Gridcoin.Asia

									HolyTransactions

							 Exchange Stats

									CoinMarketCap

									CoinGecko

									CoinCap

					BOINC links

							 Official

									BOINC Website

									BOINC Forums

									GitHub

							 Services

									FormulaBOINC

									User of the day

									Desktop Grid Federation

									Boincstats

									Statsbzh

									DC-Vault

									Free-DC

							 Team Forums

									Rechenkraft

									SETI Germany

									SETI USA

									Free-DC

									Czech national team

									L'Alliance Francophone

									Overclock.Net

									Planet3DNow

					BOINC Projects

							 Physical Science

ATLAS@Home

Cosmology@Home

LHC@Home

theSkyNet POGS

Universe@home

Asteroids@home

Einstein@home

Milkyway@home

SETI@home

							 Multiple Applications

Citizen Science Grid

SZTAKI Desktop Grid

World Community Grid

yoyo@home

							 Mathematics and Computing

Enigma@Home

NFS@Home

NumberFields@home

SRBase

VGTU

YAFU

Amicable Numbers

Collatz Conjecture

Moo! Wrapper

PrimeGrid

							 Earth Sciences

Leiden Classical

							 Biology and Medicine

Rosetta@Home

GPUgrid

					Community links

							 Gridcoin

									Official Website

									Forums

									GitHub

									Twitter

									Steemit

									Telegram

									Reddit

									IRC

									GRC MediaWiki

									GRC @ Wikipedia

							 Bitshares

									Official website

									Forums

									Telegram

									Explorer

							 Peerplays

									Official website

									Telegram

									Peerplays.chat

									GitHub

							 Steemit

									Official website

									Telegram

									Steemit.Chat

									GitHub

									Applications

									Explorer

				  <input placeholder="Search..." type="text" id="Search">
				  <button class="ui icon button" id="Button">

				  </button>

				<%= if get_flash(@conn, :info) do %>

						<%= get_flash(@conn, :info) %>

				<%end %>
				<%= if get_flash(@conn, :error) do %>

						<%= get_flash(@conn, :error) %>

				<%end %>

			<%= render @view_module, @view_template, assigns %>

Promoted Tags

	            Gridcoin
	            BOINC
	            Bitshares
	            BeyondBitcoin
	            Cryptocurrency

Promoted Authors

	            @CM-Steem
	            @OfficialFuzzy
	            @Erkan
	            @SC-Steemit
	            @moisesmcardona

Affiliate links

	            Vultr
	            Namecheap
	            NordVPN
	            Purse.IO
	            CoinPayments

About

BeyondBOINC is a Steemit backed blog, powered by the  Glasnost  library & is actively maintained by @CM-STEEM.

Want to be a featured author? Join the BeyondBOINC Telegram Chat to apply.

GRC Address: SCyjzkycFPZ1pgR2WP4xvk9o5AD5kArWfX

	      <img class="ui centered mini image" src="/images/<%=naive_image_chooser("logo", @conn.assigns[:lang])%>">

	        Home
	        Site Map
	        BeyondBOINC Telegram Chat


Layout silliness

Layout silliness

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Teal</title>
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

        Teal

        About
        Create

        <%= if get_flash(@conn, :info) do %>

<%= get_flash(@conn, :info) %>

        <% end %>
        <%= if get_flash(@conn, :error) do %>

<%= get_flash(@conn, :error) %>

        <% end %>

        <%= render @view_module, @view_template, assigns %>


Hide the plotly logo

Hide the plotly logo

<!DOCTYPE html>

    <meta http-equiv="content-type" content="text/html; charset=utf8">

Comparison

Data Table

              Name
              Iterations per Second
              Average
              Deviation
              median

            <%= for {name, statistics} <- suite.statistics do %>

                <%= name %>
                <%= statistics.ips %>
                <%= statistics.average %>
                <%= statistics.std_dev_ratio %>%
                <%= statistics.median %>

            <% end %>

    <%= for {name, _} <- suite.run_times do %>

 <%= name %>

          <div class="sorted-run-times" data-job-name="<%= name %>">

          <div class="raw-run-times" data-job-name="<%= name %>">

    <% end %>


checkbox hack for user menu

checkbox hack for user menu

  <button type="button"
          class="navbar-toggle collapsed"
          data-toggle="collapse"
          data-target="#navbar"
          aria-expanded="false"
          aria-controls="navbar">
    Toggle navigation

  </button>

  Panoptikum.io

<%= link "Home", to: category_frontend_path(@conn, :index) %>

<%= link "Podcasters", to: user_frontend_path(@conn, :index) %>

<%= link ["Random ", fa_icon("podcast")], to: recommendation_frontend_path(@conn, :random) %>

    <%= if @current_user do %>
      <input type="checkbox" id="checkbox_toggle" class="drop">

        @<%= @current_user.username %>

<%= link "My Profile",  to: user_frontend_path(@conn, :my_profile)%>

<%= link "Change Password", to: user_frontend_path(@conn, :edit_password)%>

<%= link "My Messages", to: user_frontend_path(@conn, :my_messages)%>

<%= link "My Podcasts", to: user_frontend_path(@conn, :my_podcasts)%>

<%= link "My Recommendations", to: recommendation_frontend_path(@conn, :my_recommendations)%>

<%= link "My OPMLs",    to: opml_frontend_path(@conn, :index)%>

      <%= if @current_user.admin do %>
        <input type="checkbox" id="checkbox_admin" class="drop-admin">

          Admin

<%= link "Categories",      to: category_path(@conn, :index) %>

<%= link "Feed Backlog",    to: feed_backlog_path(@conn, :index) %>

<%= link "Languages",       to: language_path(@conn, :index) %>

<%= link "Podcasts",        to: podcast_path(@conn, :index) %>

<%= link "Users",           to: user_path(@conn, :index) %>

<%= link "OPMLs",           to: opml_path(@conn, :index) %>

<%= link "Messages",      to: message_path(@conn, :index) %>

<%= link "Likes",           to: like_path(@conn, :index) %>

<%= link "Follows",         to: follow_path(@conn, :index) %>

<%= link "Subscriptions",   to: subscription_path(@conn, :index) %>

<%= link "Recommendations", to: recommendation_path(@conn, :index) %>

      <% end %>

          <%= link "Log out", to: session_path(@conn, :delete, @current_user),
                              method: "delete" %>

    <% else %>

<%= link "Register", to: user_path(@conn, :new) %>

<%= link "Log in", to: session_path(@conn, :new) %>

    <% end %>


Stupid fix

Stupid fix

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Brainstorming</title>

  </head>
  <body>

    <script id="userstate" type="application/json">
{"user_id": "<%= @user.id %>", "room": <%= @room %>,
"user_nick": "<%= @user.nick %>",
"admin": <%= @admin %>,
"chat_enabled": <%= @chat_enabled %>,
"title": "<%= @title %>",
"embed": "<%= @embed %>",
"room": <%= @room %>}

    </script>
    <script src="/live/bundle.js"></script>
  </body>
</html>

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Brainstorming</title>

  </head>
  <body>

    <script id="userstate" type="application/json">
{"user_id": "<%= @user.id %>", "room": <%= @room %>,
"user_nick": "<%= @user.nick %>",
"admin": <%= @dev %>,
"chat_enabled": <%= @chat_enabled %>,
"title": "<%= @title %>",
"embed": "<%= @embed %>",
"room": <%= @room %>}

    </script>
    <script src="/live/bundle.js"></script>
  </body>
</html>


Simplify admin overview

Simplify admin overview

      #
      Date
      Title

      detail
      clicks in post

  <%= for posting <- @postings do %>

      <%= posting.id %>
      <%= human_readable_date posting.published_at %>
      <%= link ElixirStatus.Publisher.short_title(posting.title, 30), to: permalink_posting_path(@conn, :show, posting.permalink), title: strip_tags(posting.title) %>
      <%= if false do %>

          <%= ElixirStatus.Impressionist.count_sessions "frontpage", "posting", posting.uid %>

            /
            <a href="/admin/impressions?context=frontpage&subject_type=posting&subject_uid=<%= posting.uid %>">
              <%= ElixirStatus.Impressionist.count "frontpage", "posting", posting.uid %>

          <%= ElixirStatus.Impressionist.count_sessions "rss", "posting", posting.uid %>

          <%= ElixirStatus.Impressionist.count_sessions "detail", "short_link", to_short_uid(posting.permalink) %>

            /
            <a href="/admin/impressions?subject_type=short_link&subject_uid=<%= to_short_uid(posting.permalink) %>">
              <%= ElixirStatus.Impressionist.count "detail", "short_link", to_short_uid(posting.permalink) %>

      <% end %>

        <%= ElixirStatus.Impressionist.count_sessions "detail", "posting", posting.uid %>

          /
          <a href="/admin/impressions?context=detail&subject_type=posting&subject_uid=<%= posting.uid %>">
            <%= ElixirStatus.Impressionist.count "detail", "posting", posting.uid %>

        <a href="/admin/impressions?context=<%= "postings:#{posting.uid}" %>&subject_type=short_link">
          <%= ElixirStatus.Impressionist.count "postings:#{posting.uid}", "short_link" %>

  <% end %>

      #
      Date
      Title
      frontpage
      rss
      detail
      via shortlink
      clicks in post

  <%= for posting <- @postings do %>

      <%= posting.id %>
      <%= human_readable_date posting.published_at %>
      <%= link ElixirStatus.Publisher.short_title(posting.title, 30), to: permalink_posting_path(@conn, :show, posting.permalink), title: strip_tags(posting.title) %>

        <%= ElixirStatus.Impressionist.count_sessions "frontpage", "posting", posting.uid %>

          /
          <a href="/admin/impressions?context=frontpage&subject_type=posting&subject_uid=<%= posting.uid %>">
            <%= ElixirStatus.Impressionist.count "frontpage", "posting", posting.uid %>

        <%= ElixirStatus.Impressionist.count_sessions "rss", "posting", posting.uid %>

        <%= ElixirStatus.Impressionist.count_sessions "detail", "posting", posting.uid %>

          /
          <a href="/admin/impressions?context=detail&subject_type=posting&subject_uid=<%= posting.uid %>">
            <%= ElixirStatus.Impressionist.count "detail", "posting", posting.uid %>

        <%= ElixirStatus.Impressionist.count_sessions "detail", "short_link", to_short_uid(posting.permalink) %>

          /
          <a href="/admin/impressions?subject_type=short_link&subject_uid=<%= to_short_uid(posting.permalink) %>">
            <%= ElixirStatus.Impressionist.count "detail", "short_link", to_short_uid(posting.permalink) %>

        <a href="/admin/impressions?context=<%= "postings:#{posting.uid}" %>&subject_type=short_link">
          <%= ElixirStatus.Impressionist.count "postings:#{posting.uid}", "short_link" %>

  <% end %>


remove inspect

remove inspect

      <img class="logo" src="/images/<%=naive_image_chooser("logo", @conn.assigns[:lang])%>">

    <%= if false do %>
    <%=naive_translate("home", @conn.assigns[:lang])%>

    <a href="/authors/<%=@conn.assigns[:about_blog_author]%>/<%=@conn.assigns[:about_blog_permlink]%>" class="item"><%=naive_translate("about", @conn.assigns[:lang])%>
    <a href="<%=if @conn.assigns[:lang] == "ru", do: "https://golos.io", else: "https://steemit.com"%>" class="item"><%=naive_translate("about_steemlike_chain", @conn.assigns[:lang])%>
    <% else %>
    <%= for %{item: item, dropdown_items: dropdown_items} <- @conn.assigns.menu do %>

          <%= item %>

            <%= for [title, link] <- dropdown_items do %>
              <a href="<%= link %>" class="item"><%= title %>
            <% end %>

      <% end %>
    <% end %>

      <img class="logo" src="/images/<%=naive_image_chooser("logo", @conn.assigns[:lang])%>">

    <%= if false do %>
    <%=naive_translate("home", @conn.assigns[:lang])%>

    <a href="/authors/<%=@conn.assigns[:about_blog_author]%>/<%=@conn.assigns[:about_blog_permlink]%>" class="item"><%=naive_translate("about", @conn.assigns[:lang])%>
    <a href="<%=if @conn.assigns[:lang] == "ru", do: "https://golos.io", else: "https://steemit.com"%>" class="item"><%=naive_translate("about_steemlike_chain", @conn.assigns[:lang])%>
    <% else %>
    <%= for %{item: item, dropdown_items: dropdown_items} <- IO.inspect(@conn.assigns.menu) do %>

          <%= item %>

            <%= for [title, link] <- dropdown_items do %>
              <a href="<%= link %>" class="item"><%= title %>
            <% end %>

      <% end %>
    <% end %>


Modify filters DOM

Modify filters DOM

  <%= form_for @conn, offer_path(@conn, :index), [as: :filter], fn f -> %>

      <%= text_input(f, :text,
        id: "filter_text",
        class: class_with_error(f, :text, "text"),
        placeholder: gettext("Search offers by title, location..."),
        required: true) %>

      <%= select(f, :job_place, get_job_place_options(gettext("Any job place"))) %>

    <%= select(f, :job_type, get_job_type_options(gettext("Any job type"))) %>

    <%= submit(gettext("Search"), class: "btn-success") %>
  <% end %>

  <%= form_for @conn, offer_path(@conn, :index), [as: :filter], fn f -> %>
    <%= text_input(f, :text,
      id: "filter_text",
      class: class_with_error(f, :text, "text"),
      placeholder: gettext("Search by title, location..."),
      required: true) %>
    <%= select(f, :job_place, get_job_place_options(gettext("Any job place"))) %>
    <%= select(f, :job_type, get_job_type_options(gettext("Any job type"))) %>
    <%= submit(gettext("Filter"), class: "btn-success") %>
  <% end %>


Sample size in HTML table

Sample size in HTML table

<!DOCTYPE html>

    <meta http-equiv="content-type" content="text/html; charset=utf8">

Comparison

Data Table

              Name
              Iterations per Second
              Average
              Deviation
              median
              Sample size

            <%= for {name, statistics} <- suite.statistics do %>

                <%= name %>
                <%= statistics.ips %>
                <%= statistics.average %>
                <%= statistics.std_dev_ratio %>%
                <%= statistics.median %>
                <%= Enum.count(suite.run_times[name]) %>

            <% end %>

    <%= for {name, _} <- suite.run_times do %>

 <%= name %>

          <div class="sorted-run-times" data-job-name="<%= name %>">

          <div class="raw-run-times" data-job-name="<%= name %>">

    <% end %>


Add `saltedge_transaction_id` to transactions list

  <%= render ExMoney.SharedView, "dashboard_navbar.html", conn: @conn, navigation: @navigation %>

Transactions [<%= link "New", to: transaction_path(@conn, :new) %>]

            Saltedge Id
            Date
            Payee
            Description
            Category
            Amount
            Account

          <%= for transaction <- @transactions do %>

              <%= transaction.saltedge_transaction_id %>
              <%= transaction.made_on %>
              <%= payee(transaction) %>
              <%= transaction.description %>
              <%= transaction.category.humanized_name %>
              <%= transaction.amount %>
              <%= account(transaction) %>

          <% end %>

        <li class="previous <%= disabled_previous_page?(@page_number, @total_pages) %>">
          <a href="<%= build_previous_page_url(@page_number) %>">
            ← Newer

        <li class="next <%= disabled_next_page?(@page_number, @total_pages) %>">
          <a href="<%= build_next_page_url(@page_number, @total_pages)%>">
            Older →

  <%= render ExMoney.SharedView, "dashboard_navbar.html", conn: @conn, navigation: @navigation %>

Transactions [<%= link "New", to: transaction_path(@conn, :new) %>]

            Date
            Payee
            Description
            Category
            Amount
            Account

          <%= for transaction <- @transactions do %>

              <%= transaction.made_on %>
              <%= payee(transaction) %>
              <%= transaction.description %>
              <%= transaction.category.humanized_name %>
              <%= transaction.amount %>
              <%= account(transaction) %>

          <% end %>

        <li class="previous <%= disabled_previous_page?(@page_number, @total_pages) %>">
          <a href="<%= build_previous_page_url(@page_number) %>">
            ← Newer

        <li class="next <%= disabled_next_page?(@page_number, @total_pages) %>">
          <a href="<%= build_next_page_url(@page_number, @total_pages)%>">
            Older →