Exemplo n.º 1
0
def internal_cd(args):
    """The internal CD command"""
    try:
        if len(args) == 0:
            os.chdir(expand_env_vars("~"))
        else:
            target = args[0]
            if target != u"\\" and target[1:] != u":\\":
                target = target.rstrip(u"\\")
            target = expand_env_vars(target.strip(u'"').strip(u" "))
            os.chdir(target.encode(sys.getfilesystemencoding()))
    except OSError, error:
        stdout.write(u"\n" + str(error).replace("\\\\", "\\").decode(sys.getfilesystemencoding()))
Exemplo n.º 2
0
def internal_cd(args):
    """The internal CD command"""
    try:
        if len(args) == 0:
            os.chdir(expand_env_vars('~'))
        else:
            target = args[0]
            if target != u'\\' and target[1:] != u':\\':
                target = target.rstrip(u'\\')
            target = expand_env_vars(target.strip(u'"').strip(u' '))
            os.chdir(target.encode(sys.getfilesystemencoding()))
    except OSError, error:
        stdout.write(u'\n' + str(error).replace('\\\\', '\\').decode(sys.getfilesystemencoding()))
Exemplo n.º 3
0
def internal_cd(args):
    """The internal CD command"""
    try:
        if len(args) == 0:
            os.chdir(expand_env_vars('~'))
        else:
            target = args[0]
            if target != u'\\' and target[1:] != u':\\':
                target = target.rstrip(u'\\')
            target = expand_env_vars(target.strip(u'"').strip(u' '))
            os.chdir(target.encode(sys.getfilesystemencoding()))
    except OSError, error:
        stdout.write(u'\n' + str(error).replace('\\\\', '\\').decode(
            sys.getfilesystemencoding()))
Exemplo n.º 4
0
def run_command(tokens):
    """Execute a command line (treat internal and external appropriately"""

    # Cleanup environment
    for var in pseudo_vars:
        if var in os.environ.keys():
            del os.environ[var]

    if tokens[0] == 'exit':
        internal_exit('Bye!')
    elif tokens[0].lower() == 'cd' and [t for t in tokens if t in sep_tokens
                                        ] == []:
        # This is a single CD command -- use our custom, more handy CD
        internal_cd([unescape(t) for t in tokens[1:]])
    else:
        if set(sep_tokens).intersection(tokens) == set([]):
            # This is a simple (non-compound) command
            # Crude hack so that we return to the prompt when starting GUI
            # applications: if we think that the first token on the given command
            # line is an executable, check its PE header to decide whether it's
            # GUI application. If it is, spawn the process and then get on with
            # life.
            cmd = expand_env_vars(tokens[0].strip('"'))
            dir, name = os.path.split(cmd)
            ext = os.path.splitext(name)[1]

            if not ext or ext in exec_extensions:
                # Executable given
                app = cmd
            else:
                # Not an executable -- search for the associated application
                if os.path.isfile(cmd):
                    app = associated_application(ext)
                else:
                    # No application will be spawned if the file doesn't exist
                    app = None

            if app:
                executable = full_executable_path(app)
                if executable and os.path.splitext(
                        executable)[1].lower() == '.exe':
                    # This is an exe file, try to figure out whether it's a GUI
                    # or console application
                    if is_gui_application(executable):
                        import subprocess
                        s = u' '.join([expand_tilde(t) for t in tokens])
                        subprocess.Popen(s.encode(sys.getfilesystemencoding()),
                                         shell=True)
                        return

        # Regular (external) command
        start_time = time.time()
        run_in_cmd(tokens)
        console_window = win32console.GetConsoleWindow()
        if win32gui.GetForegroundWindow(
        ) != console_window and time.time() - start_time > 15:
            # If the window is inactive, flash after long tasks
            win32gui.FlashWindowEx(console_window, win32con.FLASHW_ALL, 3, 750)
Exemplo n.º 5
0
def run_command(tokens):
    """Execute a command line (treat internal and external appropriately"""

    # Cleanup environment
    for var in pseudo_vars:
        if var in os.environ.keys():
            del os.environ[var]

    if tokens[0] == 'exit':
        internal_exit('Bye!')
    elif is_pure_cd(tokens):
        # This is a single CD command -- use our custom, more handy CD
        internal_cd([unescape(t) for t in tokens[1:]])
    else:
        if set(sep_tokens).intersection(tokens) == set([]):
            # This is a simple (non-compound) command
            # Crude hack so that we return to the prompt when starting GUI
            # applications: if we think that the first token on the given command
            # line is an executable, check its PE header to decide whether it's
            # GUI application. If it is, spawn the process and then get on with
            # life.
            cmd = expand_env_vars(tokens[0].strip('"'))
            dir, name = os.path.split(cmd)
            ext = os.path.splitext(name)[1]

            if not ext or ext in exec_extensions:
                # Executable given
                app = cmd
            else:
                # Not an executable -- search for the associated application
                if os.path.isfile(cmd):
                    app = associated_application(ext)
                else:
                    # No application will be spawned if the file doesn't exist
                    app = None

            if app:
                executable = full_executable_path(app)
                if executable and os.path.splitext(executable)[1].lower() == '.exe':
                    # This is an exe file, try to figure out whether it's a GUI
                    # or console application
                    if is_gui_application(executable):
                        import subprocess
                        s = u' '.join([expand_tilde(t) for t in tokens])
                        subprocess.Popen(s.encode(sys.getfilesystemencoding()), shell=True)
                        return

        # Regular (external) command
        start_time = time.time()
        run_in_cmd(tokens)
        console_window = win32console.GetConsoleWindow()
        if win32gui.GetForegroundWindow() != console_window and time.time() - start_time > 15:
            # If the window is inactive, flash after long t1asks
            win32gui.FlashWindowEx(console_window, win32con.FLASHW_ALL, 3, 750)
Exemplo n.º 6
0
def init():
    # %APPDATA% is not always defined (e.g. when using runas.exe)
    if "APPDATA" in os.environ.keys():
        APPDATA = "%APPDATA%"
    else:
        APPDATA = "%USERPROFILE%\\Application Data"
    global pycmd_data_dir
    pycmd_data_dir = expand_env_vars(APPDATA + "\\PyCmd")

    # Create app data directory structure if not present
    if not os.path.isdir(pycmd_data_dir):
        os.mkdir(pycmd_data_dir)
    if not os.path.isdir(pycmd_data_dir + "\\tmp"):
        os.mkdir(pycmd_data_dir + "\\tmp")

    # Determine the "installation" directory
    global pycmd_install_dir
    pycmd_install_dir = os.path.dirname(os.path.abspath(sys.argv[0]))

    # Current state of the input (prompt, entered chars, history)
    global state
    state = InputState()

    # Read/initialize command history
    state.history.list = read_history(pycmd_data_dir + "\\history")

    # Read/initialize directory history
    global dir_hist
    dir_hist = DirHistory()
    dir_hist.locations = read_history(pycmd_data_dir + "\\dir_history")
    dir_hist.index = len(dir_hist.locations) - 1
    dir_hist.visit_cwd()

    # Create temporary file
    global tmpfile
    (handle, tmpfile) = tempfile.mkstemp(dir=pycmd_data_dir + "\\tmp")
    os.close(handle)

    # Create result map file
    global resultMapFilePath
    (handle, resultMapFilePath) = tempfile.mkstemp(dir=pycmd_data_dir + "\\tmp")
    os.close(handle)
    os.environ["PYCMD_RESULT_MAP_FILE_PATH"] = resultMapFilePath

    # Create command line file
    global cmdLineFilePath
    (handle, cmdLineFilePath) = tempfile.mkstemp(dir=pycmd_data_dir + "\\tmp")
    os.close(handle)

    # Catch SIGINT to emulate Ctrl-C key combo
    signal.signal(signal.SIGINT, signal_handler)
Exemplo n.º 7
0
def init():
    # %APPDATA% is not always defined (e.g. when using runas.exe)
    if 'APPDATA' in os.environ.keys():
        APPDATA = '%APPDATA%'
    else:
        APPDATA = '%USERPROFILE%\\Application Data'

    global pycmd_data_dir
    global winstate_full_path

    pycmd_data_dir = expand_env_vars(APPDATA + '\\PyCmd')
    winstate_full_path = os.path.join(pycmd_data_dir, windows_state_path)

    if not os.path.exists(winstate_full_path):
        open(winstate_full_path, 'a').close()
Exemplo n.º 8
0
def init():
    # %APPDATA% is not always defined (e.g. when using runas.exe)
    if 'APPDATA' in os.environ.keys():
        APPDATA = '%APPDATA%'
    else:
        APPDATA = '%USERPROFILE%\\Application Data'

    global pycmd_data_dir
    global winstate_full_path

    pycmd_data_dir = expand_env_vars(APPDATA + '\\PyCmd')
    winstate_full_path = os.path.join(pycmd_data_dir, windows_state_path)

    if not os.path.exists(winstate_full_path):
        open(winstate_full_path, 'a').close()
Exemplo n.º 9
0
def init():
    # %APPDATA% is not always defined (e.g. when using runas.exe)
    if 'APPDATA' in os.environ.keys():
        APPDATA = '%APPDATA%'
    else:
        APPDATA = '%USERPROFILE%\\Application Data'
    global pycmd_data_dir
    pycmd_data_dir = expand_env_vars(APPDATA + '\\PyCmd')

    # Create app data directory structure if not present
    if not os.path.isdir(pycmd_data_dir):
        os.mkdir(pycmd_data_dir)
    if not os.path.isdir(pycmd_data_dir + '\\tmp'):
        os.mkdir(pycmd_data_dir + '\\tmp')

    # Determine the "installation" directory
    global pycmd_install_dir
    pycmd_install_dir = os.path.dirname(os.path.abspath(sys.argv[0]))

    # Current state of the input (prompt, entered chars, history)
    global state
    state = InputState()

    # Read/initialize command history
    state.history.list = read_history(pycmd_data_dir + '\\history')

    # Read/initialize directory history
    global dir_hist
    dir_hist = DirHistory()
    dir_hist.locations = read_history(pycmd_data_dir + '\\dir_history')
    dir_hist.index = len(dir_hist.locations) - 1
    dir_hist.visit_cwd()

    # Read/initialize directory history
    global dir_hist_fixed
    dir_hist_fixed = DirHistory()
    dir_hist_fixed.locations = read_history(pycmd_data_dir +
                                            '\\dir_history_fix')
    dir_hist_fixed.index = len(dir_hist_fixed.locations) - 1

    # Create temporary file
    global tmpfile
    (handle, tmpfile) = tempfile.mkstemp(dir=pycmd_data_dir + '\\tmp')
    os.close(handle)

    # Catch SIGINT to emulate Ctrl-C key combo
    signal.signal(signal.SIGINT, signal_handler)
Exemplo n.º 10
0
def complete_file_alternate(line):
    """
    Complete names of files or directories using an alternate tokenization

    This function tokenizes the line by tring to interpret the last token as a
    semicolon-separated list of paths, optionally preceded by an equals char.
    
    It returns a pair:
      - the line expanded up to the longest common sequence among the
        completions
      - the list of all possible completions (first dirs, then files)
    """
    tokens = parse_line(line)
    if tokens == [] or (line[-1] in sep_chars
                        and parse_line(line) == parse_line(line + ' ')):
        tokens += ['']  # This saves us some checks later
    (last_token_prefix, equal_char,
     last_token) = tokens[-1].replace('"', '').rpartition('=')
    last_token_prefix += equal_char

    paths = last_token.split(';')
    token = paths[-1]

    # print '\n\nTokens:', tokens, '\n\nCompleting:', token, '\n\n'

    (path_to_complete, _, prefix) = token.rpartition('\\')
    if path_to_complete == '' and token != '' and token[0] == '\\':
        path_to_complete = '\\'

    # print '\n\n', path_to_complete, '---', prefix, '\n\n'

    if path_to_complete == '':
        dir_to_complete = os.getcwd()
    elif path_to_complete == '\\':
        dir_to_complete = os.getcwd()[0:3]
    else:
        dir_to_complete = expand_env_vars(path_to_complete) + '\\'

    # This is the wildcard matcher used throughout the function
    matcher = wildcard_to_regex(prefix + '*')

    completions = []
    if os.path.isdir(dir_to_complete):
        try:
            completions = [
                elem for elem in os.listdir(dir_to_complete)
                if matcher.match(elem)
            ]
        except OSError:
            # Cannot complete, probably access denied
            pass

    # Sort directories first, also append '\'; then, files
    completions_dirs = [
        elem + '\\' for elem in completions
        if os.path.isdir(dir_to_complete + '\\' + elem)
    ]
    completions_files = [
        elem for elem in completions
        if os.path.isfile(dir_to_complete + '\\' + elem)
    ]
    completions = completions_dirs + completions_files

    if completions != []:
        # Find the longest common sequence
        common_string = find_common_prefix(prefix, completions)

        if path_to_complete == '':
            completed_file = common_string
        elif path_to_complete == '\\':
            completed_file = '\\' + common_string
        else:
            completed_file = path_to_complete + '\\' + common_string

        if expand_env_vars(last_token + completed_file).find(' ') >= 0 or \
                (prefix != '' and [elem for elem in completions if contains_special_char(elem)] != []) or \
                (prefix == '' and [elem for elem in completions if starts_with_special_char(elem)] != []):
            # We add quotes if one of the following holds:
            #   * the (env-expanded) completed string contains whitespace
            #   * there is a prefix and at least one of the valid completions contains whitespace
            #   * there is no prefix and at least one completion _starts_ with whitespace
            start_quote = '"'
        else:
            start_quote = ''

        # Build and return the result
        result = line[0:len(line) - len(tokens[-1])]
        result += last_token_prefix + start_quote
        result += last_token[:len(last_token) - len(token)]
        result += completed_file
        return (result, completions)
    else:
        # No expansion was made, return original line
        return (line, [])
