Add gosh: run Go as a shell scripting language
This commit is contained in:
parent
ba33a7bacc
commit
ad2cc63e30
57
home/bin/SimpleHTTPServer
Executable file
57
home/bin/SimpleHTTPServer
Executable file
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env gosh
|
||||
package main
|
||||
|
||||
// SimpleHTTPServer is a simple Go static file server, similar to the Python
|
||||
// module of the same name, but which supports high concurrency and all the
|
||||
// other niceties that you get from Go out of the box.
|
||||
//
|
||||
// It runs via my `gosh` wrapper for treating simple Go programs as shell
|
||||
// scripts. See my `gosh` script, or just remove the shebang line at the top
|
||||
// of this file to `go build` your own version.
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// LogMiddleware logs all HTTP requests.
|
||||
func LogMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
res := &ResponseWriter{w, 200}
|
||||
next.ServeHTTP(res, r)
|
||||
log.Printf("%s %d %s %s\n",
|
||||
r.RemoteAddr,
|
||||
res.Status,
|
||||
r.Method,
|
||||
r.RequestURI,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
// ResponseWriter is my own wrapper around http.ResponseWriter that lets me
|
||||
// capture its status code, for logging purposes.
|
||||
type ResponseWriter struct {
|
||||
http.ResponseWriter
|
||||
Status int
|
||||
}
|
||||
|
||||
// WriteHeader wraps http.WriteHeader to also capture the status code.
|
||||
func (w *ResponseWriter) WriteHeader(code int) {
|
||||
w.ResponseWriter.WriteHeader(code)
|
||||
w.Status = code
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Command line flag: the port number to listen on.
|
||||
port := flag.Int("port", 8000, "The port number to listen on.")
|
||||
flag.Parse()
|
||||
|
||||
fmt.Printf("Serving at http://0.0.0.0:%d/\n", *port)
|
||||
err := http.ListenAndServe(
|
||||
fmt.Sprintf(":%d", *port),
|
||||
LogMiddleware(http.FileServer(http.Dir("."))),
|
||||
)
|
||||
panic(err)
|
||||
}
|
56
home/bin/gosh
Executable file
56
home/bin/gosh
Executable file
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""gosh: use Golang as a shell scripting language.
|
||||
|
||||
This is written in Python so that I don't have to commit any binaries to my
|
||||
dotfiles repo, and my Go shell scripts can also remain in source form.
|
||||
|
||||
Usage: write a Go program with this shebang comment on top immediately before
|
||||
the `package main` statement:
|
||||
|
||||
#!/usr/bin/env gosh
|
||||
package main
|
||||
|
||||
And make it executable and run it like any shell script.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
def main():
|
||||
if len(sys.argv) == 1:
|
||||
die("Usage: gosh <file.go>")
|
||||
|
||||
# Get the Go source file from the command line.
|
||||
source = sys.argv[1]
|
||||
argv = sys.argv[2:]
|
||||
if not os.path.isfile(source):
|
||||
die("{}: not a file".format(source))
|
||||
|
||||
# Make a temp file that lacks the shebang line of the input file.
|
||||
with codecs.open(source, "r", "utf-8") as fh:
|
||||
# Get the shebang off and sanity check it.
|
||||
shebang = fh.readline()
|
||||
if not "gosh" in shebang:
|
||||
die("{}: doesn't appear to be a Go script".format(source))
|
||||
|
||||
# Write it to a temp file, sans shebang.
|
||||
temp = tempfile.NamedTemporaryFile(delete=False, suffix=".go")
|
||||
temp.write(fh.read().strip())
|
||||
temp.close()
|
||||
|
||||
# Call it.
|
||||
subprocess.call(["go", "run", temp.name] + argv)
|
||||
|
||||
# Clean up.
|
||||
os.unlink(temp.name)
|
||||
|
||||
def die(message):
|
||||
print(message)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user