Skip to content

Commit

Permalink
Wrote documentation for everything remaining and incremented version
Browse files Browse the repository at this point in the history
  • Loading branch information
Antoine Neveux a183276 committed Oct 27, 2016
1 parent 3693baa commit 7f786b7
Show file tree
Hide file tree
Showing 14 changed files with 232 additions and 82 deletions.
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ File-Finder is a simple tiny tool for searching through files on your computer.

![Screenshot of File-Finder](etc/screenshot.png)

It aims at letting you search through various directories, and retrieve files not only typing their names, but using kind of patterns as well. Its goal is to let you do everything from the keyboard (so not having to use your mouse) for being as quick as possible.
It aims at letting you searchTextProperty through various directories, and retrieve files not only typing their names, but using kind of patterns as well. Its goal is to let you do everything from the keyboard (so not having to use your mouse) for being as quick as possible.

## Installation and Execution

Expand Down Expand Up @@ -41,46 +41,46 @@ Meaning that for example, by typing `abc`, the file named `abc.txt` will get a h

Typing researches and getting results is one thing, but being able to use them is actually something better. Here are the keyboard shortcuts available in the application:

__From the search bar:__
__From the searchTextProperty bar:__

- `Enter` will open in the default editor the first file of the list,
- `CTRL + B` will open in the default explorer the parent folder of the first file of the list,
- `CTRL + O` will open in the default editor the first file of the list (like `ENTER`),
- `DOWN_ARROW` will bring you to the table where files are listed,
- `DOWN_ARROW` will bring you to the resultsTableView where files are listed,

__From the table of results:__
__From the resultsTableView of results:__

- `O` will open in the default editor the selected file,
- `B` will open in the default explorer the parent folder of the selected file,
- `CTRL + C` will copy in the clipboard the full path of the selected file,
- `UP_ARROW` and `DOWN_ARROW` will allow you to navigate through the list of files,
- If the selected item is the first one, `UP_ARROW` will bring you back to the search bar,
- `ESC` will bring you to the search bar,
- If the selected item is the first one, `UP_ARROW` will bring you back to the searchTextProperty bar,
- `ESC` will bring you to the searchTextProperty bar,

## Directories filtering

In order to get more precise researches, it is possible in the search bar to complete your research with specific directories filters. For this, simply use the `/` character, followed by the directory you'd like to get filtered. You can add multiple of those if you want.
In order to get more precise researches, it is possible in the searchTextProperty bar to complete your research with specific directories filters. For this, simply use the `/` character, followed by the directory you'd like to get filtered. You can add multiple of those if you want.

For example, if you want something in your working directory you could write: `dbmanager /work` and it would search for that pattern only in a directory containing a `/work` folder.
For example, if you want something in your working directory you could write: `dbmanager /work` and it would searchTextProperty for that pattern only in a directory containing a `/work` folder.

You could also write something like `dbmanager /work /src` to search it in a source folder from your working directory.
You could also write something like `dbmanager /work /src` to searchTextProperty it in a source folder from your working directory.

## Bangs!

Highly inspired from [DuckDuckGo](https://duckduckgo.com/bang), you can also use some _Bangs!_ in your research to bring on some special filters. For this, simply use the `!` character followed by the name of the _Bang!_.

Please note that those _Bang!_ can be negated by adding additional `!` characters.

For example, you could use `dbmanager !src` to search only source files matching with your patterns.
For example, you could use `dbmanager !src` to searchTextProperty only source files matching with your patterns.

Or also use `dbmanager !!src` to search only non-source files matching with your pattern.
Or also use `dbmanager !!src` to searchTextProperty only non-source files matching with your pattern.

__Available Bangs at the moment:__

- `!src`: allows to filter source files, identified by their extensions. For now, supported extensions are:
`"kt", "java", "c", "sh", "cpp", "scala", "xml", "js", "html", "css", "yml", "md"`.
- `!target`: allows to filter files coming from a target directory (basically compilation results). It is particularly interesting while being negated so you can search for anything which isn't in a target repository.
- `!ignored`: allows to filter files which are considered as ignored by researches. Again, it is particularly useful while negated so you can search for files which aren't ignored. _ignored files are defined in the global configuration of file-finder, as explained in next part of the documentation_.
- `!target`: allows to filter files coming from a target directory (basically compilation results). It is particularly interesting while being negated so you can searchTextProperty for anything which isn't in a target repository.
- `!ignored`: allows to filter files which are considered as ignored by researches. Again, it is particularly useful while negated so you can searchTextProperty for files which aren't ignored. _ignored files are defined in the global configuration of file-finder, as explained in next part of the documentation_.

Regarding that last _Bang!_, keep in mind that ignored files are only filtered by the usage of that particular _Bang!_.

Expand All @@ -100,6 +100,7 @@ __Available elements at the moment:__
- `ignored`: the list (comma separated) of all extensions to be ignored while using the `!ignored` _Bang!_.
- `dotdirectories`: boolean specifying if the program should consider dot directories or not (hidden directories). It'll be _false_ by default. Turning it to _true_ will consider way more files but might cause performances issues.
- `debounce`: integer property representing the time to wait, in milliseconds, before actually computing the research after stopping to type characters. It'll be 150 by default (increase it if you're not typing really fast on a keyboard ;)).
- `items`: the maximum number of elements to show in the searchTextProperty results.

Additional configuration (which are not listed here) won't be taken into account.

Expand Down
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.github.ktoolz</groupId>
<artifactId>filefinder</artifactId>
<version>1.0.1-SNAPSHOT</version>
<version>1.1.0-SNAPSHOT</version>
</parent>

<artifactId>filefinder-core</artifactId>
Expand Down
37 changes: 37 additions & 0 deletions core/src/main/kotlin/com/github/ktoolz/filefinder/model/queries.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,54 @@ package com.github.ktoolz.filefinder.model
import javaslang.collection.List
import java.io.File

/**
* Simple wrapper for a *Bang* query, wrapping both the [Bang] and an indication saying if it's negated
*
* @property bang the actual [Bang] which contains both the name and behavior
* @property negated indication if the [Bang] is negated or not. If that's the case, the opposite filter will be
* applied on the search query
*/
data class BangQuery(val bang: Bang, val negated: Boolean = false)

/**
* Wrapper for all information related to a search query.
* It contains both the term that we're searching for, and also the List of BangQueries, and the List of Directories
* to be filtered.
*
* @property term the actual term we're searching for
* @property bangs a List of all the [BangQuery] to apply to that search
* @property directories a List of all the directories to be filtered
*/
data class SearchQuery(val term: String, val bangs: List<BangQuery>, val directories: List<String>) {
/**
* A List of all combinations we'll use for searching through the files
* It's used in order to allow some mistakes in the term we're searching for.
*/
val combinations: List<List<Char>>

init {
val list = List.ofAll(term.toLowerCase().toCharArray())
// We're keeping all combinations of (n choose n-1), which means 1 error basically,
// and we prepend the actual search term (because we also want to search for the term without
// any errors.
combinations = list.combinations(list.size() - 1).prepend(list)
}

/**
* Indicates if the file provided as a parameter matches with the directories specified in the [SearchQuery]
* @param file the file we want to verify, searching if it's part of the directories we want to filter
*
* @return true if the file is part of the directories we specified
*/
fun filterDirectories(file: File): Boolean =
directories.forAll { file.parentFile.absolutePath?.contains("/$it") ?: false }

/**
* Indicates if the file provided as a parameter matches with the Bangs specified in the [SearchQuery]
* @param file the file we want to verify, searching if it's part of the Bangs we want to filter
*
* @return true if the file is matching with the Bangs we specified
*/
fun filterBangs(file: File): Boolean =
bangs.forAll { it.negated xor it.bang.filter(file) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,24 @@ import java.io.File
import java.util.*

/**
* Store a search result
* Stores the actual result of a File search from all matchers computed previsouly.
* It'll also compute a score allowing to order the results from best to worst.
*
* @property matchers a List of all [MatchResult] elements computed while searching through the files
* (so basically just the results of the search process)
* @property file the actual file which has been found
*/
data class FileSearchResult(val matchers: List<MatchResult<Char>>, val file: File) {
/**
* Name of the file linked to that search result
*/
val filename: String by lazy { file.name }

/**
* A computed score allowing to order the results.
* Basically, it'll be better when letters from the pattern are found and close together,
* and it'll get worse when letters aren't found or when they're far from each other.
*/
val score: Int = matchers.foldLeft(0) {
score, pattern ->
when {
Expand All @@ -36,4 +50,15 @@ data class FileSearchResult(val matchers: List<MatchResult<Char>>, val file: Fil
}
}

/**
* Wrapper for the results of matching process.
* It'll basically just contain one element of the pattern, and an indication stating if it has been found or not,
* and at which distance from the previous one.
* It'll basically allow afterwards to calculate if a result is good or not.
*
* @property element the part of the pattern which we were searching for
* @property match a boolean stating if that part of the pattern has been found or not
* @property distance an [Optional] integer matching with the distance between the current element we were searching for and
* the previous one
*/
data class MatchResult<out T>(val element: T, val match: Boolean, val distance: Optional<Int>)
21 changes: 21 additions & 0 deletions core/src/main/kotlin/com/github/ktoolz/filefinder/parser/Parser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,30 @@ import com.github.ktoolz.filefinder.model.BangQuery
import com.github.ktoolz.filefinder.model.SearchQuery
import javaslang.collection.List

/**
* Retrieves a List of all the names of a Bangs List
* @receiver a List of [Bang]
*
* @return a List of all the [Bang] names
*/
fun List<Bang>.names() = this.map { it.name }!!

/**
* Retrieves a [Bang] in a List from its name
* @param name the name of a [Bang] we'd like to retrieve
* @receiver a List of [Bang]
*
* @return a [Bang] matching with the provided name
*/
fun List<Bang>.findBang(name: String) = this.find { it.name == name }.get()!!

/**
* Allows to parse a String provided by the user in order to create a [SearchQuery] out of it.
*
* @property bangsReferences a list of all the [Bang] registered in the application
* @property bangsIdentifier the character to be used for identifying the Bangs! in the String
* @property directorySpecialChar the character to be used for identifying the directories to be filtered
*/
class ContextParser(val bangsReferences: List<Bang>,
val bangsIdentifier: Char = '!',
val directorySpecialChar: Char = '/') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,62 @@ package com.github.ktoolz.filefinder.utils
import java.io.File
import java.util.*

fun List<String>.toFiles() = this.map { File(it) }
/**
* Transforms a List of String into a List of Files by creating Files from each String :)
* @receiver a List of String, ideally containing paths cause we'll create files out of it
*
* @return a List of Files created from each String
*/
fun List<String>.toFiles() = this.map(::File)

/**
* Singleton holding the application configuration.
* Nothing fancy here, it's just reading the configuration file and loading its data :)
*/
object ExecutionContext {
/**
* Properties matching with the content of the configuration file
*/
val properties: Properties
/**
* A Set containing all the directories in which we want to perform the search
*/
val directories: MutableSet<File>
/**
* A Set containing all the extensions to be ignored while using the associate Bang
*/
val ignored: Set<String>
/**
* A boolean allowing to state if dotdirectories should be considered while searching files or not
*/
val dotdirectories: Boolean
/**
* The debounce value to be used while processing the search in milliseconds
*/
val debounce: Long

/**
* The maximum number of items to be displayed in the search results
*/
val items: Int

init {
fun String.splitParts() = this.split(",").toList().map(String::trim)
properties = loadDotFile()
directories = properties.getProperty("directories", "").splitParts().toFiles().toMutableSet()
ignored = properties.getProperty("ignored","").splitParts().toSet()
dotdirectories = properties.getProperty("dotdirectories","false").toBoolean()
debounce = properties.getProperty("debounce","150").toLong()
ignored = properties.getProperty("ignored", "").splitParts().toSet()
dotdirectories = properties.getProperty("dotdirectories", "false").toBoolean()
debounce = properties.getProperty("debounce", "150").toLong()
items = properties.getProperty("items", "15").toInt()
}

fun String.splitParts() = this.split(",").toList().map(String::trim)
}

/**
* Loads the default configuration file of the application, and returns a Properties object out of it.
*
* @return a Properties object containing all the values contained in the application default configuration file
*/
fun loadDotFile(): Properties {
val properties = Properties()
val homedir = System.getProperty("user.home")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,31 @@
*/
package com.github.ktoolz.filefinder.utils

/**
* Creates a Javaslang list out of a Kotlin List
* @receiver a Kotlin List
*
* @return a Javaslang List containing all the elements of the Kotlin List
*/
fun <T> List<T>.toJavaslang() = javaslang.collection.List.ofAll(this)!!

/**
* Creates a Javaslang list containing all the characters of a String
* @receiver a String that we want to decompose
*
* @return a Javaslang containing all the characters of the provided String
*/
fun String.toJavaslangList() = toList().toJavaslang()

/**
* Executes a particular block and returns the result as well as the time it required to compute
* @param block the block to be executed, basically just a function producing something
*
* @return a [Pair] element containing both the result of the block execution, and the time ellapsed to do that
*/
fun <T> time(block: () -> T): Pair<T, Long> {
val now = System.currentTimeMillis()
val result = block()
val elapsed = System.currentTimeMillis() - now
return result to elapsed
}

fun banner(block: () -> Any) {
println("---------------------------------------")
println(block())
println("---------------------------------------")
}

inline fun <T> T.use(block: (T) -> Unit): T = apply { block(this) }

inline fun <reified T> Any.castUse(block: T.() -> Unit) {
if (this is T) block(this)
}
Binary file modified etc/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<groupId>com.github.ktoolz</groupId>
<artifactId>filefinder</artifactId>
<version>1.0.1-SNAPSHOT</version>
<version>1.1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<name>File Finder</name>
Expand Down
2 changes: 1 addition & 1 deletion ui/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>com.github.ktoolz</groupId>
<artifactId>filefinder</artifactId>
<version>1.0.1-SNAPSHOT</version>
<version>1.1.0-SNAPSHOT</version>
</parent>

<artifactId>filefinder-ui</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import javafx.stage.Stage
import tornadofx.App
import tornadofx.importStylesheet

/**
* Main application.
* Allows to start the GUI.
*/
class FileFinderApp : App(MainView::class) {
init {
importStylesheet(Styles::class)
Expand All @@ -30,6 +34,10 @@ class FileFinderApp : App(MainView::class) {
}
}

/**
* Just the main entrypoint of the application :)
* It'll basically just run the GUI.
*/
fun main(args: Array<String>) {
Application.launch(FileFinderApp::class.java, *args)
}
4 changes: 4 additions & 0 deletions ui/src/main/kotlin/com/github/ktoolz/filefinder/Styles.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ package com.github.ktoolz.filefinder
import javafx.scene.text.FontWeight.BOLD
import tornadofx.*

/**
* Simply the Styles of our application :)
* Kind of Kotlin made CSS.
*/
class Styles : Stylesheet() {
companion object {
val heading by cssclass()
Expand Down
Loading

0 comments on commit 7f786b7

Please sign in to comment.