All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.vertx.ext.shell.system.impl.InternalCommandManager Maven / Gradle / Ivy

There is a newer version: 5.0.0.CR1
Show newest version
/*
 * Copyright 2015 Red Hat, Inc.
 *
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  and Apache License v2.0 which accompanies this distribution.
 *
 *  The Eclipse Public License is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  The Apache License v2.0 is available at
 *  http://www.opensource.org/licenses/apache2.0.php
 *
 *  You may elect to redistribute this code under either of these licenses.
 *
 *
 * Copyright (c) 2015 The original author or authors
 * ------------------------------------------------------
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Apache License v2.0 which accompanies this distribution.
 *
 *     The Eclipse Public License is available at
 *     http://www.eclipse.org/legal/epl-v10.html
 *
 *     The Apache License v2.0 is available at
 *     http://www.opensource.org/licenses/apache2.0.php
 *
 * You may elect to redistribute this code under either of these licenses.
 *
 */

package io.vertx.ext.shell.system.impl;

import io.vertx.core.Vertx;
import io.vertx.core.VertxException;
import io.vertx.ext.shell.cli.CliToken;
import io.vertx.ext.shell.cli.Completion;
import io.vertx.ext.shell.command.Command;
import io.vertx.ext.shell.command.CommandResolver;
import io.vertx.ext.shell.session.Session;
import io.vertx.ext.shell.system.Process;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.stream.Collectors;

/**
 * @author Julien Viet
 */
public class InternalCommandManager {

  private final List resolvers;

  public InternalCommandManager(CommandResolver... resolvers) {
    this.resolvers = Arrays.asList(resolvers);
  }

  public InternalCommandManager(List resolvers) {
    this.resolvers = resolvers;
  }

  public List getResolvers() {
    return resolvers;
  }

  /**
   * Parses a command line and try to create a process.
   *
   * @param line the command line to parse
   * @return the created process
   */
  public Process createProcess(String line) {
    return createProcess(CliToken.tokenize(line));
  }

  /**
   * Try to create a process from the command line tokens.
   *
   * @param line the command line tokens
   * @return the created process
   */
  public Process createProcess(List line) {
    try {
      return makeRequest(line);
    } catch (Exception e) {
      throw new VertxException(e);
    }
  }

  private Process makeRequest(List s) {
    ListIterator tokens = s.listIterator();
    while (tokens.hasNext()) {
      CliToken token = tokens.next();
      if (token.isText()) {
        for (CommandResolver resolver : resolvers) {
          Command command = resolver.getCommand(token.value());
          if (command != null) {
            List remaining = new ArrayList<>();
            while (tokens.hasNext()) {
              remaining.add(tokens.next());
            }
            return command.createProcess(remaining);
          }
        }
        throw new IllegalArgumentException(token.value() + ": command not found");
      }
    }
    throw new IllegalArgumentException();
  }

  /**
   * Perform completion, the completion argument will be notified of the completion progress.
   *
   * @param completion the completion object
   */
  public void complete(Completion completion) {
    LinkedList tokens = new LinkedList<>(completion.lineTokens());

    // Remove any leading white space
    while (tokens.size() > 0 && tokens.getFirst().isBlank()) {
      tokens.removeFirst();
    }

    // > 1 means it's a text token followed by something else
    if (tokens.size() > 1) {
      ListIterator it = tokens.listIterator();
      while (it.hasNext()) {
        CliToken ct = it.next();
        it.remove();
        if (ct.isText()) {
          List newTokens = new ArrayList<>();
          while (it.hasNext()) {
            newTokens.add(it.next());
          }
          StringBuilder tmp = new StringBuilder();
          newTokens.stream().forEach(token -> tmp.append(token.raw()));
          String line = tmp.toString();
          for (CommandResolver resolver : resolvers) {
            Command command = resolver.getCommand(ct.value());
            if (command != null) {
              command.complete(new Completion() {
                @Override
                public Vertx vertx() {
                  return completion.vertx();
                }
                @Override
                public Session session() {
                  return completion.session();
                }
                @Override
                public String rawLine() {
                  return line;
                }
                @Override
                public List lineTokens() {
                  return newTokens;
                }
                @Override
                public void complete(List candidates) {
                  completion.complete(candidates);
                }
                @Override
                public void complete(String value, boolean terminal) {
                  completion.complete(value, terminal);
                }
              });
              return;
            }
          }
          completion.complete(Collections.emptyList());
        }
      }
    } else {
      String prefix = tokens.size() > 0 ? tokens.getFirst().value() : "";
      List names = resolvers.stream().
          flatMap(res -> res.commands().stream()).
          map(Command::name).
          filter(name -> name.startsWith(prefix)).
          distinct().
          collect(Collectors.toList());
      if (names.size() == 1) {
        completion.complete(names.get(0).substring(prefix.length()), true);
      } else {
        String commonPrefix = Completion.findLongestCommonPrefix(names);
        if (commonPrefix.length() > prefix.length()) {
          completion.complete(commonPrefix.substring(prefix.length()), false);
        } else {
          completion.complete(names);
        }
      }
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy