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

sbt.internal.util.complete.ExampleSource.scala Maven / Gradle / Ivy

The newest version!
/*
 * sbt
 * Copyright 2023, Scala center
 * Copyright 2011 - 2022, Lightbend, Inc.
 * Copyright 2008 - 2010, Mark Harrah
 * Licensed under Apache License 2.0 (see LICENSE)
 */

package sbt.internal.util
package complete

import java.io.File
import sbt.io.IO

/**
 * These sources of examples are used in parsers for user input completion. An example of such a source is the
 * [[sbt.internal.util.complete.FileExamples]] class, which provides a list of suggested files to the user as they press the
 * TAB key in the console.
 */
trait ExampleSource {

  /**
   * @return a (possibly lazy) list of completion example strings. These strings are continuations of user's input. The
   *         user's input is incremented with calls to [[withAddedPrefix]].
   */
  def apply(): Iterable[String]

  /**
   * @param addedPrefix a string that just typed in by the user.
   * @return a new source of only those examples that start with the string typed by the user so far (with addition of
   *         the just added prefix).
   */
  def withAddedPrefix(addedPrefix: String): ExampleSource

}

/**
 * A convenience example source that wraps any collection of strings into a source of examples.
 * @param examples the examples that will be displayed to the user when they press the TAB key.
 */
sealed case class FixedSetExamples(examples: Iterable[String]) extends ExampleSource {
  override def withAddedPrefix(addedPrefix: String): ExampleSource =
    FixedSetExamples(examplesWithRemovedPrefix(addedPrefix))

  override def apply(): Iterable[String] = examples

  private def examplesWithRemovedPrefix(prefix: String) = examples.collect {
    case example if example startsWith prefix => example substring prefix.length
  }
}

/**
 * Provides path completion examples based on files in the base directory.
 * @param base the directory within which this class will search for completion examples.
 * @param prefix the part of the path already written by the user.
 */
class FileExamples(base: File, prefix: String = "") extends ExampleSource {
  override def apply(): Stream[String] = files(base).map(_ substring prefix.length)

  override def withAddedPrefix(addedPrefix: String): FileExamples =
    new FileExamples(base, prefix + addedPrefix)

  protected def files(directory: File): Stream[String] = {
    val childPaths = IO.listFiles(directory).toStream
    val prefixedDirectChildPaths = childPaths map { IO.relativize(base, _).get } filter {
      _ startsWith prefix
    }
    val dirsToRecurseInto = childPaths filter { _.isDirectory } map { IO.relativize(base, _).get } filter {
      dirStartsWithPrefix
    }
    prefixedDirectChildPaths append dirsToRecurseInto.flatMap(dir => files(new File(base, dir)))
  }

  private def dirStartsWithPrefix(relativizedPath: String): Boolean =
    (relativizedPath startsWith prefix) || (prefix startsWith relativizedPath)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy