All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.groovy.tools.shell.completion.FileNameCompleter.groovy Maven / Gradle / Ivy

There is a newer version: 4.15.102
Show newest version
/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package org.codehaus.groovy.tools.shell.completion

import groovy.transform.PackageScope
import jline.internal.Configuration

import static jline.internal.Preconditions.checkNotNull

/**
 * A file name completer takes the buffer and issues a list of
 * potential completions.
 * 

* This completer tries to behave as similar as possible to * bash's file name completion (using GNU readline) * with the following exceptions: *

*

    *
  • Candidates that are directories will end with "File.separator"
  • *
  • Wildcard regular expressions are not evaluated or replaced
  • *
  • The "~" character can be used to represent the user's home directory. * It cannot fully complete to other users' homes in all operating systems, since java does * not provide any way of determining that easily, but it will attempt a simplistic approach.
  • *
* * @since 2.3 */ class FileNameCompleter extends jline.console.completer.FileNameCompleter { private static final boolean OS_IS_WINDOWS = Configuration.isWindows() private final GroovyShell gs = new GroovyShell() FileNameCompleter(boolean printSpaceAfterFullCompletion = true, boolean escapeBackslash = false, boolean escapeSpaces = true) { this.printSpaceAfterFullCompletion = printSpaceAfterFullCompletion this.escapeBackslash = escapeBackslash if (OS_IS_WINDOWS) separator = escapeBackslash ? "\\\\" : "\\" this.escapeSpaces = escapeSpaces } private static boolean isWindowsSubsystemForLinux() { System.getProperty("os.name").contains('Linux') && System.getProperty('os.version').contains('Microsoft') } /** * True for say, a command-line arg, false for instance inside a String. */ boolean printSpaceAfterFullCompletion /** * If the filename will be placed inside a single/double quoted String we must escape backslash when on e.g. Windows. */ boolean escapeBackslash /** * Set false if e.g. the filename will be inside a String. Should not be true if quoteFilenamesWithSpaces is true. */ boolean escapeSpaces private String separator @Override int complete(String buffer, final int cursor, final List candidates) { checkNotNull(candidates) buffer = buffer ?: "" String translated = buffer int adjustment = 0 if (escapeBackslash) { translated = gs.evaluate("'$translated'") adjustment = buffer.size() - translated.size() } // Special character: ~ maps to the user's home directory in most OSs if (translated.startsWith("~")) { File homeDir = getUserHome() if ((OS_IS_WINDOWS || isWindowsSubsystemForLinux()) && (translated.equals("~" + separator()) || translated.equals("~/"))) { // for windows ~ isn't recognized at the file system level so replace def adjustSize = translated.size() String result String temp = (homeDir.path + translated.substring(separator().size())).toString().replace('"', '\\"').replace('\'', '\\\'') if (escapeBackslash) { temp = temp.replace('\\', '\\\\') } result = escapeSpaces ? temp.replace(' ', '\\ ') : temp candidates << result return cursor - adjustSize - adjustment } else if (translated.startsWith("~/")) { translated = homeDir.path + translated.substring(2) } else { translated = homeDir.parentFile.absolutePath + separator() + translated.substring(1) } } else if (!(new File(translated).canonicalFile.exists()) && !(new File(translated).canonicalFile.parentFile?.exists())) { String cwd = getUserDir().absolutePath translated = cwd + separator() + translated } File file = new File(translated) final File dir if ((OS_IS_WINDOWS && translated.endsWith(separator())) || translated.endsWith('/')) { dir = file } else { dir = file.parentFile } File[] entries = (dir == null) ? new File[0] : dir.listFiles() return matchFiles(buffer, translated, entries, candidates) } private static String canonicalForm(String raw) { String result = raw.replace('\\', '/') OS_IS_WINDOWS ? result.toLowerCase() : result } protected int matchFiles(final String buffer, final String translated, final File[] files, final List candidates) { if (files == null) return -1 for (File file : files) { if (canonicalForm(file.getAbsolutePath()).startsWith(canonicalForm(translated))) { CharSequence name = file.name String renderedName = render(name).toString() if (file.isDirectory()) { renderedName += separator } else { if (printSpaceAfterFullCompletion) { renderedName += ' ' } } candidates.add(renderedName) } } int index = -1 int sizeAdjust = 0 if (separator) { index = buffer.lastIndexOf(separator) sizeAdjust = separator.size() } int slashIndex = buffer.lastIndexOf('/') if (slashIndex >= 0 && slashIndex > index) { index = slashIndex sizeAdjust = 1 } return index + sizeAdjust } @PackageScope CharSequence render(CharSequence name) { String temp = name.toString().replace('"', '\\"').replace('\'', '\\\'') if (escapeBackslash) { temp = temp.replace('\\', '\\\\') } escapeSpaces ? temp.replace(' ', '\\ ') : temp } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy