Is there a command in Gnome-Terminal, or any tabbable shell to open a new tab?
I'm not looking for a keyboard shortcut, rather I want a commands for:
- New window
- New Tab
- Close Current tab or window
- Maximise Shell Window
- Minimise Shell Window
- Move Shell to a different work-space
- Switch Tab
And basically anything like this. Remember; I do not want shortcuts, but rather actual commands. The reason for this is so I can utilize alias functionality.
Solution 1:
You cannot do this by default in Gnome-Terminal, at least with raw commands.
However, you can write scripts that call keyboard shortcuts that can do this. Note that you need xdotool
for this: sudo apt install xdotool
-
New Window: Launch a new terminal window with
nw
We can do this with justgnome-terminal
.
Add to.bashrc
:echo "alias nw=gnome-terminal" >> ~/.bashrc
-
New Tab: Launch a new tab with
nt
We can do this withxdotool getactivewindow $(xdotool key ctrl+shift+t)
Add to.bashrc
:echo "alias nt='xdotool getactivewindow $(xdotool key ctrl+shift+t)'" >> .bashrc
-
Close Tab: Close the current tab or window with
ct
xdotool
strikes again:xdotool getactivewindow $(xdotool key ctrl+shift+w)
Add to.bashrc
:echo "alias ct='xdotool getactivewindow $(xdotool key ctrl+shift+w)'" >> .bashrc
-
Maximize Window: Maximize the entire window with
maw
We can usewmctrl
here:wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz
Add to.bashrc
:echo "alias maw='wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz'" >> .bashrc
-
Minimize Window: Minimize the entire window with
miw
We can usexdotool
again:xdotool windowminimize $(xdotool getactivewindow)
Add to.bashrc
:echo "alias miw='xdotool windowminimize $(xdotool getactivewindow)'" >> .bashrc
Move to Workspace: Move a window to another workspace with
mtw <id>
This would be just barely possible in shell scripting, and is way beyond my personal experience. I would recommend using Serg's script for this purpose, because it actually works as of now. Ah, the benefits of Compiz.
Solution 2:
Introduction
The script presented in this answer allows user to control their terminal window via one single command and list of options. It is simple to use and compatible with any terminal emulator that has keybindings similar to gnome-terminal
. Moving options can be used with other terminals as well, but tab opening is not guaranteed for those terminals.
The script covers tab opening, window opening, moving to workspace down, workspace right, specific workspace refereed to by integer number, minimizing, maximizing, and unmaximizing a window. The only thing the script does not cover is closing tab/window simply because each shell/terminal emulator already has a command for it - exit
or alternatively via CtrlD shortcut.
!!! NOTE : you will need xdotool
for workspace switching and tab opening. Install it via sudo apt-get install xdotool
. If you prefer to not install extra packages, keep in mind that workspace and tab switching won't work, but other options will.
Usage:
All of the arguments to windowctrl.py
are optional, so they can be used separately, or potentially together. As shown by -h
option.
$ ./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
Script Source code:
The script source code is available on GitHub as well as here. Latest changes are likely to go into the GitHub rather than here, so I strongly suggest checking for latest version there. It is also suggested to post bug reports there as well.
#!/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()
Side notes
You asked "Is there a command in Gnome-Terminal, or any tabbable shell to open a new tab?" Gnome Terminal manual doesn't list such option. The shells are command-line utilities. Tabs are feature of GUI applications. There are terminal multiplexers like
screen
ortmux
which can have "tabs" or split windows , which sort of comes close to "tabbable shell" but this is not the same type of behavior you ask. Basically, answer to your question is "No". There are always alternatives, and my answer provides one of them. It treats terminal window according to its nature - X11 GUI window.How does this answer relate to aliases ? Well, first of all aliases can be a bit messy, especially when it comes to quoting and parsing multiple outputs from multiple commands. This script gives you one , centralized command, with flags/switches to do a discrete task upon a window. It also makes aliases simpler. You could do
alias nw='windowctrl.py --window'
. Much shorter, much neater.