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

commonMain.find.FindSamples.kt Maven / Gradle / Ivy

There is a newer version: 0.0.88
Show newest version
@file:Suppress("unused")

package pl.mareklangiewicz.kommand.find

import kotlinx.coroutines.flow.*
import okio.Path
import pl.mareklangiewicz.annotations.DelicateApi
import pl.mareklangiewicz.kground.*
import pl.mareklangiewicz.kground.io.P
import pl.mareklangiewicz.kground.io.PRel
import pl.mareklangiewicz.kommand.*
import pl.mareklangiewicz.kommand.find.FindExpr.*
import pl.mareklangiewicz.kommand.find.FindOpt.*
import pl.mareklangiewicz.kommand.samples.*
import pl.mareklangiewicz.text.*
import pl.mareklangiewicz.udata.strf

// FIXME_later: use UFileSys.pathToUserHome, and generally use Path type
val myHomePath = "/home/marek".P
val myTmpPath = myHomePath / "tmp"
val myKotlinPath = myHomePath/ "code/kotlin"
val myDepsKtPath = myKotlinPath/ "DepsKt"
val myAbcdKPath = myKotlinPath/ "AbcdK"
val myKGroundPath = myKotlinPath / "KGround"
val myKommandLinePath = myKotlinPath / "KommandLine"

@OptIn(DelicateApi::class)
data object FindSamples {

  val findAbcIgnoreCase =
    find(myAbcdKPath, NameBase("*abc*", ignoreCase = true)) s
      "find $myAbcdKPath -iname *abc*"

  val findAbcWithFollowSymLinksAndOptimisation2 =
    find(myAbcdKPath, NameBase("*abc*")) { -SymLinkFollowAlways; -Optimisation(2) } s
      "find -L -O2 $myAbcdKPath -name *abc*"

  val findSomeSamples =
    findRegularNameBase(myKommandLinePath, "*Samples.kt") s
      "find $myKommandLinePath -name *Samples.kt -type f"

  val findBigFiles =
    find(PRel, FileSize(NumArg.MoreThan(100), 'M')) s
      "find . -size +100M"

  val findAndPrint0AbcFilesAndTheirSizes =
    findTypeNameBase(myAbcdKPath, "f", "*abc*", whenFoundPrintF = "%p\\0%s\\0") s
      "find $myAbcdKPath -name *abc* -type f -printf %p\\0%s\\0"

  val findSymLinksToKtsFilesInKGround =
    find(myKGroundPath, SymLinkTo("*.kts")) s
      "find $myKGroundPath -lname *.kts"

  val findDepthMax2FilesInDepsKtAndRunFileOnEach =
    find(myDepsKtPath, DepthMax(2), ActExec(kommand("file", "{}"))) s
      "find $myDepsKtPath -maxdepth 2 -execdir file {} ;"

  // WARNING: Dangerous sample! If executed, it can automatically delete a lot of files!! (but it's just tmp dir)
  val findAndDeleteAllBigFiles =
    find(myTmpPath, FileSize(NumArg.MoreThan(100), 'M'), ActPrint, ActDelete) s
      "find $myTmpPath -size +100M -print -delete"

  val findInKotlinKtFilesModifiedIn24h =
    find(
      myKotlinPath,
      OpParent(NameBase("build"), FileType("d"), ActPrune, AlwaysFalse),
      OpOr,
      OpParent(NameBase("*.kt"), ModifTime24h(NumArg.Exactly(0)), ActPrint),
    ) s
      "find $myKotlinPath ( -name build -type d -prune -false ) -o ( -name *.kt -mtime 0 -print )"

  val findInKotlinDirBuildDirs =
    findDirNameBase(myKotlinPath, "build", whenFoundPrune = true) s
      "find $myKotlinPath -name build -type d -print -prune"

  val findInKotlinDirNodeModulesDirs =
    findDirNameBase(myKotlinPath, "node_modules", whenFoundPrune = true) s
      "find $myKotlinPath -name node_modules -type d -print -prune"

  val findInKotlinDirBoringDirs =
    findBoringCodeDirs(myKotlinPath) s
      "find $myKotlinPath -regex .*/\\(build\\|node_modules\\|\\.gradle\\) -type d -print -prune"

  val findMyLastWeekKotlinCode =
    findMyKotlinCode(withModifTime24h = NumArg.LessThan(8)) s
      "find $myKotlinPath ( ( -name build -type d -prune -false ) -o ( -path */src/*/kotlin/* -name *.kt -type f -mtime -8 -print ) )"

  val findTypicalDetailsTableInParentDir =
    findTypicalDetailsTable("..".P) ts
      """find .. -name * -type f -printf """ +
      """%A+\0\0%C+\0\0%T+\0\0%B+\0\0%d\0\0%s\0\0%h\0\0%f\0\0%p\0\0%g\0\0%u\0\0%m\0\0%M\0\n"""
  // Note: this expected lineRaw was just copied and pasted from actual result (somewhat bad practice),
  // but the point is to have it here as kinda "screenshot" and to be noticed when sth changes.

}

/** Usually to exclude from some indexing. */
@OptIn(DelicateApi::class)
fun findBoringCodeDirs(
  path: Path,
  boringCodeDirRegexes: List = listOf("build", "node_modules", "\\.gradle"),
  // order is important build before node_modules, because usually node_modules are inside build,
  // so no need to search for it it as it will be marked as boring anyway (whole build pruned) in such case
) = findDirRegex(
  path,
  nameRegex = boringCodeDirRegexes.joinToString("\\|", prefix = ".*/\\(", postfix = "\\)"),
  whenFoundPrune = true,
)

@OptIn(DelicateApi::class)
fun findBoringCodeDirsAndReduceAsExcludedFoldersXml(
  path: Path = myKotlinPath,
  indent: String = "      ",
  urlPrefix: String = "file://\$MODULE_DIR\$",
  withOnEachLog: Boolean = false,
) =
  findBoringCodeDirs(path).reducedOut {
    this
      .map { it.removeReqPrefix(path.strf) }
      .map { "$indent" }
      .let { if (withOnEachLog) it.onEachLog() else it }
      .toList()
      .sorted()
      .joinToString("\n")
  }

/**
 * Note: null means do not use given test/filter/limit at all.
 * @param withModifTime24h
 *   Exactly(0) will return files modified within last 24h,
 *   LessThan(7) for files modified in last few days.
 */
@OptIn(DelicateApi::class)
fun findMyKotlinCode(
  kotlinCodePath: Path = myKotlinPath,
  vararg useNamedArgs: Unit,
  withGrepRE: String? = null,
  withNameRegex: String? = null,
  withNameBase: String? = "*.kt",
  withNameFull: String? = "*/src/*/kotlin/*",
  withPruneBuildDirsNamed: String? = "build",
  withModifTime24h: NumArg? = null,
) = find(
  kotlinCodePath,
  fexprWithPrunedDirs(
    withPruneBuildDirsNamed,
    withNameRegex?.let(::NameRegex),
    withNameFull?.let(::NameFull),
    withNameBase?.let(::NameBase),
    FileType("f"),
    withModifTime24h?.let(::ModifTime24h),
    fexprActExecGrepPrintIfMatched(withGrepRE),
  ),
)

@DelicateApi
private fun fexprActExecGrepPrintIfMatched(grepRE: String?) =
  if (grepRE == null) ActPrint
  else OpParent(
    ActExec(grepQuietly(grepRE, "{}".P)), ActPrint,
  )

/**
 * @param prunedDirsNamed null means do not prune anything at all
 * A lot of OpParent here, but it's necessary until I have better operators wrappers
 * (see fixme_comment above Find.kt:operator fun FindExpr.not)
 * @param expr Expression (joined by "and" by default), null elements are ignored
 */
@DelicateApi
private fun fexprWithPrunedDirs(prunedDirsNamed: String?, vararg expr: FindExpr?) = OpParent(
  prunedDirsNamed?.let {
    OpParent(
      NameBase(it), FileType("d"),
      ActPrune, AlwaysFalse,
    )
  } ?: AlwaysFalse,
  OpOr, OpParent(expr.filterNotNull()),
)

// TODO_later: full grep kommand wrapper class+funs.
@OptIn(DelicateApi::class)
private fun grepQuietly(regexp: String, vararg files: Path) =
  kommand("grep", "-q", regexp, *files.map { it.strf }.toTypedArray())

@OptIn(DelicateApi::class)
private fun grepWithDetails(regexp: String, vararg files: Path) =
  kommand("grep", "-H", "-n", "-T", "-e", regexp, *files.map { it.strf }.toTypedArray())





© 2015 - 2024 Weber Informatics LLC | Privacy Policy