会社でramda.jsの研修用資料を作成することになりました。全部の関数を紹介するのは無理があるため、とりあえずあるモノレポで使われているramda.jsの関数をすべて調べることにしました。
open System.IO
(* dir pathを渡されると、再帰的にファイルのパスを返す関数 *)
let rec getFiles dir =
let files = Directory.GetFiles(dir)
let dirs = Directory.GetDirectories(dir)
files |> Array.append (dirs |> Array.collect getFiles)
(* ファイルのextnameがts, tsxである場合のみtrue *)
let isTsOrTsx (filePath: string) =
let ext = Path.GetExtension(filePath)
ext = ".ts" || ext = ".tsx"
(* file pathにnode_modulesが含まれていたらexclude *)
let excludeNodeModules (filePath: string) =
let nodeModulesIndex = filePath.IndexOf("node_modules")
nodeModulesIndex = -1
(* ().ts or .tsx) && not node_modules *)
let validFiles (dirPath: string) =
getFiles dirPath |> Seq.filter isTsOrTsx |> Seq.filter excludeNodeModules
(* ファイルの中を1行ずつ確認し、"ramda"という単語があれば、その行を返す *)
let isRamdaLine (filePath: string) =
let lines = File.ReadAllLines(filePath)
lines
(* ramdaがあれば返すけれど、複数行あってimport文が終了のときはNG *)
|> Seq.filter (fun line -> line.Contains("\"ramda\"") && not (line = "} from \"ramda\";"))
(*
import { drop, includes, take } from "ramda";
こうあったときに、drop, includes, takeを取り出す
*)
let takeFunctionName (line: string) =
(* lineがlength0であれば空 *)
if line.Length = 0 then
[||]
else
(* 文字をseqとして考えて、「{」が来るまでを削除。 *)
let dropUntilBrace = line |> Seq.skipWhile (fun c -> c <> '{')
(* 「{」を削除 *)
let dropBrace = dropUntilBrace |> Seq.skip 1
(* 「}」が来るまでを取得 *)
let takeUntilBrace = dropBrace |> Seq.takeWhile (fun c -> c <> '}')
let t = takeUntilBrace |> Seq.toArray |> System.String.Concat
(* カンマがあればsplitしてtrimする *)
let splitByComma = t.Split(',') |> Array.map (fun s -> s.Trim())
(* join *)
splitByComma
(* entry point *)
[<EntryPoint>]
let main argv =
let dir = Seq.tryHead argv
match dir with
| Some dir ->
let absolutePath = Path.GetFullPath(dir)
let seqs = validFiles absolutePath |> Seq.collect isRamdaLine
seqs
|> Seq.map takeFunctionName
|> Seq.concat
|> Seq.distinct
|> Seq.sort
|> Seq.iter (fun s -> printfn "%A" s)
| None ->
printfn "no dir"
exit 1
exit 0
ちょっと力技で解決したところもありますが……。
普段はこんなにコメント書きませんが、あんまり使わない言語はcopilotに頑張ってほしくてコメント多めです。あとで見たときにコメントがないと、メイン言語以外だと本当にリーディング辛いし。
ということで、わが社のモノレポでは
"append"
"clone"
"collectBy"
"concat"
"difference"
"drop"
"dropLast"
"equals"
"filter"
"flatten"
"fromPairs"
"head"
"includes"
"insert"
"intersection"
"isEmpty"
"isNil"
"keys"
"last"
"map"
"mergeAll"
"move"
"omit"
"partition"
"pick"
"pickAll"
"pipe"
"pluck"
"prop"
"range"
"reject"
"remove"
"repeat"
"reverse"
"sortBy"
"splitEvery"
"sum"
"tail"
"take"
"takeLast"
"toPairs"
"union"
"uniq"
"values"
"without"
"xprod"
という関数が使用されていました。
どうせならuniqというかdistinctする前にカウントしておいて頻度順に並べ替えできるようにすれば良かったな。というか、そのように作り直しましょう。