Convert wsl/cygwin paths (windows).
This commit is contained in:
parent
2d90a83943
commit
b5599a5bf3
6 changed files with 87 additions and 20 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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{}
|
Loading…
Reference in a new issue