*/
class syntax_plugin_number extends SyntaxPlugin
{
/** @inheritDoc */
public function getType()
{
return 'substition';
}
/** @inheritDoc */
public function getPType()
{
return 'normal';
}
/** @inheritDoc */
public function getSort()
{
return 100;
}
/** @inheritDoc */
public function connectTo($mode)
{
$this->Lexer->addSpecialPattern('{{n>.*?}}', $mode, 'plugin_number');
}
/** @inheritDoc */
public function handle($match, $state, $pos, Doku_Handler $handler)
{
$raw = substr($match, 4, -2);
$raw = strtolower($raw);
$raw = preg_replace('/[^0-9a-z_]/', '', $raw);
$data = [];
$data['raw'] = $raw;
if (preg_match('/^\d+(e\d+)?$/', $raw)) {
$data['type'] = 'dec';
$data['value'] = intval($raw);
} else if (preg_match('/^0b[01]+$/', $raw)) {
$data['type'] = 'bin';
$data['value'] = intval(substr($raw, 2), 2);
} else if (preg_match('/^0x[0-9a-f]+$/i', $raw)) {
$data['type'] = 'hex';
$data['value'] = intval(substr($raw, 2), 16);
} else if (preg_match('/^[0-9a-z]+_[0-9]+$/i', $raw)) {
$data['type'] = 'padic';
list($number, $base) = explode('_', $raw);
$data['value'] = intval($number, $base);
$data['number'] = $number;
$data['base'] = intval($base);
if ($data['base'] < 2 || $data['base'] > 36 || base_convert($data['value'], 10, $data['base']) != $number)
$data['value'] = NAN;
} else {
$data['value'] = NAN;
}
return $data;
}
static private function renderDec($value)
{
return ''.$value.'
';
}
static private function renderHex($value)
{
return '0x'
. (is_string($value) ? substr($value, 2) : dechex($value)) . '
';
}
static private function renderBin($value)
{
return '0b'
. (is_string($value) ? substr($value, 2) : decbin($value)) . '
';
}
const NUMBERSYSTEM = ';;Binary;Ternary;Quaternary;Quinary;Senary;Septenary;Octal;Nonary;Decimal;Undecimal;Duodecimal;Tridecimal;Tetradecimal;Pentadecimal;Hexadecimal;Heptadecimal;Octodecimal;Enneadecimal;Vigesimal;Unvigesimal;Duovigesimal;Trivigesimal;Tetravigesimal;Pentavigesimal;Hexavigesimal;Heptavigesimal;Octovigesimal;Enneavigesimal;Trigesimal;Untrigesimal;Duotrigesimal;Tritrigesimal;Tetratrigesimal;Pentatrigesimal; Hexatrigesimal';
/** @inheritDoc */
public function render($mode, Doku_Renderer $renderer, $data)
{
if ($mode !== 'xhtml') {
return false;
}
$value = $data['value'];
if (is_nan($value)) {
$renderer->doc .= '⚠️ warning: ' . $data['raw'] . ' is not a valid input
';
return true;
}
if (!is_int($value) || $value >= PHP_INT_MAX) {
$renderer->doc .= '⚠️ warning: ' . $data['raw'] . ' is not a safe for conversion
'.$value;
return true;
}
$type = $data['type'];
if ($type == 'dec') {
$number = self::renderDec($data['raw']);
$tooltip = 'Decimal number (base 10)
= '
. self::renderBin($value) . ' (binary)';
if ("~$value" != '~' . $data['raw']) { //
$tooltip .= '
= ' . self::renderDec($value) . ' (decimal)';
}
$tooltip .= '
= ' . self::renderHex($value) . ' (hexadecimal)';
} else if ($type == 'bin') {
$number = self::renderBin($data['raw']);
$tooltip = 'Binary number (base 2)
= '
. self::renderDec($value) . ' (decimal)
= '
. self::renderHex($value) . ' (hexadecimal)';
} else if ($type == 'hex') {
$number = self::renderHex($data['raw']);
$tooltip = 'Hexadecimal number (base 16)
= '
. self::renderBin($value) . ' (binary)
= '
. self::renderDec($value) . ' (decimal)';
} else if ($type == 'padic') {
$number = '['
. $data['number']
. ']'
. $data['base'] . '
';
$tooltip = ''
. explode(';', self::NUMBERSYSTEM)[$data['base']]
. ' number (base ' . $data['base'] . ')
= '
. self::renderBin($value) . ' (binary)
= '
. self::renderDec($value) . ' (decimal)
= '
. self::renderHex($value) . ' (hexadecimal)';
}
//
$renderer->doc .= "$tooltip$number";
return true;
}
}