Apakah ada perintah di Gnome-Terminal, atau shell tabbable untuk membuka tab baru?

11

Saya tidak mencari pintasan keyboard, melainkan saya ingin perintah untuk:

  • Jendela baru
  • Tab baru
  • Tutup tab atau jendela saat ini
  • Maksimalkan Jendela Shell
  • Minimalkan Jendela Shell
  • Pindahkan Shell ke ruang kerja yang berbeda
  • Ganti Tab

Dan pada dasarnya hal seperti ini. Ingat; Saya tidak ingin pintasan, melainkan perintah yang sebenarnya. Alasannya adalah agar saya dapat menggunakan fungsi alias.

Akiva
sumber
1
Apakah python baik-baik saja dengan Anda?
Sergiy Kolodyazhnyy
4
"Tutup tab saat ini" - perintah ini disebut "keluar": D
egmont
"Saya tidak ingin pintasan [...] jadi saya bisa menggunakan fungsi alias" - bisakah Anda menjelaskannya? Apa keuntungan sebenarnya yang Anda harapkan daripada pintasan terkenal? Apa masalah atau fungsionalitas yang hilang pada pintasan? Saya pikir mereka adalah pendekatan yang tepat untuk apa yang Anda cari.
egmont
@egmont Saya seorang Vim Addict, jika itu masuk akal.
Akiva
Jadi, katakanlah, misalnya untuk Maximize, alih-alih memiliki hotkey pengelola jendela yang berfungsi untuk semua jenis jendela (peramban, penyunting gambar, pengolah kata, dll.) Di semua negara bagian (yaitu apa pun yang Anda lakukan di dalamnya), Anda harus d lebih suka memiliki perintah yang hanya berfungsi untuk terminal dan tidak ada aplikasi lain, dan hanya jika itu tidak menjalankan perintah apa pun di dalam (selain dari shell default, tentu saja). Tidak, maaf, ide ini masih tidak masuk akal bagi saya :(
egmont

Jawaban:

14

Anda tidak dapat melakukan ini secara default di Gnome-Terminal, setidaknya dengan perintah mentah.

Namun, Anda dapat menulis skrip yang memanggil pintasan keyboard yang bisa melakukan ini. Perhatikan bahwa Anda perlu xdotooluntuk ini:sudo apt install xdotool

  • Jendela Baru : Luncurkan jendela terminal baru dengan nw
    Kita dapat melakukan ini dengan adil gnome-terminal.
    Tambahkan ke.bashrc :

    echo "alias nw=gnome-terminal" >> ~/.bashrc
  • Tab Baru : Luncurkan tab baru dengan nt
    Kita dapat melakukan ini dengan xdotool getactivewindow $(xdotool key ctrl+shift+t)
    Tambahkan ke.bashrc :

    echo "alias nt='xdotool getactivewindow $(xdotool key ctrl+shift+t)'" >> .bashrc
  • Tutup Tab : Tutup lagi tab atau jendela dengan ct
    xdotoolserangan: xdotool getactivewindow $(xdotool key ctrl+shift+w)
    Tambahkan ke.bashrc :

    echo "alias ct='xdotool getactivewindow $(xdotool key ctrl+shift+w)'" >> .bashrc
  • Maksimalkan Jendela : Maksimalkan seluruh jendela dengan maw
    Kita dapat menggunakan di wmctrlsini: wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz
    Tambahkan ke.bashrc :

    echo "alias maw='wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz'" >> .bashrc
  • Minimalkan Jendela : Minimalkan seluruh jendela dengan miw
    Kita dapat menggunakan xdotoollagi: xdotool windowminimize $(xdotool getactivewindow)
    Tambahkan ke.bashrc :

    echo "alias miw='xdotool windowminimize $(xdotool getactivewindow)'" >> .bashrc
  • Pindah ke Workspace : Pindahkan jendela ke ruang kerja lain dengan mtw <id>
    Ini akan hampir tidak mungkin dalam skrip shell, dan jauh melampaui pengalaman pribadi saya. Saya akan merekomendasikan menggunakan skrip Serg untuk tujuan ini, karena sebenarnya berfungsi seperti yang sekarang. Ah, manfaat Compiz.

Kaz Wolfe
sumber
7

pengantar

Skrip yang disajikan dalam jawaban ini memungkinkan pengguna untuk mengontrol jendela terminal mereka melalui satu perintah dan daftar opsi. Mudah digunakan dan kompatibel dengan emulator terminal apa pun yang memiliki ikatan kunci serupa gnome-terminal. Opsi pemindahan dapat digunakan dengan terminal lain juga, tetapi pembukaan tab tidak dijamin untuk terminal tersebut.

Script mencakup pembukaan tab, pembukaan jendela, pindah ke ruang kerja ke bawah, kanan ruang kerja, ruang kerja spesifik yang direferensikan dengan angka integer, meminimalkan, memaksimalkan, dan unmaximizing jendela. Satu-satunya hal yang tidak dicakup oleh skrip adalah menutup tab / jendela hanya karena setiap shell / terminal emulator sudah memiliki perintah untuk itu - exitatau sebagai alternatif melalui CtrlDpintasan.

!!! CATATAN: Anda akan perlu xdotooluntuk berpindah ruang kerja dan membuka tab. Instal melalui sudo apt-get install xdotool. Jika Anda memilih untuk tidak menginstal paket tambahan, ingatlah bahwa ruang kerja dan penggantian tab tidak akan berfungsi , tetapi opsi lain akan melakukannya.

Pemakaian:

Semua argumen untuk windowctrl.pybersifat opsional, sehingga dapat digunakan secara terpisah, atau berpotensi bersama. Seperti yang ditunjukkan oleh -hopsi.

$ ./windowctrl.py -h                                                                               
usage: windowctrl.py [-h] [-w] [-t] [-m] [-M] [-u] [-v VIEWPORT] [-r] [-d]

Copyright 2016. Sergiy Kolodyazhnyy.

    Window control for terminal emulators. Originally written
    for gnome-terminal under Ubuntu with Unity desktop but can 
    be used with any other terminal emulator that conforms to 
    gnome-terminal keybindings. It can potentially be used for 
    controlling other windows as well via binding this script
    to a keyboard shortcut.

    Note that --viewport and --tab options require xdotool to be
    installed on the system. If you don't have it installed, you 
    can still use the other options. xdotool can be installed via
    sudo apt-get install xdotool.


optional arguments:
  -h, --help            show this help message and exit
  -w, --window          spawns new window
  -t, --tab             spawns new tab
  -m, --minimize        minimizes current window
  -M, --maximize        maximizes window
  -u, --unmaximize      unmaximizes window
  -v VIEWPORT, --viewport VIEWPORT
                        send window to workspace number
  -r, --right           send window to workspace right
  -d, --down            send window to workspace down

Kode Sumber Skrip:

Kode sumber skrip tersedia di GitHub dan juga di sini. Perubahan terbaru cenderung masuk ke GitHub daripada di sini, jadi saya sangat menyarankan memeriksa versi terbaru di sana. Disarankan juga untuk mengirim laporan bug di sana.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Program name: windowctrl.py
Author: Sergiy Kolodyazhnyy
Date:  Sept 18, 2016
Written for: http://askubuntu.com/q/826310/295286
Tested on Ubuntu 16.04 LTS
"""
from __future__ import print_function
import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gio,Gdk
import sys
import dbus
import subprocess
import argparse

def gsettings_get(schema,path,key):
    """Get value of gsettings schema"""
    if path is None:
        gsettings = Gio.Settings.new(schema)
    else:
        gsettings = Gio.Settings.new_with_path(schema,path)
    return gsettings.get_value(key)

def run_cmd(cmdlist):
    """ Reusable function for running shell commands"""
    try:
        stdout = subprocess.check_output(cmdlist)
    except subprocess.CalledProcessError:
        print(">>> subprocess:",cmdlist)
        sys.exit(1)
    else:
        if stdout:
            return stdout

def get_dbus(bus_type,obj,path,interface,method,arg):
    # Reusable function for accessing dbus
    # This basically works the same as 
    # dbus-send or qdbus. Just give it
    # all the info, and it will spit out output
    if bus_type == "session":
        bus = dbus.SessionBus() 
    if bus_type == "system":
        bus = dbus.SystemBus()
    proxy = bus.get_object(obj,path)
    method = proxy.get_dbus_method(method,interface)
    if arg:
        return method(arg)
    else:
        return method() 

def new_window():
    screen = Gdk.Screen.get_default()
    active_xid = int(screen.get_active_window().get_xid())
    app_path = get_dbus( 'session',
                         'org.ayatana.bamf',
                         '/org/ayatana/bamf/matcher',
                         'org.ayatana.bamf.matcher',
                         'ApplicationForXid',
                         active_xid
                         )

    desk_file  = get_dbus('session',
                          'org.ayatana.bamf',
                          str(app_path),
                          'org.ayatana.bamf.application',
                          'DesktopFile',
                          None
                          )

    # Big credit to Six: http://askubuntu.com/a/664272/295286
    Gio.DesktopAppInfo.new_from_filename(desk_file).launch_uris(None)



def enumerate_viewports():
    """ generates enumerated dictionary of viewports and their
        indexes, counting left to right """
    schema="org.compiz.core"
    path="/org/compiz/profiles/unity/plugins/core/"
    keys=['hsize','vsize']
    screen = Gdk.Screen.get_default()
    screen_size=[ screen.get_width(),screen.get_height()]
    grid=[ int(str(gsettings_get(schema,path,key))) for key in keys]
    x_vals=[ screen_size[0]*x for x in range(0,grid[0]) ]
    y_vals=[screen_size[1]*x for x in range(0,grid[1]) ]

    viewports=[(x,y)  for y in y_vals for x in x_vals ]

    return {vp:ix for ix,vp in enumerate(viewports,1)}


def get_current_viewport():
    """returns tuple representing current viewport, 
       in format (width,height)"""
    vp_string = run_cmd(['xprop', '-root', 
                         '-notype', '_NET_DESKTOP_VIEWPORT'])
    vp_list=vp_string.decode().strip().split('=')[1].split(',')
    return tuple( int(i)  for i in vp_list )

def maximize():

    screen = Gdk.Screen.get_default()
    window = screen.get_active_window()
    window.maximize()
    screen.get_active_window()
    window.process_all_updates()

def unmaximize():

    screen = Gdk.Screen.get_default()
    window = screen.get_active_window()
    window.unmaximize()
    screen.get_active_window()
    window.process_all_updates()

def minimize():

    screen = Gdk.Screen.get_default()
    window = screen.get_active_window()
    window.iconify()
    window.process_all_updates()

def window_move(viewport):

    # 1. grab window object
    # 2. jump viewport 0 0 so we can move only
    #    in positive plane
    # 3. move the window.
    # 4. set viewport back to what it was

    # Step 1
    screen = Gdk.Screen.get_default()
    screen_size=[ screen.get_width(),screen.get_height()]
    window = screen.get_active_window()

    viewports = enumerate_viewports()
    current = get_current_viewport()
    current_num = viewports[current]
    destination = [ 
                   key for  key,val in viewports.items() 
                   if val == int(viewport)
                   ][0]
    # Step 2.
    run_cmd([
            'xdotool',
            'set_desktop_viewport',
            '0','0'
            ]) 
    # Step 3.
    window.move(destination[0],destination[1])
    window.process_all_updates()

    run_cmd([
            'xdotool',
            'set_desktop_viewport',
            str(current[0]),
            str(current[1])
            ]) 

def move_right():
    sc = Gdk.Screen.get_default()
    width = sc.get_width()
    win = sc.get_active_window()
    pos = win.get_origin()
    win.move(width,pos.y)
    win.process_all_updates()

def move_down():
    sc = Gdk.Screen.get_default()
    height = sc.get_height()
    win = sc.get_active_window()
    pos = win.get_origin()
    win.move(pos.x,height)
    win.process_all_updates()

def new_tab():
    run_cmd(['xdotool','key','ctrl+shift+t'])

def parse_args():
    """ Parse command line arguments"""

    info="""Copyright 2016. Sergiy Kolodyazhnyy.

    Window control for terminal emulators. Originally written
    for gnome-terminal under Ubuntu with Unity desktop but can 
    be used with any other terminal emulator that conforms to 
    gnome-terminal keybindings. It can potentially be used for 
    controlling other windows as well via binding this script
    to a keyboard shortcut.

    Note that --viewport and --tab options require xdotool to be
    installed on the system. If you don't have it installed, you 
    can still use the other options. xdotool can be installed via
    sudo apt-get install xdotool.
    """
    arg_parser = argparse.ArgumentParser(
                 description=info,
                 formatter_class=argparse.RawTextHelpFormatter)
    arg_parser.add_argument(
                '-w','--window', action='store_true',
                help='spawns new window',
                required=False)
    arg_parser.add_argument(
                '-t','--tab',action='store_true',
                help='spawns new tab',
                required=False)
    arg_parser.add_argument(
                '-m','--minimize',action='store_true',
                help='minimizes current window',
                required=False)
    arg_parser.add_argument(
                '-M','--maximize',action='store_true',
                help='maximizes window',
                required=False)
    arg_parser.add_argument(
                '-u','--unmaximize',action='store_true',
                help='unmaximizes window',
                required=False)
    arg_parser.add_argument(
               '-v','--viewport',action='store',
               type=int, help='send window to workspace number',
               required=False)
    arg_parser.add_argument(
               '-r','--right',action='store_true',
               help='send window to workspace right',
               required=False)
    arg_parser.add_argument(
               '-d','--down',action='store_true',
               help='send window to workspace down',
               required=False)
    return arg_parser.parse_args()

def main():

    args = parse_args()

    if args.window:
       new_window()
    if args.tab:
       new_tab()
    if args.down:
       move_down()
    if args.right:
       move_right()       
    if args.viewport:
       window_move(args.viewport)
    if args.minimize:
       minimize()
    if args.maximize:
       maximize()
    if args.unmaximize:
       unmaximize()

if __name__ == '__main__':
    main()

Catatan samping

  • Anda bertanya "Apakah ada perintah di Gnome-Terminal, atau shell tabbable untuk membuka tab baru?" Manual Gnome Terminal tidak mencantumkan opsi tersebut. Shell adalah utilitas command-line. Tab adalah fitur aplikasi GUI. Ada multiplexer terminal seperti screenatau tmuxyang dapat memiliki "tab" atau split windows, yang semacam mendekati "tabbable shell" tetapi ini bukan jenis perilaku yang sama yang Anda tanyakan. Pada dasarnya, jawaban untuk pertanyaan Anda adalah "Tidak". Selalu ada alternatif, dan jawaban saya menyediakan salah satunya. Ini memperlakukan jendela terminal sesuai dengan sifatnya - jendela GUI X11.

  • Bagaimana jawaban ini berhubungan dengan alias? Yah, pertama-tama alias bisa sedikit berantakan, terutama ketika mengutip dan mem-parsing beberapa output dari banyak perintah. Script ini memberi Anda satu, perintah terpusat, dengan flag / switch untuk melakukan tugas diskrit pada jendela. Itu juga membuat alias lebih sederhana. Anda bisa melakukannya alias nw='windowctrl.py --window'. Jauh lebih pendek, lebih rapi.

Sergiy Kolodyazhnyy
sumber
Saya senang dengan terminal split
Akiva
1
@ Akiva Anda ingin saya menautkan pertanyaan terkait terminal pemisah? sudahkah Anda mencoba skrip ini? Bagaimana menurut anda ?
Sergiy Kolodyazhnyy
Saya akan mencoba skrip Anda, karena jawaban di atas membuat saya kesulitan. Namun saya mungkin tidak begitu beruntung, karena masalah utamanya dengan xdotool.
Akiva
@ Akiva dan apa masalahnya xdotool? Mungkin saya bisa memperbaikinya?
Sergiy Kolodyazhnyy
Saya harus kembali kepada Anda tentang hal itu. Saya mungkin harus melakukan dengan tata letak keyboard kustom saya, atau fakta bahwa saya pada 16,10, atau bahwa saya mencobanya dengan tipuan.
Akiva