なんで FilePath がエクスポートされてないんじゃあああああああああああ! 存在するのに使えないってメチャクチャ腹立つよ!
しょうがないので必要なやつだけ適当に書いといた (かなり用途特化ぎみ)。
module PathUtils (concatPath, joinPath, basename, dirname, components, ancestors) where import Data.List (intersperse) concatPath :: [String] -> String concatPath [] = "/" concatPath [""] = "/" concatPath cs = join "/" cs joinPath :: String -> String -> String joinPath a b | null a = '/' : b | last a == '/' = a ++ b | otherwise = a ++ "/" ++ b basename :: String -> String basename "/" = "/" basename path = last (components path) ancestors :: String -> [String] ancestors path = case scanl1 (joinPath) $ components path of ("":xs) -> reverse ("/":xs) xs -> reverse xs components :: String -> [String] components = split '/' dirname :: String -> String dirname "/" = "/" dirname path = case components path of [] -> "" [_] -> "." cs -> concatPath (init cs) split :: Char -> String -> [String] split _ [] = [] split sep str = word : split sep cont where (word, cont') = break (==sep) str cont = case cont' of [] -> "" (c:cs) -> cs join :: String -> [String] -> String join sep = concat . intersperse sep
ところで、この日記の記法だと Haskell のコメントが pre に入れられないことが判明した。 BitChannel と同じく {{{ ... }}} 記法を実装するべきか。
HUnit、記述がめちゃうざったい……。 関数名を三回書かないといけないのもさることながら、 頭の runTestTT なんたらもさることながら、 assert のメッセージ書くのがあまりにめんどい。 あまりにめんどくさいので番号にしてしまった。 やっぱりこういうとこは Ruby のほうが圧倒的に気楽でいいなあ。
import Test.HUnit import PathUtils main = runTestTT $ test $ [ "test_ancestors" ~: test_ancestors, "test_components" ~: test_components, "test_concatPath" ~: test_concatPath, "test_joinPath" ~: test_joinPath, "test_basename" ~: test_basename, "test_dirname" ~: test_dirname ] test_ancestors = do assertEqual "1" ["/"] (ancestors "/") assertEqual "2" ["/a", "/"] (ancestors "/a") assertEqual "3" ["/a/b", "/a", "/"] (ancestors "/a/b") assertEqual "4" ["/a/b", "/a", "/"] (ancestors "/a/b/") assertEqual "5" ["a/b", "a"] (ancestors "a/b") assertEqual "6" ["a/b", "a"] (ancestors "a/b/") assertEqual "7" ["a"] (ancestors "a") test_components = do assertEqual "1" [""] (components "/") assertEqual "2" ["", "a"] (components "/a") assertEqual "3" ["", "a", "b"] (components "/a/b") assertEqual "4" ["", "a", "b"] (components "/a/b/") assertEqual "5" ["a", "b"] (components "a/b") assertEqual "6" ["a", "b"] (components "a/b/") test_concatPath = do assertEqual "1" "/" (concatPath []) assertEqual "2" "/" (concatPath [""]) assertEqual "3" "/" (concatPath ["/"]) assertEqual "4" "/a" (concatPath ["", "a"]) assertEqual "5" "/a/b" (concatPath ["", "a", "b"]) test_joinPath = do assertEqual "1" "/a" (joinPath "/" "a") assertEqual "2" "/a/b" (joinPath "/a" "b") assertEqual "3" "a/b" (joinPath "a" "b") test_basename = do assertEqual "1" "/" (basename "/") assertEqual "2" "a" (basename "/a") assertEqual "3" "b" (basename "/a/b") assertEqual "4" "a" (basename "a") assertEqual "5" "b" (basename "a/b") assertEqual "6" "." (basename ".") assertEqual "7" ".." (basename "..") test_dirname = do assertEqual "1" "/" (dirname "/") assertEqual "2" "/" (dirname "/a") assertEqual "3" "/a" (dirname "/a/b") assertEqual "4" "/a/b" (dirname "/a/b/c") assertEqual "5" "a" (dirname "a/b") assertEqual "6" "." (dirname "a") assertEqual "7" "." (dirname ".") assertEqual "8" "." (dirname "..")
(02:50)
Haskell リファレンスマニュアル検索ツール href の 0.3 をリリースしました。
おかしい……原稿を書いていたところから転じて Wash のチュートリアルをやっていたはずが なぜ href をアップデートしているんだろう。
(02:51)
あー、そうだ、href の変更はこんなとこです。
あとは外に変化の出ないリファクタリングとか。
それとビルドに GHC 6.4 が必要です。 うちのメインは Debian なので GHC 6.2 なんですが、 そっちだと URI の関数が足りなくてエラーになります。 (まあたいしたエラーじゃないのでそこだけ変えりゃ通ります)
……なんて書いているあいだに直したほうが早いなーと思いいたったので対応しておきました。
リリースから 3 時間もたってないよ……。 まあダウンロードした人はまだいないみたいだからいいか。
(04:04)
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.
darcs get http://www.scannedinavian.org/~lemmih/FilePath/
あっ、後 patch です。入れてくれてないので、適当にファイル名つけて darcs apply して下さい。
New patches:
[fixed joinFileName bug for "../" prefixed fileName and directoryName that endend non pathSeparator.
shelarcy@capella.freemail.ne.jp**20050907143754] {
hunk ./System/FilePath.hs 146
- | chr == '.' && isPathSeparator (head fname) = joinFileName (reverse $ dropWhile (not . isPathSeparator) $ reverse dir) (tail fname)
+ | chr == '.' && isPathSeparator (head fname) =
+ joinFileName (reverse $ dropWhile (not . isPathSeparator) $ dropWhile isPathSeparator $ reverse dir) (tail fname)
}
Context:
[change joinFilePath works well for file name that use "../" or "./" prefix. And added basename, dirname, dropFileExt (dropSuffix) functions that inspired by hs-plugins' function.
shelarcy@capella.freemail.ne.jp**20050907123002]
[CPP fixes from CosmicRay.
lemmih@gmail.com**20050721174613]
[Set me (lemmih) as the maintainer.
lemmih@gmail.com**20050721173849]
[Added LICENSE
lemmih@gmail.com**20050721173422]
[Initial record.
lemmih@gmail.com**20050426222116]
Patch bundle hash:
65a356504e79c8a892b310e80f1bcb1c4b0eb59d
む、なるほど、別配布になっているのですか。
ありがとうございます。
GHC に添付してほしいっすね……。