This web site has been retired. Please follow my activities at pztrick.com.

pZtrick.com

the personal site of patrick paul

Ubuntu Guake Terminal and Sublime Text Hackery

| Comments

Guake UI overlayed over rest of windows (toggled by F1) So I’ve been happy with the Xfce4 distribution’s terminal emulator (0.4.8) for a long time, but recently I have been dishing hate on PuTTy (for the Windows systems that I utilize) and realized that I should probably re-visit my Ubuntu rig’s choice of terminal to make my life much more pleasant!

After some web surfing, I decided to give Guake a try. It’s much more aesthetically pleasing (transparent!) and much more functional for me as a drop-down terminal.

My User Story

Hitherto, I have used Sublime Text 2 to launch terminals in project directories (with project virtual environments loaded) using Ctrl+Shift+Z – but this often resulted in multiple shell windows when I would click the hotkey to open a terminal rather than reusing an existing window. Further, when I did choose to cycle windows, I often had to Alt+Tab through several other programs and/or terminals.

Obviously, a tabbed terminal emulator would make sense. While Xfce4 Terminal supports tabs, Guake takes first place for its toggability (F12 by default – since bound to F1) and drop-down overlay. Sublime Text 2 took some additional tweaking to play nice with Guake.

Installation (Ubuntu 12.04 with Xfce4 desktop)

bash terminal
1
2
3
4
5
6
7
8
# For the package included in Ubuntu 12.04 repos
patrick@bangor-dome:~$ sudo apt-get install guake

# I actually sought out a more recent version
# packaged in user PPA rather than 12.04 dist:
patrick@bangor-dome:~$ sudo add-apt-repository ppa:niteshgupta16/ubuntuvibes
patrick@bangor-dome:~$ sudo apt-get update
patrick@bangor-dome:~$ sudo apt-get install guake

Guake may require a reboot before it runs. You should see it in your system tray. You can also identify it as the default terminate in Preferred Applications, accessed via the GNOME Settings Manager.

Customization

From the screenshot album below, you can see a few of the tweaks I made.

  • ✔ Hide on lose focus
  • ✘ Show tab bar
  • ✘ Show scrollbar
  • Drop-down height @ ~40%
  • Transparency @ ~15%
  • ✔ Use the system fixed width font
    • Configured elsewhere as Droid Sans
  • Various key bindings
    • F1 Toggle Guake visibility
    • F12 Toggle Fullscreen terminal
    • Shift+Ctrl+T New tab
    • Shift+Ctrl+W Close tab (exit also works)
    • Shift+Ctrl+B Go to previous tab
    • Shift+Ctrl+F Go to next tab

Enabling transparency (compositing)

Enable display compositing Ubuntu users must ensure that display compositing is enabled before the transparency effect will work for their terminal. The image at right shows the relevant setting, Enable display compositing, in Windows Manager Tweaks accessed through the GNOME Settings Manager.

Enable display compositing You may also need to postpone the autostart script for Guake if it is loading before Compiz can enable transparency. I wrote this short autostart script guake-start.sh which should be added to the Session & Startup settings manager in GNOME (by right-clicking the list in image at right and selecting Add from context menu).

~/guake-start.sh
1
2
#!/bin/bash
sleep 15 && guake
guake-start.sh
1
patrick@bangor-dome:~$ sudo chmod +x guake-start.sh

Playing with Sublime Text 2

If you’re hoping to use this new sexy terminal with Sublime Text 2, you’re out of luck with the existing Sublime Terminal package. It will indeed open the Guake terminal if you have already designated Guake as your system default (e.g. preferred application) – but it will not open new tabs or change directory and will merely open Guake to your existing shell session.

(The Terminal package does allow user-defined parameters, but I wasn’t able to fudge enough commands together to successfully have Guake open a new tab – you’ll see my own hack required some special logic exceeding mere parameters.)

Works great with ST2 after tweaking Terminal.py I routinely hack various packages to add additional functionality. Here is a code snippet you may use in your Sublime Terminal package’s Terminal.py to add this useabity:

  • Ctrl+Shift+T Open Guake terminal
  • Ctrl+Shift+Alt+T Open Guake terminal at project directory

Remember that you already have toggle functionality for accessing an existing drop-down shell using F1.

Packages\Terminal\Terminal.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class TerminalCommand():
  # ...
    def run_terminal(self, dir, parameters):
        try:
            if not dir:
                raise NotFoundError('The file open in the selected view has ' +
                    'not yet been saved')
            for k, v in enumerate(parameters):
                parameters[k] = v.replace('%CWD%', dir)
            args = [TerminalSelector.get()]
            args.extend(parameters)
            encoding = locale.getpreferredencoding(do_setlocale=True)
            # # # #
            # HACK 1) Test for hostname 'bangor-dome' and use Guake
            #           ELSE
            #         Use original code:
            #           subprocess.Popen(args, cwd=dir.encode(encoding))
            #
            # IMPORTANT) Replace guake_path with correct path -- use $ locate guake
            # # # #
            guake_path = '/usr/bin/guake'
            if os.uname()[1] in ['bangor-dome', 'medina']:
                # Step 1) Find a tab index that doesn't exist yet
                current_tab_index = 0
                new_tab_index = 0
                while current_tab_index == new_tab_index:
                    new_tab_index += 1
                    # Try to select a tab higher than current_tab_index
                    # This no-ops if the tab does not exist...
                    p = subprocess.Popen([guake_path, '-s %s' % new_tab_index])
                    while p.poll() is not None:
                        pass  # wait until we select tab

                    # Get the currently selected tab
                    p = subprocess.Popen([guake_path, '-g'], stdout=subprocess.PIPE)
                    while p.poll() is not None:
                        pass  # wait until we get a STDOUT response
                    (stdout, stdin) = p.communicate()
                    current_tab_index = int(stdout.strip('\n'))

                    # If a tab existed, we selected it and need to run the loop again
                    #   case: current_tab_index == new_tab_index
                    # If a tab did not exist, we failed to select it and can exit the loop
                    # and a create a tab at that index.
                    #   case: new_tab_index > current_tab_index

                # Step 2) Create the tab and wait for a response
                p = subprocess.Popen([guake_path, '-n %s' % new_tab_index])
                while p.poll() is not None:
                    pass  # wait until we create tab

                import time
                time.sleep(1)  # I sleep a second here, as p.poll() wasn't enough?

                # Step 3) Change directory
                p = subprocess.Popen([guake_path, '-e cd %s' % dir.encode(encoding)])
                while p.poll() is not None:
                    pass   # wait until we cd

                # Step 4) Rename the tab to something useful?
                p = subprocess.Popen([guake_path, '-r %s' % (current_tab_index + 1)])
                while p.poll() is not None:
                    pass  # wait until we rename tab
                    # NOTE: not working in latest version of guake

                # Step 5) Toggle Guake to visible
                p = subprocess.Popen([guake_path, '-t'])
            else:
                subprocess.Popen(args, cwd=dir.encode(encoding))
            # # # #
            # ENDHACK
            # # # #

        except (OSError) as (exception):
            print str(exception)
            sublime.error_message(__name__ + ': The terminal ' +
                TerminalSelector.get() + ' was not found')
        except (Exception) as (exception):
            sublime.error_message(__name__ + ': ' + str(exception))
    # ...

Comments