def cabal_config():
    cconfig = os.environ.get('CABAL_CONFIG') or \
        ('~/.cabal' if not Utils.is_windows() else r'%APPDATA%/cabal') + \
        "/config"

    # Various patterns to match...
    re_user_dirs = re.compile(r'^install-dirs\s+user')
    re_global_dirs = re.compile(r'^install-dirs\s+global')
    re_section = re.compile(r'^\w+')
    re_prefix = re.compile(r'prefix:\s+(.*)$')
    re_bindir = re.compile(r'bindir:\s+(.*)$')

    # Things to collect
    user_prefix = "$HOME/.cabal" if not Utils.is_windows() else r'%APPDATA%/cabal'
    # FIXME: Need to interrogate Shel32 for the Windows PROGRAMFILES known
    # folder path:
    global_prefix = "/usr/local" if not Utils.is_windows() else r'%PROGRAMFILES%/Haskell'
    user_bindir = "bin"
    global_bindir = "bin"
    p_state = 0

    try:
        with open(Utils.normalize_path(cconfig), 'rU') as f_cconfig:
            # You would think that the Cabal maintainers would use a
            # well known file format... But now, they didn't. And they
            # had to go with an indentation-specific format.
            #
            # This is a "cheap and dirty" scanner to pick up
            for line in f_cconfig:
                line = line.rstrip()
                # One of the sections?
                if re_user_dirs.match(line):
                    p_state = 1
                elif re_global_dirs.match(line):
                    p_state = 2
                elif re.match(r'^\s+\w', line):
                    # prefix attribute?
                    m_prefix = re_prefix.search(line)
                    if m_prefix:
                        if p_state == 1:
                            user_prefix = m_prefix.group(1)
                        elif p_state == 2:
                            global_prefix = m_prefix.group(1)
                    # bindir attribute?
                    m_bindir = re_bindir.search(line)
                    if m_bindir:
                        if p_state == 1:
                            user_bindir = m_bindir.group(1)
                        elif p_state == 2:
                            global_bindir = m_bindir.group(1)
                elif re_section.match(line):
                    p_state = 0

    except IOError:
        # Silently fail.
        pass

    return [os.path.join(user_prefix, user_bindir)
            , os.path.join(global_prefix, global_bindir)
           ]
Beispiel #2
0
    def make_augmented_path():
        ''' Generate the augmented PATH for subprocesses: adds the appropriate cabal/stack local install directory
        ($HOME/.local/bin for *nix, %APPDATA%/local/bin for Windows) and updates PATH with `add_to_PATH` extras.
        '''
        std_places = []
        if Settings.PLUGIN.add_standard_dirs:
            std_places.append("$HOME/.local/bin" if not Utils.is_windows() else
                              "%APPDATA%/local/bin")
            if Utils.is_macosx():
                std_places.append('$HOME/Library/Haskell/bin')
            std_places += CabalConfigRdr.cabal_config()
            std_places = [
                dir
                for dir in [Utils.normalize_path(path) for path in std_places]
                if os.path.isdir(dir)
            ]

        add_to_path = list(
            filter(os.path.isdir,
                   map(Utils.normalize_path, Settings.PLUGIN.add_to_path)))

        Logging.log("std_places = {0}".format(std_places), Logging.LOG_INFO)
        Logging.log("add_to_PATH = {0}".format(add_to_path), Logging.LOG_INFO)

        return os.pathsep.join(add_to_path + std_places)
Beispiel #3
0
def which(cmd, env_path):
    cmd_is_list = isinstance(cmd, list)
    the_cmd = cmd[0] if cmd_is_list else cmd
    cmd_args = cmd[1:] if cmd_is_list else []

    if os.path.isabs(the_cmd):
        return cmd

    with WHICH_CACHE as cache:
        cval = cache.get(the_cmd)

    if cval is not None:
        return [cval] + cmd_args if cmd_is_list else cval
    else:
        exe_exts = [''] if not Utils.is_windows() else ['.exe', '.cmd', '.bat']

        program = the_cmd
        fpath, _ = os.path.split(program)
        if fpath:
            if is_exe(program):
                return cmd
        else:
            for path in env_path.split(os.pathsep):
                path = path.strip('"')
                for ext in exe_exts:
                    exe_file = os.path.join(path, program)
                    if is_exe(exe_file + ext):
                        with WHICH_CACHE as cache:
                            cache[program] = exe_file
                        return [exe_file] + cmd_args if cmd_is_list else exe_file

    return None
Beispiel #4
0
def which(cmd, env_path):
    cmd_is_list = isinstance(cmd, list)
    the_cmd = cmd[0] if cmd_is_list else cmd
    cmd_args = cmd[1:] if cmd_is_list else []

    if os.path.isabs(the_cmd):
        return cmd

    with WHICH_CACHE as cache:
        cval = cache.get(the_cmd)

    if cval is not None:
        return [cval] + cmd_args if cmd_is_list else cval
    else:
        exe_exts = [''] if not Utils.is_windows() else ['.exe', '.cmd', '.bat']

        program = the_cmd
        fpath, _ = os.path.split(program)
        if fpath:
            if is_exe(program):
                return cmd
        else:
            for path in env_path.split(os.pathsep):
                path = path.strip('"')
                for ext in exe_exts:
                    exe_file = os.path.join(path, program)
                    if is_exe(exe_file + ext):
                        with WHICH_CACHE as cache:
                            cache[program] = exe_file
                        return [exe_file
                                ] + cmd_args if cmd_is_list else exe_file

    return None
    def __init__(self, command, **popen_kwargs):
        """Open a pipe to a command or tool."""

        if ProcHelper.augmented_path is None:
            ProcHelper.augmented_path = ProcHelper.make_augmented_path()

        ## Necessary evil: Don't cache the environment, just update the PATH in the current environment.
        ## Why? Because someone could (like me) change os.environ via the ST console and those changes
        ## would never make it here. Use case: settting $http_proxy so that stack can fetch packages.
        proc_env = dict(os.environ)
        proc_env['PATH'] = ProcHelper.augmented_path + os.pathsep + proc_env.get('PATH', '')

        self.process = None
        self.process_err = None

        if Utils.is_windows():
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            popen_kwargs['startupinfo'] = startupinfo

        # Allow caller to specify something different for stdout or stderr -- provide
        # the default here if unspecified.
        popen_kwargs['stdout'] = popen_kwargs.get('stdout', subprocess.PIPE)
        popen_kwargs['stderr'] = popen_kwargs.get('stderr', subprocess.PIPE)

        try:
            normcmd = Which.which(command, proc_env['PATH'])
            if normcmd is not None:
                self.process = subprocess.Popen(normcmd, stdin=subprocess.PIPE, env=proc_env, **popen_kwargs)
            else:
                self.process = None
                self.process_err = "SublimeHaskell.ProcHelper: {0} was not found on PATH!".format(command[0])

        except OSError as os_exc:
            self.process_err = \
                '\n'.join(["SublimeHaskell: Problem executing '{0}'".format(' '.join(command))
                           , 'Operating system error: {0}'.format(os_exc)
                          ])

            if os_exc.errno == errno.EPIPE:
                # Most likely reason: subprocess output a usage message
                stdout, stderr = self.process.communicate()
                exit_code = self.process.wait()
                self.process_err = self.process_err + \
                    '\n'.join([''
                               , 'Process exit code: {0}'.format(exit_code)
                               , ''
                               , "output:"
                               , stdout if stdout else "--no output--"
                               , ''
                               , 'error:'
                               , stderr if stderr else "--no error output--"])
                self.process = None
            else:
                self.process = None
                raise os_exc
    def make_augmented_path():
        ''' Generate the augmented PATH for subprocesses: adds the appropriate cabal/stack local install directory
        ($HOME/.local/bin for *nix, %APPDATA%/local/bin for Windows) and updates PATH with `add_to_PATH` extras.
        '''
        std_places = []
        if Settings.PLUGIN.add_standard_dirs:
            std_places.append("$HOME/.local/bin" if not Utils.is_windows() else "%APPDATA%/local/bin")
            if Utils.is_macosx():
                std_places.append('$HOME/Library/Haskell/bin')
            std_places += CabalConfigRdr.cabal_config()
            std_places = [dir for dir in [Utils.normalize_path(path) for path in std_places] if os.path.isdir(dir)]

        add_to_path = list(filter(os.path.isdir, map(Utils.normalize_path, Settings.PLUGIN.add_to_path)))

        Logging.log("std_places = {0}".format(std_places), Logging.LOG_INFO)
        Logging.log("add_to_PATH = {0}".format(add_to_path), Logging.LOG_INFO)

        return os.pathsep.join(add_to_path + std_places)
