Skip to content

Instantly share code, notes, and snippets.

@7shi
Created March 25, 2010 02:53
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 7shi/343115 to your computer and use it in GitHub Desktop.
Save 7shi/343115 to your computer and use it in GitHub Desktop.
F# Interactiveの改造
#light
namespace Microsoft.FSharp.Compiler.Interactive
open System
open System.IO
open System.Text
open System.Collections.Generic
type ReadLineConsole(complete: (string option * string -> seq<string>)) as this =
let history = new List<string>()
let log = Path.Combine(Directory.GetCurrentDirectory(), "log.fsx")
let mutable complete = complete
do
if File.Exists(log) then this.AppendLog("")
this.AppendLog("// " + DateTime.Now.ToString())
member x.Complete with set(v) = (complete <- v)
member x.Prompt = "> "
member x.ReadLine() =
let count(s : string, ch : char) =
let mutable ret = 0
for c in s do if c = ch then ret <- ret + 1
ret
let getWords(s : string) =
let ret = new List<string>()
let rec getWords(p1, p2) =
if p2 >= s.Length || not (Char.IsLetterOrDigit(s.[p2])) then
if p1 < p2 then ret.Add(s.Substring(p1, p2 - p1))
if p2 < s.Length then getWords(p2 + 1, p2 + 1)
else
getWords(p1, p2 + 1)
getWords(0, 0)
ret
let lines = ref 0
let p1 = ref 0
let p2 = ref 0
let sb = new StringBuilder()
let rec readLine(indent : string) =
if indent <> "" || !lines > 0 then
Console.Write(indent + "- ")
let line = Console.ReadLine().Trim()
if indent = "" && line = "#h" then
for cmd in history do Console.WriteLine(cmd)
Console.Write(x.Prompt)
readLine(indent)
else if indent = "" && line.StartsWith("#cd ") then
Directory.SetCurrentDirectory(line.Substring(4));
Console.Write(x.Prompt)
readLine(indent)
else if indent = "" && line = "#pwd" then
Console.WriteLine(Directory.GetCurrentDirectory())
Console.Write(x.Prompt)
readLine(indent)
else if indent = "" && line = "#dir" then
let di = new DirectoryInfo(Directory.GetCurrentDirectory())
Console.WriteLine(di.FullName)
for di in di.GetDirectories() do
Console.WriteLine("{0}/", di)
for fi in di.GetFiles() do
Console.WriteLine(fi)
Console.Write(x.Prompt)
readLine(indent)
else if String.IsNullOrEmpty(line) then
()
else
if sb.Length > 0 then sb.AppendLine() |> ignore
sb.Append(indent + line) |> ignore
lines := !lines + 1
if line.StartsWith("//") then
readLine(indent)
else
let d1 = count(line, '(') - count(line, ')')
let d2 = count(line, '[') - count(line, ']')
p1 := !p1 + d1
p2 := !p2 + d2
let words = getWords(line)
let w1 = if words.Count > 0 then words.[words.Count - 1] else ""
if (!p1 <> 0 && d1 <> 0) || (!p2 <> 0 && d2 <> 0)
|| line.EndsWith("=") || line.EndsWith("->")
|| w1 = "in" || w1 = "do" || w1 = "then" || w1 = "else"
then
readLine(indent + " ")
let w2 = if words.Count > 0 then words.[0] else ""
if !p1 <> 0 || !p2 <> 0 || indent <> ""
|| (line.EndsWith(";") && not(line.EndsWith(";;")))
|| (w2 = "if" && not(words.Contains("then") && words.Contains("else")))
|| w2 = "match"
then
readLine(indent)
readLine("")
let ret = sb.ToString()
history.Add(ret)
x.AppendLog(ret)
if ret.EndsWith(";;") then
ret
else
if !lines = 1 then
ret + ";;"
else
ret + Environment.NewLine + ";;"
member x.AppendLog(cmd : string) =
use fs = new FileStream(log, FileMode.Append)
use sw = new StreamWriter(fs)
sw.WriteLine(cmd)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment