Created
May 10, 2019 03:23
-
-
Save elihart/732dc1b6c9686b531730f4a7504b9261 to your computer and use it in GitHub Desktop.
Kotlin File extension for easily editing the contents of a file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Edit the contents of a File with a [FileEditor]. The new contents will override the old. | |
| * | |
| * @param lineTransform Called with each line of the file in order. | |
| * Return the new value you would like written in the file, or null to delete the line. | |
| * You can also call [FileEditor.insertNext] to insert a line immediately above the given line, or | |
| * [FileEditor.insertPrevious] to insert a line immediately after the given line. | |
| */ | |
| fun File.edit(lineTransform: FileEditor.(line: String) -> String) { | |
| FileEditor(this).edit(lineTransform) | |
| } | |
| /** Used from [File.edit]. */ | |
| class FileEditor(val file: File) { | |
| private var lines: MutableList<String> = file.readLines().toMutableList() | |
| private val lineCount: Int get() = lines.size | |
| private var currentLineIndex = 0 | |
| fun insertPrevious(line: String) { | |
| lines.add(currentLineIndex, line) | |
| currentLineIndex++ | |
| } | |
| fun insertNext(line: String) { | |
| lines.add(currentLineIndex + 1, line) | |
| } | |
| fun edit(lineTransform: FileEditor.(line: String) -> String?): File { | |
| currentLineIndex = 0 | |
| while (currentLineIndex < lineCount) { | |
| val line = lines.getOrNull(currentLineIndex) ?: throw IllegalStateException("No line at $currentLineIndex") | |
| val newLine = lineTransform(line) | |
| if (newLine == null) { | |
| lines.removeAt(currentLineIndex) | |
| } else { | |
| lines[currentLineIndex] = newLine | |
| currentLineIndex++ | |
| } | |
| } | |
| return file.replaceContents(lines) | |
| } | |
| } | |
| /** | |
| * Replaces the contents of this file with the given lines. | |
| * Overwrites the old file and returns a new File instance with the new content. | |
| */ | |
| fun File.replaceContents(lines: List<String>): File { | |
| val tempFile = createTempFile() | |
| tempFile.printWriter().use { writer -> | |
| lines.forEach { writer.println(it) } | |
| } | |
| check(this.delete() && tempFile.renameTo(this)) { "failed to replace file" } | |
| return tempFile | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment