Entries in bibtex-entries.first should also be sorted, with tests

This commit is contained in:
James Yu 2023-01-12 22:45:49 +08:00
parent be0b0c2eca
commit 2cb3442255
2 changed files with 93 additions and 50 deletions

View File

@ -88,42 +88,48 @@ export class BibtexUtils {
* @param keys Array of sorting keys
*/
static bibtexSort(duplicates: Set<bibtexParser.Entry>, config: BibtexFormatConfig): (a: BibtexEntry, b: BibtexEntry) => number {
const keys = config.sort
return (a, b) => {
let r = 0
for (const key of keys) {
// Select the appropriate sort function
switch (key) {
case 'key':
r = BibtexUtils.bibtexSortByKey(a, b, config)
break
case 'year-desc':
r = -BibtexUtils.bibtexSortByField('year', a, b, config)
break
case 'type':
r = BibtexUtils.bibtexSortByType(a, b, config)
break
default:
r = BibtexUtils.bibtexSortByField(key, a, b, config)
}
// Compare until different
if (r !== 0) {
break
}
}
if (r === 0 && bibtexParser.isEntry(a)) {
// It seems that items earlier in the list appear as the variable b here, rather than a
duplicates.add(a)
}
return r
return (a, b) => this.bibtexSortSwitch(a, b, duplicates, config)
}
private static bibtexSortSwitch(a: BibtexEntry, b: BibtexEntry, duplicates: Set<bibtexParser.Entry>, config: BibtexFormatConfig): number {
const firstEntryCompare = BibtexUtils.bibtexSortFirstEntries(config.firstEntries, a, b)
if (firstEntryCompare !== 0) {
return firstEntryCompare
}
const keys = config.sort
let r = 0
for (const key of keys) {
// Select the appropriate sort function
switch (key) {
case 'key':
r = BibtexUtils.bibtexSortByKey(a, b)
break
case 'year-desc':
r = -BibtexUtils.bibtexSortByField('year', a, b, config)
break
case 'type':
r = BibtexUtils.bibtexSortByType(a, b)
break
default:
r = BibtexUtils.bibtexSortByField(key, a, b, config)
}
// Compare until different
if (r !== 0) {
break
}
}
if (r === 0 && bibtexParser.isEntry(a)) {
// It seems that items earlier in the list appear as the variable b here, rather than a
duplicates.add(a)
}
return r
}
/**
* If one of the entries `a` or `b` is in `firstEntries` or `stickyEntries`, return an order.
* Otherwise, return undefined
*/
private static bibtexSortFirstEntries(firstEntries: string[], a: BibtexEntry, b: BibtexEntry): number | undefined {
private static bibtexSortFirstEntries(firstEntries: string[], a: BibtexEntry, b: BibtexEntry): number {
const aFirst = firstEntries.includes(a.entryType)
const bFirst = firstEntries.includes(b.entryType)
if (aFirst && !bFirst) {
@ -133,13 +139,15 @@ export class BibtexUtils {
} else if (aFirst && bFirst) {
const aIndex = firstEntries.indexOf(a.entryType)
const bIndex = firstEntries.indexOf(b.entryType)
if (aIndex <= bIndex) {
if (aIndex < bIndex) {
return -1
} else {
} else if (aIndex > bIndex) {
return 1
} else {
return 0
}
}
return undefined
return 0
}
/**
@ -147,11 +155,6 @@ export class BibtexUtils {
* @param fieldName which field name to sort by
*/
private static bibtexSortByField(fieldName: string, a: BibtexEntry, b: BibtexEntry, config: BibtexFormatConfig): number {
const firstEntriesOrder = BibtexUtils.bibtexSortFirstEntries(config.firstEntries, a, b)
if (firstEntriesOrder) {
return firstEntriesOrder
}
let fieldA: string = ''
let fieldB: string = ''
@ -179,8 +182,7 @@ export class BibtexUtils {
return fieldA.localeCompare(fieldB)
}
private static bibtexSortByKey(a: BibtexEntry, b: BibtexEntry, config: BibtexFormatConfig): number {
const firstEntriesOrder = BibtexUtils.bibtexSortFirstEntries(config.firstEntries, a, b)
private static bibtexSortByKey(a: BibtexEntry, b: BibtexEntry): number {
let aKey: string | undefined = undefined
let bKey: string | undefined = undefined
if (bibtexParser.isEntry(a)) {
@ -189,9 +191,6 @@ export class BibtexUtils {
if (bibtexParser.isEntry(b)) {
bKey = b.internalKey
}
if (firstEntriesOrder) {
return firstEntriesOrder
}
if (!aKey && !bKey) {
return 0
} else if (!aKey) {
@ -203,11 +202,7 @@ export class BibtexUtils {
}
}
private static bibtexSortByType(a: BibtexEntry, b: BibtexEntry, config: BibtexFormatConfig): number {
const firstEntriesOrder = BibtexUtils.bibtexSortFirstEntries(config.firstEntries, a, b)
if (firstEntriesOrder) {
return firstEntriesOrder
}
private static bibtexSortByType(a: BibtexEntry, b: BibtexEntry): number {
return a.entryType.localeCompare(b.entryType)
}

View File

@ -35,6 +35,9 @@ suite('Formatter test suite', () => {
await vscode.workspace.getConfiguration('latex-workshop').update('bibtex-format.handleDuplicates', undefined)
await vscode.workspace.getConfiguration('latex-workshop').update('bibtex-format.sort.enabled', undefined)
await vscode.workspace.getConfiguration('latex-workshop').update('bibtex-format.align-equal.enabled', undefined)
await vscode.workspace.getConfiguration('latex-workshop').update('bibtex-entries.first', undefined)
await vscode.workspace.getConfiguration('latex-workshop').update('bibtex-fields.sort.enabled', undefined)
await vscode.workspace.getConfiguration('latex-workshop').update('bibtex-fields.order', undefined)
if (path.basename(fixture) === 'testground') {
rimraf(fixture + '/{*,.vscode/*}', (e) => {if (e) {console.error(e)}})
@ -165,7 +168,7 @@ suite('Formatter test suite', () => {
assert.notStrictEqual(lines[5].trim().slice(-1), ',')
})
test.run(suiteName, fixtureName, 'test bibtex sort with `bibtex-format.sortby`', async () => {
test.run(suiteName, fixtureName, 'test bibtex sorter with `bibtex-format.sortby`', async () => {
await test.load(fixture, [{src: 'formatter/bibtex_base.bib', dst: 'main.bib'}])
await test.open(fixture, 'main.bib')
@ -210,7 +213,7 @@ suite('Formatter test suite', () => {
assert.ok(entries[2].includes('MR1241645'))
})
test.run(suiteName, fixtureName, 'test bibtex formatter with `bibtex-format.handleDuplicates`', async () => {
test.run(suiteName, fixtureName, 'test bibtex sorter with `bibtex-format.handleDuplicates`', async () => {
await test.load(fixture, [{src: 'formatter/bibtex_dup.bib', dst: 'main.bib'}])
await test.open(fixture, 'main.bib')
@ -254,7 +257,7 @@ suite('Formatter test suite', () => {
assert.ok(entries[0].includes('MR1241645'))
})
test.only(suiteName, fixtureName, 'test bibtex formatter with `bibtex-format.align-equal.enabled`', async () => {
test.run(suiteName, fixtureName, 'test bibtex formatter with `bibtex-format.align-equal.enabled`', async () => {
await test.load(fixture, [{src: 'formatter/bibtex_base.bib', dst: 'main.bib'}])
await test.open(fixture, 'main.bib')
@ -273,4 +276,49 @@ suite('Formatter test suite', () => {
assert.ok(lines)
assert.ok(allEqual(lines.filter(line => line.includes('=')).map(line => line.indexOf('='))))
})
test.run(suiteName, fixtureName, 'test bibtex sorter with `bibtex-entries.first`', async () => {
await test.load(fixture, [{src: 'formatter/bibtex_base.bib', dst: 'main.bib'}])
await test.open(fixture, 'main.bib')
await vscode.workspace.getConfiguration('latex-workshop').update('bibtex-entries.first', ['book'])
await vscode.workspace.getConfiguration('latex-workshop').update('bibtex-format.sortby', ['key'])
await vscode.commands.executeCommand('latex-workshop.bibsort')
await test.sleep(1000)
const lines = vscode.window.activeTextEditor?.document.getText().split('\n')
assert.ok(lines)
const entries = lines.filter(line => line.includes('@'))
assert.ok(entries[2].includes('art1'))
assert.ok(entries[0].includes('lamport1994latex'))
assert.ok(entries[1].includes('MR1241645'))
})
test.run(suiteName, fixtureName, 'test bibtex aligner with `bibtex-fields.sort.enabled` and `bibtex-fields.order`', async () => {
await test.load(fixture, [{src: 'formatter/bibtex_base.bib', dst: 'main.bib'}])
await test.open(fixture, 'main.bib')
await vscode.workspace.getConfiguration('latex-workshop').update('bibtex-fields.sort.enabled', true)
await vscode.commands.executeCommand('latex-workshop.bibalign')
await test.sleep(1000)
let lines = vscode.window.activeTextEditor?.document.getText().split('\n')
assert.ok(lines)
let entries = lines.filter(line => line.includes('='))
assert.ok(entries[0].includes('author'))
assert.ok(entries[1].includes('description'))
assert.ok(entries[2].includes('journal'))
assert.ok(entries[3].includes('title'))
assert.ok(entries[4].includes('year'))
await vscode.workspace.getConfiguration('latex-workshop').update('bibtex-fields.order', ['title', 'author', 'year'])
await vscode.commands.executeCommand('latex-workshop.bibalign')
await test.sleep(1000)
lines = vscode.window.activeTextEditor?.document.getText().split('\n')
assert.ok(lines)
entries = lines.filter(line => line.includes('='))
assert.ok(entries[0].includes('title'))
assert.ok(entries[1].includes('author'))
assert.ok(entries[2].includes('year'))
assert.ok(entries[3].includes('description'))
assert.ok(entries[4].includes('journal'))
})
})