code: public Object evaluate(Input input) {
  		if (noInput(input)) {
  			return NO_INPUT;
  		}
  
  		String line = input.words().stream().collect(Collectors.joining(" ")).trim();
  		String command = findLongestCommand(line);
  
  		List<String> words = input.words();
  		if (command != null) {
  			MethodTarget methodTarget = methodTargets.get(command);
  			Availability availability = methodTarget.getAvailability();
  			if (availability.isAvailable()) {
  				List<String> wordsForArgs = wordsForArguments(command, words);
  				Method method = methodTarget.getMethod();
  
  				Thread commandThread = Thread.currentThread();
  				Object sh = Signals.register("INT", () -> commandThread.interrupt());
  				try {
  					Object[] args = resolveArgs(method, wordsForArgs);
  					validateArgs(args, methodTarget);
  
  					return ReflectionUtils.invokeMethod(method, methodTarget.getBean(), args);
  				}
  				catch (UndeclaredThrowableException e) {
  					if (e.getCause() instanceof InterruptedException || e.getCause() instanceof ClosedByInterruptException) {
  						Thread.interrupted(); // to reset interrupted flag
  					}
  					return e.getCause();
  				}
  				catch (Exception e) {
  					return e;
  				}
  				finally {
  					Signals.unregister("INT", sh);
  				}
  			}
  			else {
  				return new CommandNotCurrentlyAvailable(command, availability);
  			}
  		}
  		else {
  			return new CommandNotFound(words);
  		}
  	}
docs: Evaluate a single "line" of input from the user by trying to map words to a command and
  arguments.
  
  <p>
  This method does not throw exceptions, it catches them and returns them as a regular
  result
  </p>