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

ammonite.shell.ShellSession.scala Maven / Gradle / Ivy

The newest version!
package ammonite.shell

import java.nio.file.NotDirectoryException
import java.nio.file.attribute.PosixFilePermission

import ammonite.ops._
import ammonite.repl.FrontEndUtils
import pprint.{Config, PPrinter}

import scala.util.Try

case class ShellSession() extends OpsAPI {
  var wd0 = pwd
  /**
    * The current working directory of the shell, that will get picked up by
    * any ammonite.ops commands you use
    */
  implicit def wd = wd0
  /**
    * Change the working directory `wd`; if the provided path is relative it
    * gets appended on to the current `wd`, if it's absolute it replaces.
    */
  val cd = (arg: Path) => {
    /*
     * `arg` should be a directory or a symlink to a directory
     * `realPath will be None if that is not the case,
     * otherwise - Some(realPath)
     */
    val realPath = Option(arg)
      .filter(_.isDir)
      .orElse(arg.tryFollowLinks.filter(_.isDir))

    realPath match {
      case None => throw new NotDirectoryException(arg.toString)
      case Some(path) => wd0 = arg; wd0
    }
  }

  implicit def Relativizer[T](p: T)(implicit b: Path, f: T => RelPath): Path = b/f(p)
}

object PPrints{

  implicit def lsSeqRepr: PPrinter[LsSeq] =
    PPrinter { (t: LsSeq, c: Config) =>
      val snippets = for(p <- t) yield {
        c.colors.literalColor(pprint.tokenize(p relativeTo t.base)(implicitly, c).mkString)
      }
      Iterator("\n") ++ FrontEndUtils.tabulate(snippets,FrontEndUtils.width)
    }

  def reprSection(s: String, cfg: pprint.Config) = {
    val validIdentifier = "([a-zA-Z_][a-zA-Z_0-9]+)".r
    if (validIdentifier.findFirstIn(s) == Some(s)){
      implicitly[pprint.PPrinter[scala.Symbol]].render(Symbol(s), cfg)
    }else{
      implicitly[pprint.PPrinter[String]].render(s, cfg)
    }
  }

  implicit val relPathRepr = pprint.PPrinter[ammonite.ops.RelPath]{(p, c) =>
    Iterator(
      (Seq.fill(p.ups)("up") ++ p.segments.map(reprSection(_, c).mkString)).mkString("/")
    )
  }

  implicit def pathRepr = pprint.PPrinter[ammonite.ops.Path]{(p, c) =>
    Iterator("root") ++ p.segments.iterator.map("/" + reprSection(_, c).mkString)
  }
  implicit def commandResultRepr: PPrinter[CommandResult] =
    PPrinter[CommandResult]((x, c) =>
      x.chunks.iterator.flatMap { chunk =>
        val (color, s) = chunk match{
          case Left(s) => (c.colors.literalColor, s)
          case Right(s) => (fansi.Color.Red, s)
        }
        Iterator("\n", color(new String(s.array)).render)
      }
    )
  implicit def permissionPPrintConfig: PPrinter[PermSet] =
    PPrinter[PermSet]{ (p, c) =>
      Iterator(
        "rwxrwxrwx".zip(PosixFilePermission.values()).map{ case (k, v) =>
          if(p.contains(v)) k else '-'
        }.mkString)
    }

  implicit val defaultHighlightColor = {
    ammonite.runtime.tools.GrepResult.Color(
      fansi.Color.Blue ++ fansi.Back.Yellow,
      fansi.Color.Yellow
    )
  }
}
trait OpsAPI{
  /**
    * The current working directory of the shell, that will get picked up by
    * any [[Relativizer]] below, and can be modified using [[cd]]
    */
  implicit def wd: Path
  /**
    * Change the working directory `wd`; if the provided path is relative it
    * gets appended on to the current `wd`, if it's absolute it replaces. It
    * returns the resultant absolute path.
    */
  val cd: ammonite.ops.Path => ammonite.ops.Path

  /**
    * Allows you to use relative paths (and anything convertible to a relative
    * path) as absolute paths when working in the REPL. Note that this isn't
    * available when using Ammonite-Ops in a standalone project! In such cases,
    * it's good practice to convert paths from relative to absolute explicitly.
    */
  implicit def Relativizer[T](p: T)(implicit b: Path, f: T => RelPath): Path

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy