mkextenv - A script to quickstart overlay extension development

Add-ons for Pale Moon and other applications
General discussion, compatibility, contributed extensions, themes, plugins, and more.

Moderators: FranklinDM, Lootyhoof

vannilla
Moon Magic practitioner
Moon Magic practitioner
Posts: 2193
Joined: 2018-05-05, 13:29

mkextenv - A script to quickstart overlay extension development

Unread post by vannilla » 2019-06-11, 18:55

I wrote a small script that automatically builds a "project tree" for an overlay extension (i.e. that one requiring a restart.)
I generates a minimal install.rdf and a chrome.manifest, an empty skin and a XUL overlay loading a locale DTD and an empty JS script.
It also generates a folder for preferences and of course the (en-US) locale folder with the DTD and properties files.

It's written for the bash shell, because I have no idea what Windows programmers use (are batch files still a thing?), and for the first version I opted to use something I have and I find easy to work with.
I'd like to make it "multiplatform", but I need to know what other people expect me to use before working on anything.

It seems I can't attach the file for some reason, so here's a code block with the whole thing in it:

Code: Select all

#!/bin/bash

# Copyright 2019 Alessio Vanni

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:

# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.

# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THIS=$(basename $0)

VERSION="1.0.0"

DIRPATH=""
ID=""
NAME=""

ERROR=0

function usage() {
    echo "$THIS - Create a basic environment for extension development"
    echo
    echo "Usage:"
    echo "$THIS -n NAME -p PATH -i ID"
    echo "$THIS -h"
    echo "$THIS -V"
    echo
    echo -e "-n NAME\tGive the extension the name NAME (Required)"
    echo -e "-p PATH\tUse PATH as root directory (Required)"
    echo -e "-i ID\tUse the id ID in install.rdf (Required)"
    echo
    echo -e "-h\tShow this message"
    echo -e "-V\tShow the program's version"
}

while getopts 'hVp:n:i:' opts; do
    case $opts in
	'h') usage
	     exit 1
	     ;;
	'V') echo "$VERSION"
	     exit 1
	     ;;
	'n') NAME=$OPTARG
	     ;;
	'i') ID=$OPTARG
	     ;;
	'p') DIRPATH=$OPTARG
	     ;;
    esac
done

if test "x$DIRPATH" == "x" -o "x$ID" == "x" -o "x$NAME" == "x"; then
    echo 'Error: Missing required option'
    usage
    exit 1
fi

if test -d $DIRPATH -o -f $DIRPATH; then
    echo "$DIRPATH already exists"
    exit 1
fi

echo "Generating extension '$NAME' with id '$ID' in '$DIRPATH'"
echo

mkdir -p $DIRPATH
cd $DIRPATH

mkdir -p content locale/en-US skin defaults/preferences

echo 'Generating install.rdf...'
cat <<EOF > install.rdf
<?xml version='1.0' encoding='utf-8'?>

<!-- REMEMBER TO PLACE YOUR LICENSE BLOCK HERE -->

<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       xmlns="http://www.mozilla.org/2004/em-rdf#">
  <r:Description about="urn:mozilla:install-manifest">
    <id>$ID</id>
    <type>2</type>
    <name>$NAME</name>
    <description></description>
    <version>1.0.0</version>

    <targetApplication>
      <r:Description>
        <id>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</id>
        <minVersion>28.0</minVersion>
        <maxVersion>28.*</maxVersion>
      </r:Description>
    </targetApplication>
  </r:Description>
</r:RDF>
EOF

SLUG=$(echo $NAME | tr A-Z a-z | tr -d ' ')

echo 'Generating chrome.manifest...'
cat <<EOF > chrome.manifest
# REMEMBER TO PLACE YOUR LICENSE BLOCK HERE

content $SLUG content/
skin $SLUG classic/1.0 skin/
overlay chrome://browser/content/browser.xul chrome://$SLUG/content/overlay.xul
locale $SLUG en-US locale/en-US/
EOF

echo 'Generating content/overlay.xul...'
cat <<EOF > content/overlay.xul
<?xml version='1.0' encoding='utf-8'?>

<!-- REMEMBER TO PLACE YOUR LICENSE BLOCK HERE -->

<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?sml-stylesheet href="chrome://$SLUG/skin/overlay.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://$SLUG/locale/translations.dtd">

<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         id="$SLUG-overlay">
  <stringbundleset id="stringbundleset">
    <stringbundle id="strings"
                  src="chrome://$SLUG/locale/strings.properties">
    </stringbundle>
  </stringbundleset>

  <script src="overlay.js"></script>
</overlay>
EOF

echo 'Generating content/overlay.js...'
cat <<EOF > content/overlay.js
// REMEMBER TO PLACE YOUR LICENSE BLOCK HERE

'use strict';
EOF

echo 'Generating skin/overlay.css...'
cat <<EOF > skin/overlay.css
/* REMEMBER TO PLACE YOUR LICENSE BLOCK HERE */
EOF

echo 'Generating locale/translations.dtd...'
cat <<EOF > locale/en-US/translations.dtd
<!-- REMEBER TO PLACE YOUR LICENSE BLOCK HERE -->
EOF

echo 'Generating locale/strings.properties...'
cat <<EOF > locale/en-US/strings.properties
# REMEMBER TO PLACE YOUR LICENSE BLOCK HERE
EOF

echo 'Generating defaults/prefs.js...'
cat <<EOF > defaults/preferences/prefs.js
// REMEMBER TO PLACE YOUR LICENSE BLOCK HERE
EOF

echo
echo 'All done!'
echo

echo '+-----------------------------------------+'
echo '| Remember to review the generated files! |'
echo '+-----------------------------------------+'


User avatar
plushkava
Apollo supporter
Apollo supporter
Posts: 46
Joined: 2015-07-31, 04:53
Location: Clown World

Re: mkextenv - A script to quickstart overlay extension development

Unread post by plushkava » 2019-06-16, 11:29

Thanks for this. While bash is a fine shell, It's already so very close to being a pure sh script that you might consider making it so, given that portability is mentioned as a potential goal. Below is a diff that removes the bashisms. Those were the use of the function keyword, the use of echo -e and the use of == in tests (as opposed to =). It also fixes up some minor quality issues. This version should work in any implementation of /bin/sh, and even the likes of busybox-w32 in Windows. Naturally, it will continue to work in bash too, whether masquerading as /bin/sh or not.

By the way, cmd.exe is alive and well in WIndows, although Microsoft are downplaying its existence in the Windows 10 UI, in favour of PowerShell.

EDIT: Unintentionally removed needed exit statements in options check. Fixed.

Code: Select all

--- t22297.0	2019-06-16 12:47:14.413803631 +0100
+++ t22297	2019-06-16 12:46:58.400622535 +0100
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 # Copyright 2019 Alessio Vanni
 
@@ -25,7 +25,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-THIS=$(basename $0)
+THIS=${0##*/}
 
 VERSION="1.0.0"
 
@@ -33,9 +33,7 @@
 ID=""
 NAME=""
 
-ERROR=0
-
-function usage() {
+usage() {
     echo "$THIS - Create a basic environment for extension development"
     echo
     echo "Usage:"
@@ -43,21 +41,21 @@
     echo "$THIS -h"
     echo "$THIS -V"
     echo
-    echo -e "-n NAME\tGive the extension the name NAME (Required)"
-    echo -e "-p PATH\tUse PATH as root directory (Required)"
-    echo -e "-i ID\tUse the id ID in install.rdf (Required)"
+    printf '%s\t%s\n' "-n NAME" "Give the extension the name NAME (Required)"
+    printf '%s\t%s\n' "-p PATH" "Use PATH as root directory (Required)"
+    printf '%s\t%s\n' "-i ID" "Use the id ID in install.rdf (Required)"
     echo
-    echo -e "-h\tShow this message"
-    echo -e "-V\tShow the program's version"
+    printf '%s\t%s\n' "-h" "Show this message"
+    printf '%s\t%s\n' "-V" "Show the program's version"
 }
 
 while getopts 'hVp:n:i:' opts; do
     case $opts in
 	'h') usage
-	     exit 1
+	     exit
 	     ;;
 	'V') echo "$VERSION"
