سؤال

How does this Emacs command (make-comint-in-buffer "Python" nil "python" nil "-i") or (make-comint-in-buffer "git" nil "C:/Program Files (x86)/Git/bin/sh.exe" nil "--login" "-i") manage to get the prompt in an Emacs buffer and get ride of it's, Python's/sh.exe's, interactive terminal without killing the Python process?

I tried to figure out by taking a shallow dive into make-comint-in-buffer's source code but bumped into processp, which is C compiled code, whose source I couldn't find.

The reason I am asking this question is to find an alternative answer to this question without using pythonw (their aint a mayapyw.exe to mayapy.exe for example).

هل كانت مفيدة؟

المحلول

Emacs uses the SHOWWINDOW flag to CreateProcess to control display of the console window associated with a subprocess.

The key code from create_child in w32proc.c is:

if (NILP (Vw32_start_process_show_window) && !is_gui_app)
    start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
else
    start.dwFlags = STARTF_USESTDHANDLES;

start.wShowWindow = SW_HIDE;

if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE, flags, env, dir, &start, &cp->procinfo))
{ ...
}

نصائح أخرى

I can only guess how that Emacs command works, so can't really help you there... But however, I can provide you with a way to hide a window. That is possible by using the CTypes module and call the Windows-API to get the Window/Python-prompts ID/Hwin, and then hide that window.

This forces you to import/or include this piece of code in your script, and then call a function/do a little something in your script. Once your script is run, this should hide the prompt. See "main.py"-part for usage.

Window.py

from ctypes import *

user32 = windll.user32

BOOL    = c_bool
INT     = c_int
LONG    = c_long
LPVOID  = c_void_p
LPTSTR  = c_wchar_p
HWND    = LPVOID
LPARAM  = LPVOID

GW_OWNER = 4
GWL_EXSTYLE  = -20
WS_EX_TOOLWINDOW = 128
WS_EX_APPWINDOW = 262144

#------------------------------------------------------------------------ 

def GetWindowLong(hwnd, index):
    user32.GetWindowLongW.argtypes = [HWND, INT]
    return user32.GetWindowLongW(hwnd, index)

def GetWindow(hWnd, uCmd):
    user32.GetParent.argtypes = [HWND, INT]
    return user32.GetWindow(hWnd, uCmd)

def GetParent(hwnd):
    user32.GetParent.argtypes = [HWND]
    return user32.GetParent(hwnd)

def IsWindowVisible(hwnd): 
    user32.IsWindowVisible.argtypes = [HWND]
    return user32.IsWindowVisible(hwnd)

def GetWindowTextLength(hwnd):
    user32.GetWindowTextLengthW.argtypes = [HWND]
    return user32.GetWindowTextLengthW(hwnd)

def GetWindowText(hwnd):
    length = GetWindowTextLength(hwnd)
    if not length: return False
    buff = create_unicode_buffer(length + 1)
    user32.GetWindowTextW.argtypes = [HWND, LPTSTR, INT]
    res = user32.GetWindowTextW(hwnd, buff, length + 1)   
    if res: return buff.value
    else: return False  

def isRealWindow(hwnd):
    """ Check if a given window is a real Windows application frame..
        Returns a BOOL """

    if not IsWindowVisible(hwnd):
        return False
    if GetParent(hwnd) != 0:
        return False
    hasNoOwner = GetWindow(hwnd, GW_OWNER) == 0
    lExStyle = GetWindowLong(hwnd, GWL_EXSTYLE)
    if (((lExStyle & WS_EX_TOOLWINDOW) == 0 and hasNoOwner)
      or ((lExStyle & WS_EX_APPWINDOW != 0) and not hasNoOwner)):
        if GetWindowText(hwnd):
            return True
    return False

class WindowEnumerator(object):
    """ Window enumerator class.  You can pass it's instances
        as callback functions in window enumeration APIs. """

    def __init__(self):
        self.hwnd = []

    def __call__(self, hwnd, lParam):
        self.hwnd.append(hwnd)
        return True

class __EnumWndProc(WindowEnumerator):
    pass

def EnumWindows():
    WNDENUMPROC = WINFUNCTYPE(BOOL,HWND,LPARAM)
    _EnumWindows = user32.EnumWindows
    _EnumWindows.argtypes = [WNDENUMPROC, LPARAM]
    _EnumWindows.restype  = BOOL

    EnumFunc = __EnumWndProc()
    lpEnumFunc = WNDENUMPROC(EnumFunc)
    if not _EnumWindows(lpEnumFunc, None):
        errcode = GetLastError()
        if errcode not in (ERROR_NO_MORE_FILES, ERROR_SUCCESS):
            raise WinError(errcode)
    return EnumFunc.hwnd

def GetWindowByName(title):
    window = []
    hwnds = EnumWindows()
    for hwnd in hwnds:
        if not isRealWindow(hwnd):
            pass
        else:
            wndtitle = GetWindowText(hwnd)
            if title.lower() in wndtitle.lower():
                return (hwnd, wndtitle)
    return False

def ShowWindow(hWnd, arg=0):
    user32.ShowWindow.argtypes = [HWND, c_int]
    return user32.ShowWindow(hWnd, arg)

main.py

import Window

# Pass the full or partial title of the window that should be hidden.
wnd = Window.GetWindowByName('xxxxxxx.exe')
if wnd:
    Window.ShowWindow(wnd[0], 0) #Hide it. 0=SW_HIDE, 5 = SW_SHOW.

I hope this does the trick.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top