Beispiel #7
0
    def __init__(self, command, **popen_kwargs):
        """Open a pipe to a command or tool."""

        if ProcHelper.augmented_path is None:
            ProcHelper.augmented_path = ProcHelper.make_augmented_path()

        ## Necessary evil: Don't cache the environment, just update the PATH in the current environment.
        ## Why? Because someone could (like me) change os.environ via the ST console and those changes
        ## would never make it here. Use case: settting $http_proxy so that stack can fetch packages.
        proc_env = dict(os.environ)
        proc_env[
            'PATH'] = ProcHelper.augmented_path + os.pathsep + proc_env.get(
                'PATH', '')

        self.process = None
        self.process_err = None

        if Utils.is_windows():
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            popen_kwargs['startupinfo'] = startupinfo

        # Allow caller to specify something different for stdout or stderr -- provide
        # the default here if unspecified.
        popen_kwargs['stdout'] = popen_kwargs.get('stdout', subprocess.PIPE)
        popen_kwargs['stderr'] = popen_kwargs.get('stderr', subprocess.PIPE)

        try:
            normcmd = Which.which(command, proc_env['PATH'])
            if normcmd is not None:
                self.process = subprocess.Popen(normcmd,
                                                stdin=subprocess.PIPE,
                                                env=proc_env,
                                                **popen_kwargs)
            else:
                self.process = None
                self.process_err = "SublimeHaskell.ProcHelper: {0} was not found on PATH!".format(
                    command[0])

        except OSError as os_exc:
            self.process_err = \
                '\n'.join(["SublimeHaskell: Problem executing '{0}'".format(' '.join(command))
                           , 'Operating system error: {0}'.format(os_exc)
                          ])

            if os_exc.errno == errno.EPIPE:
                # Most likely reason: subprocess output a usage message
                stdout, stderr = self.process.communicate()
                exit_code = self.process.wait()
                self.process_err = self.process_err + \
                    '\n'.join([''
                               , 'Process exit code: {0}'.format(exit_code)
                               , ''
                               , "output:"
                               , stdout if stdout else "--no output--"
                               , ''
                               , 'error:'
                               , stderr if stderr else "--no error output--"])
                self.process = None
            else:
                self.process = None
                raise os_exc
def cabal_config():
    cconfig = os.environ.get('CABAL_CONFIG') or \
        ('~/.cabal' if not Utils.is_windows() else r'%APPDATA%/cabal') + \
        "/config"

    # Various patterns to match...
    re_user_dirs = re.compile(r'^install-dirs\s+user')
    re_global_dirs = re.compile(r'^install-dirs\s+global')
    re_section = re.compile(r'^\w+')
    re_prefix = re.compile(r'prefix:\s+(.*)$')
    re_bindir = re.compile(r'bindir:\s+(.*)$')

    # Things to collect
    user_prefix = "$HOME/.cabal" if not Utils.is_windows(
    ) else r'%APPDATA%/cabal'
    # FIXME: Need to interrogate Shel32 for the Windows PROGRAMFILES known
    # folder path:
    global_prefix = "/usr/local" if not Utils.is_windows(
    ) else r'%PROGRAMFILES%/Haskell'
    user_bindir = "bin"
    global_bindir = "bin"
    p_state = 0

    try:
        with open(Utils.normalize_path(cconfig), 'rU') as f_cconfig:
            # You would think that the Cabal maintainers would use a
            # well known file format... But now, they didn't. And they
            # had to go with an indentation-specific format.
            #
            # This is a "cheap and dirty" scanner to pick up
            for line in f_cconfig:
                line = line.rstrip()
                # One of the sections?
                if re_user_dirs.match(line):
                    p_state = 1
                elif re_global_dirs.match(line):
                    p_state = 2
                elif re.match(r'^\s+\w', line):
                    # prefix attribute?
                    m_prefix = re_prefix.search(line)
                    if m_prefix:
                        if p_state == 1:
                            user_prefix = m_prefix.group(1)
                        elif p_state == 2:
                            global_prefix = m_prefix.group(1)
                    # bindir attribute?
                    m_bindir = re_bindir.search(line)
                    if m_bindir:
                        if p_state == 1:
                            user_bindir = m_bindir.group(1)
                        elif p_state == 2:
                            global_bindir = m_bindir.group(1)
                elif re_section.match(line):
                    p_state = 0

    except IOError:
        # Silently fail.
        pass

    return [
        os.path.join(user_prefix, user_bindir),
        os.path.join(global_prefix, global_bindir)
    ]