-	     exit 1
+	     exit
 	     ;;
 	'n') NAME=$OPTARG
 	     ;;
@@ -65,30 +63,32 @@
 	     ;;
 	'p') DIRPATH=$OPTARG
 	     ;;
+	  *) usage
+	     exit 1
+	     ;;
     esac
 done
 
-if test "x$DIRPATH" == "x" -o "x$ID" == "x" -o "x$NAME" == "x"; then
-    echo 'Error: Missing required option'
+if [ -z "$DIRPATH" ] || [ -z "$ID" ] || [ -z "$NAME" ]; then
+    echo 'Error: Missing required option' >&2
     usage
     exit 1
 fi
 
-if test -d $DIRPATH -o -f $DIRPATH; then
-    echo "$DIRPATH already exists"
+if [ -e "$DIRPATH" ]; then
+    echo "$DIRPATH already exists" >&2
     exit 1
 fi
 
 echo "Generating extension '$NAME' with id '$ID' in '$DIRPATH'"
 echo
 
-mkdir -p $DIRPATH
-cd $DIRPATH
-
-mkdir -p content locale/en-US skin defaults/preferences
+mkdir -p "$DIRPATH" &&
+cd "$DIRPATH" &&
+mkdir -p content locale/en-US skin defaults/preferences || exit
 
 echo 'Generating install.rdf...'
-cat <<EOF > install.rdf
+cat <<EOF > install.rdf || exit
 <?xml version='1.0' encoding='utf-8'?>
 
 <!-- REMEMBER TO PLACE YOUR LICENSE BLOCK HERE -->
@@ -113,10 +113,10 @@
 </r:RDF>
 EOF
 
-SLUG=$(echo $NAME | tr A-Z a-z | tr -d ' ')
+SLUG=$(printf %s "$NAME" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')
 
 echo 'Generating chrome.manifest...'
-cat <<EOF > chrome.manifest
+cat <<EOF > chrome.manifest || exit
 # REMEMBER TO PLACE YOUR LICENSE BLOCK HERE
 
 content $SLUG content/
@@ -126,7 +126,7 @@
 EOF
 
 echo 'Generating content/overlay.xul...'
-cat <<EOF > content/overlay.xul
+cat <<EOF > content/overlay.xul || exit
 <?xml version='1.0' encoding='utf-8'?>
 
 <!-- REMEMBER TO PLACE YOUR LICENSE BLOCK HERE -->
@@ -148,29 +148,29 @@
 EOF
 
 echo 'Generating content/overlay.js...'
-cat <<EOF > content/overlay.js
+cat <<EOF > content/overlay.js || exit
 // REMEMBER TO PLACE YOUR LICENSE BLOCK HERE
 
 'use strict';
 EOF
 
 echo 'Generating skin/overlay.css...'
-cat <<EOF > skin/overlay.css
+cat <<EOF > skin/overlay.css || exit
 /* REMEMBER TO PLACE YOUR LICENSE BLOCK HERE */
 EOF
 
 echo 'Generating locale/translations.dtd...'
-cat <<EOF > locale/en-US/translations.dtd
+cat <<EOF > locale/en-US/translations.dtd || exit
 <!-- REMEBER TO PLACE YOUR LICENSE BLOCK HERE -->
 EOF
 
 echo 'Generating locale/strings.properties...'
-cat <<EOF > locale/en-US/strings.properties
+cat <<EOF > locale/en-US/strings.properties || exit
 # REMEMBER TO PLACE YOUR LICENSE BLOCK HERE
 EOF
 
 echo 'Generating defaults/prefs.js...'
-cat <<EOF > defaults/preferences/prefs.js
+cat <<EOF > defaults/preferences/prefs.js || exit
 // REMEMBER TO PLACE YOUR LICENSE BLOCK HERE
 EOF
 
@@ -181,5 +181,3 @@
 echo '+-----------------------------------------+'
 echo '| Remember to review the generated files! |'
 echo '+-----------------------------------------+'
-
-

vannilla
Moon Magic practitioner
Moon Magic practitioner
Posts: 2193
Joined: 2018-05-05, 13:29

Re: mkextenv - A script to quickstart overlay extension development

Unread post by vannilla » 2019-06-16, 16:26

Thanks, I applied some of the changes.

Code: Select all

#!/bin/sh

# Copyright 2019 Alessio Vanni

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:

# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.

# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Contributors: plushkava

THIS=$(basename $0)

VERSION="1.1.0"

DIRPATH=""
ID=""
NAME=""

usage() {
    echo "$THIS - Create a basic environment for extension development"
    echo
    echo "Usage:"
    echo "$THIS -n NAME -p PATH -i ID"
    echo "$THIS -h"
    echo "$THIS -V"
    echo
    printf "%s\t%s\n" "-n NAME" "Give the extension the name NAME (Required)"
    printf "%s\t%s\n" "-p PATH" "Use PATH as root directory (Required)"
    printf "%s\t%s\n" "-i ID" "Use the id ID in install.rdf (Required)"
    echo
    printf "%s\t%s\n" "-h" "Show this message"
    printf "%s\t%s\n" "-V" "how the program's version"
}

while getopts 'hVp:n:i:' opts; do
    case $opts in
	'h') usage
	     exit 1
	     ;;
	'V') echo "$VERSION"
	     exit 1
	     ;;
	'n') NAME=$OPTARG
	     ;;
	'i') ID=$OPTARG
	     ;;
	'p') DIRPATH=$OPTARG
	     ;;
	*) usage
	   exit 1
	   ;;
    esac
done

if test "x$DIRPATH" = "x" -o "x$ID" = "x" -o "x$NAME" = "x"; then
    echo 'Error: Missing required option'
    usage
    exit 1
fi

if test -e $DIRPATH; then
    echo "$DIRPATH already exists"
    exit 1
fi

echo "Generating extension '$NAME' with id '$ID' in '$DIRPATH'"
echo

mkdir -p $DIRPATH && cd $DIRPATH &&
    mkdir -p content locale/en-US skin defaults/preferences || exit 1

echo 'Generating install.rdf...'
cat <<EOF > install.rdf || exit 1
<?xml version='1.0' encoding='utf-8'?>

<!-- REMEMBER TO PLACE YOUR LICENSE BLOCK HERE -->

<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       xmlns="http://www.mozilla.org/2004/em-rdf#">
  <r:Description about="urn:mozilla:install-manifest">
    <id>$ID</id>
    <type>2</type>
    <name>$NAME</name>
    <description></description>
    <version>1.0.0</version>

    <targetApplication>
      <r:Description>
        <id>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</id>
        <minVersion>28.0</minVersion>
        <maxVersion>28.*</maxVersion>
      </r:Description>
    </targetApplication>
  </r:Description>
</r:RDF>
EOF

