mirror of
https://github.com/nkanaev/yarr.git
synced 2025-05-24 00:33:14 +00:00
windows console fix
This commit is contained in:
parent
26b87dee98
commit
cf30ed249f
@ -20,3 +20,8 @@ The licenses are included, and the authorship comments are left intact.
|
|||||||
https://github.com/getlantern/systray (commit:2c0986d) Apache 2.0
|
https://github.com/getlantern/systray (commit:2c0986d) Apache 2.0
|
||||||
|
|
||||||
removed golog dependency
|
removed golog dependency
|
||||||
|
|
||||||
|
- fixconsole
|
||||||
|
https://github.com/apenwarr/fixconsole (commit:5a9f648) Apache 2.0
|
||||||
|
|
||||||
|
removed `w32` dependency
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
- feedlist keyboard navigation is flaky in "unread" section
|
- feedlist keyboard navigation is flaky in "unread" section
|
||||||
- windows cli mode not working
|
|
||||||
incorporate changes from:
|
|
||||||
https://github.com/apenwarr/fixconsole/blob/master/fixconsole_windows.go
|
|
||||||
- make feed settings available in all filter modes
|
- make feed settings available in all filter modes
|
||||||
- show `mark as read` in `all feeds` filter (along with numbers)
|
- show `mark as read` in `all feeds` filter (along with numbers)
|
||||||
|
14
src/platform/fixconsole_default.go
Normal file
14
src/platform/fixconsole_default.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package platform
|
||||||
|
|
||||||
|
// On non-windows platforms, we don't need to do anything. The console
|
||||||
|
// starts off attached already, if it exists.
|
||||||
|
|
||||||
|
func AttachConsole() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FixConsoleIfNeeded() error {
|
||||||
|
return nil
|
||||||
|
}
|
131
src/platform/fixconsole_windows.go
Normal file
131
src/platform/fixconsole_windows.go
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
package platform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AttachConsole() error {
|
||||||
|
const ATTACH_PARENT_PROCESS = ^uintptr(0)
|
||||||
|
proc := syscall.MustLoadDLL("kernel32.dll").MustFindProc("AttachConsole")
|
||||||
|
r1, _, err := proc.Call(ATTACH_PARENT_PROCESS)
|
||||||
|
if r1 == 0 {
|
||||||
|
errno, ok := err.(syscall.Errno)
|
||||||
|
if ok && errno == windows.ERROR_INVALID_HANDLE {
|
||||||
|
// console handle doesn't exist; not a real
|
||||||
|
// error, but the console handle will be
|
||||||
|
// invalid.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldStdin, oldStdout, oldStderr *os.File
|
||||||
|
|
||||||
|
// Windows console output is a mess.
|
||||||
|
//
|
||||||
|
// If you compile as "-H windows", then if you launch your program without
|
||||||
|
// a console, Windows forcibly creates one to use as your stdin/stdout, which
|
||||||
|
// is silly for a GUI app, so we can't do that.
|
||||||
|
//
|
||||||
|
// If you compile as "-H windowsgui", then it doesn't create a console for
|
||||||
|
// your app... but also doesn't provide a working stdin/stdout/stderr even if
|
||||||
|
// you *did* launch from the console. However, you can use AttachConsole()
|
||||||
|
// to get a handle to your parent process's console, if any, and then
|
||||||
|
// os.NewFile() to turn that handle into a fd usable as stdout/stderr.
|
||||||
|
//
|
||||||
|
// However, then you have the problem that if you redirect stdout or stderr
|
||||||
|
// from the shell, you end up ignoring the redirection by forcing it to the
|
||||||
|
// console.
|
||||||
|
//
|
||||||
|
// To fix *that*, we have to detect whether there was a pre-existing stdout
|
||||||
|
// or not. We can check GetStdHandle(), which returns 0 for "should be
|
||||||
|
// console" and nonzero for "already pointing at a file."
|
||||||
|
//
|
||||||
|
// Be careful though! As soon as you run AttachConsole(), it resets *all*
|
||||||
|
// the GetStdHandle() handles to point them at the console instead, thus
|
||||||
|
// throwing away the original file redirects. So we have to GetStdHandle()
|
||||||
|
// *before* AttachConsole().
|
||||||
|
//
|
||||||
|
// For some reason, powershell redirections provide a valid file handle, but
|
||||||
|
// writing to that handle doesn't write to the file. I haven't found a way
|
||||||
|
// to work around that. (Windows 10.0.17763.379)
|
||||||
|
//
|
||||||
|
// Net result is as follows.
|
||||||
|
// Before:
|
||||||
|
// SHELL NON-REDIRECTED REDIRECTED
|
||||||
|
// explorer.exe no console n/a
|
||||||
|
// cmd.exe broken works
|
||||||
|
// powershell broken broken
|
||||||
|
// WSL bash broken works
|
||||||
|
// After
|
||||||
|
// SHELL NON-REDIRECTED REDIRECTED
|
||||||
|
// explorer.exe no console n/a
|
||||||
|
// cmd.exe works works
|
||||||
|
// powershell works broken
|
||||||
|
// WSL bash works works
|
||||||
|
//
|
||||||
|
// We don't seem to make anything worse, at least.
|
||||||
|
func FixConsoleIfNeeded() error {
|
||||||
|
// Retain the original console objects, to prevent Go from automatically
|
||||||
|
// closing their file descriptors when they get garbage collected.
|
||||||
|
// You never want to close file descriptors 0, 1, and 2.
|
||||||
|
oldStdin, oldStdout, oldStderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
|
|
||||||
|
stdin, _ := syscall.GetStdHandle(syscall.STD_INPUT_HANDLE)
|
||||||
|
stdout, _ := syscall.GetStdHandle(syscall.STD_OUTPUT_HANDLE)
|
||||||
|
stderr, _ := syscall.GetStdHandle(syscall.STD_ERROR_HANDLE)
|
||||||
|
|
||||||
|
var invalid syscall.Handle
|
||||||
|
con := invalid
|
||||||
|
|
||||||
|
if stdin == invalid || stdout == invalid || stderr == invalid {
|
||||||
|
err := AttachConsole()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("attachconsole: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stdin == invalid {
|
||||||
|
stdin, _ = syscall.GetStdHandle(syscall.STD_INPUT_HANDLE)
|
||||||
|
}
|
||||||
|
if stdout == invalid {
|
||||||
|
stdout, _ = syscall.GetStdHandle(syscall.STD_OUTPUT_HANDLE)
|
||||||
|
con = stdout
|
||||||
|
}
|
||||||
|
if stderr == invalid {
|
||||||
|
stderr, _ = syscall.GetStdHandle(syscall.STD_ERROR_HANDLE)
|
||||||
|
con = stderr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if con != invalid {
|
||||||
|
// Make sure the console is configured to convert
|
||||||
|
// \n to \r\n, like Go programs expect.
|
||||||
|
h := windows.Handle(con)
|
||||||
|
var st uint32
|
||||||
|
err := windows.GetConsoleMode(h, &st)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetConsoleMode: %v", err)
|
||||||
|
}
|
||||||
|
err = windows.SetConsoleMode(h, st&^windows.DISABLE_NEWLINE_AUTO_RETURN)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("SetConsoleMode: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if stdin != invalid {
|
||||||
|
os.Stdin = os.NewFile(uintptr(stdin), "stdin")
|
||||||
|
}
|
||||||
|
if stdout != invalid {
|
||||||
|
os.Stdout = os.NewFile(uintptr(stdout), "stdout")
|
||||||
|
}
|
||||||
|
if stderr != invalid {
|
||||||
|
os.Stderr = os.NewFile(uintptr(stderr), "stderr")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user