Exemplo n.º 11
0
def complete_file_simple(line):
    """
    Complete names of files or directories
    This function tokenizes the line and computes file and directory
    completions starting with the last token.
    
    It returns a pair:
      - the line expanded up to the longest common sequence among the
        completions
      - the list of all possible completions (first dirs, then files)
    """
    tokens = parse_line(line)
    if tokens == [] or (line[-1] in sep_chars and parse_line(line) == parse_line(line + ' ')):
        tokens += ['']   # This saves us some checks later
    token = tokens[-1].replace('"', '')
    
    (path_to_complete, _, prefix) = token.rpartition('\\')
    if path_to_complete == '' and token != '' and token[0] == '\\':
        path_to_complete = '\\'

    # print '\n\n', path_to_complete, '---', prefix, '\n\n'

    if path_to_complete == '':
        dir_to_complete = os.getcwd()
    elif path_to_complete == '\\':
        dir_to_complete = os.getcwd()[0:3]
    else:
        dir_to_complete = expand_env_vars(path_to_complete) + '\\'

    # This is the wildcard matcher used throughout the function
    matcher = wildcard_to_regex(prefix + '*')

    completions = []
    if os.path.isdir(dir_to_complete):
        try:
            completions = [elem for elem in os.listdir(dir_to_complete) 
                           if matcher.match(elem)]
        except OSError:
            # Cannot complete, probably access denied
            pass
        

    # Sort directories first, also append '\'; then, files
    completions_dirs = [elem + '\\' for elem in completions if os.path.isdir(dir_to_complete + '\\' + elem)]
    completions_files = [elem for elem in completions if os.path.isfile(dir_to_complete + '\\' + elem)]
    completions = completions_dirs + completions_files

    if (len(tokens) == 1 or tokens[-2] in seq_tokens) and path_to_complete == '':
        # We are at the beginning of a command ==> also complete from the path
        completions_path = []
        for elem_in_path in os.environ['PATH'].split(';'):
            dir_to_complete = expand_env_vars(elem_in_path) + '\\'
            try:                
                completions_path += [elem for elem in os.listdir(dir_to_complete) 
                                     if matcher.match(elem)
                                     and os.path.isfile(dir_to_complete + '\\' + elem)
                                     and has_exec_extension(elem)
                                     and not elem in completions
                                     and not elem in completions_path]
            except OSError:
                # Cannot complete, probably access denied
                pass

        # Add internal commands
        internal_commands = ['assoc',
                             'call', 'cd', 'chdir', 'cls', 'color', 'copy',
                             'date', 'del', 'dir',
                             'echo', 'endlocal', 'erase', 'exit',
                             'for', 'ftype',
                             'goto',
                             'if',
                             'md', 'mkdir', 'move',
                             'path', 'pause', 'popd', 'prompt', 'pushd',
                             'rem', 'ren', 'rename', 'rd', 'rmdir',
                             'set', 'setlocal', 'shift', 'start',
                             'time', 'title', 'type',
                             'ver', 'verify', 'vol']
        if sys.getwindowsversion()[0] >= 6:
            # Windows 7 or newer
            internal_commands.append('mklink')
        completions_path += [elem for elem in internal_commands
                             if matcher.match(elem)
                             and not elem in completions
                             and not elem in completions_path]


        # Sort in lexical order (case ignored)
        completions_path.sort(key=str.lower)

        # Remove .com, .exe or .bat extension where possible
        completions_path_no_ext = [strip_extension(elem) for elem in completions_path]
        completions_path_nice = []
        for i in range(0, len(completions_path_no_ext)):
            similar = [elem for elem in completions_path_no_ext if elem == completions_path_no_ext[i]]
            similar += [elem for elem in completions if strip_extension(elem) == completions_path_no_ext[i]]
            if len(similar) == 1 and has_exec_extension(completions_path[i]) and len(prefix) < len(completions_path[i]) - 3:
                # No similar executables, don't use extension
                completions_path_nice.append(completions_path_no_ext[i])
            else:
                # Similar executables found, keep extension
                completions_path_nice.append(completions_path[i])
        completions += completions_path_nice

    if completions != []:
        # Find the longest common sequence
        common_string = find_common_prefix(prefix, completions)
            
        if path_to_complete == '':
            completed_file = common_string
        elif path_to_complete == '\\':
            completed_file = '\\' + common_string
        else:
            completed_file = path_to_complete + '\\' + common_string

        if expand_env_vars(completed_file).find(' ') >= 0 or \
                (prefix != '' and [elem for elem in completions if contains_special_char(elem)] != []) or \
                (prefix == '' and [elem for elem in completions if starts_with_special_char(elem)] != []):
            # We add quotes if one of the following holds:
            #   * the (env-expanded) completed string contains whitespace
            #   * there is a prefix and at least one of the valid completions contains whitespace
            #   * there is no prefix and at least one completion _starts_ with whitespace
            start_quote = '"'
        else:
            start_quote = ''

        # Build the result
        result = line[0 : len(line) - len(tokens[-1])] + start_quote + completed_file

        if len(completions) == 1:
            # We can close the quotes if we have completed to a unique filename
            if start_quote == '"':
                end_quote = '"'
            else:
                end_quote = ''
                
            if result[-1] == '\\':
                # Directory -- we want the backslash (if any) AFTER the closing quote
                result = result[ : -1] + end_quote + '\\'
            else:
                # File -- add space if the completion is unique
                result += end_quote
                result += ' '

        return (result, completions)
    else:
        # No expansion was made, return original line
        return (line, [])
Exemplo n.º 12
0
def complete_wildcard(line):
    """
    Complete file/dir wildcards
    This function tokenizes the line and computes file and directory
    completions starting with the last token which is a wildcard
    
    It returns a pair:
      - the line expanded up to the longest common sequence among the
        completions
      - the list of all possible completions (first dirs, then files)
    """
    tokens = parse_line(line)
    if tokens == [] or (line[-1] in sep_chars and parse_line(line) == parse_line(line + ' ')):
        tokens += ['']   # This saves us some checks later
    token = tokens[-1].replace('"', '')
    
    (path_to_complete, _, prefix) = token.rpartition('\\')
    if path_to_complete == '' and token != '' and token[0] == '\\':
        path_to_complete = '\\'

    # print '\n\n', path_to_complete, '---', prefix, '\n\n'

    if path_to_complete == '':
        dir_to_complete = os.getcwd()
    elif path_to_complete == '\\':
        dir_to_complete = os.getcwd()[0:3]
    else:
        dir_to_complete = expand_env_vars(path_to_complete) + '\\'

    # This is the wildcard matcher used throughout the function
    matcher = wildcard_to_regex(prefix + '*')

    completions = []
    if os.path.isdir(dir_to_complete):
        try:
            completions = [elem for elem in os.listdir(dir_to_complete) if matcher.match(elem)]
        except OSError:
            # Cannot complete, probably access denied
            pass
        

    # Sort directories first, also append '\'; then, files
    completions_dirs = [elem + '\\' for elem in completions if os.path.isdir(dir_to_complete + '\\' + elem)]
    completions_files = [elem for elem in completions if os.path.isfile(dir_to_complete + '\\' + elem)]
    completions = completions_dirs + completions_files

    if completions != []:
        completed_suffixes = []
        for c in completions:
            match = matcher.match(c)
            completed_suffixes.append(match.group(match.lastindex))

        if len(completions) == 1:
            # Only one match, we can inline it and replace the wildcards
            common_string = completions[0]
        else:
            # Multiple matches, find the longest common sequence
            common_string = prefix + find_common_prefix(prefix, completed_suffixes)
            
        if path_to_complete == '':
            completed_file = common_string
        elif path_to_complete == '\\':
            completed_file = '\\' + common_string
        else:
            completed_file = path_to_complete + '\\' + common_string


        if expand_env_vars(completed_file).find(' ') >= 0 or \
                (prefix != '' and [elem for elem in completions if contains_special_char(elem)] != []) or \
                (prefix == '' and [elem for elem in completions if starts_with_special_char(elem)] != []):
            # We add quotes if one of the following holds:
            #   * the (env-expanded) completed string contains whitespace
            #   * there is a prefix and at least one of the valid completions contains whitespace
            #   * there is no prefix and at least one completion _starts_ with whitespace
            start_quote = '"'
        else:
            start_quote = ''

        # Build the result
        result = line[0 : len(line) - len(tokens[-1])] + start_quote + completed_file
        if len(completions) == 1 or \
                not common_string.endswith('*') and \
                max([len(c) for c in completed_suffixes]) == len(common_string) - len(prefix):
            # We can close the quotes if all the completions have the same suffix or 
            # there exists only one matching file
            if start_quote == '"':
                end_quote = '"'
            else:
                end_quote = ''
                
            if result[-1] == '\\':
                # Directory -- we want the backslash (if any) AFTER the closing quote
                result = result[ : -1] + end_quote + '\\'
            else:
                # File -- add space if the completion is unique
                result += end_quote
                result += ' '

        return (result, completions)
    else:
        # No expansion was made, return original line
        return (line, [])
Exemplo n.º 13
0
def complete_file_alternate(line):
    """
    Complete names of files or directories using an alternate tokenization

    This function tokenizes the line by tring to interpret the last token as a
    semicolon-separated list of paths, optionally preceded by an equals char.
    
    It returns a pair:
      - the line expanded up to the longest common sequence among the
        completions
      - the list of all possible completions (first dirs, then files)
    """
    tokens = parse_line(line)
    if tokens == [] or (line[-1] in sep_chars and parse_line(line) == parse_line(line + ' ')):
        tokens += ['']   # This saves us some checks later
    (last_token_prefix, equal_char, last_token) = tokens[-1].replace('"', '').rpartition('=')
    last_token_prefix += equal_char
        
    paths = last_token.split(';')
    token = paths[-1]

    # print '\n\nTokens:', tokens, '\n\nCompleting:', token, '\n\n'

    (path_to_complete, _, prefix) = token.rpartition('\\')
    if path_to_complete == '' and token != '' and token[0] == '\\':
        path_to_complete = '\\'

    # print '\n\n', path_to_complete, '---', prefix, '\n\n'

    if path_to_complete == '':
        dir_to_complete = os.getcwd()
    elif path_to_complete == '\\':
        dir_to_complete = os.getcwd()[0:3]
    else:
        dir_to_complete = expand_env_vars(path_to_complete) + '\\'

    # This is the wildcard matcher used throughout the function
    matcher = wildcard_to_regex(prefix + '*')

    completions = []
    if os.path.isdir(dir_to_complete):
        try:
            completions = [elem for elem in os.listdir(dir_to_complete) 
                           if matcher.match(elem)]
        except OSError:
            # Cannot complete, probably access denied
            pass
        

    # Sort directories first, also append '\'; then, files
    completions_dirs = [elem + '\\' for elem in completions if os.path.isdir(dir_to_complete + '\\' + elem)]
    completions_files = [elem for elem in completions if os.path.isfile(dir_to_complete + '\\' + elem)]
    completions = completions_dirs + completions_files

    if completions != []:
        # Find the longest common sequence
        common_string = find_common_prefix(prefix, completions)
            
        if path_to_complete == '':
            completed_file = common_string
        elif path_to_complete == '\\':
            completed_file = '\\' + common_string
        else:
            completed_file = path_to_complete + '\\' + common_string

        if expand_env_vars(last_token + completed_file).find(' ') >= 0 or \
                (prefix != '' and [elem for elem in completions if contains_special_char(elem)] != []) or \
                (prefix == '' and [elem for elem in completions if starts_with_special_char(elem)] != []):
            # We add quotes if one of the following holds:
            #   * the (env-expanded) completed string contains whitespace
            #   * there is a prefix and at least one of the valid completions contains whitespace
            #   * there is no prefix and at least one completion _starts_ with whitespace
            start_quote = '"'
        else:
            start_quote = ''

        # Build and return the result
        result = line[0 : len(line) - len(tokens[-1])]
        result += last_token_prefix + start_quote
        result += last_token[:len(last_token) - len(token)]
        result += completed_file
        return (result, completions)
    else:
        # No expansion was made, return original line
        return (line, [])
Exemplo n.º 14
0
                            (c_x, c_y) = get_cursor()
                            offset_from_bottom = console.get_buffer_size()[1] - c_y
                            message = ' Scroll ' + str(int(round(num_screens))) + ' screens? [Tab] '
                            stdout.write('\n' + message)
                            rec = read_input()
                            move_cursor(c_x, console.get_buffer_size()[1] - offset_from_bottom)
                            stdout.write('\n' + ' ' * len(message))
                            move_cursor(c_x, console.get_buffer_size()[1] - offset_from_bottom)
                            if rec.Char != '\t':
                                if not ord(rec.Char) in [0, 8, 13, 27]:
                                    state.handle(ActionCode.ACTION_INSERT, rec.Char)
                                continue

                        if has_wildcards(tokens[-1]):
                            # Substring matching wildcards will be printed in a different color
                            path_sep = '/' if '/' in expand_env_vars(tokens[-1]) else '\\'
                            tokens = parse_line(completed.rstrip(path_sep))
                            token = tokens[-1].replace('"', '')
                            (_, _, prefix) = token.rpartition(path_sep)
                            pattern = wildcard_to_regex(prefix + '*')
                        else:
                            # Length of the common prefix will be printed in a different color
                            common_prefix_len = len(find_common_prefix(state.before_cursor, suggestions))
                            
                        stdout.write('\n')
                        for line in range(0, num_lines):
                            # Print one line
                            stdout.write('\r')
                            for column in range(0, num_columns):
                                if line + column * num_lines < len(suggestions):
                                    s = suggestions[line + column * num_lines]
Exemplo n.º 15
0
def complete_wildcard(line):
    """
    Complete file/dir wildcards
    This function tokenizes the line and computes file and directory
    completions starting with the last token which is a wildcard
    
    It returns a pair:
      - the line expanded up to the longest common sequence among the
        completions
      - the list of all possible completions (first dirs, then files)
    """
    tokens = parse_line(line)
    if tokens == [] or (line[-1] in sep_chars
                        and parse_line(line) == parse_line(line + ' ')):
        tokens += ['']  # This saves us some checks later
    token = tokens[-1].replace('"', '')

    (path_to_complete, _, prefix) = token.rpartition('\\')
    if path_to_complete == '' and token != '' and token[0] == '\\':
        path_to_complete = '\\'

    # print '\n\n', path_to_complete, '---', prefix, '\n\n'

    if path_to_complete == '':
        dir_to_complete = os.getcwd()
    elif path_to_complete == '\\':
        dir_to_complete = os.getcwd()[0:3]
    else:
        dir_to_complete = expand_env_vars(path_to_complete) + '\\'

    # This is the wildcard matcher used throughout the function
    matcher = wildcard_to_regex(prefix + '*')

    completions = []
    if os.path.isdir(dir_to_complete):
        try:
            completions = [
                elem for elem in os.listdir(dir_to_complete)
                if matcher.match(elem)
            ]
        except OSError:
            # Cannot complete, probably access denied
            pass

    # Sort directories first, also append '\'; then, files
    completions_dirs = [
        elem + '\\' for elem in completions
        if os.path.isdir(dir_to_complete + '\\' + elem)
    ]
    completions_files = [
        elem for elem in completions
        if os.path.isfile(dir_to_complete + '\\' + elem)
    ]
    completions = completions_dirs + completions_files

    if completions != []:
        completed_suffixes = []
        for c in completions:
            match = matcher.match(c)
            completed_suffixes.append(match.group(match.lastindex))

        if len(completions) == 1:
            # Only one match, we can inline it and replace the wildcards
            common_string = completions[0]
        else:
            # Multiple matches, find the longest common sequence
            common_string = prefix + find_common_prefix(
                prefix, completed_suffixes)

        if path_to_complete == '':
            completed_file = common_string
        elif path_to_complete == '\\':
            completed_file = '\\' + common_string
        else:
            completed_file = path_to_complete + '\\' + common_string


        if expand_env_vars(completed_file).find(' ') >= 0 or \
                (prefix != '' and [elem for elem in completions if contains_special_char(elem)] != []) or \
                (prefix == '' and [elem for elem in completions if starts_with_special_char(elem)] != []):
            # We add quotes if one of the following holds:
            #   * the (env-expanded) completed string contains whitespace
            #   * there is a prefix and at least one of the valid completions contains whitespace
            #   * there is no prefix and at least one completion _starts_ with whitespace
            start_quote = '"'
        else:
            start_quote = ''

        # Build the result
        result = line[0:len(line) -
                      len(tokens[-1])] + start_quote + completed_file
        if len(completions) == 1 or \
                not common_string.endswith('*') and \
                max([len(c) for c in completed_suffixes]) == len(common_string) - len(prefix):
            # We can close the quotes if all the completions have the same suffix or
            # there exists only one matching file
            if start_quote == '"':
                end_quote = '"'
            else:
                end_quote = ''

            if result[-1] == '\\':
                # Directory -- we want the backslash (if any) AFTER the closing quote
                result = result[:-1] + end_quote + '\\'
            else:
                # File -- add space if the completion is unique
                result += end_quote
                result += ' '

        return (result, completions)
    else:
        # No expansion was made, return original line
        return (line, [])
