mirror of https://github.com/sbt/sbt.git
Added tests for FileExamples. Improved the file-searching in FileExamples.
This commit is contained in:
parent
757fe4228d
commit
cbfd3f1c08
|
|
@ -1,6 +1,7 @@
|
||||||
package sbt.complete
|
package sbt.complete
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import sbt.IO._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These sources of examples are used in parsers for user input completion. An example of such a source is the
|
* These sources of examples are used in parsers for user input completion. An example of such a source is the
|
||||||
|
|
@ -27,12 +28,15 @@ trait ExampleSource
|
||||||
* A convenience example source that wraps any collection of strings into a source of examples.
|
* 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.
|
* @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 {
|
sealed case class FixedSetExamples(examples: Iterable[String]) extends ExampleSource
|
||||||
|
{
|
||||||
override def withAddedPrefix(addedPrefix: String): ExampleSource = FixedSetExamples(examplesWithRemovedPrefix(addedPrefix))
|
override def withAddedPrefix(addedPrefix: String): ExampleSource = FixedSetExamples(examplesWithRemovedPrefix(addedPrefix))
|
||||||
|
|
||||||
override def apply(): Iterable[String] = examples
|
override def apply(): Iterable[String] = examples
|
||||||
|
|
||||||
private def examplesWithRemovedPrefix(prefix: String) = examples.collect { case example if example startsWith prefix => example substring prefix.length }
|
private def examplesWithRemovedPrefix(prefix: String) = examples.collect {
|
||||||
|
case example if example startsWith prefix => example substring prefix.length
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -40,22 +44,19 @@ sealed case class FixedSetExamples(examples: Iterable[String]) extends ExampleSo
|
||||||
* @param base the directory within which this class will search for completion examples.
|
* @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.
|
* @param prefix the part of the path already written by the user.
|
||||||
*/
|
*/
|
||||||
class FileExamples(base: File, prefix: String = "") extends ExampleSource {
|
class FileExamples(base: File, prefix: String = "") extends ExampleSource
|
||||||
private val relativizedPrefix: String = "." + File.separator + prefix
|
{
|
||||||
|
override def apply(): Stream[String] = files(base).map(_ substring prefix.length)
|
||||||
override def apply(): Iterable[String] = files(base).map(_.toString.substring(relativizedPrefix.length))
|
|
||||||
|
|
||||||
override def withAddedPrefix(addedPrefix: String): FileExamples = new FileExamples(base, prefix + addedPrefix)
|
override def withAddedPrefix(addedPrefix: String): FileExamples = new FileExamples(base, prefix + addedPrefix)
|
||||||
|
|
||||||
protected def fileStartsWithPrefix(path: File): Boolean = path.toString.startsWith(relativizedPrefix)
|
protected def files(directory: File): Stream[String] = {
|
||||||
|
val childPaths = directory.listFiles().toStream
|
||||||
protected def directoryStartsWithPrefix(path: File): Boolean = {
|
val prefixedDirectChildPaths = childPaths.map(relativize(base, _).get).filter(_ startsWith prefix)
|
||||||
val pathString = path.toString
|
val dirsToRecurseInto = childPaths.filter(_.isDirectory).map(relativize(base, _).get).filter(dirStartsWithPrefix)
|
||||||
pathString.startsWith(relativizedPrefix) || relativizedPrefix.startsWith(pathString)
|
prefixedDirectChildPaths append dirsToRecurseInto.flatMap(dir => files(new File(base, dir)))
|
||||||
}
|
}
|
||||||
|
|
||||||
protected def files(directory: File): Iterable[File] = {
|
private def dirStartsWithPrefix(relativizedPath: String): Boolean =
|
||||||
val (subDirectories, filesOnly) = directory.listFiles().toStream.partition(_.isDirectory)
|
(relativizedPath startsWith prefix) || (prefix startsWith relativizedPath)
|
||||||
filesOnly.filter(fileStartsWithPrefix) ++ subDirectories.filter(directoryStartsWithPrefix).flatMap(files)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
package sbt.complete
|
||||||
|
|
||||||
|
import org.specs2.mutable.Specification
|
||||||
|
import org.specs2.specification.Scope
|
||||||
|
import sbt.IO.withTemporaryDirectory
|
||||||
|
import java.io.File
|
||||||
|
import sbt.IO._
|
||||||
|
|
||||||
|
class FileExamplesTest extends Specification
|
||||||
|
{
|
||||||
|
|
||||||
|
"listing all files in an absolute base directory" should {
|
||||||
|
"produce the entire base directory's contents" in new directoryStructure {
|
||||||
|
fileExamples().toList should containTheSameElementsAs(allRelativizedPaths)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"listing files with a prefix that matches none" should {
|
||||||
|
"produce an empty list" in new directoryStructure(withCompletionPrefix = "z") {
|
||||||
|
fileExamples().toList should beEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"listing single-character prefixed files" should {
|
||||||
|
"produce matching paths only" in new directoryStructure(withCompletionPrefix = "f") {
|
||||||
|
fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"listing directory-prefixed files" should {
|
||||||
|
"produce matching paths only" in new directoryStructure(withCompletionPrefix = "far") {
|
||||||
|
fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly)
|
||||||
|
}
|
||||||
|
|
||||||
|
"produce sub-dir contents only when appending a file separator to the directory" in new directoryStructure(withCompletionPrefix = "far" + File.separator) {
|
||||||
|
fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"listing files with a sub-path prefix" should {
|
||||||
|
"produce matching paths only" in new directoryStructure(withCompletionPrefix = "far" + File.separator + "ba") {
|
||||||
|
fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"completing a full path" should {
|
||||||
|
"produce a list with an empty string" in new directoryStructure(withCompletionPrefix = "bazaar") {
|
||||||
|
fileExamples().toList shouldEqual List("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class directoryStructure(withCompletionPrefix: String = "") extends Scope with DelayedInit
|
||||||
|
{
|
||||||
|
var fileExamples: FileExamples = _
|
||||||
|
var baseDir: File = _
|
||||||
|
var childFiles: List[File] = _
|
||||||
|
var childDirectories: List[File] = _
|
||||||
|
var nestedFiles: List[File] = _
|
||||||
|
var nestedDirectories: List[File] = _
|
||||||
|
|
||||||
|
def allRelativizedPaths: List[String] =
|
||||||
|
(childFiles ++ childDirectories ++ nestedFiles ++ nestedDirectories).map(relativize(baseDir, _).get)
|
||||||
|
|
||||||
|
def prefixedPathsOnly: List[String] =
|
||||||
|
allRelativizedPaths.filter(_ startsWith withCompletionPrefix).map(_ substring withCompletionPrefix.length)
|
||||||
|
|
||||||
|
override def delayedInit(testBody: => Unit): Unit = {
|
||||||
|
withTemporaryDirectory {
|
||||||
|
tempDir =>
|
||||||
|
createSampleDirStructure(tempDir)
|
||||||
|
fileExamples = new FileExamples(baseDir, withCompletionPrefix)
|
||||||
|
testBody
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def createSampleDirStructure(tempDir: File): Unit = {
|
||||||
|
childFiles = toChildFiles(tempDir, List("foo", "bar", "bazaar"))
|
||||||
|
childDirectories = toChildFiles(tempDir, List("moo", "far"))
|
||||||
|
nestedFiles = toChildFiles(childDirectories(1), List("farfile1", "barfile2"))
|
||||||
|
nestedDirectories = toChildFiles(childDirectories(1), List("fardir1", "bardir2"))
|
||||||
|
|
||||||
|
(childDirectories ++ nestedDirectories).map(_.mkdirs())
|
||||||
|
(childFiles ++ nestedFiles).map(_.createNewFile())
|
||||||
|
|
||||||
|
// NOTE: Creating a new file here because `tempDir.listFiles()` returned an empty list.
|
||||||
|
baseDir = new File(tempDir.getCanonicalPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def toChildFiles(baseDir: File, files: List[String]): List[File] = files.map(new File(baseDir, _))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue