├── CHANGES.txt ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── README.txt ├── bin └── i3minator ├── docs └── info.txt ├── i3minator └── __init__.py └── setup.py /CHANGES.txt: -------------------------------------------------------------------------------- 1 | v0.0.4, 2014-02-23 -- Merged pull request #4 since we are on i3, use i3-sensible-terminal instead of $TERM 2 | v0.0.3, 2013-10-07 -- Improved python2 support 3 | v0.0.2, 2013-10-06 -- Added edit and help commands. Released under WTFLP License. Markdown version of README 4 | v0.0.1, 2013-10-06 -- Initial release. 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2013 Enrico Carlesso 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.txt 2 | recursive-include docs *.txt 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # i3minator 2 | 3 | Since now i3 supports [Layout saving/restoring](http://i3wm.org/docs/layout-saving.html), 4 | this project can be considered dead. 5 | 6 | i3minator is a simple "workspace manager" for i3. 7 | It allows to quickly manage workspaces defining windows and their layout. 8 | The project is inspired by [tmuxinator](https://github.com/aziz/tmuxinator) and uses [i3-py](https://github.com/ziberna/i3-py). 9 | 10 | # Install 11 | 12 | i3minator can be installed with pip 13 | 14 | ```shell 15 | $ sudo pip install i3minator 16 | ``` 17 | 18 | # Project description 19 | 20 | All project file are stored in `~/.i3minator/` and are in yaml format. 21 | An example: 22 | 23 | ```yaml 24 | # /home/carlesso/.i3minator/default.yml 25 | 26 | # The Name of the project 27 | name: default 28 | 29 | # If needes, where the project lives. If present, all terminal will be opened here 30 | # and all commands are relative to this path. 31 | root: ~/projects/my_project/ 32 | 33 | # The name of the workspace to open the project. 34 | # If not present, current workspace is used 35 | workspace_name: MyProject 36 | 37 | # Chain of commands to populate workspace. 38 | # Every element can be either a node (see below), or a command between: 39 | # go_vertical, vertical, v: change split mode into vertical 40 | # go_horizontal, horizontal, h: change split mode into vertical 41 | # go_stacked, stacked: set the layout to stacked 42 | # 43 | # Example for a rails application: 44 | window_chain: 45 | - gvim 46 | - console 47 | - go_vertical 48 | - server 49 | - logs 50 | 51 | # Nodes. Each node represent a window. The available parameters are: 52 | # command: the command to execute 53 | # terminal: whatever the command should be run in a terminal window 54 | # timeout: A window can take a while to be placed, if your layout does not come as you want, 55 | # inceremnt the timeout for slow windows. default: 0.1 56 | nodes: 57 | gvim: 58 | terminal: false 59 | command: gvim . 60 | timeout: 0.3 61 | console: 62 | terminal: true 63 | command: bundle exec rails c 64 | server: 65 | terminal: true 66 | command: bundle exec rails s 67 | logs: 68 | terminal: true 69 | command: tailf log/development.log 70 | ``` 71 | 72 | # List of commands 73 | 74 | i3minator supports the following commands: 75 | 76 | ``` 77 | i3minator commands: 78 | i3minator commands # Lists commands available in i3minator 79 | i3minator copy [EXISTING] [NEW] # Copy an existing project to a new project and open it in your editor 80 | i3minator edit [PROJECT] # Edit given project 81 | i3minator delete [PROJECT] # Deletes given project 82 | i3minator impolode # Delete all i3minator project, as well as the ~/.i3minator folder 83 | i3minator list # List all i3minator projects 84 | i3minator new [PROJECT] # Create a new project and open in your text editor 85 | i3minator start [PROJECT] # Start a i3minator project 86 | i3minator version # Display installed i3minator version 87 | ``` 88 | 89 | # Terminal and Editor 90 | 91 | Editor is read from shell's defaults: 92 | 93 | ```bash 94 | echo $SHELL 95 | ``` 96 | 97 | Terminal is found by i3-sensible-terminal command. 98 | 99 | Right now has been tested only with xterm and zsh 100 | 101 | # Timeouting node spawn 102 | Some windows may take more time to be insert in the workspace. If you experience this, and yout layout get messed up, try to play with `timeout` value in the node. 103 | 104 | # About 105 | Author: Enrico Carlesso 106 | License: [WTFPL](http://www.wtfpl.net/about/) 107 | 108 | Thanks: 109 | 110 | - [i3 window manager](http://i3wm.org/) and its author Michael Stapelberg 111 | - [i3-py](https://github.com/ziberna/i3-py)and its author Jure Žiberna 112 | 113 | i3minator was tested with Python 3.3.2 114 | 115 | Dependencies: 116 | 117 | - i3-wm 118 | - i3-py 119 | - Python 120 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | # i3minator 2 | 3 | i3minator is a simple "workspace manager" for i3. 4 | It allows to quickly manage workspaces defining windows and their layout. 5 | The project is inspired by [tmuxinator](https://github.com/aziz/tmuxinator) and uses [i3-py](https://github.com/ziberna/i3-py). 6 | 7 | # Install 8 | 9 | i3minator can be installed with pip 10 | 11 | ```shell 12 | $ sudo pip install i3minator 13 | ``` 14 | 15 | # Project description 16 | 17 | All project file are stored in `~/.i3minator/` and are in yaml format. 18 | An example: 19 | 20 | ```yaml 21 | # /home/carlesso/.i3minator/default.yml 22 | 23 | # The Name of the project 24 | name: default 25 | 26 | # If needes, where the project lives. If present, all terminal will be opened here 27 | # and all commands are relative to this path. 28 | root: ~/projects/my_project/ 29 | 30 | # The name of the workspace to open the project. 31 | # If not present, current workspace is used 32 | workspace_name: MyProject 33 | 34 | # Chain of commands to populate workspace. 35 | # Every element can be either a node (see below), or a command between: 36 | # go_vertical, vertical, v: change split mode into vertical 37 | # go_horizontal, horizontal, h: change split mode into vertical 38 | # go_stacked, stacked: set the layout to stacked 39 | # 40 | # Example for a rails application: 41 | window_chain: 42 | - gvim 43 | - console 44 | - go_vertical 45 | - server 46 | - logs 47 | 48 | # Nodes. Each node represent a window. The available parameters are: 49 | # command: the command to execute 50 | # terminal: whatever the command should be run in a terminal window 51 | # timeout: A window can take a while to be placed, if your layout does not come as you want, 52 | # inceremnt the timeout for slow windows. default: 0.1 53 | nodes: 54 | gvim: 55 | terminal: false 56 | command: gvim . 57 | timeout: 0.3 58 | console: 59 | terminal: true 60 | command: bundle exec rails c 61 | server: 62 | terminal: true 63 | command: bundle exec rails s 64 | logs: 65 | terminal: true 66 | command: tailf log/development.log 67 | ``` 68 | 69 | # List of commands 70 | 71 | i3minator supports the following commands: 72 | 73 | ``` 74 | i3minator commands: 75 | i3minator commands # Lists commands available in i3minator 76 | i3minator copy [EXISTING] [NEW] # Copy an existing project to a new project and open it in your editor 77 | i3minator edit [PROJECT] # Edit given project 78 | i3minator delete [PROJECT] # Deletes given project 79 | i3minator impolode # Delete all i3minator project, as well as the ~/.i3minator folder 80 | i3minator list # List all i3minator projects 81 | i3minator new [PROJECT] # Create a new project and open in your text editor 82 | i3minator start [PROJECT] # Start a i3minator project 83 | i3minator version # Display installed i3minator version 84 | ``` 85 | 86 | # Terminal and Editor 87 | 88 | Both Terminal and Editor are read from shell's defaults: 89 | 90 | ```bash 91 | echo $TERM 92 | echo $SHELL 93 | ``` 94 | 95 | Right now has been tested only with xterm and zsh 96 | 97 | # Timeouting node spawn 98 | Some windows may take more time to be insert in the workspace. If you experience this, and yout layout get messed up, try to play with `timeout` value in the node. 99 | 100 | # About 101 | Author: Enrico Carlesso 102 | License: [WTFPL](http://www.wtfpl.net/about/) 103 | 104 | Thanks: 105 | 106 | - [i3 window manager](http://i3wm.org/) and its author Michael Stapelberg 107 | - [i3-py](https://github.com/ziberna/i3-py)and its author Jure Žiberna 108 | 109 | i3minator was tested with Python 3.3.2 110 | 111 | Dependencies: 112 | 113 | - i3-wm 114 | - i3-py 115 | - Python 116 | -------------------------------------------------------------------------------- /bin/i3minator: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import i3 5 | import sys 6 | import stat 7 | 8 | from yaml import load 9 | from time import sleep 10 | from shutil import copy, rmtree 11 | from tempfile import NamedTemporaryFile 12 | 13 | 14 | BASE_PATH = os.path.expanduser("~/.i3minator/") 15 | __version__ = "0.0.4" 16 | example_project = """# %(path)s 17 | 18 | # The Name of the project 19 | name: %(name)s 20 | 21 | # If needes, where the project lives. If present, all terminal will be opened here 22 | # and all commands are relative to this path. 23 | root: ~/projects/my_project/ 24 | 25 | # The name of the workspace to open the project. 26 | # If not present, current workspace is used 27 | workspace_name: MyProject 28 | 29 | # Chain of commands to populate workspace. 30 | # Every element can be either a node (see below), or a command between: 31 | # go_vertical, vertical, v: change split mode into vertical 32 | # go_horizontal, horizontal, h: change split mode into vertical 33 | # go_stacked, stacked: set the layout to stacked 34 | # 35 | # Example for a rails application: 36 | window_chain: 37 | - gvim 38 | - console 39 | - go_vertical 40 | - server 41 | - logs 42 | 43 | # Nodes. Each node represent a window. The available parameters are: 44 | # command: the command to execute 45 | # terminal: whatever the command should be run in a terminal window 46 | # timeout: A window can take a while to be placed, if your layout does not come as you want, 47 | # inceremnt the timeout for slow windows. default: 0.1 48 | nodes: 49 | gvim: 50 | terminal: false 51 | command: gvim . 52 | timeout: 0.3 53 | console: 54 | terminal: true 55 | command: bundle exec rails c 56 | server: 57 | terminal: true 58 | command: bundle exec rails s 59 | logs: 60 | terminal: true 61 | command: tailf log/development.log 62 | """ 63 | 64 | 65 | class i3minatorProject: 66 | 67 | def __init__(self, project): 68 | self.project_file = project_location(project) 69 | 70 | self.info = load(open(os.path.expanduser(self.project_file), "r")) 71 | self.terminal = "i3-sensible-terminal" 72 | 73 | def run(self): 74 | # Switch to worspace if specified 75 | if "workspace_name" in self.info.keys(): 76 | print("Switching to " + self.info["workspace_name"]) 77 | i3.workspace(self.info["workspace_name"]) 78 | 79 | # Find Root of project, if existing 80 | self.root_dir = False 81 | if "root" in self.info.keys(): 82 | self.root_dir = os.path.expanduser(self.info["root"]) 83 | 84 | for step_name in self.info["window_chain"]: 85 | if step_name in self.info["nodes"].keys(): 86 | self.spawn_node(step_name) 87 | else: 88 | # Special keys management, used to move in layout 89 | if step_name in ["v", "go_vertical"]: 90 | print("Splitting vertical") 91 | i3.split("v") 92 | elif step_name in ["h", "go_horizontal"]: 93 | print("Splitting horizontal") 94 | i3.split("h") 95 | elif step_name in ["stacked", "go_stacked", "stack"]: 96 | i3.layout("stacked") 97 | 98 | def spawn_node(self, node_name): 99 | node = self.info["nodes"][node_name] 100 | 101 | name = node_name if "name" not in node.keys() else node["name"] 102 | 103 | if node["terminal"]: 104 | command = "%s -e \"%s && $SHELL\"" % (self.terminal, node["command"]) 105 | if self.root_dir: 106 | command = "(cd %(path)s ; %(terminal)s -T %(name)s -e $SHELL -l -c \"%(command)s; $SHELL\")&" % \ 107 | { 108 | 'path': self.root_dir, 109 | 'command': node["command"], 110 | 'name': name, 111 | 'terminal': self.terminal 112 | } 113 | else: 114 | command = node["command"] 115 | if self.root_dir: 116 | command = "cd %s && %s" %(self.root_dir, node["command"]) 117 | print("Executing " + command) 118 | script = NamedTemporaryFile("w", prefix="i3p_") 119 | script.file.write(command + "\n") 120 | script.file.close() 121 | current_stats = os.stat(script.name) 122 | os.chmod(script.name, current_stats.st_mode | stat.S_IEXEC) 123 | i3.command("exec " + script.name) 124 | timeout = 0.1 if "timeout" not in node.keys() else node["timeout"] 125 | sleep(timeout) 126 | 127 | 128 | def print_help(): 129 | help_string = """i3minator commands: 130 | i3minator commands # Lists commands available in i3minator 131 | i3minator copy [EXISTING] [NEW] # Copy an existing project to a new project and open it in your editor 132 | i3minator edit [PROJECT] # Edit given project 133 | i3minator delete [PROJECT] # Deletes given project 134 | i3minator implode # Delete all i3minator project, as well as the ~/.i3minator folder 135 | i3minator help # This help plus link to github repository 136 | i3minator list # List all i3minator projects 137 | i3minator new [PROJECT] # Create a new project and open in your text editor 138 | i3minator start [PROJECT] # Start a i3minator project 139 | i3minator version # Display installed i3minator version 140 | """ 141 | print(help_string) 142 | 143 | def project_location(project): 144 | if not (project.endswith(".yaml") or project.endswith(".yml")): 145 | project += ".yml" 146 | return "%s%s" % (BASE_PATH, project) 147 | 148 | def project_exists(project): 149 | try: 150 | with open(project_location(project)): return True 151 | except IOError: 152 | return False 153 | 154 | def copy_project(target, source = None): 155 | if not os.path.exists(BASE_PATH): 156 | os.mkdir(BASE_PATH) 157 | target_file = project_location(target) 158 | if source is None: 159 | f = open(target_file, "w") 160 | f.write(example_project % { 161 | 'name': target, 162 | 'path': target_file 163 | }) 164 | f.close() 165 | return True 166 | 167 | source_file = project_location(source) 168 | print("Copy", source_file, target_file) 169 | copy(source_file, target_file) 170 | return True 171 | 172 | def check_args(command, num = 3, placeholder = "[PROJECT]"): 173 | if len(sys.argv) < num: 174 | sys.stderr.write("ERROR: i3minator was called with no arguments\n") 175 | sys.stderr.write("Usage: \"i3minator %s %s\"\n" % (command, placeholder)) 176 | exit(1) 177 | if len(sys.argv) > num: 178 | sys.stderr.write("ERROR: i3minator was called with arguments " + str(sys.argv[2:]) + "\n") 179 | sys.stderr.write("Usage: \"i3minator %s %s\"\n" % (command, placeholder)) 180 | exit(1) 181 | 182 | def confirm(message): 183 | sys.stdout.write('\033[91m%s\033[0m [y/N] ' % message) 184 | choice = input().lower() 185 | if choice in ["yes", "y"]: 186 | return True 187 | else: 188 | return False 189 | 190 | def edit_project(project): 191 | editor = os.environ.get("EDITOR") 192 | os.system("%s %s" % (editor, project_location(project))) 193 | 194 | if __name__ == "__main__": 195 | 196 | if len(sys.argv) is 1: 197 | print_help() 198 | exit(0) 199 | 200 | 201 | if sys.argv[1] == "commands": 202 | # Lists commands 203 | print_help() 204 | exit(0) 205 | 206 | elif sys.argv[1] == "copy": 207 | # Copy existing project 208 | check_args("copy", 4, "[EXISTING] [NEW]") 209 | if project_exists(sys.argv[2]): 210 | copy_project(sys.argv[3], sys.argv[2]) 211 | edit_project(sys.argv[3]) 212 | else: 213 | # Project not existing 214 | sys.stderr.write("Project %s doesn't exists\n" % sys.argv[2]) 215 | 216 | elif sys.argv[1] == "delete": 217 | # Delete project 218 | check_args("delete") 219 | if project_exists(sys.argv[2]): 220 | if confirm("Are you sure you want to delete %s" % sys.argv[2]): 221 | os.remove(project_location(sys.argv[2])) 222 | else: 223 | sys.stderr.write("Project %s doesn't exists\n" % sys.argv[2]) 224 | 225 | elif sys.argv[1] == "implode": 226 | if confirm("Are you sure you want to delete all i3minator projects?"): 227 | rmtree(BASE_PATH) 228 | print("Deleted all i3minator projects.") 229 | 230 | 231 | elif sys.argv[1] == "new": 232 | # Create new project 233 | check_args("new") 234 | copy_project(sys.argv[2]) 235 | edit_project(sys.argv[2]) 236 | 237 | elif sys.argv[1] == "start": 238 | # Start given project 239 | check_args("start") 240 | if project_exists(sys.argv[2]): 241 | p = i3minatorProject(sys.argv[2]) 242 | p.run() 243 | else: 244 | # Project not existing 245 | sys.stderr.write("Project %s doesn't exists.\n" % sys.argv[2]) 246 | 247 | elif sys.argv[1] == "list": 248 | # List availabe projects 249 | files = [i for i in os.listdir(BASE_PATH) if (i.endswith(".yml") or i.endswith(".yaml"))] 250 | print("i3minator projects:") 251 | for i in files: 252 | print(i.replace(".yml", "").replace(".yaml", "")) 253 | elif sys.argv[1] == "edit": 254 | # Edit project 255 | check_args("edit") 256 | if project_exists(sys.argv[2]): 257 | edit_project(sys.argv[2]) 258 | else: 259 | # Project not existing 260 | sys.stderr.write("Project %s doesn't exists.\n" % sys.argv[2]) 261 | 262 | elif sys.argv[1] == "version": 263 | print("i3minator %s" % __version__) 264 | 265 | elif sys.argv[1] == "help": 266 | print_help() 267 | print("Additional information can be found at https://github.com/carlesso/i3minator") 268 | else: 269 | sys.stderr.write("Could not find command %s\n" % sys.argv[1]) 270 | 271 | -------------------------------------------------------------------------------- /docs/info.txt: -------------------------------------------------------------------------------- 1 | i3minator is a i3-based version of tmuxinator 2 | -------------------------------------------------------------------------------- /i3minator/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carlesso/i3minator/1db5a52fcaea6e3ca706a8e30a5da0e8d18f5385/i3minator/__init__.py -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name = 'i3minator', 5 | version = '0.0.4', 6 | author = 'Enrico Carlesso', 7 | author_email = 'enricocarlesso@gmail.com', 8 | packages = ['i3minator'], 9 | scripts = ['bin/i3minator'], 10 | url = 'https://github.com/carlesso/i3minator', 11 | license = 'LICENSE.txt', 12 | description = 'i3 project manager similar to tmuxinator', 13 | long_description = open("README.txt").read(), 14 | install_requires = [ 15 | 'i3-py >= 0.6.4', 16 | 'PyYAML' 17 | ] 18 | ) 19 | --------------------------------------------------------------------------------