X-Git-Url: https://code.wpia.club/?a=blobdiff_plain;f=src%2Fclub%2Fwpia%2Fgigi%2Foutput%2Ftemplate%2FSprintfCommand.java;h=7a525ab77cfaa69227cfe64ecb4ba50fb52de00d;hb=372ce0e8485d3a3d29f43c894c70383e9f55883b;hp=6b40c8fd0ab49bd88b6f4c6f4dba4aca934b4dfc;hpb=bccd4cc0dba0f89aa045b113bac46eb8cc1dab4e;p=gigi.git diff --git a/src/club/wpia/gigi/output/template/SprintfCommand.java b/src/club/wpia/gigi/output/template/SprintfCommand.java index 6b40c8fd..7a525ab7 100644 --- a/src/club/wpia/gigi/output/template/SprintfCommand.java +++ b/src/club/wpia/gigi/output/template/SprintfCommand.java @@ -10,6 +10,7 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import club.wpia.gigi.Gigi; import club.wpia.gigi.localisation.Language; import club.wpia.gigi.util.HTMLEncoder; @@ -18,81 +19,113 @@ import club.wpia.gigi.util.HTMLEncoder; */ public final class SprintfCommand implements Translatable { - private final String text; + /** + * The pattern to fill. Containing placeholders of pattern + * {@link #placeholder}. This is the string that will be translated. + */ + private final String pattern; - private final String[] store; + /** + * A regex that matches the replacement patterns like "{0}" or "{1}". + */ + private static final Pattern placeholder = Pattern.compile("\\{([0-9]+)\\}"); + + /** + * The values describing what to put into the {@link #placeholder}s of + * {@link #pattern}. + */ + private final String[] replacements; /** - * Creates a new SprintfCommand based on its pre-parsed contents. + * Regex for detecting processing instructions in a in-template + * SprintfCommand. + */ + private static final Pattern processingInstruction = Pattern.compile("(?:(\\$!?\\{[a-zA-Z0-9_-]+)\\})|(?:(!'[^{}'\\$]*)')|(?:(!\\([^{})\\$]*)\\))"); + + /** + * Creates a new SprintfCommand based on its pre-parsed contents. This is + * the variant that the data is stored internally in this class. So the + * pattern has numbers as placeholders and the replacement list + * contains the instructions on what to put in there (without closing + * brackets, etc.). * - * @param text + * @param pattern * a string with {0},{1},.. as placeholders. - * @param store - * the data to put into the placeholders: ${var}, $!{var}, - * !'plain'. + * @param replacements + * instructions for what data to put into the placeholders: + * ${var, $!{var, !'plain, + * !(/link. */ - public SprintfCommand(String text, List store) { - this.text = text; - this.store = store.toArray(new String[store.size()]); + public SprintfCommand(String pattern, List replacements) { + this.pattern = pattern; + this.replacements = replacements.toArray(new String[replacements.size()]); } - private static final String VARIABLE = "\\$!?\\{[a-zA-Z0-9_-]+\\}"; - - private static final Pattern processingInstruction = Pattern.compile("(" + VARIABLE + ")|(!'[^{}'\\$]*)'"); - /** - * Creates a new SprintfCommand that is parsed as from template source. + * Creates a new SprintfCommand that is parsed as from template source. This + * version is internally used to create {@link SprintfCommand}s from the + * literals specified in {@link Template}s. * * @param content * the part from the template that is to be parsed. */ protected SprintfCommand(String content) { - StringBuffer raw = new StringBuffer(); - List var = new LinkedList(); + StringBuffer pattern = new StringBuffer(); + List replacements = new LinkedList(); int counter = 0; Matcher m = processingInstruction.matcher(content); int last = 0; while (m.find()) { - raw.append(content.substring(last, m.start())); + pattern.append(content.substring(last, m.start())); String group = null; if ((group = m.group(1)) != null) { - var.add(group); + replacements.add(group); } else if ((group = m.group(2)) != null) { - var.add(group); + replacements.add(group); + } else if ((group = m.group(3)) != null) { + replacements.add(group); } else { throw new Error("Regex is broken??"); } last = m.end(); - raw.append("{" + (counter++) + "}"); + pattern.append("{" + (counter++) + "}"); } - raw.append(content.substring(last)); - text = raw.toString(); - store = var.toArray(new String[var.size()]); + pattern.append(content.substring(last)); + this.pattern = pattern.toString(); + this.replacements = replacements.toArray(new String[replacements.size()]); } - private static final Pattern replacant = Pattern.compile("\\{([0-9]+)\\}"); - @Override - public void output(PrintWriter out, Language l, Map vars) { - String parts = l.getTranslation(text); - Matcher m = replacant.matcher(parts); + public void output(PrintWriter out, Language l, Map externalVariables) { + String parts = l.getTranslation(pattern); + Matcher m = placeholder.matcher(parts); int pos = 0; while (m.find()) { - out.print(escape(vars, parts.substring(pos, m.start()))); - String var = store[Integer.parseInt(m.group(1))]; - if (var.startsWith("$!")) { - Template.outputVar(out, l, vars, var.substring(3, var.length() - 1), true); - } else if (var.startsWith("!'")) { - out.print(var.substring(2)); - } else if (var.startsWith("$")) { - Template.outputVar(out, l, vars, var.substring(2, var.length() - 1), false); + out.print(escape(externalVariables, parts.substring(pos, m.start()))); + String replacement = replacements[Integer.parseInt(m.group(1))]; + if (replacement.startsWith("$!")) { + Template.outputVar(out, l, externalVariables, replacement.substring(3), true); + } else if (replacement.startsWith("!'")) { + out.print(replacement.substring(2)); + } else if (replacement.startsWith("!(")) { + String host = (String) externalVariables.get(Gigi.LINK_HOST); + if (host == null) { + throw new Error("Unconfigured link-host while interpreting link-syntax."); + } + if (replacement.charAt(2) != '/') { + throw new Error("Need an absolute link for the link service."); + } + String link = "//" + host + replacement.substring(2); + out.print(""); + } else if (replacement.startsWith("$")) { + Template.outputVar(out, l, externalVariables, replacement.substring(2), false); } else { throw new Error("Processing error in template."); } pos = m.end(); } - out.print(escape(vars, parts.substring(pos))); + out.print(escape(externalVariables, parts.substring(pos))); } private String escape(Map vars, String target) { @@ -104,7 +137,7 @@ public final class SprintfCommand implements Translatable { @Override public void addTranslations(Collection s) { - s.add(text); + s.add(pattern); } /** @@ -115,7 +148,7 @@ public final class SprintfCommand implements Translatable { * the message (to be translated) with {0},{1},... * as placeholders. * @param vars - * the variables to put into the placeholders. + * the contents of the variables to put into the placeholders. * @return the constructed {@link Outputable}. */ public static Outputable createSimple(String msg, Object... vars) { @@ -123,7 +156,7 @@ public final class SprintfCommand implements Translatable { String[] store = new String[vars.length]; for (int i = 0; i < vars.length; i++) { scope.put("autoVar" + i, vars[i]); - store[i] = "${autoVar" + i + "}"; + store[i] = "${autoVar" + i; } return new Scope(new SprintfCommand(msg, Arrays.asList(store)), scope); }