001/* 002 * This file is part of Baritone. 003 * 004 * Baritone is free software: you can redistribute it and/or modify 005 * it under the terms of the GNU Lesser General Public License as published by 006 * the Free Software Foundation, either version 3 of the License, or 007 * (at your option) any later version. 008 * 009 * Baritone is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public License 015 * along with Baritone. If not, see <https://www.gnu.org/licenses/>. 016 */ 017 018package baritone.api.command.helpers; 019 020import baritone.api.BaritoneAPI; 021import baritone.api.Settings; 022import baritone.api.command.argument.IArgConsumer; 023import baritone.api.command.manager.ICommandManager; 024import baritone.api.event.events.TabCompleteEvent; 025import baritone.api.utils.SettingsUtil; 026import net.minecraft.util.ResourceLocation; 027 028import java.util.Comparator; 029import java.util.List; 030import java.util.Locale; 031import java.util.function.Function; 032import java.util.function.Predicate; 033import java.util.stream.Stream; 034 035/** 036 * The {@link TabCompleteHelper} is a <b>single-use</b> object that helps you handle tab completion. It includes helper 037 * methods for appending and prepending streams, sorting, filtering by prefix, and so on. 038 * <p> 039 * The recommended way to use this class is: 040 * <ul> 041 * <li>Create a new instance with the empty constructor</li> 042 * <li>Use {@code append}, {@code prepend} or {@code add<something>} methods to add completions</li> 043 * <li>Sort using {@link #sort(Comparator)} or {@link #sortAlphabetically()} and then filter by prefix using 044 * {@link #filterPrefix(String)}</li> 045 * <li>Get the stream using {@link #stream()}</li> 046 * <li>Pass it up to whatever's calling your tab complete function (i.e. 047 * {@link ICommandManager#tabComplete(String)} or {@link IArgConsumer}#tabCompleteDatatype(IDatatype)})</li> 048 * </ul> 049 * <p> 050 * For advanced users: if you're intercepting {@link TabCompleteEvent}s directly, use {@link #build()} instead for an 051 * array. 052 */ 053public class TabCompleteHelper { 054 055 private Stream<String> stream; 056 057 public TabCompleteHelper(String[] base) { 058 stream = Stream.of(base); 059 } 060 061 public TabCompleteHelper(List<String> base) { 062 stream = base.stream(); 063 } 064 065 public TabCompleteHelper() { 066 stream = Stream.empty(); 067 } 068 069 /** 070 * Appends the specified stream to this {@link TabCompleteHelper} and returns it for chaining 071 * 072 * @param source The stream to append 073 * @return This {@link TabCompleteHelper} after having appended the stream 074 * @see #append(String...) 075 * @see #append(Class) 076 */ 077 public TabCompleteHelper append(Stream<String> source) { 078 stream = Stream.concat(stream, source); 079 return this; 080 } 081 082 /** 083 * Appends the specified strings to this {@link TabCompleteHelper} and returns it for chaining 084 * 085 * @param source The stream to append 086 * @return This {@link TabCompleteHelper} after having appended the strings 087 * @see #append(Stream) 088 * @see #append(Class) 089 */ 090 public TabCompleteHelper append(String... source) { 091 return append(Stream.of(source)); 092 } 093 094 /** 095 * Appends all values of the specified enum to this {@link TabCompleteHelper} and returns it for chaining 096 * 097 * @param num The enum to append the values of 098 * @return This {@link TabCompleteHelper} after having appended the values 099 * @see #append(Stream) 100 * @see #append(String...) 101 */ 102 public TabCompleteHelper append(Class<? extends Enum<?>> num) { 103 return append( 104 Stream.of(num.getEnumConstants()) 105 .map(Enum::name) 106 .map(String::toLowerCase) 107 ); 108 } 109 110 /** 111 * Prepends the specified stream to this {@link TabCompleteHelper} and returns it for chaining 112 * 113 * @param source The stream to prepend 114 * @return This {@link TabCompleteHelper} after having prepended the stream 115 * @see #prepend(String...) 116 * @see #prepend(Class) 117 */ 118 public TabCompleteHelper prepend(Stream<String> source) { 119 stream = Stream.concat(source, stream); 120 return this; 121 } 122 123 /** 124 * Prepends the specified strings to this {@link TabCompleteHelper} and returns it for chaining 125 * 126 * @param source The stream to prepend 127 * @return This {@link TabCompleteHelper} after having prepended the strings 128 * @see #prepend(Stream) 129 * @see #prepend(Class) 130 */ 131 public TabCompleteHelper prepend(String... source) { 132 return prepend(Stream.of(source)); 133 } 134 135 /** 136 * Prepends all values of the specified enum to this {@link TabCompleteHelper} and returns it for chaining 137 * 138 * @param num The enum to prepend the values of 139 * @return This {@link TabCompleteHelper} after having prepended the values 140 * @see #prepend(Stream) 141 * @see #prepend(String...) 142 */ 143 public TabCompleteHelper prepend(Class<? extends Enum<?>> num) { 144 return prepend( 145 Stream.of(num.getEnumConstants()) 146 .map(Enum::name) 147 .map(String::toLowerCase) 148 ); 149 } 150 151 /** 152 * Apply the specified {@code transform} to every element <b>currently</b> in this {@link TabCompleteHelper} and 153 * return this object for chaining 154 * 155 * @param transform The transform to apply 156 * @return This {@link TabCompleteHelper} 157 */ 158 public TabCompleteHelper map(Function<String, String> transform) { 159 stream = stream.map(transform); 160 return this; 161 } 162 163 /** 164 * Apply the specified {@code filter} to every element <b>currently</b> in this {@link TabCompleteHelper} and return 165 * this object for chaining 166 * 167 * @param filter The filter to apply 168 * @return This {@link TabCompleteHelper} 169 */ 170 public TabCompleteHelper filter(Predicate<String> filter) { 171 stream = stream.filter(filter); 172 return this; 173 } 174 175 /** 176 * Apply the specified {@code sort} to every element <b>currently</b> in this {@link TabCompleteHelper} and return 177 * this object for chaining 178 * 179 * @param comparator The comparator to use 180 * @return This {@link TabCompleteHelper} 181 */ 182 public TabCompleteHelper sort(Comparator<String> comparator) { 183 stream = stream.sorted(comparator); 184 return this; 185 } 186 187 /** 188 * Sort every element <b>currently</b> in this {@link TabCompleteHelper} alphabetically and return this object for 189 * chaining 190 * 191 * @return This {@link TabCompleteHelper} 192 */ 193 public TabCompleteHelper sortAlphabetically() { 194 return sort(String.CASE_INSENSITIVE_ORDER); 195 } 196 197 /** 198 * Filter out any element that doesn't start with {@code prefix} and return this object for chaining 199 * 200 * @param prefix The prefix to filter for 201 * @return This {@link TabCompleteHelper} 202 */ 203 public TabCompleteHelper filterPrefix(String prefix) { 204 return filter(x -> x.toLowerCase(Locale.US).startsWith(prefix.toLowerCase(Locale.US))); 205 } 206 207 /** 208 * Filter out any element that doesn't start with {@code prefix} and return this object for chaining 209 * <p> 210 * Assumes every element in this {@link TabCompleteHelper} is a {@link ResourceLocation} 211 * 212 * @param prefix The prefix to filter for 213 * @return This {@link TabCompleteHelper} 214 */ 215 public TabCompleteHelper filterPrefixNamespaced(String prefix) { 216 return filterPrefix(new ResourceLocation(prefix).toString()); 217 } 218 219 /** 220 * @return An array containing every element in this {@link TabCompleteHelper} 221 * @see #stream() 222 */ 223 public String[] build() { 224 return stream.toArray(String[]::new); 225 } 226 227 /** 228 * @return A stream containing every element in this {@link TabCompleteHelper} 229 * @see #build() 230 */ 231 public Stream<String> stream() { 232 return stream; 233 } 234 235 /** 236 * Appends every command in the specified {@link ICommandManager} to this {@link TabCompleteHelper} 237 * 238 * @param manager A command manager 239 * @return This {@link TabCompleteHelper} 240 */ 241 public TabCompleteHelper addCommands(ICommandManager manager) { 242 return append(manager.getRegistry().descendingStream() 243 .flatMap(command -> command.getNames().stream()) 244 .distinct() 245 ); 246 } 247 248 /** 249 * Appends every setting in the {@link Settings} to this {@link TabCompleteHelper} 250 * 251 * @return This {@link TabCompleteHelper} 252 */ 253 public TabCompleteHelper addSettings() { 254 return append( 255 BaritoneAPI.getSettings().allSettings.stream() 256 .filter(s -> !SettingsUtil.javaOnlySetting(s)) 257 .map(Settings.Setting::getName) 258 .sorted(String.CASE_INSENSITIVE_ORDER) 259 ); 260 } 261 262 /** 263 * Appends every modified setting in the {@link Settings} to this {@link TabCompleteHelper} 264 * 265 * @return This {@link TabCompleteHelper} 266 */ 267 public TabCompleteHelper addModifiedSettings() { 268 return append( 269 SettingsUtil.modifiedSettings(BaritoneAPI.getSettings()).stream() 270 .map(Settings.Setting::getName) 271 .sorted(String.CASE_INSENSITIVE_ORDER) 272 ); 273 } 274 275 /** 276 * Appends every {@link Boolean} setting in the {@link Settings} to this {@link TabCompleteHelper} 277 * 278 * @return This {@link TabCompleteHelper} 279 */ 280 public TabCompleteHelper addToggleableSettings() { 281 return append( 282 BaritoneAPI.getSettings().getAllValuesByType(Boolean.class).stream() 283 .map(Settings.Setting::getName) 284 .sorted(String.CASE_INSENSITIVE_ORDER) 285 ); 286 } 287}