Skip to content

Instantly share code, notes, and snippets.

@nafg
Created September 2, 2014 09:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nafg/a1c289c8fbded77534ff to your computer and use it in GitHub Desktop.
Save nafg/a1c289c8fbded77534ff to your computer and use it in GitHub Desktop.
Put IntelliJ projects in .desktop jumplist
import java.nio.file._
import java.nio.file.attribute.BasicFileAttributes
import scala.collection.convert.decorateAsJava._
val ideaFile = "/home/naftoli/.local/share/applications/jetbrains-idea-ce.desktop"
val file = io.Source.fromFile(ideaFile)
case class Section(head: Option[String], entries: Seq[Either[String, (String, String)]]) {
def +(x: Either[String, (String, String)]) = Section(head, entries :+ x)
override def toString = toLines.mkString("\n")
def toLines =
head.fold("")("[" + _ + "]") +: entries.map{
case Left(c) => s"$c"
case Right((k, v)) => s"$k=$v"
}
}
val header = """\[([^]]+)\]""".r
val kv = """([A-Za-z0-9-]+(\[\w+(_\w+)?(\.\w+)?(@\w+)?\])?) *= *(.*)""".r
def config(lines: List[String], acc: Vector[Section], sec: Section): Vector[Section] = lines match {
case Nil => acc :+ sec
case s :: rest =>
s.trim match {
case ss if s.startsWith("#") || s.isEmpty =>
config(rest, acc, sec + Left(s))
case header(name) =>
config(rest, acc :+ sec, Section(Some(name), Nil))
case kv(name, _, _, _, _, value) =>
config(rest, acc, sec + Right((name, value)))
}
}
val secs = config(file.getLines().toList, Vector.empty, Section(None, Nil))
var projs: List[Path] = Nil
Files.walkFileTree(Paths.get("/home/naftoli/dev"),
new SimpleFileVisitor[Path] {
override def preVisitDirectory(dir: Path, attrs: BasicFileAttributes) =
if (dir.toFile.getName == ".idea") {
projs ::= dir.getParent
FileVisitResult.SKIP_SIBLINGS
} else FileVisitResult.CONTINUE
}
)
val main = secs.find(_.head == Some("Desktop Entry")) getOrElse sys.error("No [Desktop Entry] section found")
val exec: String = main.entries.collectFirst{ case Right(("Exec", v)) => v } getOrElse sys.error("No Exec key found")
//TODO unescape \;
val actions: Seq[String] = main.entries.collectFirst{ case Right(("Actions", v)) => v.split(";").filter(_ != "").toList } getOrElse Nil
def putValue(key: String, value: String, sec: Section): Section =
sec.entries.toList.span(_.fold(_ => true, _._1 != key)) match {
case (xs, hit :: others) => sec.copy(entries = xs ::: Right((key, value)) :: others)
case (xs, Nil) => sec + Right((key, value))
}
def putActionsSections(ps: List[Path], secs: List[Section]): List[Section] = ps match {
case Nil => secs
case p :: rest =>
val cmd = exec.replace("%f", '"' + p.toAbsolutePath.toString + '"')
val name = p.toFile.getName
val applied = secs.span(_.head != Some("Desktop Action " + name)) match {
case (xs, hit :: others) =>
(xs :+ putValue("Exec", cmd, putValue("Name", name, hit))) ++: others
case (xs, Nil) =>
xs :+ Section(Some("Desktop Action " + name), Right(("Exec", cmd)) :: Right(("Name", name)) :: Nil)
}
putActionsSections(rest, applied)
}
val withActSecs = putActionsSections(projs, secs.toList)
//TODO escape ;
val allActs = (actions ++ projs.map(_.toFile.getName)).distinct.mkString("", ";", ";")
val mainWithActions = putValue("Actions", allActs, main)
val result = mainWithActions :: withActSecs.filter(_.head != Some("Desktop Entry"))
val lines = result.flatMap(_.toLines)
Files.write(Paths.get(ideaFile), lines.asJava)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment