<commit_before>import argparse
import os
import platform
import shlex
import subprocess
import sys
from subprocess import CalledProcessError, list2cmdline

from . import core, dockercore, state
from .core import BuildError
from .dockercore import DockerBuildError, docker_get_image_shell
from .eval import ActionNotFoundError, ArgError, EvalError, eval, layer
from .utils import (disable_friendly_exception, friendly_exception, hashstr,
                    rand)

HELP = 'my help'
PROG = 'plash'


NO_TERM_BUILD_ERROR = """plash error: Refusing to build when not connected to a tty(-like) device.
Set the env PLASH_BUILD_SILENT to enable building without output is such cases.
Or invoke this call with --build-only from a terminal to build and then run again.
The argv of this program was: {}""".format(sys.argv)

# shortcuts are specific to the stdlib
SHORTCUTS = [
    # shortcut, lsp, nargs
    ('-x', ['run'], '+'),
    ('-a', ['apt'], '+'),
    ('-y', ['yum'], '+'),
    ('-p', ['pip'], '+'),
    ('-b', ['apt', 'ubuntu-server'], 0),
    ('-o', ['os'], 1),
    ('-r', ['include', '~/.plashrc'], 0),
    ('-U', ['os', 'ubuntu'], 0),
    ('-F', ['os', 'fedora'], 0),
    ('-D', ['os', 'debian'], 0),
 ]

def add_shortcuts_to_parser(parser):
    group = parser.add_argument_group('shortcuts', 'shortcuts')
    for shortcut, lsp, nargs in SHORTCUTS:
        group.add_argument(
            shortcut,
            action=create_collect_lsp_action(lsp),
            nargs=nargs)

def create_collect_lsp_action(lsp_begin):
    class CollectAction(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            if not 'lsp' in namespace:
                setattr(namespace, 'lsp', [])
            previous = namespace.lsp
            previous.append(lsp_begin + list(values))
            setattr(namespace, 'lsp', previous) 
    return CollectAction

def get_argument_parser():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawTextHelpFormatter,
        description='Run programm from any Linux',
        prog=PROG,
        epilog=HELP)

    parser.add_argument("subcommand", nargs='?')

    parser.add_argument("--build-silent", action='store_true')
    parser.add_argument("--build-verbose", "--build-loud", action='store_true', dest='verbose')
    parser.add_argument("--build-only", action='store_true')
    parser.add_argument("--build-again", "--rebuild", "--again", action='store_true')

    parser.add_argument("--no-stdlib", action='store_true')
    parser.add_argument("--traceback", action='store_true')
    parser.add_argument("--debug-lsp", action='store_true')

    parser.add_argument("--ignore-no-tty", action='store_false')

    parser.add_argument("--docker", "-d", action='store_true')

    parser.add_argument("--docker-save-image")

    add_shortcuts_to_parser(parser)

    return parser



def main():
    argv = sys.argv[1:]

    try:
        delimiter = argv.index('--')
        command = argv[delimiter+1:]
        argv = argv[:delimiter]
        # assert False, (args, command)
    except ValueError:
        command = None

    ap = get_argument_parser()
    _, unused_args = ap.parse_known_args(argv)
    # lsp = unused_args_to_lsp(unused_args)
    for arg in set(unused_args):
        if arg == '--':
            break
        if arg.startswith('--'):
            ap.add_argument(
                arg,
                action=create_collect_lsp_action([arg[2:]]),
                nargs='*')
    args = ap.parse_args(argv)

    if args.subcommand:
        if argv[0].startswith('-'):
            ap.error('Subcommand must always be the first argument')
        else:
            
            this_file_folder = os.path.abspath(os.path.dirname(__file__))
            subcommand_executable = os.path.join(this_file_folder, 'subcommands', args.subcommand)
            os.execvpe(
                subcommand_executable,
                [subcommand_executable] + argv[1:],
                dict(os.environ, PLASH_DATA=core.BASE_DIR))


    build_silent = args.build_silent or os.environ.get('PLASH_BUILD_SILENT')
    lsp = getattr(args, 'lsp', [])

    if args.traceback:
        disable_friendly_exception()<commit_msg>Fixes in subcommand handling<commit_after>import argparse
import os
import platform
import shlex
import subprocess
import sys
from subprocess import CalledProcessError, list2cmdline

from . import core, dockercore, state
from .core import BuildError
from .dockercore import DockerBuildError, docker_get_image_shell
from .eval import ActionNotFoundError, ArgError, EvalError, eval, layer
from .utils import (disable_friendly_exception, friendly_exception, hashstr,
                    rand)

HELP = 'my help'
PROG = 'plash'


NO_TERM_BUILD_ERROR = """plash error: Refusing to build when not connected to a tty(-like) device.
Set the env PLASH_BUILD_SILENT to enable building without output is such cases.
Or invoke this call with --build-only from a terminal to build and then run again.
The argv of this program was: {}""".format(sys.argv)

# shortcuts are specific to the stdlib
SHORTCUTS = [
    # shortcut, lsp, nargs
    ('-x', ['run'], '+'),
    ('-a', ['apt'], '+'),
    ('-y', ['yum'], '+'),
    ('-p', ['pip'], '+'),
    ('-b', ['apt', 'ubuntu-server'], 0),
    ('-o', ['os'], 1),
    ('-r', ['include', '~/.plashrc'], 0),
    ('-U', ['os', 'ubuntu'], 0),
    ('-F', ['os', 'fedora'], 0),
    ('-D', ['os', 'debian'], 0),
 ]

def add_shortcuts_to_parser(parser):
    group = parser.add_argument_group('shortcuts', 'shortcuts')
    for shortcut, lsp, nargs in SHORTCUTS:
        group.add_argument(
            shortcut,
            action=create_collect_lsp_action(lsp),
            nargs=nargs)

def create_collect_lsp_action(lsp_begin):
    class CollectAction(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            if not 'lsp' in namespace:
                setattr(namespace, 'lsp', [])
            previous = namespace.lsp
            previous.append(lsp_begin + list(values))
            setattr(namespace, 'lsp', previous) 
    return CollectAction

def get_argument_parser():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawTextHelpFormatter,
        description='Run programm from any Linux',
        prog=PROG,
        epilog=HELP)

    # parser.add_argument("subcommand", nargs='?')
    parser.add_argument("--build-silent", action='store_true')
    parser.add_argument("--build-verbose", "--build-loud", action='store_true', dest='verbose')
    parser.add_argument("--build-only", action='store_true')
    parser.add_argument("--build-again", "--rebuild", "--again", action='store_true')

    parser.add_argument("--no-stdlib", action='store_true')
    parser.add_argument("--traceback", action='store_true')
    parser.add_argument("--debug-lsp", action='store_true')

    parser.add_argument("--ignore-no-tty", action='store_false')

    parser.add_argument("--docker", "-d", action='store_true')

    parser.add_argument("--docker-save-image")

    add_shortcuts_to_parser(parser)

    return parser



def main():
    argv = sys.argv[1:]

    if not argv[0].startswith('-'): # suppose its a subcommand
        subcommand = argv[0]
        subcommands_dir = os.path.join(
            os.path.abspath(os.path.dirname(__file__)),
            'subcommands')
        all_subcommands = os.listdir(subcommands_dir)
        if not subcommand in all_subcommands:
            with friendly_exception([ArgError]):
                raise ArgError('no subcommand {}, available: {}'.format(repr(subcommand), ' '.join(all_subcommands)))

        subcommand_executable = os.path.join(subcommands_dir, subcommand)
        os.execvpe(
            subcommand_executable,
            [subcommand_executable] + argv[1:],
            dict(os.environ, PLASH_DATA=core.BASE_DIR))

    try:
        delimiter = argv.index('--')
        command = argv[delimiter+1:]
        argv = argv[:delimiter]
        # assert False, (args, command)
    except ValueError:
        command = None

    ap = get_argument_parser()
    _, unused_args = ap.parse_known_args(argv)
    # lsp = unused_args_to_lsp(unused_args)
    for arg in set(unused_args):
        if arg == '--':
            break
        if arg.startswith('--'):
            ap.add_argument(
                arg,
                action=create_collect_lsp_action([arg[2:]]),
                nargs='*')

    args = ap.parse_args(argv)

    build_silent = args.build_silent or os.environ.get('PLASH_BUILD_SILENT')
    lsp = getattr(args, 'lsp', [])

    if args.traceback:
        disable_friendly_exception()
{'fraction_non_alphanumeric': 0.14257586286773222, 'fraction_numerical': 0.0028955293027565438, 'mean_word_length': 2.986611265004617, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1399126', 'n_tokens_mistral': 2781, 'n_tokens_neox': 2671, 'n_words': 605}