Exemplo n.º 16
0
def complete_file_simple(line):
    """
    Complete names of files or directories
    This function tokenizes the line and computes file and directory
    completions starting with the last token.
    
    It returns a pair:
      - the line expanded up to the longest common sequence among the
        completions
      - the list of all possible completions (first dirs, then files)
    """
    tokens = parse_line(line)
    if tokens == [] or (line[-1] in sep_chars
                        and parse_line(line) == parse_line(line + ' ')):
        tokens += ['']  # This saves us some checks later
    token = tokens[-1].replace('"', '')

    (path_to_complete, _, prefix) = token.rpartition('\\')
    if path_to_complete == '' and token != '' and token[0] == '\\':
        path_to_complete = '\\'

    # print '\n\n', path_to_complete, '---', prefix, '\n\n'

    if path_to_complete == '':
        dir_to_complete = os.getcwd()
    elif path_to_complete == '\\':
        dir_to_complete = os.getcwd()[0:3]
    else:
        dir_to_complete = expand_env_vars(path_to_complete) + '\\'

    # This is the wildcard matcher used throughout the function
    matcher = wildcard_to_regex(prefix + '*')

    completions = []
    if os.path.isdir(dir_to_complete):
        try:
            completions = [
                elem for elem in os.listdir(dir_to_complete)
                if matcher.match(elem)
            ]
        except OSError:
            # Cannot complete, probably access denied
            pass

    # Sort directories first, also append '\'; then, files
    completions_dirs = [
        elem + '\\' for elem in completions
        if os.path.isdir(dir_to_complete + '\\' + elem)
    ]
    completions_files = [
        elem for elem in completions
        if os.path.isfile(dir_to_complete + '\\' + elem)
    ]
    completions = completions_dirs + completions_files

    if (len(tokens) == 1
            or tokens[-2] in seq_tokens) and path_to_complete == '':
        # We are at the beginning of a command ==> also complete from the path
        completions_path = []
        for elem_in_path in os.environ['PATH'].split(';'):
            dir_to_complete = expand_env_vars(elem_in_path) + '\\'
            try:
                completions_path += [
                    elem for elem in os.listdir(dir_to_complete)
                    if matcher.match(elem) and os.path.isfile(dir_to_complete +
                                                              '\\' + elem)
                    and has_exec_extension(elem) and not elem in completions
                    and not elem in completions_path
                ]
            except OSError:
                # Cannot complete, probably access denied
                pass

        # Add internal commands
        internal_commands = [
            'assoc', 'call', 'cd', 'chdir', 'cls', 'color', 'copy', 'date',
            'del', 'dir', 'echo', 'endlocal', 'erase', 'exit', 'for', 'ftype',
            'goto', 'if', 'md', 'mkdir', 'move', 'path', 'pause', 'popd',
            'prompt', 'pushd', 'rem', 'ren', 'rename', 'rd', 'rmdir', 'set',
            'setlocal', 'shift', 'start', 'time', 'title', 'type', 'ver',
            'verify', 'vol'
        ]
        if sys.getwindowsversion()[0] >= 6:
            # Windows 7 or newer
            internal_commands.append('mklink')
        completions_path += [
            elem for elem in internal_commands if matcher.match(elem)
            and not elem in completions and not elem in completions_path
        ]

        # Sort in lexical order (case ignored)
        completions_path.sort(key=str.lower)

        # Remove .com, .exe or .bat extension where possible
        completions_path_no_ext = [
            strip_extension(elem) for elem in completions_path
        ]
        completions_path_nice = []
        for i in range(0, len(completions_path_no_ext)):
            similar = [
                elem for elem in completions_path_no_ext
                if elem == completions_path_no_ext[i]
            ]
            similar += [
                elem for elem in completions
                if strip_extension(elem) == completions_path_no_ext[i]
            ]
            if len(similar) == 1 and has_exec_extension(
                    completions_path[i]) and len(prefix) < len(
                        completions_path[i]) - 3:
                # No similar executables, don't use extension
                completions_path_nice.append(completions_path_no_ext[i])
            else:
                # Similar executables found, keep extension
                completions_path_nice.append(completions_path[i])
        completions += completions_path_nice

    if completions != []:
        # Find the longest common sequence
        common_string = find_common_prefix(prefix, completions)

        if path_to_complete == '':
            completed_file = common_string
        elif path_to_complete == '\\':
            completed_file = '\\' + common_string
        else:
            completed_file = path_to_complete + '\\' + common_string

        if expand_env_vars(completed_file).find(' ') >= 0 or \
                (prefix != '' and [elem for elem in completions if contains_special_char(elem)] != []) or \
                (prefix == '' and [elem for elem in completions if starts_with_special_char(elem)] != []):
            # We add quotes if one of the following holds:
            #   * the (env-expanded) completed string contains whitespace
            #   * there is a prefix and at least one of the valid completions contains whitespace
            #   * there is no prefix and at least one completion _starts_ with whitespace
            start_quote = '"'
        else:
            start_quote = ''

        # Build the result
        result = line[0:len(line) -
                      len(tokens[-1])] + start_quote + completed_file

        if len(completions) == 1:
            # We can close the quotes if we have completed to a unique filename
            if start_quote == '"':
                end_quote = '"'
            else:
                end_quote = ''

            if result[-1] == '\\':
                # Directory -- we want the backslash (if any) AFTER the closing quote
                result = result[:-1] + end_quote + '\\'
            else:
                # File -- add space if the completion is unique
                result += end_quote
                result += ' '

        return (result, completions)
    else:
        # No expansion was made, return original line
        return (line, [])
Exemplo n.º 17
0
                                if not ord(rec.Char) in [0, 8, 13, 27]:
                                    state.handle(ActionCode.ACTION_INSERT,
                                                 rec.Char)
                                continue

                        stdout.write('\n')
                        for line in range(0, num_lines):
                            # Print one line
                            stdout.write('\r')
                            for column in range(0, num_columns):
                                if line + column * num_lines < len(
                                        suggestions):
                                    s = suggestions[line + column * num_lines]
                                    if has_wildcards(tokens[-1]):
                                        # Print wildcard matches in a different color
                                        path_sep = '/' if '/' in expand_env_vars(
                                            tokens[-1]) else '\\'
                                        tokens = parse_line(
                                            completed.rstrip(path_sep))
                                        token = tokens[-1].replace('"', '')
                                        (_, _,
                                         prefix) = token.rpartition(path_sep)
                                        match = wildcard_to_regex(prefix +
                                                                  '*').match(s)
                                        current_index = 0
                                        for i in range(1, match.lastindex + 1):
                                            stdout.write(
                                                color.Fore.DEFAULT +
                                                color.Back.DEFAULT + appearance
                                                .colors.completion_match +
                                                s[current_index:match.start(i)]
                                                + color.Fore.DEFAULT +