I just completed a long overdue item on my todo-list. A combination of the scripts that @GermainZ and I made. It can match by either name and class - both regex enabled. It's written as in node.js.
See this repository:
https://github.com/gustavnikolaj/i3-r...
You will need to have node installed and run npm install in the directory you've cloned it into. After that, you can either reference it by the full path to bin/i3-run-or-raise or you could add it somewhere on your path. (Remember that you'll have to manually set that path available to the X server, by adding it to .xsession/.xinitrc or where it would be appropriate on your system).
Rewriting the examples that I made in my first answer in this thread:
bindsym F1 exec ~/path/to/i3-run-or-raise -c "Google-chrome" google-chrome
bindsym F2 exec ~/path/to/i3-run-or-raise -n "Sublime Text 2$" sublime-text
Below is my original answer for reference.
I wrote a python script to solve this problem.
I use it in my configuration like this:
bindsym F1 exec python ~/.i3/scripts/next_window.py "Chrome$" google-chrome
bindsym F2 exec python ~/.i3/scripts/next_window.py "Sublime Text 2$" sublime-text
The first parameter is a regex to match the window title. The second parameter is the application to launch if no active window is found.
import json
import re
import subprocess
import sys
I3MSG = '/usr/bin/i3-msg'
windows = []
def parse_args():
if len(sys.argv) == 3:
return (sys.argv[1], sys.argv[2])
else:
sys.exit('Must provide 2 arguments.')
def get_tree():
process = subprocess.Popen([I3MSG, "-t", "get_tree"], stdout=subprocess.PIPE)
tree = str(process.communicate()[0])
process.stdout.close()
return json.loads(tree)
def walk_tree(tree):
if tree['window']:
windows.append({
'name': tree['name'],
'id': str(tree['id']),
'focused': tree['focused']
})
if len(tree['nodes']) > 0:
for node in tree['nodes']:
walk_tree(node)
def main():
pattern, command = parse_args()
tree = get_tree()
walk_tree(tree)
focused = filter(lambda x: x['focused'], windows)
if len(focused) == 1:
focused = focused[0]
else:
focused = False
filteredWindows = filter(lambda x: re.search(pattern, x['name']), windows)
if len(filteredWindows) == 0:
subprocess.call([I3MSG, 'exec', '--no-startup-id', command])
else:
nextWindow = False
try:
if not focused:
raise ValueError
nextIndex = filteredWindows.index(focused) + 1
if nextIndex == len(filteredWindows):
raise ValueError
else:
nextWindow = filteredWindows[nextIndex]
except ValueError:
nextWindow = filteredWindows[0]
con_id = nextWindow['id']
subprocess.call([I3MSG, '[con_id=' + con_id + ']', 'focus'])
if __name__ == '__main__':
main()
You can see the code at my github dotfiles repository: https://github.com/gustavnikolaj/dotf...