php-kilo/src/functions.php

226 lines
5.0 KiB
PHP
Raw Normal View History

2019-10-10 12:28:46 -04:00
<?php declare(strict_types=1);
2019-11-08 16:27:08 -05:00
namespace Aviat\Kilo;
2019-10-10 12:28:46 -04:00
2021-04-09 13:52:01 -04:00
use Aviat\Kilo\Enum\{Color, Highlight, RawKeyCode};
2019-10-14 16:21:41 -04:00
// ----------------------------------------------------------------------------
// ! C function/macro equivalents
// ----------------------------------------------------------------------------
2019-10-22 16:16:28 -04:00
/**
* Do bit twiddling to convert a letter into
* its Ctrl-letter equivalent ordinal ascii value
2019-10-22 16:16:28 -04:00
*
* @param string $char
* @return int
*/
2019-10-11 16:32:47 -04:00
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
2019-10-11 16:32:47 -04:00
return ord($char) & 0x1f;
2019-10-22 17:50:35 -04:00
}
/**
* 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
*/
2020-02-05 14:50:31 -05:00
function is_ctrl(string $char): bool
{
$c = ord($char);
2019-11-19 13:48:12 -05:00
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
{
2021-03-03 16:35:58 -05:00
return match($char) {
2021-04-09 13:52:01 -04:00
RawKeyCode::CARRIAGE_RETURN,
RawKeyCode::FORM_FEED,
RawKeyCode::NEWLINE,
RawKeyCode::SPACE,
RawKeyCode::TAB,
RawKeyCode::VERTICAL_TAB => true,
2021-03-04 16:41:12 -05:00
2021-03-03 16:35:58 -05:00
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;
}
2020-02-05 14:50:31 -05:00
$isSep = str_contains(',.()+-/*=~%<>[];', $char);
2021-04-09 13:52:01 -04:00
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);
}
2019-10-24 16:57:27 -04:00
2019-11-19 13:48:12 -05:00
/**
* Does the string $haystack contain $str, optionally searching from $offset?
*
* @param string $haystack
* @param string $str
* @param int|null $offset
* @return bool
*/
2021-04-14 16:38:41 -04:00
function str_has(string $haystack, string $str, ?int $offset = NULL): bool
2019-11-14 11:12:32 -05:00
{
2019-11-14 17:11:10 -05:00
if (empty($str))
{
return FALSE;
}
2019-11-14 11:12:32 -05:00
return ($offset !== NULL)
? strpos($haystack, $str, $offset) !== FALSE
2021-03-03 13:14:44 -05:00
: \str_contains($haystack, $str);
2019-11-14 11:12:32 -05:00
}
/**
* Get the ASCII color escape number for the specified syntax type
*
* @param int $hl
* @return int
*/
2019-10-24 16:57:27 -04:00
function syntax_to_color(int $hl): int
{
2021-03-03 13:14:44 -05:00
return match ($hl)
{
2019-11-06 16:11:38 -05:00
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::CHARACTER => Color::FG_BRIGHT_MAGENTA,
2021-03-03 20:23:12 -05:00
Highlight::NUMBER => Color::FG_BRIGHT_RED,
2019-11-06 16:11:38 -05:00
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,
2021-03-03 20:23:12 -05:00
Highlight::IDENTIFIER => Color::FG_BRIGHT_WHITE,
2021-03-03 13:14:44 -05:00
default => Color::FG_WHITE,
};
2019-10-24 16:57:27 -04:00
}
2019-11-08 16:27:08 -05:00
/**
* Replace tabs with the specified number of spaces.
*
* @param string $str
2021-03-04 12:03:51 -05:00
* @param int $number
2019-11-08 16:27:08 -05:00
* @return string
*/
2021-03-04 12:03:51 -05:00
function tabs_to_spaces(string $str, int $number = KILO_TAB_STOP): string
{
2021-04-09 13:52:01 -04:00
return str_replace(RawKeyCode::TAB, str_repeat(RawKeyCode::SPACE, $number), $str);
}
2021-03-17 15:38:52 -04:00
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',
};
2021-04-14 16:38:41 -04:00
}
function saturating_add(int $a, int $b, int $max): int
{
return ($a + $b > $max) ? $max : $a + $b;
}
function saturating_sub(int $a, int $b): int
{
if ($b > $a)
{
return 0;
}
return $a - $b;
2021-03-17 15:38:52 -04:00
}