1<?php
2
3/*
4 * This file is part of Psy Shell.
5 *
6 * (c) 2012-2020 Justin Hileman
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Psy\Readline;
13
14use Psy\Exception\BreakException;
15
16/**
17 * An array-based Readline emulation implementation.
18 */
19class Transient implements Readline
20{
21    private $history;
22    private $historySize;
23    private $eraseDups;
24    private $stdin;
25
26    /**
27     * Transient Readline is always supported.
28     *
29     * {@inheritdoc}
30     */
31    public static function isSupported()
32    {
33        return true;
34    }
35
36    /**
37     * Transient Readline constructor.
38     */
39    public function __construct($historyFile = null, $historySize = 0, $eraseDups = false)
40    {
41        // don't do anything with the history file...
42        $this->history = [];
43        $this->historySize = $historySize;
44        $this->eraseDups = $eraseDups;
45    }
46
47    /**
48     * {@inheritdoc}
49     */
50    public function addHistory($line)
51    {
52        if ($this->eraseDups) {
53            if (($key = \array_search($line, $this->history)) !== false) {
54                unset($this->history[$key]);
55            }
56        }
57
58        $this->history[] = $line;
59
60        if ($this->historySize > 0) {
61            $histsize = \count($this->history);
62            if ($histsize > $this->historySize) {
63                $this->history = \array_slice($this->history, $histsize - $this->historySize);
64            }
65        }
66
67        $this->history = \array_values($this->history);
68
69        return true;
70    }
71
72    /**
73     * {@inheritdoc}
74     */
75    public function clearHistory()
76    {
77        $this->history = [];
78
79        return true;
80    }
81
82    /**
83     * {@inheritdoc}
84     */
85    public function listHistory()
86    {
87        return $this->history;
88    }
89
90    /**
91     * {@inheritdoc}
92     */
93    public function readHistory()
94    {
95        return true;
96    }
97
98    /**
99     * {@inheritdoc}
100     *
101     * @throws BreakException if user hits Ctrl+D
102     *
103     * @return string
104     */
105    public function readline($prompt = null)
106    {
107        echo $prompt;
108
109        return \rtrim(\fgets($this->getStdin()), "\n\r");
110    }
111
112    /**
113     * {@inheritdoc}
114     */
115    public function redisplay()
116    {
117        // noop
118    }
119
120    /**
121     * {@inheritdoc}
122     */
123    public function writeHistory()
124    {
125        return true;
126    }
127
128    /**
129     * Get a STDIN file handle.
130     *
131     * @throws BreakException if user hits Ctrl+D
132     *
133     * @return resource
134     */
135    private function getStdin()
136    {
137        if (!isset($this->stdin)) {
138            $this->stdin = \fopen('php://stdin', 'r');
139        }
140
141        if (\feof($this->stdin)) {
142            throw new BreakException('Ctrl+D');
143        }
144
145        return $this->stdin;
146    }
147}
148