blob: f8cd6f810429d80515ddb9bbd9d1e84bc5ce41c2 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_SHELL_CONSOLE_CONSOLE_H_
#define SRC_DEVELOPER_SHELL_CONSOLE_CONSOLE_H_
#include <lib/async/dispatcher.h>
#include <lib/fdio/unsafe.h>
#include <iostream>
#include <string>
#include <vector>
#include "src/developer/shell/console/command.h"
#include "src/lib/fsl/tasks/fd_waiter.h"
#include "src/lib/line_input/modal_line_input.h"
namespace shell::console {
class Console {
public:
class Client {
public:
Client() = default;
// A |command| has been read from the console.
//
// May return ZX_ERR_STOP, ZX_ERR_NEXT, or ZX_ERR_ASYNC.
//
// If this function returns |ZX_ERR_STOP|, no further commands will be read
// from the console.
//
// If this function returns |ZX_ERR_NEXT|, the console will continue to read
// commands from the console.
//
// If this function returns |ZX_ERR_ASYNC|, the console will wait to read
// further commands from the console until the |GetNextCommand| method is
// called on the console.
//
// If this function returns anything else, the result will be treated as a
// ZX_ERR_NEXT, but the resulting error message will be printed to the
// console.
virtual Err OnConsoleCommand(std::unique_ptr<Command> command) = 0;
// The console has been asked to interrupt the current command.
//
// Called only between |OnConsoleCommand| returning |ZX_ERR_ASYNC| and
// |GetNextCommand|.
virtual void OnConsoleInterrupt() = 0;
// The console has encountered an error.
//
// No further commands can be read from the console.
//
// If the console reaches the end of the input stream, |status| will be
// |ZX_ERR_PEER_CLOSED|.
virtual void OnConsoleError(zx_status_t status) = 0;
protected:
virtual ~Client();
};
// Create an interactive console.
//
// Reads input from the |input_fd| file description, which is typically
// |STDIN_FILENO| but can be set to another valid file descriptor for testing.
//
// Uses |dispatcher| to schedule asynchronous waits on |input_fd|.
// Writes to stdout and stderr.
Console(Client* client, async_dispatcher_t* dispatcher, int input_fd,
std::ostream& out = std::cout, std::ostream& err = std::cerr);
~Console();
// Initialize the console.
//
// The given |prompt| is displayed to the user when the user is expected to
// input another command.
//
// Does not prompt the user to input a command. Call |GetNextCommand| to get
// the first command from the user.
void Init(std::string prompt);
// Get the next command from the user.
//
// This operation completes asynchronously by calling methods on the |client|
// provided to the constructor. A single call to |GetNextCommand| will result
// in one or more calls to |OnConsoleCommand| and at most one call to
// |OnConsoleError|. See |Client| for more information.
//
// It is an error to call |GetNextCommand| again until |OnConsoleCommand| has
// returned |ZX_ERR_ASYNC|.
void GetNextCommand();
// Output the given string |output| to this console's standard output stream.
std::ostream& out() { return out_stream_; }
// Output the given string |output| to this console's standard error stream.
std::ostream& err() { return err_stream_; }
private:
void WaitForInputAsynchronously();
void WaitForInterruptAsynchronously();
void OnAccept(const std::string& line);
void OnError(zx_status_t status);
Client* client_;
int input_fd_;
fsl::FDWaiter input_waiter_;
fdio_t* tty_ = nullptr;
fsl::FDWaiter interrupt_waiter_;
line_input::ModalLineInput line_input_;
bool should_read_ = false;
std::ostream& out_stream_;
std::ostream& err_stream_;
};
} // namespace shell::console
#endif // SRC_DEVELOPER_SHELL_CONSOLE_CONSOLE_H_