Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
phroa committed Aug 23, 2017
0 parents commit 37d6777
Show file tree
Hide file tree
Showing 12 changed files with 1,393 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
*.bat
*.class
*.ear
*.jar
*.launch
*.war
.apt_generated/
.classpath
.factorypath
.gradle/
.idea/
.mtj.tmp/
.project
.settings/
bin/
build/
gradle/
gradlew
hs_err_pid*
run/
build.number
*.iml
342 changes: 342 additions & 0 deletions LICENSE.2

Large diffs are not rendered by default.

677 changes: 677 additions & 0 deletions LICENSE.3

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Readline

Provides readline/emacs-ish bindings for text boxes in Minecraft.

Available mappings:

```
C-a = beginning-of-line
C-e = end-of-line
C-b = backward-char
C-f = forward-char
M-b = backward-word
M-f = forward-word
C-h = backward-delete-char
C-w = backward-delete-word
C-u = backward-delete-line
C-k = forward-delete-line
C-t = transpose-chars
M-t = transpose-chars
M-c = capitalize-word
M-u = upcase-word
M-l = downcase-word
```

You'll be able to change these one day.

-----

Copyright (C) 2017 Jack Stratton


This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public Licenses along
with this program; if not, https://choosealicense.org has version 2 & 3
59 changes: 59 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
buildscript {
repositories {
mavenLocal()
mavenCentral()
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/"
}
maven {
name = "forge"
url = "https://files.minecraftforge.net/maven"
}
maven {
name = 'sponge'
url = 'https://repo.spongepowered.org/maven'
}
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
classpath 'org.spongepowered:mixingradle:0.4-SNAPSHOT'
}
}

apply plugin: 'net.minecraftforge.gradle.liteloader'
apply plugin: 'org.spongepowered.mixin'

version = modVersion
group = modGroup
archivesBaseName = modBaseName

minecraft {
version = project.mcVersion
mappings = project.mcpMappings
runDir = "run"
replaceIn 'src/main/java/net/phroa/readline/LiteModReadline.java'
replace '@NAME@', project.modBaseName
replace '@VERSION@', project.version
}

sourceSets.main {
refMap = 'mixin.readline.refmap.json'
}

mixin {
defaultObfuscationEnv notch
}

litemod {
json {
author = 'phroa'
mcversion = project.mcVersion
description = 'Readline keybindings'
mixinConfigs = ['mixin.readline.json']
}
}

jar {
from litemod.outputs
}
6 changes: 6 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
modVersion=1.0-SNAPSHOT
# http://maven.apache.org/guides/mini/guide-naming-conventions.html
modGroup=net.phroa
modBaseName=Readline
mcVersion=1.12
mcpMappings=snapshot_20170822
47 changes: 47 additions & 0 deletions src/main/java/net/phroa/readline/Binding.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package net.phroa.readline;

import net.minecraft.client.gui.GuiTextField;
import net.phroa.readline.func.Case;
import net.phroa.readline.func.Transpose;
import org.lwjgl.input.Keyboard;

import java.util.function.Consumer;

public enum Binding {
BEGINNING_OF_LINE("beginning-of-line", Keyboard.KEY_A, true, false, GuiTextField::setCursorPositionZero),
END_OF_LINE("end-of-line", Keyboard.KEY_E, true, false, GuiTextField::setCursorPositionEnd),

BACKWARD_CHAR("backward-char", Keyboard.KEY_B, true, false, field -> field.moveCursorBy(-1)),
FORWARD_CHAR("forward-char", Keyboard.KEY_F, true, false, field -> field.moveCursorBy(1)),

BACKWARD_WORD("backward-word", Keyboard.KEY_B, false, true, field -> field.setCursorPosition(field.getNthWordFromCursor(-1))),
FORWARD_WORD("forward-word", Keyboard.KEY_F, false, true, field -> field.setCursorPosition(field.getNthWordFromCursor(1))),

BACKWARD_DELETE_CHAR("backward-delete-char", Keyboard.KEY_H, true, false, field -> field.deleteFromCursor(-1)),

BACKWARD_DELETE_WORD("backward-delete-word", Keyboard.KEY_W, true, false, field -> field.deleteWords(-1)),

BACKWARD_DELETE_LINE("backward-delete-line", Keyboard.KEY_U, true, false, field -> field.deleteFromCursor(-field.getCursorPosition())),
FORWARD_DELETE_LINE("forward-delete-line", Keyboard.KEY_K, true, false, field -> field.deleteFromCursor(field.getMaxStringLength() - field.getCursorPosition())),

TRANSPOSE_CHARS("transpose-chars", Keyboard.KEY_T, true, false, Transpose.CHARS),
TRANSPOSE_WORDS("transpose-words", Keyboard.KEY_T, false, true, Transpose.WORDS),

CAPITALIZE_WORD("capitalize-word", Keyboard.KEY_C, false, true, Case.CAPITALIZE),
UPCASE_WORD("upcase-word", Keyboard.KEY_U, false, true, Case.UPCASE),
DOWNCASE_WORD("downcase-word", Keyboard.KEY_L, false, true, Case.DOWNCASE);

public final String name;
public final int key;
public final boolean control;
public final boolean meta;
public final Consumer<GuiTextField> action;

Binding(String name, int key, boolean control, boolean meta, Consumer<GuiTextField> action) {
this.name = name;
this.key = key;
this.control = control;
this.meta = meta;
this.action = action;
}
}
29 changes: 29 additions & 0 deletions src/main/java/net/phroa/readline/LiteModReadline.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package net.phroa.readline;

import com.mumfrey.liteloader.LiteMod;

import java.io.File;
import java.util.Arrays;

public class LiteModReadline implements LiteMod {
@Override
public void init(File configPath) {
}

@Override
public String getName() {
return "@NAME@";
}

@Override
public String getVersion() {
return "@VERSION@";
}

@Override
public void upgradeSettings(String version, File configPath, File oldConfigPath) {
}
}



71 changes: 71 additions & 0 deletions src/main/java/net/phroa/readline/func/Case.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package net.phroa.readline.func;

import net.minecraft.client.gui.GuiTextField;

import java.util.function.Consumer;

public final class Case {

public static final Consumer<GuiTextField> CAPITALIZE = field -> {
int pos = field.getCursorPosition();
String text = field.getText();
if (text.length() < 1)
return;
if (text.length() == 1) {
field.setText(text.toUpperCase());
return;
}

int start = text.lastIndexOf(' ', pos) + 1;
int end = text.indexOf(' ', pos);
if (start == end)
return;
if (start < 0)
start = 0;
if (end >= text.length() || end < 0) {
end = text.length() - 1;
}

char[] word = text.substring(start, end).toLowerCase().toCharArray();
word[0] = ("" + text.charAt(start)).toUpperCase().charAt(0);

char[] out = text.toCharArray();
System.arraycopy(word, 0, out, start, word.length);
field.setText(new String(out));
field.setCursorPosition(end + 1);
};

public static final Consumer<GuiTextField> UPCASE = field -> {
int pos = field.getCursorPosition();
String text = field.getText();
if (text.length() < 1)
return;

int start = Math.max(0, text.lastIndexOf(' ', pos));
int i = text.indexOf(' ', pos);
int end = Math.min(text.length(), i < 1 ? Integer.MAX_VALUE : i);
char[] word = text.substring(start, end).toUpperCase().toCharArray();

char[] out = text.toCharArray();
System.arraycopy(word, 0, out, start, word.length);
field.setText(new String(out));
field.setCursorPosition(end);
};

public static final Consumer<GuiTextField> DOWNCASE = field -> {
int pos = field.getCursorPosition();
String text = field.getText();
if (text.length() < 1)
return;

int start = Math.max(0, text.lastIndexOf(' ', pos));
int i = text.indexOf(' ', pos);
int end = Math.min(text.length(), i < 1 ? Integer.MAX_VALUE : i);
char[] word = text.substring(start, end).toLowerCase().toCharArray();

char[] out = text.toCharArray();
System.arraycopy(word, 0, out, start, word.length);
field.setText(new String(out));
field.setCursorPosition(end);
};
}
53 changes: 53 additions & 0 deletions src/main/java/net/phroa/readline/func/Transpose.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package net.phroa.readline.func;

import net.minecraft.client.gui.GuiTextField;

import java.util.function.Consumer;

public final class Transpose {
public static final Consumer<GuiTextField> CHARS = field -> {
int pos = field.getCursorPosition();
String text = field.getText();

if (pos < 1)
return;
if (pos >= text.length())
pos = text.length() - 1;

char[] chars = text.toCharArray();
char tmp = chars[pos];
chars[pos] = chars[pos - 1];
chars[pos - 1] = tmp;
field.setText(new String(chars));
field.setCursorPosition(pos + 1);
};

public static final Consumer<GuiTextField> WORDS = field -> {
int pos = field.getCursorPosition();
String text = field.getText();
int firstSpace = text.indexOf(' ');
String[] words = text.split("\\s+"); // yes, this'll eat duplicated spaces anywhere...

if (words.length < 2 || pos < firstSpace)
return;

int wordUnderCursor = -1;
int chars = 0;
for (String word : words) {
wordUnderCursor++;
chars += word.length() + 1;
if (pos < chars)
break;
}

if (wordUnderCursor < 1)
return;

String tmp = words[wordUnderCursor];
words[wordUnderCursor] = words[wordUnderCursor - 1];
words[wordUnderCursor - 1] = tmp;

field.setText(String.join(" ", words));
field.setCursorPosition(text.indexOf(' ', pos) + 1);
};
}
30 changes: 30 additions & 0 deletions src/main/java/net/phroa/readline/mixin/MixinGuiTextField.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package net.phroa.readline.mixin;

import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
import net.phroa.readline.Binding;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(GuiTextField.class)
public abstract class MixinGuiTextField {
@Inject(method = "textboxKeyTyped", at = @At(value = "HEAD"), cancellable = true)
private void textboxKeyTyped(char typedChar, int keyCode, CallbackInfoReturnable<Boolean> cir) {
for (Binding binding : Binding.values()) {
if (binding.key == keyCode) {
if (binding.control && !GuiScreen.isCtrlKeyDown()) {
continue;
}
if (binding.meta && !GuiScreen.isAltKeyDown()) {
continue;
}

binding.action.accept((GuiTextField) (Object) this);
cir.setReturnValue(true);
return;
}
}
}
}
9 changes: 9 additions & 0 deletions src/main/resources/mixin.readline.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"required": true,
"minVersion": "0.6.10",
"package": "net.phroa.readline.mixin",
"refmap": "mixin.readline.refmap.json",
"mixins": [
"MixinGuiTextField"
]
}

0 comments on commit 37d6777

Please sign in to comment.