filepatterns to exclude a match - shake-build-system
Shake uses various forms of matching, filepath against pattern. Is there one which can be used to exclude a pattern?
Example:
I have three directories a, b, c (somewhere in directory x) and each needs html files. There is a rule
(dir <> "//*.html") %> \out -> do -- deal with a and b
which should only deal with the directories a and b and a similar rule to process the files in c.
Is there a way (perhaps using ?>) to separate the two rules for one
(\f -> "x" prefixOf f && not "x/c" prefixOf f) <> "//*.html")
(\f -> "x/x" prefixOf f ) <> "//*.html")
and the other similarly?
The recommended approach to use xx.a.html and xx.b.html is here not possible, because files are processed with other programs which expect the regular html extension.
Alternatively
The rule:
pattern %> action
Is equivalent to:
(pattern ?==) ?> action
So you can write:
(\x -> "//*.html" ?== x && not ("c//*.html" ?== x) ?> action
To match rules matching //*.html, but not c//*.html.
More generally, there is no requirement to use the FilePattern ?== operator at all, so arbitrary matching predicates can be used instead.
With the advice (especially the hint about using **/*.html) I have it working.
The path bakedD is a prefix of staticD and the first rule deals only with files in bakedD which are not in staticD, the other only with these:
(\x -> ((bakedD <> "**/*.html") ?== x)
&& not ((staticD <> "**/*.html") ?== x)) ?> \out -> do
let md = doughD </> (makeRelative bakedD $ out -<.> "md")
runErr2action $ bakeOneFileFPs md doughD templatesD out
(staticD <> "**/*.html" ) %> \out -> do
copyFileChanged (replaceDirectory out doughD) out
There is no overlap between the two rules.
I hope this is useful for others with the same type of issue.
Related
Eiffel: regular expressions how to do grouping
I'd like to do grouping of regular expressions with eiffel. How do I do something like l_reg.compile ("^([0-9]{3}) (rabbit[0-9]).*") l_groups := l_reg.groups ("123 rabbit1") my_first_rabbit := l_groups.at (2) Didn't find any example on groups, LX_DFA_REGULAR_EXPRESSION class and other googlings
One solution is to use RX_PCRE_REGULAR_EXPRESSION instead of LX_DFA_REGULAR_EXPRESSION: Including $ISE_LIBRARY\contrib\library\gobo\library\regexp\src\library.ecf library l_reg: RX_PCRE_REGULAR_EXPRESSION ... l_reg.compile ("^([0-9]{3}) (rabbit[0-9]).*") l_reg.match ("123 rabbit1") my_first_rabbit := l_reg.captured_substring (2) There is no groups routine, although it could be implemented by calling captured_substring internally. There is only a routine split which does the reverse: returns the substrings which did not match the regular expression. Something like regex_groups (a_haystack, a_needle: STRING): ARRAY[STRING] -- Test with https://www.regextester.com/1911 require regex_match (a_haystack, a_needle) local l_reg: RX_PCRE_REGULAR_EXPRESSION l_index: like {RX_PCRE_REGULAR_EXPRESSION}.match_count do create Result.make_empty create l_reg.make l_reg.compile (a_needle) if l_reg.is_compiled then l_reg.match (a_haystack) from l_index := 1 until l_index > l_reg.match_count loop Result.extend (l_reg.captured_substring (l_index)) l_index := l_index + 1 end else --- error compiling regex fallible.set_last_error (create {SIT_INTERNAL_ERROR}.make ("regex_group-> regex does not compile:" + a_needle)) end ensure not fallible.has_error instance_free: Class end you could test your regex here: https://www.regextester.com/1911
Recursing directories only goes one file deep
I have the following code: find_info(File) -> case file:read_file_info(File) of {ok, Facts} -> case Facts#file_info.type of directory -> directory; regular -> regular end; {error,Reason} -> exit(Reason) end. find_files(Dir,Flag,Ending,Acc) -> case file:list_dir(Dir) of {ok,A} -> find_files_helper(A,Dir,Flag,Acc,Ending); {_,_} -> Acc end. find_files_helper([H|Tail],Dir,Flag,Acc,Ending) -> A = find_info(filename:absname_join(Dir,H)), case A of directory -> case Flag of true -> find_files(filename:absname_join(Dir,H),Flag,Ending,Acc ++ find_files_helper(Tail,Dir,Flag,Acc,Ending)); false -> find_files_helper(Tail,Dir,Flag,Acc,Ending) end; regular -> case filename:extension(H) of Ending -> find_files_helper(Tail,Dir,Flag,[to_md5_large(H)] ++ Acc, Ending); _ -> find_files_helper(Tail,Dir,Flag,Acc,Ending) end; {error,Reason} -> exit(Reason) end; find_files_helper([],_,_,Acc,_) -> Acc. However whenever I run the find_files/4 the program only goes one file deep before crashing. Say I have the following directory home/ a/ ser.erl b/ c/ file.erl file2.erl When run I will get the md5 of file.erl of file2.erl and of ser.erl. However if the directory looks like this: home/ a/ ser.erl back.erl b/ c/ file.erl file2.erl Then the whole program crashes. I have spent few good hours looking for what I'm missing here in my logic however I have no idea. The error message that I get is exception enoent in function p:to_md5_large/1. In case the md5 is needed here it is: to_md5_large(File) -> case file:read_file(File) of {ok, <<B/binary>>} -> md5_helper(B,erlang:md5_init()); {error,Reason} -> exit(Reason) end. md5_helper(<<A:4/binary,B>>,Acc) -> md5_helper(B,erlang:md5_update(Acc,A)); md5_helper(A,Acc) -> B = erlang:md5_update(Acc,A), erlang:md5_final(B).
You're getting enoent because you're passing a filename like back.erl to to_md5_large when you're not in the directory where back.erl is located. Try passing the full filename instead. You're already calling filename:absname_join(Dir,H) in find_files_helper, so just save that to a variable and pass that variable instead of H to to_md5_large.
There is a function that does this for you: fold_files(Dir, RegExp, Recursive, Fun, AccIn) -> AccOut in your case: Result = filelib:fold_files(Dir, ".*\.erl", true, fun(X,Acc) -> {ok,B} = file:read_file(X), [erlang:md5(B)|Acc] end, []). [edit] #Bula: I didn't answer directly to your question for 2 reasons: The first one is that, at the time I was writing my answer, you didn't provide the type of error you get. It is very important, with any language, to learn how to get information from error report. In erlang, most of the time, you get the error type an the line where it occurs, looking at the documentation you will have a very helpful information about what was going wrong. By the way, unless you want to manage errors, I discourage you to write things like: case file:read_file(File) of {ok, <<B/binary>>} -> md5_helper(B,erlang:md5_init()); {error,Reason} -> exit(Reason) end. The following code will do the same, shorter, and you'll get the exact line number where you got an issue (its not the best example in your code, but it's the shorter) {ok, <<B/binary>>} = file:read_file(File), md5_helper(B,erlang:md5_init()), The second is that I find your code too big, with useless helper functions. I think it is important to try to have a concise and readable code, and also to try to use the library function in the right way. For example you are using erlang:md5:init/0, erlang:md5_update/2 and erlang:md5_final/1 while a single call to erlang:md5/1 is enough in your case. The way you use it exists to be able to calculate the md5 when you get the data chunk by chunk, which is not your case, and the way you wrote the helper function does not allow to use this feature. I don't understand why you want to have a "deployed" version of your code, but I propose you another version where I tried to follow my advices (written directly in the shell, so it need R17+ for the definition of recursive anonymous function) :o) 1> F = fun F(X,D,Ending) -> 1> {ok,StartD} = file:get_cwd(), %% save current directory 1> ok = file:set_cwd(D), %% move to the directory to explore 1> R = case filelib:is_dir(X) of 1> true -> %% if the element to analyze is a directory 1> {ok,Files} = file:list_dir(X), %% getits content 1> [F(Y,X,Ending) || Y <- Files]; %% and recursively analyze all its elements 1> false -> 1> case filelib:is_regular(X) andalso (filename:extension(X) == Ending) of 1> true -> %% if it is a regular file with the right extension 1> {ok,B} = file:read_file(X), %% read it 1> [erlang:md5(B)]; %% and calculate the md5 (must be return in a list 1> %% for consistancy with directory results) 1> false -> 1> [] %% in other cases (symlink, ...) return empty 1> end 1> end, 1> ok = file:set_cwd(StartD), %% restore current directory 1> lists:flatten(R) %% flatten for nicer result 1> end. #Fun<erl_eval.42.90072148> 2> Md5 = fun(D) -> F(D,D,".erl") end. #Fun<erl_eval.6.90072148> 3> Md5("C:/My programs/erl6.2/lib/stdlib-2.2"). [<<150,238,21,49,189,164,184,32,42,239,200,52,135,78,12, 112>>, <<226,53,12,102,125,107,137,149,116,47,50,30,37,13,211,243>>, <<193,114,120,24,175,27,23,218,7,169,146,8,19,208,73,255>>, <<227,219,237,12,103,218,175,238,194,103,52,180,132,113, 184,68>>, <<6,16,213,41,39,138,161,36,184,86,17,183,125,233,20,125>>, <<23,208,91,76,69,173,159,200,44,72,9,9,50,40,226,27>>, <<92,8,168,124,230,1,167,199,6,150,239,62,146,119,83,36>>, <<100,238,68,145,58,22,88,221,179,204,19,26,50,172,142,193>>, <<253,79,101,49,78,235,151,104,188,223,55,228,163,25,16, 147>>, <<243,189,25,98,170,97,88,90,174,178,162,19,249,141,94,60>>, <<237,85,6,153,218,60,23,104,162,112,65,69,148,90,15,240>>, <<225,48,238,193,120,43,124,63,156,207,11,4,254,96,250,204>>, <<67,254,107,82,106,87,36,119,140,78,216,142,66,225,8,40>>, <<185,246,227,162,211,133,212,10,174,21,204,75,128,125, 200,...>>, <<234,191,210,59,62,148,130,187,60,0,187,124,150,213,...>>, <<199,231,45,34,185,9,231,162,187,130,134,246,54,...>>, <<157,226,127,87,191,151,81,50,19,116,96,121,...>>, <<15,59,143,114,184,207,96,164,155,44,238,...>>, <<176,139,190,30,114,248,0,144,201,14,...>>, <<169,79,218,157,20,10,20,146,12,...>>, <<131,25,76,110,14,183,5,103,...>>, <<91,197,189,2,48,142,67,...>>, <<94,202,72,164,129,237,...>>, <<"^NQÙ¡8hÿèkàå"...>>,<<"ðÙ.Q"...>>, <<150,101,76,...>>, <<"A^ÏrÔ"...>>,<<"¹"...>>,<<...>>|...] 4>
Running join on Maybe Relation
I have a model Assignment blah Text .... and a model File assignmentId AssignmentId Maybe ... and I want to get all the files associated with an assignment in a join query. I have tried Esqueleto and runJoin with selectOneMany but haven't had any luck, so I am considering not using a join, or using rawSql. That really doesn't seem like a good idea, but I can't figure this out. Is there any support for that feature?
Update, working example: {-# LANGUAGE PackageImports, OverloadedStrings, ConstraintKinds #-} module Handler.HTest where import Import import "esqueleto" Database.Esqueleto as Esql import "monad-logger" Control.Monad.Logger (MonadLogger) import "resourcet" Control.Monad.Trans.Resource (MonadResourceBase) import qualified Data.List as L getFilesByAssignment :: (PersistQuery (SqlPersist m), MonadLogger m , MonadResourceBase m) => Text -> SqlPersist m [Entity File] getFilesByAssignment myAssign = do result <- select $ from $ \(assign `InnerJoin` file) -> do on (just (assign ^. AssignmentId) Esql.==. file ^. FileAssignmentId) where_ (assign ^. AssignmentBlah Esql.==. val myAssign) return (assign, file) return $ map snd (result :: [(Entity Assignment, Entity File)]) (.$) = flip ($) getTestR :: Handler RepHtml getTestR = do entFiles <- runDB $ getFilesByAssignment "test" defaultLayout $ do setTitle "Test page" entFiles .$ map (show . unKey . entityKey) .$ L.intercalate ", " .$ toHtml .$ toWidget
TypeError: invalid file: When trying to make a file name a variable
Hi I am trying to represent a file location as a variable because the finial script will be run on another machine. This is the code I have tried followed by the error I get. It seems to me that some how python is adding "\" and that is causing the problem. If that is the case how do I get it not to insert the "\"? Thank you F = 'C:\Documents and Settings\myfile.txt','r' f = open(F) and the error TypeError: invalid file: ('C:\\Documents and Settings\\myfile.txt', 'r')
From the docs: http://docs.python.org/tutorial/inputoutput.html#reading-and-writing-files Try this: F = r'C:\Documents and Settings\myfile.txt' f = open(F, 'r') About the "double backslashes" - you need to escape backslashes in your strings or use r'string', see this: http://docs.python.org/release/2.5.2/ref/strings.html E.g. try this: >>> a = 'a\nb' >>> print a a b To get what you expect, you need this: >>> a = r'a\nb' >>> print a a\nb or this: >>> a = 'a\\nb' >>> print a a\nb
Try f=open('C:\Documents and Settings\myfile.txt','r') Instead of using the variable F. the way you have it 'r' is part of the file name, which it is not.
Instead of writing / or \, you should do this: import os F = os.path.join( "C:", os.path.join( "Documents and Settings", "myfile.txt" ) ) f = open(F, 'r')` so that it uses / or \ according to your os. (Although if you write C:/ it must mean you want to run your code on Windows... Hum...)
Compact C Folding in Vim
I'm trying to make a simple Vim script that would create very compact top-level folds for c files. Ideally, if it was run on this code: static void funca(...) { ... } /* Example comment */ static void funcb(...) { ... } Then it would create folds which would look like this when closed: +-- x Lines: static void funca(...)---------------------- +-- x Lines: static void funcb(...)---------------------- So basically it would be like foldmethod=syntax with foldlevel=1, except that each fold would start one line further up, and would extend further down to include all following blank lines. I know how to make one of these folds (assuming foldmethod=manual): /^{<cr>kVnn?^$<cr>zf But I'm not sure how to put it into a function. This is my effort: function Cfold() set foldmethod=manual " Manual folds ggzE " Delete all folds while (/^{<cr>) " Somehow loop through each match kVnn?^$<cr>zf " This would work fine except for the last function endwhile endfunction map <Leader>f :call Cfold()<cr> But it isn't valid, I'm not entirely sure how functions work. Also, it won't work for the last function in the file, since it won't find '^{' again. If someone could help me get this working, and somehow add a case for the last function in a file, I would be extremely grateful. Thanks in advance :)
You can create folds programmatically using the foldexpr and foldtext. Try this, though you may have to tweak CFoldLevel so it doesn't swallow non-function parts of the code: function! CFoldLevel(lnum) let line = getline(a:lnum) if line =~ '^/\*' return '>1' " A new fold of level 1 starts here. else return '1' " This line has a foldlevel of 1. endif endfunction function! CFoldText() " Look through all of the folded text for the function signature. let signature = '' let i = v:foldstart while signature == '' && i < v:foldend let line = getline(i) if line =~ '\w\+(.*)$' let signature = line endif let i = i + 1 endwhile " Return what the fold should show when folded. return '+-- ' . (v:foldend - v:foldstart) . ' Lines: ' . signature . ' ' endfunction function! CFold() set foldenable set foldlevel=0 set foldmethod=expr set foldexpr=CFoldLevel(v:lnum) set foldtext=CFoldText() set foldnestmax=1 endfunction See :help 'foldexpr' for more details.