mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
Sync upstream Gemini-CLI v0.8.2 (#838)
This commit is contained in:
@@ -4,45 +4,113 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import React from 'react';
|
||||
import { Text } from 'ink';
|
||||
import { Colors } from '../colors.js';
|
||||
import { theme } from '../semantic-colors.js';
|
||||
|
||||
interface PrepareLabelProps {
|
||||
export const MAX_WIDTH = 150; // Maximum width for the text that is shown
|
||||
|
||||
export interface PrepareLabelProps {
|
||||
label: string;
|
||||
matchedIndex?: number;
|
||||
userInput: string;
|
||||
textColor: string;
|
||||
highlightColor?: string;
|
||||
isExpanded?: boolean;
|
||||
}
|
||||
|
||||
export const PrepareLabel: React.FC<PrepareLabelProps> = ({
|
||||
const _PrepareLabel: React.FC<PrepareLabelProps> = ({
|
||||
label,
|
||||
matchedIndex,
|
||||
userInput,
|
||||
textColor,
|
||||
highlightColor = Colors.AccentYellow,
|
||||
isExpanded = false,
|
||||
}) => {
|
||||
if (
|
||||
matchedIndex === undefined ||
|
||||
matchedIndex < 0 ||
|
||||
matchedIndex >= label.length ||
|
||||
userInput.length === 0
|
||||
) {
|
||||
return <Text color={textColor}>{label}</Text>;
|
||||
const hasMatch =
|
||||
matchedIndex !== undefined &&
|
||||
matchedIndex >= 0 &&
|
||||
matchedIndex < label.length &&
|
||||
userInput.length > 0;
|
||||
|
||||
// Render the plain label if there's no match
|
||||
if (!hasMatch) {
|
||||
const display = isExpanded
|
||||
? label
|
||||
: label.length > MAX_WIDTH
|
||||
? label.slice(0, MAX_WIDTH) + '...'
|
||||
: label;
|
||||
return (
|
||||
<Text wrap="wrap" color={textColor}>
|
||||
{display}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
const start = label.slice(0, matchedIndex);
|
||||
const match = label.slice(matchedIndex, matchedIndex + userInput.length);
|
||||
const end = label.slice(matchedIndex + userInput.length);
|
||||
const matchLength = userInput.length;
|
||||
let before = '';
|
||||
let match = '';
|
||||
let after = '';
|
||||
|
||||
// Case 1: Show the full string if it's expanded or already fits
|
||||
if (isExpanded || label.length <= MAX_WIDTH) {
|
||||
before = label.slice(0, matchedIndex);
|
||||
match = label.slice(matchedIndex, matchedIndex + matchLength);
|
||||
after = label.slice(matchedIndex + matchLength);
|
||||
}
|
||||
// Case 2: The match itself is too long, so we only show a truncated portion of the match
|
||||
else if (matchLength >= MAX_WIDTH) {
|
||||
match = label.slice(matchedIndex, matchedIndex + MAX_WIDTH - 1) + '...';
|
||||
}
|
||||
// Case 3: Truncate the string to create a window around the match
|
||||
else {
|
||||
const contextSpace = MAX_WIDTH - matchLength;
|
||||
const beforeSpace = Math.floor(contextSpace / 2);
|
||||
const afterSpace = Math.ceil(contextSpace / 2);
|
||||
|
||||
let start = matchedIndex - beforeSpace;
|
||||
let end = matchedIndex + matchLength + afterSpace;
|
||||
|
||||
if (start < 0) {
|
||||
end += -start; // Slide window right
|
||||
start = 0;
|
||||
}
|
||||
if (end > label.length) {
|
||||
start -= end - label.length; // Slide window left
|
||||
end = label.length;
|
||||
}
|
||||
start = Math.max(0, start);
|
||||
|
||||
const finalMatchIndex = matchedIndex - start;
|
||||
const slicedLabel = label.slice(start, end);
|
||||
|
||||
before = slicedLabel.slice(0, finalMatchIndex);
|
||||
match = slicedLabel.slice(finalMatchIndex, finalMatchIndex + matchLength);
|
||||
after = slicedLabel.slice(finalMatchIndex + matchLength);
|
||||
|
||||
if (start > 0) {
|
||||
before = before.length >= 3 ? '...' + before.slice(3) : '...';
|
||||
}
|
||||
if (end < label.length) {
|
||||
after = after.length >= 3 ? after.slice(0, -3) + '...' : '...';
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Text>
|
||||
<Text color={textColor}>{start}</Text>
|
||||
<Text color="black" bold backgroundColor={highlightColor}>
|
||||
{match}
|
||||
</Text>
|
||||
<Text color={textColor}>{end}</Text>
|
||||
<Text color={textColor} wrap="wrap">
|
||||
{before}
|
||||
{match
|
||||
? match.split(/(\s+)/).map((part, index) => (
|
||||
<Text
|
||||
key={`match-${index}`}
|
||||
color={theme.background.primary}
|
||||
backgroundColor={theme.text.primary}
|
||||
>
|
||||
{part}
|
||||
</Text>
|
||||
))
|
||||
: null}
|
||||
{after}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
export const PrepareLabel = React.memo(_PrepareLabel);
|
||||
|
||||
Reference in New Issue
Block a user