Yeah, there are a TON of Clojure form/data validation libraries out there. I wasn't happy with any of them, which is why I made Red Tape.
Red Tape is designed specifically with user-submitted, web-based forms. It might work with other stuff too, but that's what I had in mind for it.
All the existing libraries seem to suffer from one or more problems when you're dealing with user-submitted, web-based forms.
Some of them are pure "validation" libraries. That doesn't work for web forms because you want to not only validate that "34" is a valid user id or whatever, but also transform it into your representation of a user to make it easier to work with. So pure validation isn't enough, we need to validate and transform fields.
Some libraries use a complicated DSL of keywords and vectors and stuff to decribe validations. Red Tape just uses functions, because functions are really simple and easy to get your head around.
Almost none of the libraries handle "initial data". This is one of the things that was annoying as hell when I wrote django-goodfields, so I made sure Red Tape had support for it built in right from the start.
Initial data is important when you're working with websites in the real world. For example, you have a profile page for a user with their name, bio, etc. When they first load the page you want to prepopulate that with the existing data in your database. But if they change some of it and submit and there's an error, you want to prepopulate the form with the data they submitted. Not the data from your db, and not the cleaned data, but the original strings they submitted. As far as I could tell, none of the existing Clojure validation libraries help you out here.
Another thing to consider is "dynamic" forms, where you have some extra data that's not a form field, but that you need to use when validating a form. The example in Red Tape's docs of a "video delete" form is a good one. Red Tape uses its "form arguments" to handle this. Some libraries use a similar method, and some ignore it entirely.
EDIT: A problem I forgot to mention is that some "form libraries" want to handle generating the HTML for the form fields. Unless you're making a vanilla Twitter Bootstrap site with the plainest HTML forms imagineable this ends up being awful. In the real world your frontend developers will always want control of their forms' markup, especially if they're using something more dynamic like angular or backbone. Libraries that try to handle the HTML generation tend to hide away stuff like "what should the initial data for this field be" so you can't get to it as easily when you're trying to write the HTML yourself. Red Tape is designed to make it as easy as possible for your frontend developers to get what they need from your forms when writing their markup.
And of course there's the perpetual Clojure problem of documentation. Half the validation libraries out there have a 100-line README and no other docs.
So yeah, I definitely looked at the other options, but I couldn't find one that satisfied all of the above problems to my liking. So I wrote it!
I previously found Metis to potentially be the best, but it's fragile, uses a DSL of vectors and if you e.g. spell one incorrectly it'll silently fail. The DSL isn't very complicated, but the lack of robustness, when something will only fire when input data is wrong, is seriously subpar.
1. If a new version of git adds a command that shadows one of your aliases, you'd really prefer "git foo" to silently run the new command? That's better than telling you "hey this isn't going to do what you think any more"? Do you have `try: foo except: pass` in your Python code too? Come on. There's no reason git shouldn't at least warn you on stderr here.
2. `git checkout -- somefile.py` does not have anything to do with checking out a revision. It changes a file's contents, but doesn't change the parent of your working tree at all. Unlike `git checkout -b` which is inconsistent for convenience like you mentioned, the "make file x look like it was in rev y" function here is unique to git checkout as far as I can tell. Then again this is git, so there's probably at least four other ways to do this with cryptic plumbing commands.
3. I like Mercurial's named branches because I don't need to create a branch for every single commit. But even if you don't like them, the "record which branch X was made on" and "use that recorded information to group branches and such in the UI" are two different things. The second requires the first, but git could record which branch was checked out when each commit was made as some metadata in the commit, instead of dropping it on the floor. It would be a godsend when trying to figure out what actually happened during a merge.
4. `git branch` doesn't show you the current branch. It shows you all the local branches, with colors and padding spaces and asterisks and crap. What if you want the current branch in your prompt? Or just want to grab it in a script? Your choices are "pipe to grep and sed" or "use this ugly-ass rev-parse thing" instead of "git branch --current".
Git's UI is still abysmal. Mercurial preserves more data (branches), gives you the same power as Git and has a UI where "--help x", "-h x", "help x", "x -h", and "x --help" all do the same thing (pop quiz: how many different things does git do for those? hint: it's more than two).
> 1. If a new version of git adds a command that shadows one of your aliases, you'd really prefer "git foo" to silently run the new command?
Yes. Otherwise command line scripts will start doing horrible things. It was never intended that you can alias builtins, the only reason you might think you can is because it is allowed in mercurial which I think is a horrible idea.
> `git checkout -- somefile.py` does not have anything to do with checking out a revision.
Of course not. `git checkout` checks out things. You can check out a lot of things. Just because it works differently in hg does not mean it's wrong in git. git checkout does what it says on the tin: it checks out a branch or paths to the working tree.
> I like Mercurial's named branches because I don't need to create a branch for every single commit.
I think the concept of named branches in mercurial are hugely flawed and were the final nail in the coffin of why I migrated over to git. And I never looked back.
> What if you want the current branch in your prompt?
Then you use the underlying low-level commands or even better, you cat `.git/HEAD` which will be even faster. Not sure why for your prompt to look nice you need to have non-cryptic commands. Exactly for things like prompts there is the plumbing.
> gives you the same power as Git and has a UI where "--help x", "-h x", "help x", "x -h", and "x --help" all do the same thing
How is this different from mercurial? If anything mercurial has even more ways to show help: `man hg` which shows the manpage for all the builtin commands. `hg help` which shows a short version or `hg -v help` which shows a long version (which is not the man page). git only has two help pages: man pages for long and short text for short.
If your solution to "get the current branch" is "cat out this magic data file that happens to exist in the data directory" then we have completely incompatible definitions of "user interface" and are never going to agree on this.
The question was not how to just get the current branch, thought, right? As pointed out already, `git branch` does that.
The question was how to do it programmatically, and there are multiple ways to do it. You might still call that user interface, but it's that's a stretch; fancy shell magic like branch-in-prompt is typically write-once.
> Yes. Otherwise command line scripts will start doing horrible things. It was never intended that you can alias builtins, the only reason you might think you can is because it is allowed in mercurial which I think is a horrible idea.
You should understand what you are responding to before typing your answer.
Say today I create an alias “boom = <whatever>” and next week git introduces a boom command.
Now my alias is ignored, my scripts are broken and I might destroy my working copy or kill my cat by using it without knowing it now means something else.
Git gives some very stupid hints “branhc is not a git command, did you mean branch?” it should also warn me when I defined an invalid alias.
Maybe that alias was valid two versions ago or I just don’t know that command exists, since there are eleventy thousand of them.
>> Git gives some very stupid hints “branhc is not a git command, did you mean branch?” it should also warn me when I defined an invalid alias.
This is the thing that really infuriates me - having a message from my tool that tells me there's an error is one thing, but offering a (frequently incorrect) correction forces me stop and try to figure out why this suggestion was offered, since it frequently has NOTHING to do with what I actually (mis)typed.
Lets put it this way - if this autocorrection feature is so great, then it should prompt you Y/N after giving the error message. Would it then be a better feature? Or would it make more people want to stab it in the eyeballs? Or if this suggestion feature is so great, then it should just DWIM in the first place.
Someone needs to take gits levenshtein algorithm away.
>I think the concept of named branches in mercurial are hugely flawed and were the final nail in the coffin of why I migrated over to git. And I never looked back.
How does having more information available ever hurt you?
Now, fair enough, the fact that mercurial expects branches to be unique might be annoying if you have the tendency to call all branches 'bugfix', but you seem to imply that simply having the branch name in which the commit was originally created as metadata on it would be somehow bad.
>git checkout does what it says on the tin: it checks out a branch or paths to the working tree.
'git checkout is good because checkout means the thing that git checkout does'
`And how should I create a branch?. Use git checkout.` No. You create a branch with git branch. If you want to create a branch and immediately switch to it, use git branch (to create it) + git checkout (to switch to it). git checkout -b is just a shorthand for the two, it's there just for convenience. Unix has a lot of these occurrences. rm -rf as a shorthand for rm+rmdir, the open() syscall with O_CREAT shorthand for creat()+open() etc.
I used the one I did because it's the one Zed used for his books (at least that's what it was when I started this one) and since the book is heavily influenced by his I wanted to stay in the spirit of Learn X the Hard Way.
If this were software I'd probably use a more structured license, but since it's just a book I think this is fine. Worst case: someone doesn't redistribute it because it's not a CC license. Well... they can still read it online...
If you use chrome on windows, pretty much any web font is going to look like shit. I don't understand why google, one of the biggest pushers of web fonts, can't make a browser that renders them sanely.
It has nothing whatsoever to do with caching. It's jQuery timeago. The incorrect time was coming from the lack of a timezone in the date, which I just fixed. If you reload the page it should now look correct no matter what timezone you're in.