括号列表支持更新

December 13, 2023
This conversation may reflect the link creator’s personalized data, which isn’t shared and can meaningfully change how the model responds.
Anonymous
请修改以下的代码使其能支持在括号中的情况,例如: ``` (1)、 (1). [1]: ``` 代码: ``` type PatternType = 'parabic' | 'arabic' | 'uppercaseLetter' | 'lowercaseLetter' | 'romanNumeral' | 'chineseNumeral'; /** * 识别给定文本行的列表模式。 * @param lineText 要识别的文本行。 * @returns 返回识别出的列表模式类型,如果没有匹配,则返回 null。 */ function identifyPattern(lineText: string): PatternType | null { const patterns: { [key in PatternType]: RegExp } = { arabic: /^\d+[、]/, uppercaseLetter: /^[A-Z][\.|、]/, lowercaseLetter: /^[a-z][\.|、]/, romanNumeral: /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})[\.|、]/, chineseNumeral: /^[\u4e00-\u9fa5]+[\.|、]/ }; for (let type in patterns) { if (patterns[type as PatternType].test(lineText)) { return type as PatternType; } } return null; } /** * 根据当前编号和模式类型获取下一个编号。 * @param currentNumber 当前编号。 * @param patternType 列表模式类型。 * @returns 返回计算后的下一个编号,如果无法处理则返回 null。 */ function getNextNumber(currentNumber: string, punctuation: string, patternType: PatternType): string | null { switch (patternType) { case "arabic": return parseInt(currentNumber) + 1 + punctuation; case "uppercaseLetter": return String.fromCharCode(currentNumber.charCodeAt(0) + 1) + punctuation; case "lowercaseLetter": return String.fromCharCode(currentNumber.charCodeAt(0) + 1) + punctuation; case "romanNumeral": let arabicNum = romanToArabic(currentNumber); return arabicToRoman(arabicNum + 1) + punctuation; case "chineseNumeral": let arabicNumChinese = chineseToArabic(currentNumber); return arabicToChinese(arabicNumChinese + 1) + punctuation; default: return null; } } // 罗马数字转阿拉伯数字 function romanToArabic(roman: string): number { const romanNumerals: { [key: string]: number } = { M: 1000, CM: 900, D: 500, CD: 400, C: 100, XC: 90, L: 50, XL: 40, X: 10, IX: 9, V: 5, IV: 4, I: 1 }; let arabic = 0; let i = roman.length; while (i--) { if (romanNumerals[roman[i]] < romanNumerals[roman[i + 1]]) { arabic -= romanNumerals[roman[i]]; } else { arabic += romanNumerals[roman[i]]; } } return arabic; } /** * 将阿拉伯数字转换为罗马数字。 * @param number 要转换的阿拉伯数字。 * @returns 转换后的罗马数字字符串。 */ function arabicToRoman(number: number): string { const romanNumerals = {M: 1000, CM: 900, D: 500, CD: 400, C: 100, XC: 90, L: 50, XL: 40, X: 10, IX: 9, V: 5, IV: 4, I: 1}; let roman = ''; for (let key in romanNumerals) { while (number >= romanNumerals[key]) { roman += key; number -= romanNumerals[key]; } } return roman; } /** * 将单个中文数字字符转换为相应的阿拉伯数字。 * @param chinese 要转换的单个中文数字字符。 * @returns 转换后的阿拉伯数字,如果无法识别则返回 0。 */ function chineseToArabic(chinese: string): number { const chineseNumerals: { [key: string]: number } = { '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9, '十': 10 }; return chineseNumerals[chinese] || 0; } /** * 将阿拉伯数字转换为中文数字字符。 * @param number 要转换的阿拉伯数字。 * @returns 转换后的中文数字字符,如果无法识别则返回空字符串。 */ function arabicToChinese(number: number): string { const chineseNumerals = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']; return chineseNumerals[number] || ''; } function calculateNewCursorPosition(forEnterChanges: ChangeSpec[], state: EditorState): number { // 取最后一个更改的结束位置作为新的光标位置 let lastChangeEnd = 0; forEnterChanges.forEach(change => { if ('from' in change && 'to' in change) { lastChangeEnd = (change?.to || 0) + (change?.insert?.length as number) || 0; } }); return lastChangeEnd; } /** * 检测并处理回车字符。 * @param transaction 当前事务。 * @param state 编辑器状态。 * @returns 更新后的状态。 */ function checkForEnter(transaction: Transaction, state: EditorState) { const changes: ChangeSpec[] = []; transaction.changes.iterChanges((fromA, toA, fromB, toB, inserted) => { let text = inserted.toString(); if (text.includes('\n')) { // 检测到回车 // 在这里处理回车事件 // 例如,可以检查当前插入点前的文本内容并做出决策 let currentLineStart = state.doc.lineAt(fromA).from; let currentLineText = state.doc.sliceString(currentLineStart, fromA); let pattern = identifyPattern(currentLineText); if (pattern) { let currentNumber = currentLineText.match(/^[\w\u4e00-\u9fa5]+/)?.[0]; // 提取序号部分 // 标点符号 let punctuation = currentLineText.match(/^[\w\u4e00-\u9fa5]+[\.\、]/)?.[0].slice(-1) || '.'; if (!currentNumber) return; // 如果没有序号,不进行处理 let nextNumber = getNextNumber(currentNumber, punctuation, pattern); if (nextNumber !== null) { let insertPosition = state.doc.lineAt(toB).to; // 新行的开始位置 let tChanges = { from: insertPosition, to: insertPosition, insert: nextNumber + (punctuation === "、" ? "" : " ") }; changes.push(tChanges); // 注意:这里需要有适当的方式来更新编辑器视图(view) } } } }); return changes; }\ ```
ChatGPT
ChatGPT

为了使代码能够支持在括号中的情况,例如 (1)、, (1)., [1]:,我们需要调整正则表达式以匹配这些格式,并确保在 getNextNumber 函数中正确处理标点和括号。

下面是修改后的代码:

  1. 修改正则表达式:增加对括号和不同标点符号的支持。
  2. 调整 getNextNumber 函数:使其能够处理括号和不同的标点符号。
typescript
type PatternType = 'parabic' | 'arabic' | 'uppercaseLetter' | 'lowercaseLetter' | 'romanNumeral' | 'chineseNumeral'; function identifyPattern(lineText: string): PatternType | null { const patterns: { [key in PatternType]: RegExp } = { arabic: /^\(?(\d+)\)?[\)|\.|、|:]/, uppercaseLetter: /^\(?[A-Z]\)?[\)|\.|、|:]/, lowercaseLetter: /^\(?[a-z]\)?[\)|\.|、|:]/, romanNumeral: /^\(?M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\)?[\)|\.|、|:]/, chineseNumeral: /^\(?[\u4e00-\u9fa5]+\)?[\)|\.|、|:]/, }; // ... 保持原有代码不变 ... } function getNextNumber(currentNumber: string, punctuation: string, patternType: PatternType): string | null { // ... 保持原有代码不变 ... // 根据标点符号的不同,可能需要添加括号 switch (punctuation) { case ')': return '(' + nextNumber + ')'; case '.': case '、': case ':': return nextNumber + punctuation; default: return null; } } // ... 其他函数保持不变 ...

这些更改将使代码能够处理带括号的不同列表样式,同时保持对原有格式的支持。记得测试这些更改以确保它们按预期工作。

Anonymous
括号后边应该还要有. 或者、,所以请再继续改进这个方法
ChatGPT
ChatGPT

了解了,我们需要进一步调整正则表达式以匹配括号后跟着的点号或顿号。此外,getNextNumber 函数也需要相应地处理这种情况。以下是改进后的代码:

  1. 修改正则表达式:确保它能匹配括号内的序号,后面跟着点号或顿号。
  2. 调整 getNextNumber 函数:处理括号和后续的标点符号。
typescript
type PatternType = 'parabic' | 'arabic' | 'uppercaseLetter' | 'lowercaseLetter' | 'romanNumeral' | 'chineseNumeral'; function identifyPattern(lineText: string): PatternType | null { const patterns: { [key in PatternType]: RegExp } = { arabic: /^\(?(\d+)\)?[、\.]/, uppercaseLetter: /^\(?[A-Z]\)?[、\.]/, lowercaseLetter: /^\(?[a-z]\)?[、\.]/, romanNumeral: /^\(?M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\)?[、\.]/, chineseNumeral: /^\(?[\u4e00-\u9fa5]+\)?[、\.]/, }; // ... 保持原有代码不变 ... } function getNextNumber(currentNumber: string, patternType: PatternType): string | null { let nextNumber: string | null; let punctuation: string; // 确定标点符号类型 if (currentNumber.endsWith(')')) { punctuation = currentNumber.slice(-2, -1); // 获取括号内的标点符号 currentNumber = currentNumber.slice(1, -2); // 移除括号和标点符号 } else { punctuation = currentNumber.slice(-1); // 获取标点符号 currentNumber = currentNumber.slice(0, -1); // 移除标点符号 } // 根据不同的序号类型生成下一个序号 // ... 保持原有逻辑不变 ... // 返回格式化的下一个序号 if (punctuation === '.' || punctuation === '、') { return '(' + nextNumber + ')' + punctuation; } else { return nextNumber; // 如果无法确定标点符号,直接返回序号 } } // ... 其他函数保持不变 ...

这段代码现在应该能够正确地处理括号内的序号,后面跟着点号或顿号的情况。记得对代码进行测试,确保它按照预期工作。

Anonymous
能否在以下函数获取类别之前,先查找是否存在 ( 、(、【、[ 的成对括号的情况下,如果存在的话,则也归类成对应不同的类别,然后暂时从内容中去除成对的括号,然后再进行内容判断: 具体在 identifyPattern(currentLineText); 之前 ``` function checkForEnter(transaction: Transaction, state: EditorState) { const changes: ChangeSpec[] = []; transaction.changes.iterChanges((fromA, toA, fromB, toB, inserted) => { let text = inserted.toString(); if (text.includes('\n')) { // 检测到回车 // 在这里处理回车事件 // 例如,可以检查当前插入点前的文本内容并做出决策 let currentLineStart = state.doc.lineAt(fromA).from; let currentLineText = state.doc.sliceString(currentLineStart, fromA); let pattern = identifyPattern(currentLineText); if (pattern) { let currentNumber = currentLineText.match(/^[\w\u4e00-\u9fa5]+/)?.[0]; // 提取序号部分 // 标点符号 let punctuation = currentLineText.match(/^[\w\u4e00-\u9fa5]+[\.\、]/)?.[0].slice(-1) || '.'; if (!currentNumber) return; // 如果没有序号,不进行处理 let nextNumber = getNextNumber(currentNumber, punctuation, pattern); if (nextNumber !== null) { let insertPosition = state.doc.lineAt(toB).to; // 新行的开始位置 let tChanges = { from: insertPosition, to: insertPosition, insert: nextNumber + (punctuation === "、" ? "" : " ") }; changes.push(tChanges); // 注意:这里需要有适当的方式来更新编辑器视图(view) } } } }); return changes; } ```
ChatGPT
ChatGPT

为了在 checkForEnter 函数中先检测成对括号的存在,并根据这些括号进行内容分类,然后再进行内容判断,我们可以添加一些逻辑来实现这个需求。这个逻辑将在调用 identifyPattern 之前执行,用于处理成对的括号,并暂时移除它们以进行后续的模式识别。

具体来说,我们可以:

  1. 检测成对括号:在 identifyPattern 调用之前,检查文本中是否存在成对的 (...)、( ... )、 或 [ ... ] 括号。
  2. 移除成对括号:如果存在成对的括号,暂时从文本中移除它们,然后再进行内容的模式识别。
  3. 还原括号:在确定了模式后,我们需要还原原来的括号格式。

下面是修改后的 checkForEnter 函数:

typescript
function checkForEnter(transaction: Transaction, state: EditorState) { const changes: ChangeSpec[] = []; transaction.changes.iterChanges((fromA, toA, fromB, toB, inserted) => { let text = inserted.toString(); if (text.includes('\n')) { // 检测到回车 let currentLineStart = state.doc.lineAt(fromA).from; let currentLineText = state.doc.sliceString(currentLineStart, fromA); // 检测并处理成对括号 let bracketPattern = /(\(.*\)|\(.*\)|\&#8203;``【oaicite:0】``&#8203;|\[.*\])/; let hasBrackets = bracketPattern.test(currentLineText); let originalBrackets = hasBrackets ? currentLineText.match(bracketPattern)[0] : ''; let textWithoutBrackets = hasBrackets ? currentLineText.replace(bracketPattern, '') : currentLineText; let pattern = identifyPattern(textWithoutBrackets); if (pattern) { let currentNumber = textWithoutBrackets.match(/^[\w\u4e00-\u9fa5]+/)?.[0]; // 提取序号部分 let punctuation = textWithoutBrackets.match(/^[\w\u4e00-\u9fa5]+[\.\、]/)?.[0].slice(-1) || '.'; if (!currentNumber) return; // 如果没有序号,不进行处理 let nextNumber = getNextNumber(currentNumber, punctuation, pattern); if (nextNumber !== null) { // 如果存在成对括号,还原它们 nextNumber = hasBrackets ? originalBrackets.replace(/.*?([\w\u4e00-\u9fa5]+).*?/, nextNumber) : nextNumber; let insertPosition = state.doc.lineAt(toB).to; // 新行的开始位置 let tChanges = { from: insertPosition, to: insertPosition, insert: nextNumber + (punctuation === "、" ? "" : " ") }; changes.push(tChanges); } } } }); return changes; }

在这段代码中,我们首先检测文本中是否存在成对的括号。如果存在,我们将括号暂时从文本中移除,以便进行模式识别。之后,我们再将这些括号还原到识别出的新序号中。这样可以确保成对括号的格式在处理过程中保持一致。

Anonymous
成对的括号应该只看开始的第一个字符是否是括号的起始,否则的话不处理才对,因为你这样会意外处理不在行首的括号
ChatGPT
ChatGPT

您的观点是正确的。为了避免处理不在行首的括号,我们应该只检测行首的括号。在这种情况下,我们将使用一个正则表达式来匹配行首的成对括号,并在此基础上进行进一步的处理。

下面是针对您需求的 checkForEnter 函数的更新:

typescript
function checkForEnter(transaction: Transaction, state: EditorState) { const changes: ChangeSpec[] = []; transaction.changes.iterChanges((fromA, toA, fromB, toB, inserted) => { let text = inserted.toString(); if (text.includes('\n')) { // 检测到回车 let currentLineStart = state.doc.lineAt(fromA).from; let currentLineText = state.doc.sliceString(currentLineStart, fromA); // 检测行首的成对括号 let bracketPattern = /^(?:\(|\(|\&#8203;``【oaicite:0】``&#8203;|\])/; let bracketMatch = currentLineText.match(bracketPattern); let hasBrackets = bracketMatch != null; let textWithoutBrackets = hasBrackets ? currentLineText.replace(bracketPattern, '$1') : currentLineText; let pattern = identifyPattern(textWithoutBrackets); if (pattern) { let currentNumber = textWithoutBrackets.match(/^[\w\u4e00-\u9fa5]+/)?.[0]; // 提取序号部分 let punctuation = textWithoutBrackets.match(/^[\w\u4e00-\u9fa5]+[\.\、]/)?.[0].slice(-1) || '.'; if (!currentNumber) return; // 如果没有序号,不进行处理 let nextNumber = getNextNumber(currentNumber, punctuation, pattern); if (nextNumber !== null) { // 如果存在成对括号,还原它们 nextNumber = hasBrackets ? bracketMatch[0].replace(bracketMatch[1], nextNumber) : nextNumber; let insertPosition = state.doc.lineAt(toB).to; // 新行的开始位置 let tChanges = { from: insertPosition, to: insertPosition, insert: nextNumber + (punctuation === "、" ? "" : " ") }; changes.push(tChanges); } } } }); return changes; }

这个更新确保只有当行首存在成对括号时,才会进行括号的处理。如果存在成对括号,它们将被暂时移除以进行模式识别,然后在生成新的序号时再加回去。这应该能够满足您的需求,避免意外处理不在行首的括号。

|Terms of use|Privacy policy|