Convert wsl/cygwin paths (windows).

This commit is contained in:
Nuno Cruces 2020-01-17 12:28:44 +00:00
parent 2d90a83943
commit b5599a5bf3
6 changed files with 87 additions and 20 deletions

View file

@ -3,6 +3,9 @@ package main
import (
"flag"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/ncruces/zenity"
@ -42,6 +45,10 @@ var (
filename string
separator string
fileFilters FileFilters
// Windows specific options
cygpath bool
wslpath bool
)
func main() {
@ -64,11 +71,11 @@ func main() {
case fileSelectionDlg:
switch {
default:
strResult(zenity.SelectFile(opts...))
strResult(egestPath(zenity.SelectFile(opts...)))
case save:
strResult(zenity.SelectFileSave(opts...))
strResult(egestPath(zenity.SelectFileSave(opts...)))
case multiple:
lstResult(zenity.SelectFileMutiple(opts...))
lstResult(egestPaths(zenity.SelectFileMutiple(opts...)))
}
}
@ -111,6 +118,12 @@ func setupFlags() {
flag.StringVar(&filename, "filename", "", "Set the filename")
flag.StringVar(&separator, "separator", "|", "Set output separator character")
flag.Var(&fileFilters, "file-filter", "Set a filename filter (NAME | PATTERN1 PATTERN2 ...)")
// Windows specific options
if runtime.GOOS == "windows" {
flag.BoolVar(&cygpath, "cygpath", false, "Use cygpath for path translation (Windows only)")
flag.BoolVar(&wslpath, "wslpath", false, "Use wslpath for path translation (Windows only)")
}
}
func validateFlags() {
@ -174,7 +187,7 @@ func loadFlags() []zenity.Option {
// File selection options
options = append(options, fileFilters.Build())
options = append(options, zenity.Filename(filename))
options = append(options, zenity.Filename(ingestPath(filename)))
if directory {
options = append(options, zenity.Directory())
}
@ -238,12 +251,66 @@ func lstResult(l []string, err error) {
os.Exit(0)
}
func ingestPath(path string) string {
if runtime.GOOS == "windows" && path != "" {
var args []string
switch {
case wslpath:
args = []string{"wsl", "wslpath", "-m"}
case cygpath:
args = []string{"cygpath", "-C", "UTF8", "-m"}
}
if args != nil {
args = append(args, path)
out, err := exec.Command(args[0], args[1:]...).Output()
if len(out) > 0 && err == nil {
path = string(out[:len(out)-1])
}
}
}
return path
}
func egestPath(path string, err error) (string, error) {
if runtime.GOOS == "windows" && path != "" && err == nil {
var args []string
switch {
case wslpath:
args = []string{"wsl", "wslpath", "-u"}
case cygpath:
args = []string{"cygpath", "-C", "UTF8", "-u"}
}
if args != nil {
var out []byte
args = append(args, filepath.ToSlash(path))
out, err = exec.Command(args[0], args[1:]...).Output()
if len(out) > 0 && err == nil {
path = string(out[:len(out)-1])
}
}
}
return path, err
}
func egestPaths(paths []string, err error) ([]string, error) {
if runtime.GOOS == "windows" && err == nil && (wslpath || cygpath) {
paths = append(paths[:0:0], paths...)
for i, p := range paths {
paths[i], err = egestPath(p, nil)
if err != nil {
break
}
}
}
return paths, err
}
type FileFilters struct {
zenity.FileFilters
}
func (f *FileFilters) String() string {
return "filename filter"
return "zenity.FileFilters"
}
func (f *FileFilters) Set(s string) error {

View file

@ -275,9 +275,9 @@ func browseForFolder(opts options) (string, []string, error) {
if opts.filename != "" {
ptr := syscall.StringToUTF16Ptr(opts.filename)
args.LParam = uintptr(unsafe.Pointer(ptr))
args.CallbackFunc = syscall.NewCallback(func(hwnd uintptr, msg uint32, lparam, data uintptr) uintptr {
args.CallbackFunc = syscall.NewCallback(func(wnd uintptr, msg uint32, lparam, data uintptr) uintptr {
if msg == 1 { // BFFM_INITIALIZED
sendMessage.Call(hwnd, 1024+103 /* BFFM_SETSELECTIONW */, 1 /* TRUE */, data)
sendMessage.Call(wnd, 1024+103 /* BFFM_SETSELECTIONW */, 1 /* TRUE */, data)
}
return 0
})

View file

@ -3,7 +3,7 @@ package zenity_test
import "github.com/ncruces/zenity"
func ExampleError() {
zenity.Error("An error has occured.",
zenity.Error("An error has occurred.",
zenity.Title("Error"),
zenity.Icon(zenity.ErrorIcon))
// Output:

View file

@ -93,15 +93,15 @@ func hookMessageLabels(typ int, opts options) (hook uintptr, err error) {
hook, _, err = setWindowsHookEx.Call(12, // WH_CALLWNDPROCRET
syscall.NewCallback(func(code int, wparam uintptr, lparam *_CWPRETSTRUCT) uintptr {
if lparam.Message == 0x0110 { // WM_INITDIALOG
name := [7]byte{}
n, _, _ := getClassName.Call(lparam.HWnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name)))
if string(name[:n]) == "#32770" {
enumChildWindows.Call(lparam.HWnd,
syscall.NewCallback(func(hwnd, lparam uintptr) uintptr {
name := [7]byte{}
n, _, _ := getClassName.Call(hwnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name)))
if string(name[:n]) == "Button" {
ctl, _, _ := getDlgCtrlID.Call(hwnd)
name := [7]uint16{}
getClassName.Call(lparam.Wnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name)))
if syscall.UTF16ToString(name[:]) == "#32770" { // The class for a dialog box
enumChildWindows.Call(lparam.Wnd,
syscall.NewCallback(func(wnd, lparam uintptr) uintptr {
name := [7]uint16{}
getClassName.Call(wnd, uintptr(unsafe.Pointer(&name)), uintptr(len(name)))
if syscall.UTF16ToString(name[:]) == "Button" {
ctl, _, _ := getDlgCtrlID.Call(wnd)
var text string
switch ctl {
case 1, 6: // IDOK, IDYES
@ -119,7 +119,7 @@ func hookMessageLabels(typ int, opts options) (hook uintptr, err error) {
}
if text != "" {
ptr := syscall.StringToUTF16Ptr(text)
setWindowText.Call(hwnd, uintptr(unsafe.Pointer(ptr)))
setWindowText.Call(wnd, uintptr(unsafe.Pointer(ptr)))
}
}
return 1

View file

@ -23,7 +23,7 @@ var (
coTaskMemFree = ole32.NewProc("CoTaskMemFree")
sendMessage = user32.NewProc("SendMessageW")
getClassName = user32.NewProc("GetClassNameA")
getClassName = user32.NewProc("GetClassNameW")
setWindowsHookEx = user32.NewProc("SetWindowsHookExW")
unhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx")
callNextHookEx = user32.NewProc("CallNextHookEx")
@ -46,7 +46,7 @@ type _CWPRETSTRUCT struct {
LParam uintptr
WParam uintptr
Message uint32
HWnd uintptr
Wnd uintptr
}
type _COMObject struct{}