initial commit

This commit is contained in:
skratchdot 2013-06-09 08:04:09 -04:00
commit 9723076429
8 changed files with 941 additions and 0 deletions

25
.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
# Eclipse files
.project
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe

22
LICENSE-MIT Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2013 skratchdot
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

5
Makefile Normal file
View File

@ -0,0 +1,5 @@
all:
@echo "Try 'make readme'"
readme:
godoc -templates=./readme-template/ "github.com/skratchdot/open-golang/open" > ./README.md

71
README.md Normal file
View File

@ -0,0 +1,71 @@
# open
## Description ##
Open a file, directory, or URI using the OS's default application for
that object type. Optionally, you can specify an application to use.
This is a proxy for the following commands:
OSX: "open"
Windows: "start"
Linux/Other: "xdg-open"
This is a golang port of the node.js module:
https://github.com/pwnall/node-open
## Documentation ##
[http://godoc.org/github.com/skratchdot/open-golang/open](http://godoc.org/github.com/skratchdot/open-golang/open)
## Import ##
import "github.com/skratchdot/open-golang/open"
## Usage ##
### open google.com in the user's default browser (method 1):
open.Run("https://google.com/")
### open google.com in the user's default browser (method 1):
open.Start("https://google.com")
### you can listen for errors
err := open.Run("https://google.com/")
### you can specify the program to use
open.RunWith("https://google.com/", "firefox")
## Functions ##
### func Run(input string) error
Open a file, directory, or URI using the OS's default application for
that object type. Wait for the open command to complete.
### func RunWith(input string, appName string) error
Open a file, directory, or URI using the specified application. Wait for
the open command to complete.
### func Start(input string) error
Open a file, directory, or URI using the OS's default application for
that object type. Don't wait for the open command to complete.
### func StartWith(input string, appName string) error
Open a file, directory, or URI using the specified application. Don't
wait for the open command to complete.
## License ##
Copyright (c) 2013 skratchdot
Licensed under the MIT license.

80
open/open.go Normal file
View File

@ -0,0 +1,80 @@
/*
Open a file, directory, or URI using the OS's default
application for that object type. Optionally, you can
specify an application to use.
This is a proxy for the following commands:
OSX: "open"
Windows: "start"
Linux/Other: "xdg-open"
This is a golang port of the node.js module: https://github.com/pwnall/node-open
*/
package open
import (
"os/exec"
"path"
"runtime"
)
/*
Open a file, directory, or URI using the OS's default
application for that object type. Wait for the open
command to complete.
*/
func Run(input string) error {
return open(input).Run()
}
/*
Open a file, directory, or URI using the OS's default
application for that object type. Don't wait for the
open command to complete.
*/
func Start(input string) error {
return open(input).Start()
}
/*
Open a file, directory, or URI using the specified application.
Wait for the open command to complete.
*/
func RunWith(input string, appName string) error {
return openWith(input, appName).Run()
}
/*
Open a file, directory, or URI using the specified application.
Don't wait for the open command to complete.
*/
func StartWith(input string, appName string) error {
return openWith(input, appName).Start()
}
func open(input string) *exec.Cmd {
switch runtime.GOOS {
case "darwin":
return exec.Command("open", input)
case "windows":
return exec.Command("start", "", input)
default:
_, file, _, _ := runtime.Caller(0)
app := path.Join(path.Dir(file), "..", "vendor", "xdg-open")
return exec.Command(app, input)
}
}
func openWith(input string, appName string) *exec.Cmd {
switch runtime.GOOS {
case "darwin":
return exec.Command("open", "-a", appName, input)
case "windows":
return exec.Command("start", "", appName, input)
default:
return exec.Command(appName, input)
}
}

70
open/open_test.go Normal file
View File

@ -0,0 +1,70 @@
package open
import "testing"
func TestRun(t *testing.T) {
// shouldn't error
input := "https://google.com/"
err := Run(input)
if err != nil {
t.Errorf("open.Run(\"%s\") threw an error: %s", input, err)
}
// should error
input = "xxxxxxxxxxxxxxx"
err = Run(input)
if err == nil {
t.Errorf("Run(\"%s\") did not through an error as expected", input)
}
}
func TestStart(t *testing.T) {
// shouldn't error
input := "https://google.com/"
err := Start(input)
if err != nil {
t.Errorf("open.Start(\"%s\") threw an error: %s", input, err)
}
// shouldn't error
input = "xxxxxxxxxxxxxxx"
err = Start(input)
if err != nil {
t.Errorf("open.Start(\"%s\") shouldn't even fail on invalid input: %s", input, err)
}
}
func TestRunWith(t *testing.T) {
// shouldn't error
input := "https://google.com/"
app := "firefox"
err := RunWith(input, app)
if err != nil {
t.Errorf("open.RunWith(\"%s\", \"%s\") threw an error: %s", input, app, err)
}
// should error
app = "xxxxxxxxxxxxxxx"
err = RunWith(input, app)
if err == nil {
t.Errorf("RunWith(\"%s\", \"%s\") did not through an error as expected", input, app)
}
}
func TestStartWith(t *testing.T) {
// shouldn't error
input := "https://google.com/"
app := "firefox"
err := StartWith(input, app)
if err != nil {
t.Errorf("open.StartWith(\"%s\", \"%s\") threw an error: %s", input, app, err)
}
// shouldn't error
app = "xxxxxxxxxxxxxxx"
err = StartWith(input, app)
if err != nil {
t.Errorf("StartWith(\"%s\", \"%s\") shouldn't even fail on invalid input: %s", input, app, err)
}
}

111
readme-template/package.txt Normal file
View File

@ -0,0 +1,111 @@
{{with .PAst}}{{node $ .}}{{end}}{{/*
---------------------------------------
*/}}{{with .PDoc}}{{if $.IsMain}}COMMAND DOCUMENTATION
{{comment_text .Doc " " "\t"}}
{{else}}# {{.Name}}
## Description ##
{{comment_text .Doc " " "\t"}}
## Documentation ##
[http://godoc.org/{{.ImportPath}}](http://godoc.org/{{.ImportPath}})
## Import ##
import "{{.ImportPath}}"
## Usage ##
### open google.com in the user's default browser (method 1):
open.Run("https://google.com/")
### open google.com in the user's default browser (method 1):
open.Start("https://google.com")
### you can listen for errors
err := open.Run("https://google.com/")
### you can specify the program to use
open.RunWith("https://google.com/", "firefox")
{{example_text $ "" " "}}{{/*
---------------------------------------
*/}}{{with .Consts}}
CONSTANTS
{{range .}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .Vars}}
VARIABLES
{{range .}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .Funcs}}
## Functions ##
{{range .}}### {{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{example_text $ .Name " "}}{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .Types}}
TYPES
{{range .}}{{$tname := .Name}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{range .Consts}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{end}}{{range .Vars}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{end}}{{example_text $ .Name " "}}
{{range .Funcs}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{example_text $ .Name " "}}
{{end}}{{range .Methods}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{$name := printf "%s_%s" $tname .Name}}{{example_text $ $name " "}}{{end}}
{{end}}{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with $.Notes}}
{{range $marker, $content := .}}
{{$marker}}S
{{range $content}}{{comment_text .Body " " "\t"}}
{{end}}{{end}}{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .Dirs}}
SUBDIRECTORIES
{{if $.DirFlat}}{{range .List}}{{if .HasPkg}}
{{.Path}}{{end}}{{end}}
{{else}}{{range .List}}
{{repeat `. ` .Depth}}{{.Name}}{{end}}
{{end}}{{end}}
## License ##
Copyright (c) 2013 skratchdot
Licensed under the MIT license.

557
vendor/xdg-open vendored Executable file
View File

@ -0,0 +1,557 @@
#!/bin/sh
#---------------------------------------------
# xdg-open
#
# Utility script to open a URL in the registered default application.
#
# Refer to the usage() function below for usage.
#
# Copyright 2009-2010, Fathi Boudra <fabo@freedesktop.org>
# Copyright 2009-2010, Rex Dieter <rdieter@fedoraproject.org>
# Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
# Copyright 2006, Jeremy White <jwhite@codeweavers.com>
#
# LICENSE:
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
#---------------------------------------------
manualpage()
{
cat << _MANUALPAGE
Name
xdg-open - opens a file or URL in the user's preferred application
Synopsis
xdg-open { file | URL }
xdg-open { --help | --manual | --version }
Description
xdg-open opens a file or URL in the user's preferred application. If a URL is
provided the URL will be opened in the user's preferred web browser. If a file
is provided the file will be opened in the preferred application for files of
that type. xdg-open supports file, ftp, http and https URLs.
xdg-open is for use inside a desktop session only. It is not recommended to use
xdg-open as root.
Options
--help
Show command synopsis.
--manual
Show this manualpage.
--version
Show the xdg-utils version information.
Exit Codes
An exit code of 0 indicates success while a non-zero exit code indicates
failure. The following failure codes can be returned:
1
Error in command line syntax.
2
One of the files passed on the command line did not exist.
3
A required tool could not be found.
4
The action failed.
Examples
xdg-open 'http://www.freedesktop.org/'
Opens the Freedesktop.org website in the user's default browser
xdg-open /tmp/foobar.png
Opens the PNG image file /tmp/foobar.png in the user's default image viewing
application.
_MANUALPAGE
}
usage()
{
cat << _USAGE
xdg-open - opens a file or URL in the user's preferred application
Synopsis
xdg-open { file | URL }
xdg-open { --help | --manual | --version }
_USAGE
}
#@xdg-utils-common@
#----------------------------------------------------------------------------
# Common utility functions included in all XDG wrapper scripts
#----------------------------------------------------------------------------
DEBUG()
{
[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0;
[ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0;
shift
echo "$@" >&2
}
#-------------------------------------------------------------
# Exit script on successfully completing the desired operation
exit_success()
{
if [ $# -gt 0 ]; then
echo "$@"
echo
fi
exit 0
}
#-----------------------------------------
# Exit script on malformed arguments, not enough arguments
# or missing required option.
# prints usage information
exit_failure_syntax()
{
if [ $# -gt 0 ]; then
echo "xdg-open: $@" >&2
echo "Try 'xdg-open --help' for more information." >&2
else
usage
echo "Use 'man xdg-open' or 'xdg-open --manual' for additional info."
fi
exit 1
}
#-------------------------------------------------------------
# Exit script on missing file specified on command line
exit_failure_file_missing()
{
if [ $# -gt 0 ]; then
echo "xdg-open: $@" >&2
fi
exit 2
}
#-------------------------------------------------------------
# Exit script on failure to locate necessary tool applications
exit_failure_operation_impossible()
{
if [ $# -gt 0 ]; then
echo "xdg-open: $@" >&2
fi
exit 3
}
#-------------------------------------------------------------
# Exit script on failure returned by a tool application
exit_failure_operation_failed()
{
if [ $# -gt 0 ]; then
echo "xdg-open: $@" >&2
fi
exit 4
}
#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file
exit_failure_file_permission_read()
{
if [ $# -gt 0 ]; then
echo "xdg-open: $@" >&2
fi
exit 5
}
#------------------------------------------------------------
# Exit script on insufficient permission to write a specified file
exit_failure_file_permission_write()
{
if [ $# -gt 0 ]; then
echo "xdg-open: $@" >&2
fi
exit 6
}
check_input_file()
{
if [ ! -e "$1" ]; then
exit_failure_file_missing "file '$1' does not exist"
fi
if [ ! -r "$1" ]; then
exit_failure_file_permission_read "no permission to read file '$1'"
fi
}
check_vendor_prefix()
{
file_label="$2"
[ -n "$file_label" ] || file_label="filename"
file=`basename "$1"`
case "$file" in
[a-zA-Z]*-*)
return
;;
esac
echo "xdg-open: $file_label '$file' does not have a proper vendor prefix" >&2
echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2
echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2
echo "Use --novendor to override or 'xdg-open --manual' for additional info." >&2
exit 1
}
check_output_file()
{
# if the file exists, check if it is writeable
# if it does not exists, check if we are allowed to write on the directory
if [ -e "$1" ]; then
if [ ! -w "$1" ]; then
exit_failure_file_permission_write "no permission to write to file '$1'"
fi
else
DIR=`dirname "$1"`
if [ ! -w "$DIR" -o ! -x "$DIR" ]; then
exit_failure_file_permission_write "no permission to create file '$1'"
fi
fi
}
#----------------------------------------
# Checks for shared commands, e.g. --help
check_common_commands()
{
while [ $# -gt 0 ] ; do
parm="$1"
shift
case "$parm" in
--help)
usage
echo "Use 'man xdg-open' or 'xdg-open --manual' for additional info."
exit_success
;;
--manual)
manualpage
exit_success
;;
--version)
echo "xdg-open 1.0.2"
exit_success
;;
esac
done
}
check_common_commands "$@"
[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL;
if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then
# Be silent
xdg_redirect_output=" > /dev/null 2> /dev/null"
else
# All output to stderr
xdg_redirect_output=" >&2"
fi
#--------------------------------------
# Checks for known desktop environments
# set variable DE to the desktop environments name, lowercase
detectDE()
{
if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde;
elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
elif `dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetNameOwner string:org.gnome.SessionManager > /dev/null 2>&1` ; then DE=gnome;
elif xprop -root _DT_SAVE_MODE 2> /dev/null | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
elif [ x"$DESKTOP_SESSION" == x"LXDE" ]; then DE=lxde;
else DE=""
fi
}
#----------------------------------------------------------------------------
# kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4
# It also always returns 1 in KDE 3.4 and earlier
# Simply return 0 in such case
kfmclient_fix_exit_code()
{
version=`kde${KDE_SESSION_VERSION}-config --version 2>/dev/null | grep '^KDE'`
major=`echo $version | sed 's/KDE.*: \([0-9]\).*/\1/'`
minor=`echo $version | sed 's/KDE.*: [0-9]*\.\([0-9]\).*/\1/'`
release=`echo $version | sed 's/KDE.*: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'`
test "$major" -gt 3 && return $1
test "$minor" -gt 5 && return $1
test "$release" -gt 4 && return $1
return 0
}
# This handles backslashes but not quote marks.
first_word()
{
read first rest
echo "$first"
}
open_kde()
{
if kde-open -v 2>/dev/null 1>&2; then
kde-open "$1"
else
if [ x"$KDE_SESSION_VERSION" = x"4" ]; then
kfmclient openURL "$1"
else
kfmclient exec "$1"
kfmclient_fix_exit_code $?
fi
fi
if [ $? -eq 0 ]; then
exit_success
else
exit_failure_operation_failed
fi
}
open_gnome()
{
if gvfs-open --help 2>/dev/null 1>&2; then
gvfs-open "$1"
else
gnome-open "$1"
fi
if [ $? -eq 0 ]; then
exit_success
else
exit_failure_operation_failed
fi
}
open_xfce()
{
exo-open "$1"
if [ $? -eq 0 ]; then
exit_success
else
exit_failure_operation_failed
fi
}
open_generic_xdg_mime()
{
filetype=`xdg-mime query filetype "$1" | sed "s/;.*//"`
default=`xdg-mime query default "$filetype"`
if [ -n "$default" ] ; then
xdg_user_dir="$XDG_DATA_HOME"
[ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share"
xdg_system_dirs="$XDG_DATA_DIRS"
[ -n "$xdg_system_dirs" ] || xdg_system_dirs=/usr/local/share/:/usr/share/
for x in `echo "$xdg_user_dir:$xdg_system_dirs" | sed 's/:/ /g'`; do
local file="$x/applications/$default"
if [ -r "$file" ] ; then
command="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word`"
command_exec=`which $command 2>/dev/null`
if [ -x "$command_exec" ] ; then
$command_exec "$1"
if [ $? -eq 0 ]; then
exit_success
fi
fi
fi
done
fi
}
open_generic()
{
# Paths or file:// URLs
if (echo "$1" | grep -q '^file://' ||
! echo "$1" | egrep -q '^[a-zA-Z+\.\-]+:'); then
local file="$1"
# Decode URLs
if echo "$file" | grep -q '^file:///'; then
file=${file#file://}
file="$(printf "$(echo "$file" | sed -e 's@%\([a-f0-9A-F]\{2\}\)@\\x\1@g')")"
fi
check_input_file "$file"
open_generic_xdg_mime "$file"
if [ -f /etc/debian_version ] &&
which run-mailcap 2>/dev/null 1>&2; then
run-mailcap --action=view "$file"
if [ $? -eq 0 ]; then
exit_success
fi
fi
if mimeopen -v 2>/dev/null 1>&2; then
mimeopen -L -n "$file"
if [ $? -eq 0 ]; then
exit_success
fi
fi
fi
IFS=":"
for browser in $BROWSER; do
if [ x"$browser" != x"" ]; then
browser_with_arg=`printf "$browser" "$1" 2>/dev/null`
if [ $? -ne 0 ]; then
browser_with_arg=$browser;
fi
if [ x"$browser_with_arg" = x"$browser" ]; then
"$browser" "$1";
else eval '$browser_with_arg'$xdg_redirect_output;
fi
if [ $? -eq 0 ]; then
exit_success;
fi
fi
done
exit_failure_operation_impossible "no method available for opening '$1'"
}
open_lxde()
{
# pcmanfm only knows how to handle file:// urls and filepaths, it seems.
if (echo "$1" | grep -q '^file://' ||
! echo "$1" | egrep -q '^[a-zA-Z+\.\-]+:')
then
local file="$(echo "$1" | sed 's%^file://%%')"
# handle relative paths
if ! echo "$file" | grep -q '^/'; then
file="$(pwd)/$file"
fi
pcmanfm "$file"
else
open_generic "$1"
fi
if [ $? -eq 0 ]; then
exit_success
else
exit_failure_operation_failed
fi
}
[ x"$1" != x"" ] || exit_failure_syntax
url=
while [ $# -gt 0 ] ; do
parm="$1"
shift
case "$parm" in
-*)
exit_failure_syntax "unexpected option '$parm'"
;;
*)
if [ -n "$url" ] ; then
exit_failure_syntax "unexpected argument '$parm'"
fi
url="$parm"
;;
esac
done
if [ -z "${url}" ] ; then
exit_failure_syntax "file or URL argument missing"
fi
detectDE
if [ x"$DE" = x"" ]; then
DE=generic
fi
# if BROWSER variable is not set, check some well known browsers instead
if [ x"$BROWSER" = x"" ]; then
BROWSER=links2:links:lynx:w3m
if [ -n "$DISPLAY" ]; then
BROWSER=firefox:mozilla:epiphany:konqueror:chromium-browser:google-chrome:$BROWSER
fi
fi
case "$DE" in
kde)
open_kde "$url"
;;
gnome)
open_gnome "$url"
;;
xfce)
open_xfce "$url"
;;
lxde)
open_lxde "$url"
;;
generic)
open_generic "$url"
;;
*)
exit_failure_operation_impossible "no method available for opening '$url'"
;;
esac