Skip to content

Commit

Permalink
feat: adding auto complete for tags
Browse files Browse the repository at this point in the history
  • Loading branch information
sekwah41 committed Dec 1, 2023
1 parent 19d6d8f commit b68153d
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import com.sekwah.advancedportals.core.commands.subcommands.desti.CreateDestiSubCommand;
import com.sekwah.advancedportals.core.commands.subcommands.portal.*;
import com.sekwah.advancedportals.core.connector.commands.CommandRegister;
import com.sekwah.advancedportals.core.registry.TagRegistry;
import com.sekwah.advancedportals.core.serializeddata.DataStorage;
import com.sekwah.advancedportals.core.module.AdvancedPortalsModule;
import com.sekwah.advancedportals.core.repository.ConfigRepository;
import com.sekwah.advancedportals.core.tags.activation.DestiTag;
import com.sekwah.advancedportals.core.util.InfoLogger;
import com.sekwah.advancedportals.core.util.Lang;

Expand All @@ -35,6 +37,9 @@ public class AdvancedPortalsCore {
@Inject
private ConfigRepository configRepository;

@Inject
private TagRegistry tagRegistry;

public AdvancedPortalsCore(File dataStorageLoc, InfoLogger infoLogger) {
this.dataStorage = new DataStorage(dataStorageLoc);
this.infoLogger = infoLogger;
Expand All @@ -61,24 +66,26 @@ public void onEnable() {
Lang.loadLanguage(configRepository.getTranslation());

this.registerCommands();
this.registerTags();

this.infoLogger.log(Lang.translate("logger.pluginenable"));
}

private void registerTags() {
this.tagRegistry.registerTag(new DestiTag());
}

/**
*
*/
public void registerCommands() {
this.registerPortalCommand(commandRegister);
this.registerDestinationCommand(commandRegister);

// TODO run annotation grabbing shit
}

private void registerPortalCommand(CommandRegister commandRegister) {
this.portalCommand = new CommandWithSubCommands(this);

// TODO remove once annotations are done
this.portalCommand.registerSubCommand("version", new VersionSubCommand());
this.portalCommand.registerSubCommand("langupdate", new LangUpdateSubCommand());
this.portalCommand.registerSubCommand("reload", new ReloadSubCommand());
Expand All @@ -95,8 +102,6 @@ private void registerPortalCommand(CommandRegister commandRegister) {

private void registerDestinationCommand(CommandRegister commandRegister) {
this.destiCommand = new CommandWithSubCommands(this);

// TODO remove once annotations are done
this.destiCommand.registerSubCommand("create", new CreateDestiSubCommand());

commandRegister.registerCommand("destination", this.destiCommand);
Expand Down Expand Up @@ -126,4 +131,8 @@ public DataStorage getDataStorage() {
public AdvancedPortalsModule getModule() {
return this.module;
}

public TagRegistry getTagRegistry() {
return this.tagRegistry;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import com.sekwah.advancedportals.core.commands.SubCommand;
import com.sekwah.advancedportals.core.connector.containers.CommandSenderContainer;
import com.sekwah.advancedportals.core.connector.containers.PlayerContainer;
import com.sekwah.advancedportals.core.registry.TagRegistry;
import com.sekwah.advancedportals.core.serializeddata.DataTag;
import com.sekwah.advancedportals.core.permissions.PortalPermissions;
import com.sekwah.advancedportals.core.portal.AdvancedPortal;
import com.sekwah.advancedportals.core.services.PortalServices;
import com.sekwah.advancedportals.core.util.InfoLogger;
import com.sekwah.advancedportals.core.util.Lang;
import com.sekwah.advancedportals.core.util.TagReader;
import com.sekwah.advancedportals.core.warphandler.Tag;

import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -24,6 +26,9 @@ public class CreatePortalSubCommand implements SubCommand {
@Inject
InfoLogger infoLogger;

@Inject
TagRegistry tagRegistry;

@Override
public void onCommand(CommandSenderContainer sender, String[] args) {
if(args.length > 1) {
Expand Down Expand Up @@ -67,8 +72,63 @@ public boolean hasPermission(CommandSenderContainer sender) {

@Override
public List<String> onTabComplete(CommandSenderContainer sender, String[] args) {
// TODO add tab complete for tags
return null;

if(TagReader.isClosedString(args)) {
return List.of();
}



List<Tag> allTags = tagRegistry.getTags();
List<String> suggestions = new ArrayList<>();
if(args.length > 0) {
var lastArg = args[args.length - 1];
// Check if the split results in exactly 2 or if its 1 and ends with :
var split = lastArg.split(":");
if(split.length == 2 || (split.length == 1 && lastArg.endsWith(":"))) {
// Loop over tags in allTags and check if the first half of split is equal to the tag name or alias
for(Tag tag : allTags) {
if(tag instanceof Tag.AutoComplete autoComplete) {
var tagSuggestions = autoComplete.autoComplete(split.length == 2 ? split[1] : "");
if(tagSuggestions != null) {
// Loop over suggestions and add split[0] + ":" to the start
for (String tagSuggestion : tagSuggestions) {
suggestions.add(split[0] + ":" + tagSuggestion);
}
}
}
}
// This is returning right but something is going wrong with "desti:A" whenever anything is typed after :
return suggestions;
}
}

ArrayList<DataTag> portalTags = TagReader.getTagsFromArgs(args);

allTags.stream().filter(tag -> {
for (DataTag portalTag : portalTags) {
if(portalTag.NAME.equals(tag.getName())) {
return false;
}
// check the tag aliases
for (String alias : tag.getAliases()) {
if(portalTag.NAME.equals(alias)) {
return false;
}
}
}
return true;
}).forEach(tag -> {
suggestions.add(tag.getName());
suggestions.addAll(Arrays.stream(tag.getAliases()).toList());
});

// Loop over all suggestions and add : to the end
for (int i = 0; i < suggestions.size(); i++) {
suggestions.set(i, suggestions.get(i) + ":");
}

return suggestions;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
public class Destination implements TagTarget {

@Inject
TagRegistry<Destination> tagRegistry;
TagRegistry tagRegistry;

@SerializedName("l")
private PlayerLocation loc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.inject.*;
import com.sekwah.advancedportals.core.AdvancedPortalsCore;
import com.sekwah.advancedportals.core.registry.TagRegistry;
import com.sekwah.advancedportals.core.serializeddata.config.Config;
import com.sekwah.advancedportals.core.serializeddata.config.ConfigProvider;
import com.sekwah.advancedportals.core.serializeddata.DataStorage;
Expand Down Expand Up @@ -45,6 +46,7 @@ protected void configure() {

// Providers
bind(Config.class).toProvider(ConfigProvider.class);
bind(TagRegistry.class).asEagerSingleton();

// Delayed Bindings
for(DelayedBinding delayedBinding : delayedBindings) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
public class AdvancedPortal implements TagTarget {

@Inject
transient TagRegistry<AdvancedPortal> tagRegistry;
transient TagRegistry tagRegistry;

@SerializedName("max")
private WorldLocation maxLoc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,28 @@

import com.google.inject.Inject;
import com.sekwah.advancedportals.core.AdvancedPortalsCore;
import com.sekwah.advancedportals.core.portal.AdvancedPortal;
import com.sekwah.advancedportals.core.warphandler.Tag;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.*;

/**
* Allows a portal to register a tag and add a handler. If a plugin wants to add functionality
* to someone elses tag then they should use the events.
*
* @author sekwah41
*/
public class TagRegistry<T> {
public class TagRegistry {

@Inject
private AdvancedPortalsCore portalsCore;
AdvancedPortalsCore portalsCore;

/**
* List of tag names which should be in order alphabetically
*/
private ArrayList<String> tags = new ArrayList();
/**
* Description of tags for help commands (will try to use translation strings before rendering
* Possibly add a way to allow addons to supply extra info to the Lang class in the future.
*/
private Map<String, String> tagDesc = new HashMap();
private Map<String, Tag.Activation> activationHandlers = new HashMap();
private Map<String, Tag.Creation> creationHandlers = new HashMap();
private Map<String, Tag.TagStatus> statusHandlers = new HashMap();
private final ArrayList<String> literalTags = new ArrayList<>();

private final ArrayList<Tag> tags = new ArrayList<>();

private final Map<String, Tag.Activation> activationTags = new HashMap<>();
private final Map<String, Tag.Creation> creationTags = new HashMap<>();
private final Map<String, Tag.TagStatus> statusTags = new HashMap<>();

/**
* Portals to trigger when a portal is activated
Expand All @@ -41,7 +32,7 @@ public class TagRegistry<T> {
* @return
*/
public Tag.Activation getActivationHandler(String arg) {
return this.activationHandlers.get(arg);
return this.activationTags.get(arg);
}

/**
Expand All @@ -50,7 +41,7 @@ public Tag.Activation getActivationHandler(String arg) {
* @return
*/
public Tag.Creation getCreationHandler(String arg) {
return this.creationHandlers.get(arg);
return this.creationTags.get(arg);
}

/**
Expand All @@ -59,81 +50,57 @@ public Tag.Creation getCreationHandler(String arg) {
* @return
*/
public Tag.TagStatus getTagStatusHandler(String arg) {
return this.statusHandlers.get(arg);
return this.statusTags.get(arg);
}


/**
* It is reccomended that you use the taghandlers to add tag functionality. However
* if needed such as extra data for a tag then this is here.
*
* @param tag
* @return if the tag was registered
* File must extend
* @return if the tag has been registered or if it already exists.
*/
private boolean registerTag(String tag) {
if (tag.contains(" ")) {
this.portalsCore.getInfoLogger().logWarning("The tag '"
+ tag + "' is invalid as it contains spaces.");
return false;
}
if (this.tags.contains(tag)) {
this.portalsCore.getInfoLogger().logWarning("The tag "
+ tag + " has already been registered.");
return false;
}
public boolean registerTag(Tag tag) {

String tagName = tag.getName();

this.tags.add(tag);
Collections.sort(this.tags);
return true;
}

private boolean registerTag(String tag, String desc) {
if (registerTag(tag)) {
this.tagDesc.put(tag, desc);
return true;
// Check literal tags for clashes
if(this.literalTags.contains(tagName)) {
this.portalsCore.getInfoLogger().logWarning("A tag with the name " + tagName + " already exists.");
return false;
}
return false;
}

/**
* Returns a non referenced copy of the array list.
* @return
*/
public ArrayList<String> getTags() {
ArrayList<String> newArrayList = new ArrayList<>();
newArrayList.addAll(this.tags);
return newArrayList;
}

public boolean isTagRegistered(String tag){
return this.tagDesc.containsKey(tag);
}
for (String alias : tag.getAliases()) {
if(this.literalTags.contains(alias)) {
this.portalsCore.getInfoLogger().logWarning("A tag with the alias " + alias + " already exists.");
return false;
}
}

/**
* File must extend
* @return if the tag has been registered or if it already exists.
*/
public boolean registerTag(String tag, Tag tagHandler) {
// Add name and aliases to literalTags to check for clashes
this.literalTags.add(tagName);
Collections.addAll(this.literalTags, tag.getAliases());

if (tag == null) {
if (tagName == null) {
this.portalsCore.getInfoLogger().logWarning("A tag cannot be null.");
return false;
}

if (!this.registerTag(tag)) {
return false;
if (tag instanceof Tag.Activation tagActivation) {
this.activationTags.put(tagName, tagActivation);
}

if (tagHandler instanceof Tag.Activation tagActivation) {
this.activationHandlers.put(tag, tagActivation);
}
if (tagHandler instanceof Tag.TagStatus tagStatus) {
this.statusHandlers.put(tag, tagStatus);
if (tag instanceof Tag.TagStatus tagStatus) {
this.statusTags.put(tagName, tagStatus);
}
if (tagHandler instanceof Tag.Creation tagCreation) {
this.creationHandlers.put(tag, tagCreation);
if (tag instanceof Tag.Creation tagCreation) {
this.creationTags.put(tagName, tagCreation);
}
return true;
}


public List<Tag> getTags() {
// Make a copy of the list to prevent issues with modification

return this.tags;
}
}
Loading

0 comments on commit b68153d

Please sign in to comment.