diff --git a/README.md b/README.md index ea27a3a..6b6ccee 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,19 @@ print "success!" ``` +### File encodings + +Python and Ruby support comments to control the file encoding only within +the first two lines of the file. When using sbang with encoding comments, +put the shebang line for sbang first, then the encoding comment, and then +the interpreter to use. E.g.: + +```sh +#!/bin/sh /path/to/sbang +# -*- coding: latin-1 -*- +#!/very/long/path/to/python +``` + ## How it works `sbang` is a very simple POSIX shell script. It looks at the first two diff --git a/sbang b/sbang index 6478347..6b057c8 100755 --- a/sbang +++ b/sbang @@ -22,6 +22,14 @@ # # See https://github.com/spack/sbang for more details. # +# If using python- or ruby- style source code encoding, put that on the second +# line of the file and the shebang line for the long path to the real +# interpreter on the third line, like this: +# +# #!/bin/sh /path/to/sbang +# # -*- coding: utf-8 -*- +# #!/long/path/to/real/interpreter with arguments +# # Generic error handling die() { @@ -46,19 +54,39 @@ elif [ ! -f "$script" ]; then fi # Search the first two lines of script for interpreters. +# Search the third line if one of the first two is an encoding declaration lines=0 while read -r line && [ $lines -ne 2 ]; do if [ "${line#\#!}" != "$line" ]; then shebang_line="${line#\#!}" + lines=$((lines+1)) elif [ "${line#//!}" != "$line" ]; then # // comments shebang_line="${line#//!}" + lines=$((lines+1)) elif [ "${line#--!}" != "$line" ]; then # -- lua comments shebang_line="${line#--!}" + lines=$((lines+1)) elif [ "${line#}" + lines=$((lines+1)) + else + # Check whether this is a python/ruby encoding line + # Strip leading whitespace, whitespace is allowed before encoding + leading_whitespace=${line%%[![:space:]]*} + line=${line#"$leading_whitespace"} + + # encoding declaration starts with comment character + if [ "${line#\#}" != "$line" ]; then + case "$line" in + *"coding:"* | *"coding="*) + ;; # skip encoding line + *) + lines=$((lines+1)) + ;; + esac + fi fi - lines=$((lines+1)) done < "$script" # error if we did not find any interpreter diff --git a/test/shebangs/python_with_encoding_emacs.py b/test/shebangs/python_with_encoding_emacs.py new file mode 100755 index 0000000..1171ed9 --- /dev/null +++ b/test/shebangs/python_with_encoding_emacs.py @@ -0,0 +1,5 @@ +#!/usr/bin/env sbang +# -*- coding: utf-8 -*- +#!/usr/bin/python + +print("python") diff --git a/test/shebangs/python_with_encoding_equals.py b/test/shebangs/python_with_encoding_equals.py new file mode 100755 index 0000000..41ac909 --- /dev/null +++ b/test/shebangs/python_with_encoding_equals.py @@ -0,0 +1,5 @@ +#!/usr/bin/env sbang +# encoding=utf-8 +#!/usr/bin/python + +print("python") diff --git a/test/shebangs/python_with_encoding_minimal.py b/test/shebangs/python_with_encoding_minimal.py new file mode 100755 index 0000000..9d6fbe4 --- /dev/null +++ b/test/shebangs/python_with_encoding_minimal.py @@ -0,0 +1,5 @@ +#!/usr/bin/env sbang +# coding: utf-8 +#!/usr/bin/python + +print("python") diff --git a/test/shebangs/python_with_encoding_vim.py b/test/shebangs/python_with_encoding_vim.py new file mode 100755 index 0000000..95ef94d --- /dev/null +++ b/test/shebangs/python_with_encoding_vim.py @@ -0,0 +1,5 @@ +#!/usr/bin/env sbang +# vim: set fileencoding=utf-8 +#!/usr/bin/python + +print("python") diff --git a/test/shebangs/ruby_with_encoding.rb b/test/shebangs/ruby_with_encoding.rb new file mode 100755 index 0000000..2943cd4 --- /dev/null +++ b/test/shebangs/ruby_with_encoding.rb @@ -0,0 +1,5 @@ +#!/usr/bin/env sbang +# encoding: utf-8 +#!/usr/bin/ruby + +puts "ruby" diff --git a/test/test-suite.sh b/test/test-suite.sh index aee584c..4e40740 100755 --- a/test/test-suite.sh +++ b/test/test-suite.sh @@ -33,12 +33,17 @@ equals "/usr/bin/env perl -w -x shebangs/perl-w-env.pl" $SBANG shebangs/perl-w-e equals "/usr/bin/ruby -x shebangs/ruby.rb" $SBANG shebangs/ruby.rb equals "/usr/bin/env ruby -x shebangs/ruby-env.rb" $SBANG shebangs/ruby-env.rb +equals "/usr/bin/ruby -x shebangs/ruby_with_encoding.rb" $SBANG shebangs/ruby_with_encoding.rb equals "/usr/bin/perl5.32.0 -x shebangs/perl-ver.pl" $SBANG shebangs/perl-ver.pl equals "/usr/bin/ruby2.7 -x shebangs/ruby-ver.rb" $SBANG shebangs/ruby-ver.rb equals "/usr/bin/python shebangs/python.py" $SBANG shebangs/python.py equals "/usr/bin/env python shebangs/python-env.py" $SBANG shebangs/python-env.py +equals "/usr/bin/python shebangs/python_with_encoding_emacs.py" $SBANG shebangs/python_with_encoding_emacs.py +equals "/usr/bin/python shebangs/python_with_encoding_minimal.py" $SBANG shebangs/python_with_encoding_minimal.py +equals "/usr/bin/python shebangs/python_with_encoding_equals.py" $SBANG shebangs/python_with_encoding_equals.py +equals "/usr/bin/python shebangs/python_with_encoding_vim.py" $SBANG shebangs/python_with_encoding_vim.py equals "/bin/sh shebangs/sh.sh" $SBANG shebangs/sh.sh equals "/bin/bash shebangs/bash.bash" $SBANG shebangs/bash.bash