Skip to content

Commit d30801e

Browse files
committed
feat(commands): split & join by sentences
1 parent 5fed9a4 commit d30801e

File tree

2 files changed

+71
-17
lines changed

2 files changed

+71
-17
lines changed

src/app.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { BlockEntity, SettingSchemaDesc } from '@logseq/libs/dist/LSPlugin.user'
22

33
import {
4-
ICON, editNextBlockCommand, editPreviousBlockCommand, joinBlocksCommand,
4+
ICON, editNextBlockCommand, editPreviousBlockCommand, joinAsSentences_Map, joinBlocksCommand,
55
joinViaCommas_Attach,
66
joinViaNewLines_Attach,
77
joinViaNewLines_Map,
8+
joinViaSpaces_Attach,
89
lastChildBlockCommand, magicJoinCommand, magicSplit,
910
moveToBottomOfSiblingsCommand,
1011
moveToTopOfSiblingsCommand,
@@ -13,7 +14,7 @@ import {
1314
parentBlockCommand,
1415
previousSiblingBlockCommand,
1516
reverseBlocksCommand, shuffleBlocksCommand, sortBlocksCommand, splitBlocksCommand,
16-
splitByLines, splitByWords, toggleAutoHeadingCommand,
17+
splitByLines, splitBySentences, splitByWords, toggleAutoHeadingCommand,
1718
} from './commands'
1819
import { getChosenBlocks, p, scrollToBlock } from './utils'
1920

@@ -150,24 +151,33 @@ async function main() {
150151
keybinding: {},
151152
}, (e) => splitBlocksCommand(magicSplit, setting_storeChildBlocksIn(), true) )
152153

154+
logseq.App.registerCommandPalette({
155+
label: ICON + ' Split by sentences', key: 'mc-5-split-7-by-sentences',
156+
// @ts-expect-error
157+
keybinding: {},
158+
}, (e) => splitBlocksCommand(splitBySentences, setting_storeChildBlocksIn()))
159+
logseq.App.registerCommandPalette({
160+
label: ICON + ' Split by sentences (with nested)', key: 'mc-5-split-8-by-sentences-nested',
161+
// @ts-expect-error
162+
keybinding: {},
163+
}, (e) => splitBlocksCommand(
164+
splitBySentences, setting_storeChildBlocksIn(), true))
165+
153166

154167
// Joining
155168
logseq.App.registerCommandPalette({
156169
label: ICON + ' Join via spaces', key: 'mc-6-join-1-spaces',
157170
// @ts-expect-error
158171
keybinding: {},
159-
}, (e) => joinBlocksCommand(
160-
false,
161-
(content, level, children) => (content ? content + ' ' : '') + children.join(' '),
162-
))
172+
}, (e) => joinBlocksCommand(false, joinViaSpaces_Attach))
163173

164174
logseq.App.registerCommandPalette({
165-
label: ICON + ' Join selected together via commas (with respect to root block)', key: 'mc-6-join-2-commas',
175+
label: ICON + ' Join together via commas (with respect to root block)', key: 'mc-6-join-2-commas',
166176
// @ts-expect-error
167177
keybinding: {},
168178
}, (e) => joinBlocksCommand(false, joinViaCommas_Attach))
169179
logseq.App.registerCommandPalette({
170-
label: ICON + ' Join selected independently via commas (with respect to root block)', key: 'mc-6-join-3-commas-independently',
180+
label: ICON + ' Join independently via commas (with respect to root block)', key: 'mc-6-join-3-commas-independently',
171181
// @ts-expect-error
172182
keybinding: {},
173183
}, (e) => joinBlocksCommand(true, joinViaCommas_Attach))
@@ -184,16 +194,28 @@ async function main() {
184194
}, (e) => joinBlocksCommand(false, joinViaNewLines_Attach, joinViaNewLines_Map))
185195

186196
logseq.App.registerCommandPalette({
187-
label: ICON + ' Magic Join selected together', key: 'mc-6-join-6-magic',
197+
label: ICON + ' Magic Join', key: 'mc-6-join-6-magic',
188198
// @ts-expect-error
189199
keybinding: {},
190200
}, (e) => magicJoinCommand(false))
191201
logseq.App.registerCommandPalette({
192-
label: ICON + ' Magic Join selected independently', key: 'mc-6-join-7-magic-independently',
202+
label: ICON + ' Magic Join (independently)', key: 'mc-6-join-7-magic-independently',
193203
// @ts-expect-error
194204
keybinding: {},
195205
}, (e) => magicJoinCommand(true))
196206

207+
logseq.App.registerCommandPalette({
208+
label: ICON + ' Join as sentences', key: 'mc-6-join-8-sentences',
209+
// @ts-expect-error
210+
keybinding: {},
211+
}, (e) => joinBlocksCommand(false, joinViaSpaces_Attach, joinAsSentences_Map, {shouldHandleSingleBlock: true}))
212+
logseq.App.registerCommandPalette({
213+
label: ICON + ' Join as sentences (independently)', key: 'mc-6-join-9-sentences-independently',
214+
// @ts-expect-error
215+
keybinding: {},
216+
}, (e) => joinBlocksCommand(true, joinViaSpaces_Attach, joinAsSentences_Map, {shouldHandleSingleBlock: true}))
217+
218+
197219

198220
// Navigation
199221
logseq.App.registerCommandPalette({

src/commands.ts

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,13 @@ export function splitByWords(text: string): IBatchBlock[] {
387387
return textBlocks.filter((tb) => !!tb).map((tb) => {return {content: tb}})
388388
}
389389

390+
export function splitBySentences(text: string): IBatchBlock[] {
391+
const textBlocks = text.split(/(?<=[.!?])\s+/)
392+
return textBlocks
393+
.map((tb) => tb.endsWith('.') ? tb.slice(0, -1) : tb)
394+
.map((tb) => {return {content: tb}})
395+
}
396+
390397
export function magicSplit(text: string): IBatchBlock[] {
391398
// add special types of ordered lists for parser to recognize it
392399
// (1) → 1)
@@ -554,6 +561,12 @@ export async function splitBlocksCommand(
554561
}
555562

556563

564+
export function joinAsSentences_Map(content, level): string {
565+
if (content && /(?<![.!?])$/.test(content))
566+
content += '.'
567+
return content
568+
}
569+
557570
export function joinViaNewLines_Attach(content, level, children): string {
558571
const childrenContent = children.join('\n')
559572
if (!content)
@@ -577,10 +590,19 @@ export function joinViaCommas_Attach(content, level, children): string {
577590
return prefix + children.join(', ')
578591
}
579592

593+
export function joinViaSpaces_Attach(content, level, children): string {
594+
if (children.length === 0)
595+
return content
596+
597+
const prefix = content ? content + ' ' : ''
598+
return prefix + children.join(' ')
599+
}
600+
580601
export async function joinBlocksCommand(
581602
independentMode: boolean,
582603
joinAttachCallback: (root: string, level: number, children: string[], block?: BlockEntity) => string,
583604
joinMapCallback?: (content: string, level: number, block: BlockEntity, parent?: BlockEntity) => string,
605+
opts: {shouldHandleSingleBlock: boolean} = {shouldHandleSingleBlock: false},
584606
) {
585607
let [ blocks, isSelectedState ] = await getChosenBlocks()
586608
if (blocks.length === 0)
@@ -598,9 +620,11 @@ export async function joinBlocksCommand(
598620

599621
if (blocks.length === 0)
600622
return
601-
if (blocks.length === 1)
602-
if (!blocks[0].children || blocks[0].children.length === 0)
603-
return // nothing to join
623+
624+
// ensure .children always is array
625+
for (const block of blocks)
626+
if (!block.children)
627+
block.children = []
604628

605629
independentMode = independentMode || blocks.length === 1
606630

@@ -641,6 +665,7 @@ export async function joinBlocksCommand(
641665
if (!noWarnings)
642666
return
643667

668+
644669
// check for properties
645670
for (const block of blocks) {
646671
const names = checkPropertyExistenceInTree(block as IBatchBlock, {skipRoot: independentMode})
@@ -684,15 +709,22 @@ export async function joinBlocksCommand(
684709

685710
if (independentMode) {
686711
for (const block of blocks) {
687-
if (!block.children || block.children.length === 0)
688-
continue // nothing to join
712+
// fix tsc error: non-undefined
713+
block.children = block.children!
714+
715+
if (block.children.length === 0) {
716+
if (!opts.shouldHandleSingleBlock)
717+
continue // nothing to join
718+
else
719+
block.children = [] // ensure non-null
720+
}
689721

690722
const content = reduceTree(block as IBatchBlock, {startLevel: 0})
691723
const properties = PropertiesUtils.fromCamelCaseAll(block.properties)
692724

693-
if (block._rootHasReferences) {
725+
if (block._rootHasReferences || block.children.length === 0) {
694726
await logseq.Editor.updateBlock(block.uuid, content, {properties})
695-
for (const child of block.children!)
727+
for (const child of block.children)
696728
await logseq.Editor.removeBlock((child as BlockEntity).uuid)
697729
} else {
698730
await insertBatchBlockBefore(block, {content, properties})

0 commit comments

Comments
 (0)