Skip to content

Commit

Permalink
command: try to resolve command
Browse files Browse the repository at this point in the history
  • Loading branch information
Silvigarabis committed Jan 29, 2024
1 parent 977eeb6 commit 6ce9951
Show file tree
Hide file tree
Showing 8 changed files with 277 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package io.github.silvigarabis.thesudo;

public enum CommandSenderType {
CONSOLE, REMOTE_CONSOLE, PLAYER
CONSOLE, REMOTE_CONSOLE, PLAYER, UNKNOWN;
}
196 changes: 196 additions & 0 deletions src/main/java/io/github/silvigarabis/thesudo/CommandUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
package io.github.silvigarabis.thesudo;

import java.util.regex.*;
import java.util.*;

public class CommandUtil {
public static class ArgumentsParseResult {
public boolean hasError = false;
public ArgumentsParseErrorType errorType = ArgumentsParseErrorType.NONE;
public List<String> args = null;
public String rawCommand = null;
public int incompleteEscapeIndex = -1;
public int unterminatedQuoteStartIndex = -1;
public static enum ArgumentsParseErrorType {
NONE, UNTERMINATED_QUOTE, UNTERMINATED_SINGLE_QUOTE, INCOMPLETE_ESCAPE;
}
public ArgumentsParseResult(String rawCommand, List<String> args, int dquotedStartIndex, int squotedStartIndex, int escapeIndex){
if (escapeIndex != -1){
incompleteEscapeIndex = escapeIndex;
errorType = ArgumentsParseErrorType.INCOMPLETE_ESCAPE;
}
if (squotedStartIndex != -1){
unterminatedQuoteStartIndex = squotedStartIndex;
errorType = ArgumentsParseErrorType.UNTERMINATED_SINGLE_QUOTE;
} else if (dquotedStartIndex != -1){
unterminatedQuoteStartIndex = dquotedStartIndex;
errorType = ArgumentsParseErrorType.UNTERMINATED_QUOTE;
}
if (errorType != ArgumentsParseErrorType.NONE){
hasError = true;
}
this.args = Collections.unmodifiableList(args);
this.rawCommand = rawCommand;
}
}

/**
* 解析命令参数。
*/
public static ArgumentsParseResult parseArguments(String command){
List<String> args = new ArrayList<>();
List<String> chars = unicodeSplit(command);

Pattern matchSpace = Pattern.compile("\\s+");

int i = 0;
String dquotedChars = "";
String squotedChars = "";
int dquotedStartIndex = -1;
int squotedStartIndex = -1;
int escapeIndex = -1;
while (i < chars.size()){
while (i < chars.size() && matchSpace.matcher(chars.get(i)).matches()){
i += 1;
}
String carg = null;
boolean quoted = false;
boolean squoted = false;
boolean dquoted = false;
while ( // an complex condition: chars still available, and no quote or empty char
i < chars.size()
&& (
quoted || squoted || dquoted
|| (! matchSpace.matcher(chars.get(i)).matches())
)
){
boolean valid = false;
String character = chars.get(i);

if (quoted){
valid = true;
quoted = false;
escapeIndex = -1;
} else if (character.equals("\\") && !squoted){
quoted = true;
escapeIndex = i;
} else if (character.equals("\"") && !squoted){
dquoted = !dquoted;
dquotedStartIndex = dquoted ? i : -1;
} else if (character.equals("'") && !dquoted){
squoted = !squoted;
squotedStartIndex = squoted ? i : -1;
} else {
valid = true;
}

if (valid){
if (carg == null && !(squoted || dquoted)){
carg = "";
}

if (squoted){
squotedChars += character;
} else if (dquoted){
dquotedChars += character;
} else {
carg += chars.get(i);
}

if (!squoted && squotedChars.length() > 0){
carg += squotedChars;
squotedChars = "";
} else if (!dquoted && dquotedChars.length() > 0){
carg += dquotedChars;
dquotedChars = "";
}
}

i += 1;
}

if (carg != null){
args.add(carg);
}
}

return new ArgumentsParseResult(command, args, squotedStartIndex, dquotedStartIndex, escapeIndex);
}

/**
* 简单的解析命令参数,而不处理错误。
*/
public static List<String> parseArgumentsSimply(String command){
List<String> args = new ArrayList<>();
List<String> chars = unicodeSplit(command);

Pattern matchSpace = Pattern.compile("\\s+");

int i = 0;
while (i < chars.size()){
while (i < chars.size() && matchSpace.matcher(chars.get(i)).matches()){
i += 1;
}
String carg = null;
boolean qouted = false;
boolean sqouted = false;
boolean dqouted = false;
while ( // an complex condition: chars still available, and no quote or empty char
i < chars.size()
&& (
qouted || sqouted || dqouted
|| (! matchSpace.matcher(chars.get(i)).matches())
)
){
boolean valid = false;

if (qouted){
valid = true;
qouted = false;
} else if (chars.get(i).equals("\\") && !sqouted){
qouted = true;
} else if (chars.get(i).equals("\"") && !sqouted){
dqouted = !dqouted;
} else if (chars.get(i).equals("'") && !dqouted){
sqouted = !sqouted;
} else {
valid = true;
}

if (valid){
if (carg == null){
carg = "";
}
carg += chars.get(i);
}

if (carg == null && (qouted || sqouted || dqouted)){
carg = "";
}

i += 1;
}

if (carg != null){
args.add(carg);
}
}

return args;
}

public static List<String> unicodeSplit(String text){
List<String> unicodeChars = new ArrayList<>();

for (int i = 0; i < text.length(); i++){
int codePoint = text.codePointAt(i);
if (codePoint > 0xffff){
i += 1;
}

unicodeChars.add(Character.toString(codePoint));
}

return unicodeChars;
}
}
19 changes: 19 additions & 0 deletions src/main/java/io/github/silvigarabis/thesudo/Sudo.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
package io.github.silvigarabis.thesudo;

