[MLton] replaced tabs by spaces in source files
Stephen Weeks
MLton@mlton.org
Sat, 20 Aug 2005 14:31:23 -0700
Files with the following suffixes were changed.
c, cm, el, fun, grm, h, lex, mlb, sig, sml, tex, txt
I think it makes sense for whatever automated "no tabs" enforcement we
put in place to continue to enforce the rule for these suffixes.
Some unsuffixed files were also changed, mostly READMEs and shell
scripts. I'm not sure what to do about automated enforcement for
unsuffixed files, but it's not a huge deal to me.
Some files with tabs were not changed, in particular, regression
output, .st files (Matthew, what about these?), Makefiles, patches
that include Makefiles require tabs. Here's a complete list of
(ASCII) files that still have tabs in them.
regression/textio.ok
regression/array.ok
regression/word8array.ok
regression/timer.ok
regression/substring.ok
regression/string.ok
regression/check_arrays.ok
regression/pack-real.ok
regression/stringcvt.ok
regression/Makefile
regression/filesys.ok
regression/word8vector.ok
regression/time.ok
regression/bytechar.ok
regression/listpair.ok
regression/math.ok
regression/unixpath.ok
regression/date.ok
regression/word-all.ok
regression/kitsimple.ok
regression/listsort.ok
regression/real.ok
regression/list.ok
regression/int.ok
mlnlffigen/Makefile
mllex/Makefile
Makefile
include/Makefile
runtime/Makefile
mlton/front-end/Makefile
mlton/Makefile
benchmark/tests/Makefile
benchmark/Makefile
bytecode/Makefile
mlprof/Makefile
ide/enscript/sml_verbose.st
ide/enscript/sml_fancy.st
ide/enscript/sml_all.st
ide/enscript/sml_gaudy.st
basis-library/libs/basis-2002/top-level/Makefile
basis-library/Makefile
doc/library-guide/Makefile
doc/hacker-guide/structure.fig
doc/hacker-guide/Makefile
doc/mlb-formal/Makefile
doc/style-guide/Makefile
doc/examples/finalizable/Makefile
doc/examples/save-world/Makefile
doc/examples/ffi/Makefile
doc/examples/profiling/Makefile
doc/examples/Makefile
lib/basis-stubs/Makefile
lib/opengl/Makefile
lib/mlton-stubs/Makefile
lib/mlton/basic/Makefile
lib/mlton/Makefile
lib/mlton-stubs-in-smlnj/Makefile
lib/smlnj-lib/Makefile
lib/smlnj-lib/smlnj-lib.patch
lib/Makefile
lib/ckit-lib/ckit.patch
lib/ckit-lib/Makefile
bin/Makefile
mlyacc/doc/Makefile
mlyacc/examples/pascal/test/c1.p
mlyacc/examples/pascal/test/t1.p
mlyacc/Makefile
man/Makefile
package/debian/mlton.postinst
package/debian/rules
package/debian/mlton.prerm
package/freebsd/pkg-descr
package/freebsd/Makefile
package/rpm/mlton.spec
Finally, for the record, here's the script I used to make the changes.
----------------------------------------------------------------------
structure List =
struct
open List
fun exists (l, f) = List.exists f l
fun map (l, f) = List.map f l
end
structure String =
struct
open String
fun hasSuffix (s, {suffix}) =
Int.>= (size s, size suffix)
andalso suffix = extract (s, size s - size suffix, NONE)
end
val name = #file (OS.Path.splitDirFile (CommandLine.name ()))
fun die s =
(TextIO.output (TextIO.stdErr, s)
; let open OS.Process in exit failure end)
val root =
case CommandLine.arguments () of
[dir] => dir
| _ => die (concat ["usage: ", name, " <dir>"])
val numFiles = ref 0
val numFilesWithTabs = ref 0
val numTabs = ref 0
fun ++ x = x := 1 + !x
fun msg ss =
if true then () else
TextIO.output (TextIO.stdErr, concat [concat ss, "\n"])
val tab = CharVector.tabulate (8, fn _ => #" ")
fun replaceTabs f =
let
val mode = Posix.FileSys.ST.mode (Posix.FileSys.stat f)
val ins = TextIO.openIn f
val tmp = "/tmp/z.tab"
val out = TextIO.openOut tmp
fun loop () =
case TextIO.input1 ins of
NONE => ()
| SOME c =>
(if c = #"\t"
then TextIO.output (out, tab)
else TextIO.output1 (out, c)
; loop ())
val () = loop ()
val () = TextIO.closeIn ins
val () = TextIO.closeOut out
val () = OS.FileSys.rename {new = f, old = tmp}
val () = Posix.FileSys.chmod (f, mode)
in
()
end
val replaceSuffixes =
List.map
(["c", "cm", "doc", "el", "fun", "grm", "h", "lex", "mlb", "sig", "sml",
"tex", "txt"],
fn s => concat [".", s])
fun shouldReplace (dir, f) =
(dir = "./bin" andalso f <> "Makefile")
orelse List.exists (["changelog", "README", "README.Debian", "README.kit"],
fn f' => f = f')
orelse List.exists (replaceSuffixes, fn s =>
String.hasSuffix (f, {suffix = s}))
fun handleFile (dir, f) =
let
val () = ++numFiles
val isAscii = ref true
val hasTab = ref false
val numTabsInFile = ref 0
val ins = TextIO.openIn f
fun loop (filePos) =
case TextIO.input1 ins of
NONE => ()
| SOME c =>
if not (Char.isAscii c)
then isAscii := false
else
let
val () =
if c = #"\t" then (++numTabsInFile; hasTab := true)
else ()
in
loop (filePos + 1)
end
val () = loop 0
val () = TextIO.closeIn ins
val () =
if not (!isAscii) then ()
else if !hasTab then
(++numFilesWithTabs
; (if shouldReplace (dir, f) then replaceTabs f
else (print (concat ["skipping ",
OS.Path.joinDirFile {dir = dir, file = f},
"\n"]))))
else ()
in
()
end
fun loop (dir, path) =
let
val () = msg ["entering ", dir]
open OS.FileSys
val saved = getDir ()
val () = chDir dir
val ds = openDir "."
val path = OS.Path.joinDirFile {dir = path, file = dir}
fun loop' () =
case readDir ds of
NONE => ()
| SOME s =>
let
val () =
case s of
"." => ()
| ".." => ()
| ".svn" => ()
| _ =>
if isDir s then loop (s, path)
else if isLink s then ()
else handleFile (path, s)
in
loop' ()
end
val () = loop' ()
val () = closeDir ds
val () = chDir saved
val () = msg ["leaving ", dir]
in
()
end
val () = loop (root, "")
val () =
List.app
(fn (s, r) =>
print (concat [s, " = ", Int.toString (!r), "\n"]))
[("numFiles", numFiles),
("numFilesWithTabs", numFilesWithTabs),
("numTabs", numTabs)]