Package org.locationtech.geogig.cli

Source Code of org.locationtech.geogig.cli.GeogigConsole

/* Copyright (c) 2012-2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Gabriel Roldan (Boundless) - initial implementation
*/
package org.locationtech.geogig.cli;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import jline.Terminal;
import jline.UnsupportedTerminal;
import jline.console.ConsoleReader;
import jline.console.completer.AggregateCompleter;
import jline.console.completer.ArgumentCompleter;
import jline.console.completer.Completer;
import jline.console.completer.StringsCompleter;

import org.locationtech.geogig.api.GeoGIG;
import org.locationtech.geogig.api.Ref;
import org.locationtech.geogig.api.SymRef;
import org.locationtech.geogig.api.plumbing.RefParse;
import org.locationtech.geogig.api.plumbing.ResolveGeogigDir;
import org.locationtech.geogig.repository.Hints;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterDescription;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;

/**
* Provides the ability to execute several commands in succession without re-initializing GeoGig or
* the command line interface.
*/
public class GeogigConsole {

    private boolean interactive;

    /**
     * Entry point for the Geogig console.
     *
     * @param args unused
     */
    public static void main(String... args) {
        Logging.tryConfigureLogging();
        try {
            if (args.length == 1) {
                new GeogigConsole().runFile(args[0]);
            } else if (args.length == 0) {
                new GeogigConsole().run();
            } else {
                System.out.println("Too many arguments.\nUsage: geogig-console [batch_file]");
            }
            System.exit(0);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }

    private void runFile(String filename) throws IOException {
        final File file = new File(filename);
        if (!file.exists()) {
            System.out.println("The specified batch file does not exist");
            return;
        }

        // take the input from the console with its input stream directly from the file
        InputStream in = new FileInputStream(file);
        try {
            interactive = false;
            run(in, System.out);
        } finally {
            in.close();
        }
    }

    /**
     * @throws IOException
     *
     */
    private void run() throws IOException {
        // interactive will be false if stdin/stdout is redirected
        interactive = null != System.console();
        run(System.in, System.out);
    }

    private void run(final InputStream in, final OutputStream out) throws IOException {

        final Terminal terminal;
        if (interactive) {
            terminal = null;/* let jline select an appropriate one */
        } else {
            // no colors in output
            terminal = new UnsupportedTerminal();
        }
        ConsoleReader consoleReader = new ConsoleReader(in, out, terminal);
        consoleReader.setAutoprintThreshold(20);
        consoleReader.setPaginationEnabled(interactive);
        consoleReader.setHistoryEnabled(interactive);
        // needed for CTRL+C not to let the console broken
        consoleReader.getTerminal().setEchoEnabled(interactive);

        final GeogigCLI cli = new GeogigCLI(consoleReader);
        if (interactive) {
            addCommandCompleter(consoleReader, cli);
        } else {
            // no progress percent in output
            cli.disableProgressListener();
        }

        GeogigCLI.addShutdownHook(cli);

        setPrompt(cli);
        cli.close();

        try {
            runInternal(cli);
        } finally {
            try {
                cli.close();
            } finally {
                try {
                    if (terminal != null) {
                        terminal.restore();
                    }
                    consoleReader.shutdown();
                } catch (Exception e) {
                    throw Throwables.propagate(e);
                }
            }
        }
    }

    private void addCommandCompleter(ConsoleReader consoleReader, final GeogigCLI cli) {
        final JCommander globalCommandParser = cli.newCommandParser();

        final Map<String, JCommander> commands = globalCommandParser.getCommands();

        List<Completer> completers = new ArrayList<Completer>(commands.size());
        for (Map.Entry<String, JCommander> entry : commands.entrySet()) {

            String commandName = entry.getKey();
            JCommander commandParser = entry.getValue();

            List<ParameterDescription> parameters = commandParser.getParameters();
            List<String> options = new ArrayList<String>(parameters.size());
            for (ParameterDescription pd : parameters) {
                String longestName = pd.getLongestName();
                options.add(longestName);
            }
            Collections.sort(options);

            ArgumentCompleter commandCompleter = new ArgumentCompleter(new StringsCompleter(
                    commandName), new StringsCompleter(options));
            completers.add(commandCompleter);
        }

        completers.add(new StringsCompleter("exit", "clear"));

        Completer completer = new AggregateCompleter(completers);
        consoleReader.addCompleter(completer);
    }

    /**
     * Sets the command prompt
     *
     * @throws IOException
     */
    private void setPrompt(GeogigCLI cli) throws IOException {
        if (!interactive) {
            return;
        }
        String currentDir = new File(".").getCanonicalPath();
        String currentHead = "";
        GeoGIG geogig;
        try {
            geogig = cli.newGeoGIG(Hints.readOnly());
        } catch (Exception e) {
            geogig = null;
        }
        if (geogig != null) {
            Optional<URL> dir = geogig.command(ResolveGeogigDir.class).call();
            if (dir.isPresent()) {
                try {
                    Optional<Ref> ref = geogig.command(RefParse.class).setName(Ref.HEAD).call();
                    if (ref.isPresent()) {
                        if (ref.get() instanceof SymRef) {
                            currentHead = ((SymRef) ref.get()).getTarget();
                            int idx = currentHead.lastIndexOf("/");
                            if (idx != -1) {
                                currentHead = currentHead.substring(idx + 1);
                            }
                        } else {
                            currentHead = ref.get().getObjectId().toString().substring(0, 7);
                        }
                        currentHead = " (" + currentHead + ")";
                    }
                } finally {
                    geogig.close();
                }
            }
        }
        String prompt = "(geogig):" + currentDir + currentHead + " $ ";
        cli.getConsole().setPrompt(prompt);
    }

    private void runInternal(final GeogigCLI cli) throws IOException {

        final ConsoleReader consoleReader = cli.getConsole();
        while (true) {
            String line = consoleReader.readLine();
            if (line == null) {
                // EOF / CTRL-D
                return;
            }
            if (line.trim().length() == 0) {
                continue;
            }
            if (line.trim().startsWith("#")) {// comment
                continue;
            }

            String[] args = ArgumentTokenizer.tokenize(line);

            if (interactive && args != null && args.length == 1) {
                if ("exit".equals(args[0])) {
                    return;
                }
                if ("clear".equals(args[0])) {
                    consoleReader.clearScreen();
                    consoleReader.redrawLine();
                    continue;
                }
            }

            cli.execute(args);
            setPrompt(cli);// in case HEAD has changed
            cli.close();
        }
    }

}
TOP

Related Classes of org.locationtech.geogig.cli.GeogigConsole

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.