1import locale 2import argparse 3import os 4import sys 5 6from asciinema import __version__ 7import asciinema.config as config 8from asciinema.commands.auth import AuthCommand 9from asciinema.commands.record import RecordCommand 10from asciinema.commands.play import PlayCommand 11from asciinema.commands.cat import CatCommand 12from asciinema.commands.upload import UploadCommand 13from asciinema.api import Api 14 15 16def positive_float(value): 17 value = float(value) 18 if value <= 0.0: 19 raise argparse.ArgumentTypeError("must be positive") 20 21 return value 22 23 24def rec_command(args, config): 25 api = Api(config.api_url, os.environ.get("USER"), config.install_id) 26 return RecordCommand(api, args) 27 28 29def play_command(args, config): 30 return PlayCommand(args.filename, args.idle_time_limit, args.speed) 31 32 33def cat_command(args, config): 34 return CatCommand(args.filename) 35 36 37def upload_command(args, config): 38 api = Api(config.api_url, os.environ.get("USER"), config.install_id) 39 return UploadCommand(api, args.filename) 40 41 42def auth_command(args, config): 43 api = Api(config.api_url, os.environ.get("USER"), config.install_id) 44 return AuthCommand(api) 45 46 47def maybe_str(v): 48 if v is not None: 49 return str(v) 50 51 52def main(): 53 if locale.nl_langinfo(locale.CODESET).upper() not in ['US-ASCII', 'UTF-8']: 54 print("asciinema needs an ASCII or UTF-8 character encoding to run. Check the output of `locale` command.") 55 sys.exit(1) 56 57 try: 58 cfg = config.load() 59 except config.ConfigError as e: 60 sys.stderr.write(str(e) + '\n') 61 sys.exit(1) 62 63 # create the top-level parser 64 parser = argparse.ArgumentParser( 65 description="Record and share your terminal sessions, the right way.", 66 epilog="""example usage: 67 Record terminal and upload it to asciinema.org: 68 \x1b[1masciinema rec\x1b[0m 69 Record terminal to local file: 70 \x1b[1masciinema rec demo.cast\x1b[0m 71 Record terminal and upload it to asciinema.org, specifying title: 72 \x1b[1masciinema rec -t "My git tutorial"\x1b[0m 73 Record terminal to local file, limiting idle time to max 2.5 sec: 74 \x1b[1masciinema rec -i 2.5 demo.cast\x1b[0m 75 Replay terminal recording from local file: 76 \x1b[1masciinema play demo.cast\x1b[0m 77 Replay terminal recording hosted on asciinema.org: 78 \x1b[1masciinema play https://asciinema.org/a/difqlgx86ym6emrmd8u62yqu8\x1b[0m 79 Print full output of recorded session: 80 \x1b[1masciinema cat demo.cast\x1b[0m 81 82For help on a specific command run: 83 \x1b[1masciinema <command> -h\x1b[0m""", 84 formatter_class=argparse.RawDescriptionHelpFormatter 85 ) 86 parser.add_argument('--version', action='version', version='asciinema %s' % __version__) 87 88 subparsers = parser.add_subparsers() 89 90 # create the parser for the "rec" command 91 parser_rec = subparsers.add_parser('rec', help='Record terminal session') 92 parser_rec.add_argument('--stdin', help='enable stdin recording, disabled by default', action='store_true', default=cfg.record_stdin) 93 parser_rec.add_argument('--append', help='append to existing recording', action='store_true', default=False) 94 parser_rec.add_argument('--raw', help='save only raw stdout output', action='store_true', default=False) 95 parser_rec.add_argument('--overwrite', help='overwrite the file if it already exists', action='store_true', default=False) 96 parser_rec.add_argument('-c', '--command', help='command to record, defaults to $SHELL', default=cfg.record_command) 97 parser_rec.add_argument('-e', '--env', help='list of environment variables to capture, defaults to ' + config.DEFAULT_RECORD_ENV, default=cfg.record_env) 98 parser_rec.add_argument('-t', '--title', help='title of the asciicast') 99 parser_rec.add_argument('-i', '--idle-time-limit', help='limit recorded idle time to given number of seconds', type=positive_float, default=maybe_str(cfg.record_idle_time_limit)) 100 parser_rec.add_argument('-y', '--yes', help='answer "yes" to all prompts (e.g. upload confirmation)', action='store_true', default=cfg.record_yes) 101 parser_rec.add_argument('-q', '--quiet', help='be quiet, suppress all notices/warnings (implies -y)', action='store_true', default=cfg.record_quiet) 102 parser_rec.add_argument('filename', nargs='?', default='', help='filename/path to save the recording to') 103 parser_rec.set_defaults(func=rec_command) 104 105 # create the parser for the "play" command 106 parser_play = subparsers.add_parser('play', help='Replay terminal session') 107 parser_play.add_argument('-i', '--idle-time-limit', help='limit idle time during playback to given number of seconds', type=positive_float, default=maybe_str(cfg.play_idle_time_limit)) 108 parser_play.add_argument('-s', '--speed', help='playback speedup (can be fractional)', type=positive_float, default=cfg.play_speed) 109 parser_play.add_argument('filename', help='local path, http/ipfs URL or "-" (read from stdin)') 110 parser_play.set_defaults(func=play_command) 111 112 # create the parser for the "cat" command 113 parser_cat = subparsers.add_parser('cat', help='Print full output of terminal session') 114 parser_cat.add_argument('filename', help='local path, http/ipfs URL or "-" (read from stdin)') 115 parser_cat.set_defaults(func=cat_command) 116 117 # create the parser for the "upload" command 118 parser_upload = subparsers.add_parser('upload', help='Upload locally saved terminal session to asciinema.org') 119 parser_upload.add_argument('filename', help='filename or path of local recording') 120 parser_upload.set_defaults(func=upload_command) 121 122 # create the parser for the "auth" command 123 parser_auth = subparsers.add_parser('auth', help='Manage recordings on asciinema.org account') 124 parser_auth.set_defaults(func=auth_command) 125 126 # parse the args and call whatever function was selected 127 args = parser.parse_args() 128 129 if hasattr(args, 'func'): 130 command = args.func(args, cfg) 131 code = command.execute() 132 sys.exit(code) 133 else: 134 parser.print_help() 135 sys.exit(1) 136 137 138if __name__ == '__main__': 139 main() 140