SLUG=$(echo $NAME | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')

echo 'Generating chrome.manifest...'
cat <<EOF > chrome.manifest || exit 1
# REMEMBER TO PLACE YOUR LICENSE BLOCK HERE

content $SLUG content/
skin $SLUG classic/1.0 skin/
overlay chrome://browser/content/browser.xul chrome://$SLUG/content/overlay.xul
locale $SLUG en-US locale/en-US/
EOF

echo 'Generating content/overlay.xul...'
cat <<EOF > content/overlay.xul || exit 1
<?xml version='1.0' encoding='utf-8'?>

<!-- REMEMBER TO PLACE YOUR LICENSE BLOCK HERE -->

<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?sml-stylesheet href="chrome://$SLUG/skin/overlay.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://$SLUG/locale/translations.dtd">

<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         id="$SLUG-overlay">
  <stringbundleset id="stringbundleset">
    <stringbundle id="strings"
                  src="chrome://$SLUG/locale/strings.properties">
    </stringbundle>
  </stringbundleset>

  <script src="overlay.js"></script>
</overlay>
EOF

echo 'Generating content/overlay.js...'
cat <<EOF > content/overlay.js || exit 1
// REMEMBER TO PLACE YOUR LICENSE BLOCK HERE

'use strict';
EOF

echo 'Generating skin/overlay.css...'
cat <<EOF > skin/overlay.css || exit 1
/* REMEMBER TO PLACE YOUR LICENSE BLOCK HERE */
EOF

echo 'Generating locale/translations.dtd...'
cat <<EOF > locale/en-US/translations.dtd || exit 1
<!-- REMEBER TO PLACE YOUR LICENSE BLOCK HERE -->
EOF

echo 'Generating locale/strings.properties...'
cat <<EOF > locale/en-US/strings.properties || exit 1
# REMEMBER TO PLACE YOUR LICENSE BLOCK HERE
EOF

echo 'Generating defaults/prefs.js...'
cat <<EOF > defaults/preferences/prefs.js || exit 1
// REMEMBER TO PLACE YOUR LICENSE BLOCK HERE
EOF

echo
echo 'All done!'
echo

echo '+-----------------------------------------+'
echo '| Remember to review the generated files! |'
echo '+-----------------------------------------+'
Certain things you changed are actually sh-compliant, like test EXP -o EXP, or the basename command.
I tested it with busybox's sh and with OpenBSD's ksh and sh shells, and it worked.
plushkava wrote:
2019-06-16, 11:29
By the way, cmd.exe is alive and well in WIndows, although Microsoft are downplaying its existence in the Windows 10 UI, in favour of PowerShell.
I used to write cmd.exe scripts long ago, maybe I can put something together, if people are actually still using them.

User avatar
plushkava
Apollo supporter
Apollo supporter
Posts: 46
Joined: 2015-07-31, 04:53
Location: Clown World

Re: mkextenv - A script to quickstart overlay extension development

Unread post by plushkava » 2019-06-16, 19:31

vannilla wrote:
2019-06-16, 16:26
Certain things you changed are actually sh-compliant, like test EXP -o EXP, or the basename command.
I tested it with busybox's sh and with OpenBSD's ksh and sh shells, and it worked.
None of the changes were for aesthetic reasons alone. Be cautious in testing as a given implementation will almost always support (various) features and extensions above and beyond the specification. My changes to that particular test were partly motivated by using a non-antiquated syntax (-a and -o are subject to pitfalls, and using -z would be sufficient to test for emptiness). However, if one is to continue using a stringwise equality operator while aiming for POSIX sh conformance then it cannot be ==, because it does not exist. Note that there are some implementations that are more likely than others to complain about non-conforming syntax, such as posh ...

Code: Select all

$ posh
$ test foo = foo; echo $?
0
$ test foo == foo; echo $?
posh: test: ==: unexpected operator/operand
2
Anyway, the syntax of your revised test, while remaining old-fashioned, is now correct for sh.

Incidentally, no conforming shell needs an arbitrary prefix to compare to an empty string; that's very much an antiquity. To perform the test using a string comparison, just "$var" = "" will do. It's the quoting of the variable expansion and the fact that three distinct parameters are provided - including the operator itself - that is important. On the other hand, the bash [[ test keyword has super powers and supports the likes of [[ ! $var ]] which is functionally identical to all of [ "$var" = "" ], [ -z "$var" ] and test "$var" = "".

All of the cases in which I added enclosing double quotes to a variable expansion are addressing real bugs that you may not have noticed in your testing but which, nonetheless, exist. An unquoted variable expansion is subject to both word splitting and other forms of expansion, including pathname expansion, before the resulting command is executed. I can assure you that such is undesirable and that the correct thing to do is to double quote the expansions in question. Even the $0 in the basename command should be double quoted (command substitutions establish their own quoting context). For example, THIS=$(basename "$0") would be correct. I didn't claim that basename is non-standard. It's just that the ${0##*/} parameter expansion does the same thing, faster, and made for another way of addressing the defect. The unquoted $opts following the case keyword is a curious exception where leaving it unquoted is actually safe, but keep in mind that such exceptions are exceedingly rare.

Regarding the assignment of SLUG, the use of printf %s instead of echo defends against the case where your variable expansion happens to look like an echo option, as supported by bash. It simply eliminates another corner case that hinges on user input. The use of A-Z was dangerous because it doesn't mean what one thinks it means, depending on the user's effective collation. Postfix || exit 1 is fine but note that the exit value can be left out, which renders it equivalent to exit $?, thus propagating the real exit status value of the failing command.

vannilla
Moon Magic practitioner
Moon Magic practitioner
Posts: 2193
Joined: 2018-05-05, 13:29

Re: mkextenv - A script to quickstart overlay extension development

Unread post by vannilla » 2019-06-16, 20:42

Some of the unquoted variables are actually errors on my part because I simply forgot to quote them. It's the case of $0 for example.
I'm not sure what the pitfalls of using test EXP -o/-a are; the bourne shell (aka sh) manual says that those options are the way to chain conditional expressions, even when using the [ syntax, so I use them when building a test with multiple conditions.
The "prefix" letter when comparing for empty string is something I picked up from Windows actually, because if I remember correctly cmd.exe has trouble comparing empty strings (or anyway everyone suggested doing it that way and I picked up this usage too.)
It's not inherently wrong and makes sure the check is performed as intended.
Also I don't want to propagate error codes, so exit always give error code 1.

Minor version update:

Code: Select all

#!/bin/sh

# Copyright 2019 Alessio Vanni

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:

# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.

# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Contributors: plushkava

THIS=$(basename "$0")

VERSION="1.1.1"

DIRPATH=""
ID=""
NAME=""

usage() {
    echo "$THIS - Create a basic environment for extension development"
    echo
    echo "Usage:"
    echo "$THIS -n NAME -p PATH -i ID"
    echo "$THIS -h"
    echo "$THIS -V"
    echo
    printf "%s\t%s\n" "-n NAME" "Give the extension the name NAME (Required)"
    printf "%s\t%s\n" "-p PATH" "Use PATH as root directory (Required)"
    printf "%s\t%s\n" "-i ID" "Use the id ID in install.rdf (Required)"
    echo
    printf "%s\t%s\n" "-h" "Show this message"
    printf "%s\t%s\n" "-V" "how the program's version"
}

while getopts 'hVp:n:i:' opts; do
    case $opts in
	'h') usage
	     exit 1
	     ;;
	'V') echo "$VERSION"
	     exit 1
	     ;;
	'n') NAME="$OPTARG"
	     ;;
	'i') ID="$OPTARG"
	     ;;
	'p') DIRPATH="$OPTARG"
	     ;;
	*) usage
	   exit 1
	   ;;
    esac
done

if test "x$DIRPATH" = "x" -o "x$ID" = "x" -o "x$NAME" = "x"; then
    echo 'Error: Missing required option'
    usage
    exit 1
fi

if test -e "$DIRPATH"; then
    echo "$DIRPATH already exists"
    exit 1
fi

echo "Generating extension '$NAME' with id '$ID' in '$DIRPATH'"
echo

mkdir -p "$DIRPATH" && cd "$DIRPATH" &&
    mkdir -p content locale/en-US skin defaults/preferences || exit 1

echo 'Generating install.rdf...'
cat <<EOF > install.rdf || exit 1
<?xml version='1.0' encoding='utf-8'?>

<!-- REMEMBER TO PLACE YOUR LICENSE BLOCK HERE -->

<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       xmlns="http://www.mozilla.org/2004/em-rdf#">
  <r:Description about="urn:mozilla:install-manifest">
    <id>$ID</id>
    <type>2</type>
    <name>$NAME</name>
    <description></description>
    <version>1.0.0</version>

    <targetApplication>
      <r:Description>
        <id>{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}</id>
        <minVersion>28.0</minVersion>
        <maxVersion>28.*</maxVersion>
      </r:Description>
    </targetApplication>
  </r:Description>
</r:RDF>
EOF

SLUG=$(echo "$NAME" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')

echo 'Generating chrome.manifest...'
cat <<EOF > chrome.manifest || exit 1
# REMEMBER TO PLACE YOUR LICENSE BLOCK HERE

content $SLUG content/
skin $SLUG classic/1.0 skin/
overlay chrome://browser/content/browser.xul chrome://$SLUG/content/overlay.xul
locale $SLUG en-US locale/en-US/
EOF

echo 'Generating content/overlay.xul...'
cat <<EOF > content/overlay.xul || exit 1
<?xml version='1.0' encoding='utf-8'?>

<!-- REMEMBER TO PLACE YOUR LICENSE BLOCK HERE -->

<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?sml-stylesheet href="chrome://$SLUG/skin/overlay.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://$SLUG/locale/translations.dtd">

<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         id="$SLUG-overlay">
  <stringbundleset id="stringbundleset">
    <stringbundle id="strings"
                  src="chrome://$SLUG/locale/strings.properties">
    </stringbundle>
  </stringbundleset>

  <script src="overlay.js"></script>
</overlay>
EOF

echo 'Generating content/overlay.js...'
cat <<EOF > content/overlay.js || exit 1
// REMEMBER TO PLACE YOUR LICENSE BLOCK HERE

'use strict';
EOF

echo 'Generating skin/overlay.css...'
cat <<EOF > skin/overlay.css || exit 1
/* REMEMBER TO PLACE YOUR LICENSE BLOCK HERE */
EOF

echo 'Generating locale/translations.dtd...'
cat <<EOF > locale/en-US/translations.dtd || exit 1
<!-- REMEBER TO PLACE YOUR LICENSE BLOCK HERE -->
EOF

echo 'Generating locale/strings.properties...'
cat <<EOF > locale/en-US/strings.properties || exit 1
# REMEMBER TO PLACE YOUR LICENSE BLOCK HERE
EOF

echo 'Generating defaults/prefs.js...'
cat <<EOF > defaults/preferences/prefs.js || exit 1
// REMEMBER TO PLACE YOUR LICENSE BLOCK HERE
EOF

echo
echo 'All done!'
echo

echo '+-----------------------------------------+'
echo '| Remember to review the generated files! |'
echo '+-----------------------------------------+'

User avatar
plushkava
Apollo supporter
Apollo supporter
Posts: 46
Joined: 2015-07-31, 04:53
Location: Clown World

Re: mkextenv - A script to quickstart overlay extension development

Unread post by plushkava » 2019-06-16, 23:34

vannilla wrote:
2019-06-16, 20:42
I'm not sure what the pitfalls of using test EXP -o/-a are; the bourne shell (aka sh) manual says that those options are the way to chain conditional expressions, even when using the [ syntax, so I use them when building a test with multiple conditions.
Both -a and -o are officially considered as "obselescent" and may be removed from future POSIX revisions, however unlikely that may be. See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html#tag_20_128_16, which contains some rationale. They are too easily affected by user input and their precedence may be unpredictable, even though POSIX makes it clear that -a is supposed to have a higher precedence. These issues are more likely to arise if using the [ form of the test command. The point is, their behaviour is not wholly predictable across the various implementations and that these issues can be dealt with by chaining tests with && and || instead, or by using the more powerful [[ keyword in shells such as bash.
vannilla wrote:
2019-06-16, 20:42
The "prefix" letter when comparing for empty string is something I picked up from Windows actually, because if I remember correctly cmd.exe has trouble comparing empty strings (or anyway everyone suggested doing it that way and I picked up this usage too.)
It's not inherently wrong and makes sure the check is performed as intended.
I didn't say it was inherently wrong, merely antiquated. The shell has a tremendous number of rough edges and, by developing an awareness of them and ingraining certain habits, many hazards may be circumvented in the longer term. Please consider any suggestions or criticisms that (ostensibly) pertain to matters of style in that spirit. That said, I am less concerned with the application of best practice than correctness. Obsolescence aside, the test command functions as intended. As the quoting issues have been addressed, there's nothing further to add, so I'll leave it at that.

User avatar
Moonchild
Pale Moon guru
Pale Moon guru
Posts: 35602
Joined: 2011-08-28, 17:27
Location: Motala, SE
Contact:

Re: mkextenv - A script to quickstart overlay extension development

Unread post by Moonchild » 2019-06-17, 09:15

So, why not just stick to a bash script like was done initially, instead of trying to cater to all flavors of sh?
Just make it a prerequisite that people use the correct shell to run this script.
"Sometimes, the best way to get what you want is to be a good person." -- Louis Rossmann
"Seek wisdom, not knowledge. Knowledge is of the past; wisdom is of the future." -- Native American proverb
"Linux makes everything difficult." -- Lyceus Anubite

vannilla
Moon Magic practitioner
Moon Magic practitioner
Posts: 2193
Joined: 2018-05-05, 13:29

Re: mkextenv - A script to quickstart overlay extension development

Unread post by vannilla » 2019-06-17, 12:13

Moonchild wrote:
2019-06-17, 09:15
So, why not just stick to a bash script like was done initially, instead of trying to cater to all flavors of sh?
Just make it a prerequisite that people use the correct shell to run this script.
Mostly because plushkava showed that it takes very little (style choices aside) to make it portable among various sh-compliant shells.
If it needed more than changing == to = and not using bash-specific keywords, I wouldn't really bother.
After all, I'm not making a zsh version too (for example); at that point might as well use something else like python or whatever.

User avatar
plushkava
Apollo supporter
Apollo supporter
Posts: 46
Joined: 2015-07-31, 04:53
Location: Clown World

Re: mkextenv - A script to quickstart overlay extension development

Unread post by plushkava » 2019-06-17, 12:14

Moonchild wrote:
2019-06-17, 09:15
So, why not just stick to a bash script like was done initially, instead of trying to cater to all flavors of sh?
Just make it a prerequisite that people use the correct shell to run this script.
Targetting POSIX sh isn't all that difficult. The specification exists and it works. The reason that I suggested it is that the original version had all the hallmarks of a trivial sh script with a bash shebang slapped on top out of reflex. The script was written an an sh-like way from the outset and did not make use of any genuinely differentiating capability of bash. The function keyword doesn't count; it merely ties scripts to bash with no functional gain. == isn't a feature, as = does the same thing in either (for the part of the script that was under discussion). echo -e isn't an important feature because printf is capable of the same thing without the pitfalls anyway. Had it used any notable feature of bash, be it arrays, the unique capabilities of its [[ keyword, arithmetic tests, its more powerful parameter expansions, extended globs, C-like for loops ... I could go on but you get the picture ... then, yes, it would have made sense to maintain bash as a prerequisite. But it did not.

As for the various other changes that were uplifted such as missing quotes around expansions and explicitly checking for errors with certain commands, those would have been no less applicable had /bin/bash remained the target. Indeed, in some cases, that was due to the use of non-idiomatic bash code to begin with! Bash's [[ keyword wouldn't require quoting of its left-hand argument, for example, but was nowhere to be seen. In fact, had it remained as bash, the number of alterations that I would have been able to suggest would have been greater.

Locked