@@ 5,9 5,9 @@ Quake mode for terminals under the [i3](
i3quake creates, shows, and hides a terminal of your choosing. Common use for these sorts of tools is to bind a hotkey to the command and thereby create a pop-up-on-demand terminal. Features are:
* The terminal instance is persistent, which is a bit more lightweight than creating and destroying terminals; it also preserves your current workstream in that terminal.
-* Uses any terminal you choose. It's been tested with alacritty, roxterm, xterm, gnome-terminal, xfce4-terminal, termite, and st. st is the default.
+* Uses any program you choose. It's been tested with alacritty, roxterm, xterm, gnome-terminal, xfce4-terminal, termite, st, and gvim. By default, `i3-sensible-terminal` is used to select a terminal.
* Opens the terminal on any edge, with configurable size.
-* Written in Go, and there are no additional dependencies.
+* Single binary executable, with no additional dependencies.
* It's stateless. There's no server process.
![i3quake](https://hg.sr.ht/~ser/i3quake/raw/default/screenshot.png)
@@ 29,29 29,19 @@ bindsym $mod+n exec i3quake -p right -H
Arguments are (currently) ignored after the first run.
-## Options
-
+## Examples
+```bash
+$ i3quake # default use i3-sensible-terminal and open $SHELL
+```
```bash
-➜ ~ i3quake -h
-Usage of i3quake:
- -H float
- % height of window, 0-1 (0.25) (default 0.25)
- -p string
- Position: top, bottom, left, right (top) (default "top")
- -t string
- Terminal program (default "st")
+$ i3quake -p right -H 0.5 -t termite
+```
+```bash
+$ i3quake -p right -H 0.5 -t termite # Opens termite to right
+$ i3quake -p left -H 0.5 -m gvim -t gvim # Opens gvim to left
```
-## Examples
-```bash
-$ i3quake # default use st and open $SHELL
-```
-```bash
-$ i3quake -H 0.5 -t termite
-```
-```bash
-$ i3quake -p right -H 0.6 -t xfce4-terminal
-```
+The last example can be used to bind multiple utility programs to different keys that are popped-up on demand.
## Why
I first tried a couple of other projects, but they were all several years old. The one I liked the most had a couple of limitations, bugs, and were out of date with the i3 IPC API. The main bug was that it used the WM_NAME property to identify the quake window, and **everybody** changes that, so it's not reliable. At first I tried to fix the program -- it was only a few dozen lines of Python, after all -- but I encountered three roadblocks:
@@ 1,7 1,10 @@
package main
-// TODO: code cleanup
-// TODO: AUR & download
+// Provides Quake-style pop-up applications for i3
+// (c) 2020 Sean E. Russell
+// BSD-3 Licensed
+
+// TODO: AUR
import (
"flag"
@@ 15,9 18,11 @@ import (
"github.com/xxxserxxx/i3ipc-go"
)
-var Version, BuildDate string
+// These get set at build time.
+var Version, BuildDate string = "dev", ""
const (
+ // Used for the i3 mark to identify the window
NAME = "i3quake"
)
@@ 37,14 42,30 @@ func main() {
pos := flag.String("p", "top", "Position: top, bottom, left, right (top)")
ratio := flag.Float64("H", 0.25, "% height of window, 0-1 (0.25)")
// TODO: allow arguments for terminal command
- cmd := flag.String("t", "st", "Terminal program")
+ cmd := flag.String("t", "i3-sensible-terminal", "Terminal program (default i3-sensible-terminal)")
version := flag.Bool("v", false, "Print the version and exit")
+ help := flag.Bool("h", false, "Show help and exit")
+ mark := flag.String("m", "", "Additional marking")
// TODO: allow shell command as argument (e.g., tmux)
flag.Parse()
if *version {
fmt.Printf("i3quake version %s (built %s)", Version, BuildDate)
os.Exit(0)
}
+ if *help {
+ flag.PrintDefaults()
+ fmt.Println("Launches a terminal in quake mode, or toggles visibility of an existing")
+ fmt.Println("application. The location (top/left/bottom/right) and size (%% of screen")
+ fmt.Println("width/height) is configurable. The application that is run is specificed")
+ fmt.Println("with -t; this can be any GUI program. Multiple applications can be ")
+ fmt.Println("managed by using the -m flag to specify additional marks; only one ")
+ fmt.Println("program can use a given mark.")
+ fmt.Println()
+ fmt.Println("Examples:")
+ fmt.Println("\ti3quake -p left -h 0.5 # open terminal on left, half-screen")
+ fmt.Println("\ti3quake -p right -h 0.5 -m gvim -t gvim # open gvim on right")
+ os.Exit(0)
+ }
var p int
switch strings.ToLower(*pos) {
default:
@@ 63,17 84,16 @@ func main() {
panic(e)
}
cx := con{c}
- // TODO: i3-sensible-terminal if unset
- cx.toggleQuake(p, *ratio, *cmd)
+ cx.toggleQuake(p, *mark, *ratio, *cmd)
}
-func (c con) toggleQuake(pos int, ratio float64, cmd string) {
+func (c con) toggleQuake(pos int, mark string, ratio float64, cmd string) {
t, e := c.GetTree()
if e != nil {
panic(e)
}
- w := t.FindMarked(NAME)
- // QT hasn't been started yet, so fire one off
+ w := t.FindMarked(NAME + mark)
+ // quake hasn't been started yet, so fire one off
if w == nil {
if cmd == "" {
cmd = "st"
@@ 94,12 114,12 @@ func (c con) toggleQuake(pos int, ratio
if ok {
switch we.Change {
case "new":
- cmd := fmt.Sprintf("[con_id=%d], mark %s", we.Container.ID, NAME)
+ cmd := fmt.Sprintf("[con_id=%d], mark %s", we.Container.ID, NAME+mark)
_, err := c.Command(cmd)
if err != nil {
panic(err)
}
- c.position(pos, ratio)
+ c.position(mark, pos, ratio)
w.Done()
return
default:
@@ 114,7 134,7 @@ func (c con) toggleQuake(pos int, ratio
w.Wait()
} else {
// TODO: Don't ignore argumentas after first run
- cmd := fmt.Sprintf(`[con_mark="%s"], scratchpad show`, NAME)
+ cmd := fmt.Sprintf(`[con_mark="%s"], scratchpad show`, NAME+mark)
suc, _ := c.Command(cmd)
if !suc {
log.Printf("ERROR %s", cmd)
@@ 122,7 142,7 @@ func (c con) toggleQuake(pos int, ratio
}
}
-func (c con) position(pos int, ratio float64) {
+func (c con) position(mark string, pos int, ratio float64) {
ws := c.getCurrentWorkspace()
wheight := int64(float64(ws.Rect.Height) * ratio)
wwidth := int64(float64(ws.Rect.Width) * ratio)
@@ 155,7 175,7 @@ func (c con) position(pos int, ratio flo
resize set %d px %d px,
move absolute position %dpx %dpx,
move scratchpad,
- scratchpad show`, NAME, width, height, posx, posy)
+ scratchpad show`, NAME+mark, width, height, posx, posy)
suc := false
var retries int
var err error