Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,19 @@ print "success!"
<?php echo "success!\n"; ?>
```

### 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
Expand Down
30 changes: 29 additions & 1 deletion sbang
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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#<?php\ }" != "$line" ]; then # php comments
shebang_line="${line#<?php\ \#!}"
shebang_line="${shebang_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
Expand Down
5 changes: 5 additions & 0 deletions test/shebangs/python_with_encoding_emacs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env sbang
# -*- coding: utf-8 -*-
#!/usr/bin/python

print("python")
5 changes: 5 additions & 0 deletions test/shebangs/python_with_encoding_equals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env sbang
# encoding=utf-8
#!/usr/bin/python

print("python")
5 changes: 5 additions & 0 deletions test/shebangs/python_with_encoding_minimal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env sbang
# coding: utf-8
Comment thread
tgamblin marked this conversation as resolved.
#!/usr/bin/python

print("python")
5 changes: 5 additions & 0 deletions test/shebangs/python_with_encoding_vim.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env sbang
# vim: set fileencoding=utf-8
#!/usr/bin/python

print("python")
5 changes: 5 additions & 0 deletions test/shebangs/ruby_with_encoding.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env sbang
# encoding: utf-8
#!/usr/bin/ruby

puts "ruby"
5 changes: 5 additions & 0 deletions test/test-suite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading