210 lines
4.7 KiB
PHP
210 lines
4.7 KiB
PHP
<?php declare(strict_types=1);
|
|
|
|
namespace Aviat\Kilo;
|
|
|
|
use Aviat\Kilo\Enum\{Color, Highlight, RawKeyCode};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ! C function/macro equivalents
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Do bit twiddling to convert a letter into
|
|
* its Ctrl-letter equivalent ordinal ascii value
|
|
*
|
|
* @param string $char
|
|
* @return int
|
|
*/
|
|
function ctrl_key(string $char): int
|
|
{
|
|
if ( ! is_ascii($char))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// b1,100,001 (a) & b0,011,111 (0x1f) = b0,000,001 (SOH)
|
|
// b1,100,010 (b) & b0,011,111 (0x1f) = b0,000,010 (STX)
|
|
// ...and so on
|
|
return ord($char) & 0x1f;
|
|
}
|
|
|
|
/**
|
|
* Does the one-character string contain an ascii ordinal value?
|
|
*
|
|
* @param string $single_char
|
|
* @return bool
|
|
*/
|
|
function is_ascii(string $single_char): bool
|
|
{
|
|
if (strlen($single_char) > 1)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return ord($single_char) < 0x80;
|
|
}
|
|
|
|
/**
|
|
* Does the one-character string contain an ascii control character?
|
|
*
|
|
* @param string $char
|
|
* @return bool
|
|
*/
|
|
function is_ctrl(string $char): bool
|
|
{
|
|
$c = ord($char);
|
|
return is_ascii($char) && ( $c === 0x7f || $c < 0x20 );
|
|
}
|
|
|
|
/**
|
|
* Does the one-character string contain an ascii number?
|
|
*
|
|
* @param string $char
|
|
* @return bool
|
|
*/
|
|
function is_digit(string $char): bool
|
|
{
|
|
$c = ord($char);
|
|
return is_ascii($char) && ( $c > 0x2f && $c < 0x3a );
|
|
}
|
|
|
|
/**
|
|
* Does the one-character string contain ascii whitespace?
|
|
*
|
|
* @param string $char
|
|
* @return bool
|
|
*/
|
|
function is_space(string $char): bool
|
|
{
|
|
return match($char) {
|
|
RawKeyCode::CARRIAGE_RETURN,
|
|
RawKeyCode::FORM_FEED,
|
|
RawKeyCode::NEWLINE,
|
|
RawKeyCode::SPACE,
|
|
RawKeyCode::TAB,
|
|
RawKeyCode::VERTICAL_TAB => true,
|
|
|
|
default => false,
|
|
};
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ! Helper functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Does the one-character string contain a character that separates tokens?
|
|
*
|
|
* @param string $char
|
|
* @return bool
|
|
*/
|
|
function is_separator(string $char): bool
|
|
{
|
|
if ( ! is_ascii($char))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
$isSep = str_contains(',.()+-/*=~%<>[];', $char);
|
|
|
|
return is_space($char) || $char === RawKeyCode::NULL || $isSep;
|
|
}
|
|
|
|
/**
|
|
* Replaces a slice of an array with the same value
|
|
*
|
|
* @param array $array The array to update
|
|
* @param int $offset The index of the first location to update
|
|
* @param int $length The number of indices to update
|
|
* @param mixed $value The value to replace in the range
|
|
*/
|
|
function array_replace_range(array &$array, int $offset, int $length, mixed $value):void
|
|
{
|
|
if ($length === 1)
|
|
{
|
|
$array[$offset] = $value;
|
|
return;
|
|
}
|
|
|
|
$replacement = array_fill(0, $length, $value);
|
|
array_splice($array, $offset, $length, $replacement);
|
|
}
|
|
|
|
/**
|
|
* Does the string $haystack contain $str, optionally searching from $offset?
|
|
*
|
|
* @param string $haystack
|
|
* @param string $str
|
|
* @param int|null $offset
|
|
* @return bool
|
|
*/
|
|
function str_contains(string $haystack, string $str, ?int $offset = NULL): bool
|
|
{
|
|
if (empty($str))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return ($offset !== NULL)
|
|
? strpos($haystack, $str, $offset) !== FALSE
|
|
: \str_contains($haystack, $str);
|
|
}
|
|
|
|
/**
|
|
* Get the ASCII color escape number for the specified syntax type
|
|
*
|
|
* @param int $hl
|
|
* @return int
|
|
*/
|
|
function syntax_to_color(int $hl): int
|
|
{
|
|
return match ($hl)
|
|
{
|
|
Highlight::COMMENT => Color::FG_CYAN,
|
|
Highlight::ML_COMMENT => Color::FG_BRIGHT_BLACK,
|
|
Highlight::KEYWORD1 => Color::FG_YELLOW,
|
|
Highlight::KEYWORD2 => Color::FG_GREEN,
|
|
Highlight::STRING => Color::FG_MAGENTA,
|
|
Highlight::NUMBER => Color::FG_BRIGHT_RED,
|
|
Highlight::OPERATOR => Color::FG_BRIGHT_GREEN,
|
|
Highlight::VARIABLE => Color::FG_BRIGHT_CYAN,
|
|
Highlight::DELIMITER => Color::FG_BLUE,
|
|
Highlight::INVALID => Color::BG_BRIGHT_RED,
|
|
Highlight::MATCH => Color::INVERT,
|
|
Highlight::IDENTIFIER => Color::FG_BRIGHT_WHITE,
|
|
default => Color::FG_WHITE,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Replace tabs with the specified number of spaces.
|
|
*
|
|
* @param string $str
|
|
* @param int $number
|
|
* @return string
|
|
*/
|
|
function tabs_to_spaces(string $str, int $number = KILO_TAB_STOP): string
|
|
{
|
|
return str_replace(RawKeyCode::TAB, str_repeat(RawKeyCode::SPACE, $number), $str);
|
|
}
|
|
|
|
function error_code_name(int $code): string
|
|
{
|
|
return match ($code) {
|
|
E_ERROR => 'Error',
|
|
E_WARNING => 'Warning',
|
|
E_PARSE => 'Parse Error',
|
|
E_NOTICE => 'Notice',
|
|
E_CORE_ERROR => 'Core Error',
|
|
E_CORE_WARNING => 'Core Warning',
|
|
E_COMPILE_ERROR => 'Compile Error',
|
|
E_COMPILE_WARNING => 'Compile Warning',
|
|
E_USER_ERROR => 'User Error',
|
|
E_USER_WARNING => 'User Warning',
|
|
E_USER_NOTICE => 'User Notice',
|
|
E_RECOVERABLE_ERROR => 'Recoverable Error',
|
|
E_DEPRECATED => 'Deprecated',
|
|
E_USER_DEPRECATED => 'User Deprecated',
|
|
default => 'Unknown',
|
|
};
|
|
} |