├── .hgignore
├── LICENSE.markdown
├── README.markdown
└── rerun
/.hgignore:
--------------------------------------------------------------------------------
1 | syntax: glob
2 |
3 | .DS_Store
4 | *.pyc
5 | *.swp
6 | *.swo
7 | *.un~
8 | .ropeproject
9 | tags
10 |
--------------------------------------------------------------------------------
/LICENSE.markdown:
--------------------------------------------------------------------------------
1 | MIT/X11 License
2 | ===============
3 |
4 | Copyright (c) 2011 Steve Losh and contributors
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | rerun
2 | =====
3 |
4 | `rerun` is a tiny little script that helps you run repetetive shell commands
5 | over and over again.
6 |
7 | The Problem
8 | -----------
9 |
10 | Imagine you're working on debugging an issue with a particular daemon, like
11 | Celery. In one window you're editing code to try solutions, and in another
12 | you're stopping and starting the Celery and RabbitMQ daemons.
13 |
14 | The commands
15 | you're running over and over in varying order might look like this:
16 |
17 | sudo /etc/init.d/rabbitmq-server restart
18 | sudo /etc/init.d/celeryd stop
19 | sudo /etc/init.d/celeryd start
20 | tail /var/log/celery/myhost.log
21 | tail /var/log/celery/myotherhost.log
22 |
23 | Running the various commands can be a pain. They're similar enough that tab
24 | completion, zsh's history completion, and `Ctrl-R` searching all fall short.
25 | That's where `rerun` comes in:
26 |
27 | 
28 |
29 | Installation
30 | ------------
31 |
32 | curl 'https://raw.githubusercontent.com/mandarg/rerun/master/rerun' > /usr/local/bin/rerun
33 | chmod a+x /usr/local/bin/rerun
34 |
35 | Usage
36 | -----
37 |
38 | When you run `rerun` you're greeted with a prompt like this:
39 |
40 | >
41 |
42 | Type `/help` (or just `/h`) to get a list of commands:
43 |
44 | > /help
45 | (/a)dd [command]
46 | (/d)elete [key]
47 | (/h)elp
48 | (/q)uit
49 | (/r)run all commands in order shown
50 |
51 | >
52 |
53 | Add commands to the list with `/add`. You can specify the command right in the
54 | `/add` command or let `rerun` prompt you for it:
55 |
56 | > /add ls
57 |
58 | [a] ls
59 | > /add
60 | Enter command: pwd
61 |
62 | [a] ls
63 | [b] pwd
64 | >
65 |
66 | Now that you've got some commands in the list, run them by entering the key
67 | displayed next to their name:
68 |
69 | [a] ls
70 | [b] pwd
71 | > a
72 | LICENSE.markdown README.markdown rerun
73 |
74 | [a] ls
75 | [b] pwd
76 | > b
77 | /Users/sjl/src/rerun
78 |
79 | [a] ls
80 | [b] pwd
81 | >
82 |
83 | If you don't need a command any more you can `/delete` it:
84 |
85 | [a] ls
86 | [b] pwd
87 | > /delete b
88 |
89 | [a] ls
90 | > /d
91 | Which command? a
92 |
93 | >
94 |
95 | You can also run all commands currently in the queue with a `/run` or `/r`:
96 |
97 | > /run
98 | /home/mandar/sandbox/rerun
99 | LICENSE.markdown README.markdown rerun
100 |
101 | [a] pwd
102 | [b] ls
103 |
104 | Use `/quit` or `Ctrl-D` to exit.
105 |
106 | Other Information
107 | -----------------
108 |
109 | * Written by [@sjl](https://github.com/sjl), currently maintained by [@mandarg](https://github.com/mandarg)
110 | * Source (Mercurial):
111 | * Source (Git):
112 | * License: MIT/X11
113 | * Issues:
114 |
--------------------------------------------------------------------------------
/rerun:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sys, subprocess
4 | import readline
5 | from string import lowercase, uppercase
6 |
7 | readline.parse_and_bind("tab: complete")
8 | commands = {}
9 |
10 | def _get_key():
11 | used = commands.keys()
12 |
13 | for c in lowercase + uppercase:
14 | if c not in used:
15 | return c
16 |
17 | return None
18 |
19 |
20 | def run(key):
21 | try:
22 | subprocess.check_call(commands[key], shell=True, stdout=sys.stdout, stderr=sys.stderr)
23 | except subprocess.CalledProcessError:
24 | return False
25 |
26 | return True
27 |
28 | def add(choice):
29 | parts = choice.split(' ', 1)
30 |
31 | if len(parts) > 1:
32 | cmd = parts[-1]
33 | else:
34 | cmd = raw_input('Enter command: ')
35 |
36 | if cmd not in commands.values():
37 | commands[_get_key()] = cmd
38 |
39 | def delete(choice):
40 | parts = choice.split(' ', 1)
41 |
42 | if len(parts) > 1:
43 | key = parts[-1]
44 | else:
45 | key = raw_input('Which command? ')
46 |
47 | del commands[key]
48 |
49 | def copy():
50 | # TODO
51 | pass
52 |
53 | def halp():
54 | print "(/a)dd [command]"
55 | print "(/d)elete [key]"
56 | print "(/h)elp"
57 | print "(/q)uit"
58 | print "(/r)run all commands in order shown"
59 |
60 |
61 | def _print_list():
62 | print
63 | for cmd in sorted(commands.items()):
64 | print '[%s] %s' % cmd
65 |
66 |
67 | def runall():
68 | for key in sorted(commands.keys()):
69 | run(key)
70 |
71 |
72 | def loop():
73 | _print_list()
74 | choice = raw_input('> ')
75 |
76 | if choice.startswith('/d'):
77 | delete(choice)
78 | elif choice.startswith('/a'):
79 | add(choice)
80 | elif choice.startswith('/c'):
81 | copy(choice)
82 | elif choice.startswith('/h'):
83 | halp()
84 | elif choice.startswith('/q'):
85 | return False
86 | elif choice.startswith('/r'):
87 | runall()
88 | elif not choice.strip():
89 | pass
90 | elif choice in commands.keys():
91 | run(choice)
92 | else:
93 | print 'Derp?'
94 |
95 | return True
96 |
97 |
98 | if __name__ == '__main__':
99 | try:
100 | while loop():
101 | pass
102 | except EOFError:
103 | pass
104 |
--------------------------------------------------------------------------------