All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.ure.UreLogseq.kt Maven / Gradle / Ivy

There is a newer version: 0.0.87
Show newest version
@file:OptIn(NotPortableApi::class)

package pl.mareklangiewicz.ure.logseq

import okio.Path
import pl.mareklangiewicz.annotations.NotPortableApi
import pl.mareklangiewicz.bad.reqTrue
import pl.mareklangiewicz.io.processSingleFile
import pl.mareklangiewicz.io.processWholeTree
import pl.mareklangiewicz.kground.io.localUFileSys
import pl.mareklangiewicz.ure.*

/**
 * Micro regular expressions for markdown/yaml content like in Logseq graphs. https://logseq.com/
 * TODO_later: Separate into more general/robust UreMarkdown.kt and UreYaml.kt
 */

// TODO_later: change ure defs below to functions for any block and it's properties (and optional sub-block tree/list).
//   Taking ureBlock as parameter (default ureWhatevaInLine). Then just use it providing #card like ure for ureBlock..

val ureCardFirstLineContent = ure {
  +chDash
  +chSpace
  +ureWhatevaInLine().withName("cardQuestion")
  +chSpace.timesAny()
  +ureText("#card")
}

val ureCardFirstLine = ureLineWithContent(ureCardFirstLineContent)

val urePropContent = ure {
  +ureIdent(allowDashesInside = true).withName("cardPropName")
  +ureText(":: ")
  +ureWhatevaInLine().withName("cardPropValue")
}

val urePropLine = ureLineWithContent(urePropContent)

val urePropLines = urePropLine.timesAny().withName("cardPropLines")

val ureCard = ure {
  +ureCardFirstLine
  +urePropLines
  // I don't want to complicate YET with capturing answer (would have to rely on indentation level..)
}

// TODO_someday: add full answer too
data class Card(val question: String, val props: Map)

suspend fun Path.processAllCardsInLogseqGraph(
  process: suspend (file: Path, card: Card) -> Unit,
) {
  val fs = localUFileSys()
  fs.exists(this / "logseq").reqTrue { "Doesn't look like a Logseq Graph: $this/logseq doesn't exist." }
  (this / "pages").processAllCardsInAllMarkdownFiles(process)
  (this / "journals").processAllCardsInAllMarkdownFiles(process)
}

suspend fun Path.processAllCardsInAllMarkdownFiles(
  process: suspend (file: Path, card: Card) -> Unit,
) = processWholeTree { file, _, content ->
  file.name.endsWith(".md") || return@processWholeTree null
  file.processAllCardsInSingleFile { process(file, it) }
  null
}

suspend fun Path.processAllCardsInSingleFile(process: suspend (card: Card) -> Unit) =
  processSingleFile { content ->
    content.findAll(ureCard).forEach {
      val cardQuestion by it
      val cardPropLines by it
      val props: Map = cardPropLines.findAll(urePropLine).associate {
        val cardPropName by it
        val cardPropValue by it
        cardPropName to cardPropValue
      }
      process(Card(cardQuestion, props))
    }
    null
  }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy