From 22a401fe2e1157de0fa15a64276ceb4c80fe44b4 Mon Sep 17 00:00:00 2001 From: Vitasek Date: Tue, 6 Mar 2018 12:58:59 +0100 Subject: [PATCH 1/2] support for bash like prompt and groups command --- README.md | 12 +- gradle.properties | 2 +- .../hdfsshell/commands/ContextCommands.java | 52 ++- .../hdfsshell/ui/ShellBannerProvider.java | 17 +- .../hdfsshell/ui/ShellPromptProvider.java | 84 +++- .../ui/SimpleBashPromptInterpreter.java | 421 ++++++++++++++++++ 6 files changed, 572 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/avast/server/hdfsshell/ui/SimpleBashPromptInterpreter.java diff --git a/README.md b/README.md index 82b5ff3..5e158cd 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ There are 3 possible usecases: - you can easily add any other HDFS manipulation function - there is a command history persisting in history log (~/.hdfs-shell/hdfs-shell.log) - **support for relative directory + commands ```cd``` and ```pwd```** +- advanced commands like ```su```, ```groups```, ```whoami``` +- customizable shell prompt #### Disadvantages UI against direct calling hdfs dfs function: @@ -72,6 +74,7 @@ For our purposes we also integrated following commands: - ```cd```, ```pwd``` - ```su ``` - ***experimental*** - changes current active user - it won't probably work on secured HDFS (KERBEROS) - ```whoami``` - prints effective username +- ```groups >``` - eg.```groups hdfs``` prints groups for given users, same as ```hdfs groups my_user my_user2``` functionality - ```edit 'my file'``` - see the config below @@ -79,6 +82,13 @@ For our purposes we also integrated following commands: Since the version 1.0.4 the simple command 'edit' is available. The command gets selected file from HDFS to the local temporary directory and launches the editor. Once the editor saves the file (with a result code 0), the file is uploaded back into HDFS (target file is overwritten). By default the editor path is taken from ```$EDITOR``` environment variable. If ```$EDITOR``` is not set, ```vim``` (Linux, Mac) or ```notepad.exe``` (Windows) is used. +###### How to change command (shell) prompt +HDFS Shell supports customized bash-like prompt setting! +I implemented support for these switches listed in this [table](https://bash.cyberciti.biz/guide/Changing_bash_prompt) (include colors!, exclude ```\!, \#```). +You can also use this [online prompt generator](http://ezprompt.net/) to create prompt value of your wish. +To setup your favorite prompt simply add ```export HDFS_SHELL_PROMPT="value"``` to your .bashrc (or set env variable on Windows) and that's it. Restart HDFS Shell to apply change. +Default value is currently set to ```\e[36m\u@\h \e[0;39m\e[33m\w\e[0;39m\e[36m\\$ \e[37;0;39m```. + ### Running Daemon mode ![Image of HDFS-Shell](https://github.com/avast/hdfs-shell/blob/master/web/screenshot2.png) @@ -101,7 +111,7 @@ For developing, add to JVM args in your IDE launch config dialog: #### Known limitations & problems -- There is a problem with a parsing of commands containing a file or directory including a space - eg. it's not possible to create directory ```My dir``` using command ```mkdir "My dir"``` . This would be probably resolved with an upgrade to Spring Shell 2. +- There is a problem with a parsing of commands containing a file or directory including a space - eg. it's not possible to create directory ```My dir``` using command ```mkdir "My dir"``` . This should be probably resolved with an upgrade to Spring Shell 2. - It's not possible to remove root directory (```rm -R dir```) from root (```/```) directory. You have to use absolut path instead (```rm -R /dir```). It's caused by bug in Hadoop. See [HADOOP-15233](https://issues.apache.org/jira/browse/HADOOP-15233) for more details. Removing directory from another cwd is not affected. ### Contact diff --git a/gradle.properties b/gradle.properties index 173ae14..6db47c1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ springShellVersion = 1.2.0.RELEASE theGroup=com.avast.server -theVersion=1.0.6 \ No newline at end of file +theVersion=1.0.7 \ No newline at end of file diff --git a/src/main/java/com/avast/server/hdfsshell/commands/ContextCommands.java b/src/main/java/com/avast/server/hdfsshell/commands/ContextCommands.java index 3489be0..7811876 100644 --- a/src/main/java/com/avast/server/hdfsshell/commands/ContextCommands.java +++ b/src/main/java/com/avast/server/hdfsshell/commands/ContextCommands.java @@ -4,7 +4,12 @@ import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; +import org.apache.hadoop.hdfs.HdfsConfiguration; +import org.apache.hadoop.hdfs.NameNodeProxies; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.tools.GetUserMappingsProtocol; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.shell.core.CommandMarker; import org.springframework.shell.core.annotation.CliAvailabilityIndicator; import org.springframework.shell.core.annotation.CliCommand; @@ -12,12 +17,15 @@ import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; +import javax.annotation.PostConstruct; import java.io.IOException; import java.util.Arrays; +import java.util.stream.Collectors; @SuppressWarnings("SameParameterValue") @Component public class ContextCommands implements CommandMarker { + private static final Logger logger = LoggerFactory.getLogger(ContextCommands.class); private String currentDir; private Configuration configuration; @@ -26,13 +34,55 @@ public class ContextCommands implements CommandMarker { private boolean showResultCode = false; private boolean failOnError; + private GetUserMappingsProtocol userMappingsProtocol; - @CliAvailabilityIndicator({"pwd", "cd"}) + @PostConstruct + public void init() { + try { + final HdfsConfiguration conf = new HdfsConfiguration(); + userMappingsProtocol = NameNodeProxies.createProxy(conf, FileSystem.getDefaultUri(conf), + GetUserMappingsProtocol.class).getProxy(); + } catch (Exception e) { + logger.error("Failed to create proxy to get user groups", e); + } + } + + public String[] getGroupsForUser(String username) { + if (userMappingsProtocol != null) { + try { + return userMappingsProtocol.getGroupsForUser(username); + } catch (IOException e) { + return new String[0]; + } + } + return new String[0]; + } + + @CliAvailabilityIndicator({"pwd", "cd", "groups"}) public boolean isSimpleAvailable() { //always available return true; } + @CliCommand(value = "groups", help = "Get groups for user") + public String groups(@CliOption(key = {""}) String username) throws IOException { + if (StringUtils.isEmpty(username)) { + username = whoami(); + } + final StringBuilder result = new StringBuilder(); + Arrays.stream(username.split("\\W+")).forEach((user) -> { + if (!user.trim().isEmpty()) { + user = user.trim(); + if (result.length() > 0) { + result.append(System.lineSeparator()); + } + result.append(user).append(" : ").append(Arrays.stream(this.getGroupsForUser(user)).collect(Collectors.joining(" "))); + } + } + ); + return result.toString(); + } + @CliCommand(value = "set", help = "Set switch value") public String set(@CliOption(key = {""}, help = "showResultCodeON/showResultCodeOFF") String commandSwitch) { if (commandSwitch == null) { diff --git a/src/main/java/com/avast/server/hdfsshell/ui/ShellBannerProvider.java b/src/main/java/com/avast/server/hdfsshell/ui/ShellBannerProvider.java index 05ae06d..d5ef916 100644 --- a/src/main/java/com/avast/server/hdfsshell/ui/ShellBannerProvider.java +++ b/src/main/java/com/avast/server/hdfsshell/ui/ShellBannerProvider.java @@ -15,11 +15,15 @@ */ package com.avast.server.hdfsshell.ui; +import org.springframework.boot.ansi.AnsiColor; +import org.springframework.boot.ansi.AnsiOutput; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.shell.plugin.support.DefaultBannerProvider; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; + /** * @author Jarred Li */ @@ -27,6 +31,8 @@ @Order(Ordered.HIGHEST_PRECEDENCE) public class ShellBannerProvider extends DefaultBannerProvider { + private SimpleBashPromptInterpreter bashPromptInterpreter; + public String getBanner() { return "";//we are using Spring Boot for that } @@ -36,13 +42,18 @@ public String getVersion() { return ShellBannerProvider.versionInfo(); } + @PostConstruct + public void init() { + bashPromptInterpreter = new SimpleBashPromptInterpreter.Builder("HDFS-shell CLI \\h").setAddResetEnd(false).build(); + } + public String getWelcomeMessage() { - return "Welcome to HDFS-shell CLI"; + return AnsiOutput.toString(AnsiColor.BRIGHT_GREEN, "Welcome to HDFS-shell CLI ", AnsiColor.DEFAULT); } - + @Override public String getProviderName() { - return "HDFS-shell CLI"; + return bashPromptInterpreter.interpret(); } public static String versionInfo() { diff --git a/src/main/java/com/avast/server/hdfsshell/ui/ShellPromptProvider.java b/src/main/java/com/avast/server/hdfsshell/ui/ShellPromptProvider.java index c2fa397..6b43cda 100644 --- a/src/main/java/com/avast/server/hdfsshell/ui/ShellPromptProvider.java +++ b/src/main/java/com/avast/server/hdfsshell/ui/ShellPromptProvider.java @@ -1,12 +1,12 @@ /* * Copyright 2011-2012 the original author or authors. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,42 +16,106 @@ package com.avast.server.hdfsshell.ui; import com.avast.server.hdfsshell.commands.ContextCommands; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.ansi.AnsiColor; -import org.springframework.boot.ansi.AnsiOutput; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.shell.core.AbstractShell; import org.springframework.shell.plugin.support.DefaultPromptProvider; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; +import java.io.IOException; +import java.util.Arrays; +import java.util.Locale; +import java.util.Set; +import java.util.stream.Collectors; + /** - * @author Jarred Li + * @author Vitasek L. */ @Component @Order(Ordered.HIGHEST_PRECEDENCE) public class ShellPromptProvider extends DefaultPromptProvider { + private static final Logger logger = LoggerFactory.getLogger(ShellPromptProvider.class); + + private static final String DEFAULT_PROMPT = "\033[36m\\u@\\h \033[0;39m\033[33m\\w\033[0;39m\033[36m\\$ \033[37;0;39m"; final ContextCommands contextCommands; + private SimpleBashPromptInterpreter simpleBashPromptInterpreter; + @Autowired public ShellPromptProvider(ContextCommands contextCommands) { this.contextCommands = contextCommands; } + @PostConstruct + public void init() { + setPs1(System.getenv().getOrDefault("HDFS_SHELL_PROMPT", DEFAULT_PROMPT)); + } + + public void setPs1(String ps1) { + simpleBashPromptInterpreter = new SimpleBashPromptInterpreter.Builder(ps1). + setAppName(() -> "hdfs-shell").setAppVersion(ShellBannerProvider::versionInfo). + setLocale(Locale.ENGLISH). + setUsername(this::getWhoami). + setIsRoot(this::isRootPrompt). + setCwdAbsolut(contextCommands::getCurrentDir). + setCwdShort(this::getShortCwd). + build(); + } + + private boolean isRootPrompt() { + final String whoami = this.getWhoami(); + final String[] groupsForUser = contextCommands.getGroupsForUser(whoami); + if (groupsForUser.length == 0) { //make guess + return "root".equals(whoami) || "hdfs".equals(whoami); + } + final String[] groups = contextCommands.getConfiguration().get("dfs.permissions.superusergroup", "supergroup").split(","); + final Set adminGroups = Arrays.stream(groups).map(String::trim).collect(Collectors.toSet()); + adminGroups.add("Administrators");//for Windows + adminGroups.add("hdfs");//special cases + adminGroups.add("root"); + return Arrays.stream(groupsForUser).anyMatch(adminGroups::contains); + } @Override public String getPrompt() { - return AbstractShell.shellPrompt = - AnsiOutput.toString(AnsiColor.CYAN, "hdfs-shell ") + - AnsiOutput.toString(AnsiColor.YELLOW, contextCommands.getCurrentDir()) + - AnsiOutput.toString(AnsiColor.CYAN, " >", AnsiColor.WHITE); + return AbstractShell.shellPrompt = simpleBashPromptInterpreter.interpret(); + } + + private String getWhoami() { + try { + return contextCommands.whoami(); + } catch (IOException e) { + logger.error("Failed to get active user", e); + return "hdfs-shell"; + } } +// private String defaultPrompt() { +// return AnsiOutput.toString(AnsiColor.CYAN, "hdfs-shell ") + +// AnsiOutput.toString(AnsiColor.YELLOW, contextCommands.getCurrentDir()) + +// AnsiOutput.toString(AnsiColor.CYAN, " >", AnsiColor.WHITE); +// } + @Override public String getProviderName() { return "Hdfs-shell prompt"; } + private String getShortCwd() { + String currentDir = contextCommands.getCurrentDir(); + if (currentDir.startsWith("/user/")) { + final String userHome = "/user/" + this.getWhoami();//call getWhoami later + if (currentDir.startsWith(userHome)) { + currentDir = StringUtils.replaceOnce(currentDir, userHome, "~"); + } + } + return currentDir; + } } diff --git a/src/main/java/com/avast/server/hdfsshell/ui/SimpleBashPromptInterpreter.java b/src/main/java/com/avast/server/hdfsshell/ui/SimpleBashPromptInterpreter.java new file mode 100644 index 0000000..903745b --- /dev/null +++ b/src/main/java/com/avast/server/hdfsshell/ui/SimpleBashPromptInterpreter.java @@ -0,0 +1,421 @@ +package com.avast.server.hdfsshell.ui; + +import org.springframework.util.StringUtils; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Locale; +import java.util.Map; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Naive bash prompt interpreter into Java. + * The implementation is thread safe. + *
+ * Sequence	Description
+ * \a	An ASCII bell character (07)
+ * \d	The date in "Weekday Month Date" format (e.g., "Tue May 26")
+ * \e	An ASCII escape character (033)
+ * \h	The hostname up to the first .
+ * \H	The hostname (FQDN)
+ * \j	The number of jobs currently managed by the shell
+ * \l	The basename of the shell’s terminal device name
+ * \n	Newline
+ * \r	Carriage return
+ * \s	The name of the shell, the basename of $0 (the portion following the final slash)
+ * \t	The current time in 24-hour HH:MM:SS format
+ * \T	The current time in 12-hour HH:MM:SS format
+ * \@	The current time in 12-hour am/pm format
+ * \A	The current time in 24-hour HH:MM format
+ * \\u	The username of the current user
+ * \v	The version of bash (e.g., 2.00)
+ * \V 	The release of bash, version + patch level (e.g., 2.00.0)
+ * \w	The current working directory, with $HOME abbreviated with a tilde  (note: tilde is not supported yet in HDFS)
+ * \W	The basename of the current working directory, with $HOME abbreviated with a tilde (note: tilde is not supported yet in HDFS)
+ * \!	The history number of this command
+ * \#	The command number of this command
+ * \$	If the effective UID is 0, a #, otherwise a $
+ * \nnn	The character corresponding to the octal number nnn
+ * \\	A backslash
+ * \[	Begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
+ * \]	End a sequence of non-printing characters
+ * + * + * @author Vitasek L. + */ + +public class SimpleBashPromptInterpreter { + + private final DateTimeFormatter PATTERN_24_HH_mm; + private final DateTimeFormatter PATTERN_24_HH_mm_ss; + private final DateTimeFormatter PATTERN_12_hh_mm; + private final DateTimeFormatter PATTERN_12_hh_mm_ss; + private final DateTimeFormatter WEEKDAY_MONTH_DATE; + + private final static Pattern DYNAMIC_ENCODING = Pattern.compile("\\\\[u#!HhdtT@AWw$]"); + + private final String promptPS1; + private boolean addResetEnd; + private boolean useCacheForNetInfo = true; + + private final static String RESET_POSTFIX = ";39m"; + + private String reset = "\033[37;0" + RESET_POSTFIX; + + + private Supplier username; + private Supplier commandNum; + private Supplier cwdAbsolut; + private Supplier cwdShort; + private Supplier historyNumber; + private Supplier isRoot; + + //for cache reasons in default methods + private String inetAddress = null; + private String fqdn = null; + + private Supplier fqdnSupplier = this::getFQDN; + private Supplier inetAddressSupplier = this::getInetAddress; + + private SimpleBashPromptInterpreter(final String promptPS1, final Supplier appName, final Supplier appVersion, Locale locale, final boolean addResetEnd) { + this.addResetEnd = addResetEnd; + this.promptPS1 = replaceStaticProperties(promptPS1, appName, appVersion); + if (locale == null) { + locale = Locale.getDefault(); + } + PATTERN_24_HH_mm = DateTimeFormatter.ofPattern("HH:mm", locale); + PATTERN_24_HH_mm_ss = DateTimeFormatter.ofPattern("HH:mm:ss", locale); + PATTERN_12_hh_mm = DateTimeFormatter.ofPattern("h:mm a", locale); + PATTERN_12_hh_mm_ss = DateTimeFormatter.ofPattern("h:mm:ss a", locale); + WEEKDAY_MONTH_DATE = DateTimeFormatter.ofPattern("E MMM dd", locale); + } + + public String interpret() { + + LocalDateTime now = null;//we don't want to call get time when not needed + final Matcher matcher = DYNAMIC_ENCODING.matcher(promptPS1); + final StringBuffer resultString = new StringBuffer(); + while (matcher.find()) { + final String group = matcher.group(); + switch (group) { + case "\\$": + appendReplacement(matcher, resultString, isRoot == null ? "$" : isRoot.get() ? "#" : "$"); + break; + case "\\u": + appendReplacement(matcher, resultString, username); + break; + case "\\w": + appendReplacement(matcher, resultString, cwdAbsolut); + break; + case "\\W": + appendReplacement(matcher, resultString, cwdShort); + break; + case "\\#": + appendReplacement(matcher, resultString, commandNum); + break; + case "\\!": + appendReplacement(matcher, resultString, historyNumber); + break; + case "\\h": + appendReplacement(matcher, resultString, getComputerName()); + break; + case "\\H": + appendReplacement(matcher, resultString, fqdnSupplier); + break; + case "\\d": + now = getNow(now); + appendReplacement(matcher, resultString, now.format(WEEKDAY_MONTH_DATE)); + break; + case "\\t": + now = getNow(now); + appendReplacement(matcher, resultString, now.format(PATTERN_24_HH_mm_ss)); + break; + case "\\T": + now = getNow(now); + appendReplacement(matcher, resultString, now.format(PATTERN_12_hh_mm_ss)); + break; + case "\\@": + now = getNow(now); + appendReplacement(matcher, resultString, now.format(PATTERN_12_hh_mm)); + break; + case "\\A": + now = getNow(now); + appendReplacement(matcher, resultString, now.format(PATTERN_24_HH_mm)); + break; + } + } + matcher.appendTail(resultString); + + final String newPrompt = resultString.toString().replace("\\\\", "\\");//do it as last + + return appendReset(newPrompt); + } + + private String appendReset(String newPrompt) { + return newPrompt + ((addResetEnd && !newPrompt.endsWith(RESET_POSTFIX)) ? getReset() : ""); + } + + private LocalDateTime getNow(LocalDateTime now) { + if (now == null) { + now = LocalDateTime.now(); + } + return now; + } + + + public String getPromptPS1() { + return promptPS1; + } + + void setAddResetEnd(boolean addResetEnd) { + this.addResetEnd = addResetEnd; + } + + String getReset() { + return reset; + } + + void setReset(String reset) { + this.reset = reset; + } + + + void setFqdnSupplier(Supplier fqdnSupplier) { + this.fqdnSupplier = fqdnSupplier; + } + + void setInetAddressSupplier(Supplier inetAddressSupplier) { + this.inetAddressSupplier = inetAddressSupplier; + } + + boolean isUseCacheForNetInfo() { + return useCacheForNetInfo; + } + + void setUseCacheForNetInfo(boolean useCacheForNetInfo) { + this.useCacheForNetInfo = useCacheForNetInfo; + } + + + private String replaceStaticProperties(final String promptPS1, Supplier appName, Supplier appVersion) { + final String appVersionValue = appVersion == null ? "" : appVersion.get(); + return promptPS1. + replace("\\[", ""). + replace("\\]", ""). + replace("\\\\$", "\\$"). //some generators produce \\$ , we convert it to \$ + replace("\\e", "\033"). + replace("\\s", appName == null ? "" : appName.get()). + replace("\\a", "\u0007"). + replace("\\V", appVersionValue). + replace("\\v", appVersionValue). + replace("\\n", "\n"). + replace("\\r", "\r"); + } + + private void appendReplacement(Matcher matcher, StringBuffer resultString, Supplier supplier) { + if (supplier == null) { + supplier = () -> ""; + } + appendReplacement(matcher, resultString, supplier.get()); + } + + private void appendReplacement(Matcher matcher, StringBuffer resultString, String value) { + if (StringUtils.isEmpty(value)) { + matcher.appendReplacement(resultString, ""); + } else { + matcher.appendReplacement(resultString, Matcher.quoteReplacement(value)); + } + } + + private String getFQDN() { + if (useCacheForNetInfo && fqdn != null) { + return fqdn; + } + try { + return fqdn = InetAddress.getLocalHost().getCanonicalHostName(); + } catch (UnknownHostException ex) { + return "unknownHost"; + } + } + + + private String getComputerName() { + Map env = System.getenv(); + if (env.containsKey("COMPUTERNAME")) { + return env.get("COMPUTERNAME"); + } else { + return env.getOrDefault("HOSTNAME", inetAddressSupplier == null ? "" : inetAddressSupplier.get()); + } + } + + private String getInetAddress() { + if (useCacheForNetInfo && inetAddress != null) { + return inetAddress; + } + try { + return inetAddress = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException ex) { + return "unknownHost"; + } + } + + + @SuppressWarnings("unused") + public static class Builder { + + private String promptPS1; + private Locale locale = Locale.ENGLISH; + + private boolean addResetEnd = true; + private boolean useCacheForNetInfo = true; + + private Supplier fqdnSupplier; + private Supplier inetAddressSupplier; + private Supplier username; + private Supplier commandNum; + private Supplier cwdAbsolut; + private Supplier cwdShort; + private Supplier historyNumber; + private Supplier isRoot; + + private Supplier appName; + private Supplier appVersion; + private String reset; + + + public Builder(final String promptPS1) { + this.promptPS1 = promptPS1; + } + + + public Builder setLocale(Locale locale) { + this.locale = locale; + return this; + } + + + public Builder setPromptPS1(String promptPS1) { + this.promptPS1 = promptPS1; + return this; + } + + public Builder setFqdnSupplier(Supplier fqdnSupplier) { + this.fqdnSupplier = fqdnSupplier; + return this; + } + + public Builder setInetAddressSupplier(Supplier inetAddressSupplier) { + this.inetAddressSupplier = inetAddressSupplier; + return this; + } + + public Builder setUsername(Supplier username) { + this.username = username; + return this; + } + + public Builder setCommandNum(Supplier commandNum) { + this.commandNum = commandNum; + return this; + } + + public Builder setCwdAbsolut(Supplier cwdAbsolut) { + this.cwdAbsolut = cwdAbsolut; + return this; + } + + public Builder setCwdShort(Supplier cwdShort) { + this.cwdShort = cwdShort; + return this; + } + + public Builder setHistoryNumber(Supplier historyNumber) { + this.historyNumber = historyNumber; + return this; + } + + public Builder setIsRoot(Supplier isRoot) { + this.isRoot = isRoot; + return this; + } + + public Builder setAppName(Supplier appName) { + this.appName = appName; + return this; + } + + public Builder setAppVersion(Supplier appVersion) { + this.appVersion = appVersion; + return this; + } + + public Builder setAddResetEnd(boolean addResetEnd) { + this.addResetEnd = addResetEnd; + return this; + } + + public Builder setReset(String reset) { + this.reset = reset; + return this; + } + + public SimpleBashPromptInterpreter build() { + final SimpleBashPromptInterpreter interpreter = new SimpleBashPromptInterpreter(promptPS1, appName, appVersion, locale, addResetEnd); + interpreter.setUsername(username); + + interpreter.setIsRoot(isRoot); + interpreter.setCommandNum(commandNum); + interpreter.setUseCacheForNetInfo(useCacheForNetInfo); + if (fqdnSupplier != null) { + interpreter.setFqdnSupplier(fqdnSupplier); + } + if (historyNumber != null) { + interpreter.setHistoryNumber(historyNumber); + } + if (inetAddressSupplier != null) { + interpreter.setInetAddressSupplier(inetAddressSupplier); + } + if (cwdAbsolut != null) { + interpreter.setCwdAbsolut(cwdAbsolut); + } + interpreter.setCwdShort(cwdShort); + interpreter.setAddResetEnd(addResetEnd); + if (reset != null) { + interpreter.setReset(reset); + } + + + return interpreter; + } + + } + + + void setUsername(Supplier username) { + this.username = username; + } + + void setCommandNum(Supplier commandNum) { + this.commandNum = commandNum; + } + + void setCwdAbsolut(Supplier cwdAbsolut) { + this.cwdAbsolut = cwdAbsolut; + } + + void setCwdShort(Supplier cwdShort) { + this.cwdShort = cwdShort; + } + + void setHistoryNumber(Supplier historyNumber) { + this.historyNumber = historyNumber; + } + + void setIsRoot(Supplier isRoot) { + this.isRoot = isRoot; + } +} From 7345434e7a7eb1ba384f7125ccda3cd6d019fb54 Mon Sep 17 00:00:00 2001 From: Vitasek Date: Tue, 6 Mar 2018 14:02:26 +0100 Subject: [PATCH 2/2] banner update --- src/main/resources/banner.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt index e94a1eb..5bdcef7 100644 --- a/src/main/resources/banner.txt +++ b/src/main/resources/banner.txt @@ -4,4 +4,4 @@ | _ || | | )| _) `\__ \(______)`\__ \ | _ || _)_ | | _ | | _ | | | || |_) || | ( )_) | ( )_) || | | || (_( )| |_( )| |_( ) (_) (_)(____/'(_) `\____) `\____)(_) (_)(____/'(____/'(____/' - by Vity (2017) + by Vity (2017-2018)