import org.bukkit.command.CommandSender;

import java.util.List;
import java.util.ArrayList;

public class Sudo {
public static void executeCommand(LastCommandData command){
CommandSender sender = command.sender;
List<String> args;
{
CommandUtil.ArgumentsParseResult arguments = CommandUtil.parseArguments(command.command);
if (arguments.hasError){
return;
}
args = arguments.args;
}
}
public static List<String> startTabComplete(LastCommandData command){
CommandSender sender = command.sender;
List<String> currentArgs = CommandUtil.parseArgumentsSimply(command.command);
return null;
}
}
21 changes: 18 additions & 3 deletions src/main/java/io/github/silvigarabis/thesudo/TheSudoPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.server.ServerCommandEvent;
import org.bukkit.event.server.RemoteServerCommandEvent;
import org.bukkit.event.server.TabCompleteEvent;
import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
Expand Down Expand Up @@ -58,22 +59,28 @@ public void onDisable(){

//we need raw command text
private LastCommandData lastCommand;
private LastCommandData lastTabCompleteRequestCommand;

@EventHandler(priority=EventPriority.MONITOR)
public void onPlayerCommandPreprocessing(PlayerCommandPreprocessEvent event){
public void onPlayerCommandPreprocessingEvent(PlayerCommandPreprocessEvent event){
lastCommand = new LastCommandData(event.getPlayer(), event.getMessage(), CommandSenderType.PLAYER);
}

@EventHandler(priority=EventPriority.MONITOR)
public void onServerCommand(ServerCommandEvent event){
public void onServerCommandEvent(ServerCommandEvent event){
lastCommand = new LastCommandData(event.getSender(), event.getCommand(), CommandSenderType.CONSOLE);
}

@EventHandler(priority=EventPriority.MONITOR)
public void onRemoteServerCommand(RemoteServerCommandEvent event){
public void onRemoteServerCommandEvent(RemoteServerCommandEvent event){
lastCommand = new LastCommandData(event.getSender(), event.getCommand(), CommandSenderType.REMOTE_CONSOLE);
}

@EventHandler(priority=EventPriority.MONITOR)
public void onTabCompleteEvent(TabCompleteEvent event){
lastTabCompleteRequestCommand = new LastCommandData(event.getSender(), event.getBuffer(), CommandSenderType.UNKNOWN);
}

@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args){
if (lastCommand.sender.equals(sender)){
Expand All @@ -84,4 +91,12 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
return true;
}

public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args){
if (lastCommand.sender.equals(sender)){
return Sudo.startTabComplete(lastTabCompleteRequestCommand);
} else {
sender.sendMessage("命令执行者不匹配,无法解析命令");
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.github.silvigarabis.thesudo.logcat;

public abstract class AbstractLogCatter implements LogCatter {
public abstract boolean hasNextLine();
public abstract String nextLine();
public void onNextLine(Consumer<String> nextLineCallback){
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.github.silvigarabis.thesudo.logcat;

import org.bukkit.entity.Player;

public class ConsoleLoggerLogCatter extends AbstractLogCatter {
public String nextLine(){
}
public boolean hasNextLine(){
}
public static ConsoleLoggerLogCatter getLogCatter(){
return new ConsoleLoggerLogCatter();
}
private ConsoleLoggerLogCatter(){
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.github.silvigarabis.thesudo.logcat;

public interface LogCatter {
boolean hasNextLine();
String nextLine();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.github.silvigarabis.thesudo.logcat;

import org.bukkit.entity.Player;

public class PlayerMessageLogCatter extends AbstractLogCatter {
public String nextLine(){
}
public boolean hasNextLine(){
}

private Player player;
public PlayerMessageLogCatter(Player player){
}
}

0 comments on commit 6ce9951

Please sign in to comment.