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 ( import (
"flag" "flag"
"os" "os"
"os/exec"
"path/filepath"
"runtime"
"strings" "strings"
"github.com/ncruces/zenity" "github.com/ncruces/zenity"
@ -42,6 +45,10 @@ var (
filename string filename string
separator string separator string
fileFilters FileFilters fileFilters FileFilters
// Windows specific options
cygpath bool
wslpath bool
) )
func main() { func main() {
@ -64,11 +71,11 @@ func main() {
case fileSelectionDlg: case fileSelectionDlg:
switch { switch {
default: default:
strResult(zenity.SelectFile(opts...)) strResult(egestPath(zenity.SelectFile(opts...)))
case save: case save:
strResult(zenity.SelectFileSave(opts...)) strResult(egestPath(zenity.SelectFileSave(opts...)))
case multiple: 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(&filename, "filename", "", "Set the filename")
flag.StringVar(&separator, "separator", "|", "Set output separator character") flag.StringVar(&separator, "separator", "|", "Set output separator character")
flag.Var(&fileFilters, "file-filter", "Set a filename filter (NAME | PATTERN1 PATTERN2 ...)") 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() { func validateFlags() {
@ -174,7 +187,7 @@ func loadFlags() []zenity.Option {
// File selection options // File selection options
options = append(options, fileFilters.Build()) options = append(options, fileFilters.Build())
options = append(options, zenity.Filename(filename)) options = append(options, zenity.Filename(ingestPath(filename)))
if directory { if directory {
options = append(options, zenity.Directory()) options = append(options, zenity.Directory())
} }
@ -238,12 +251,66 @@ func lstResult(l []string, err error) {
os.Exit(0) 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 { type FileFilters struct {
zenity.FileFilters zenity.FileFilters
} }
func (f *FileFilters) String() string { func (f *FileFilters) String() string {
return "filename filter" return "zenity.FileFilters"
} }
func (f *FileFilters) Set(s string) error { func (f *FileFilters) Set(s string) error {

View file

@ -275,9 +275,9 @@ func browseForFolder(opts options) (string, []string, error) {
if opts.filename != "" { if opts.filename != "" {
ptr := syscall.StringToUTF16Ptr(opts.filename) ptr := syscall.StringToUTF16Ptr(opts.filename)
args.LParam = uintptr(unsafe.Pointer(ptr)) 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 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 return 0
}) })

View file

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

View file

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

View file

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