packages feed

historian (empty) → 0.0

raw patch · 6 files changed

+171/−0 lines, 6 filesdep +basedep +containersdep +directorysetup-changed

Dependencies added: base, containers, directory, filepath, process, regex-compat, regex-posix

Files

+ EXAMPLE view
@@ -0,0 +1,23 @@+BORING COMMANDS:++> ls+> cd+> pwd+> cd .*+> cp [^-].*+> mv [^-].*+> python++FILE COMPARISON:++Side-by-side diff+> diff -y .*++Standard diff+> diff [^-].*++FILE MANAGEMENT:++Make a directory and all its ancestors+> mkdir -p .*+
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2009 Max Rabkin++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ README view
@@ -0,0 +1,30 @@+HISTORIAN+---------------------------------------------------------------------------------++Historian extracts interesting commands from your shell history and adds them to+a text file. "Interesting" means not matching any regular expression in the+file. This allows one to keep a textual "database" of commands.++Never again say "I wish I remembered what arguments to give wibble to make it+flibber the gibbet" three months after you looked it up.++---------------------------------------------------------------------------------++WARNING: when historian is run, it truncates ~/.bash_history++When you run historian, it looks for lines in ~/interesting_history that+starts with start with a greater-than symbol. These lines are interpreted as+regexes. It then looks in ~/.bash_history for lines that don't match any of+the regexes, appends them to ~/interesting_history and opens your favourite+editor to edit the file.++You can then generalise the commands into regexes so that subsequent runs of+historian will ignore similar ones. You can delete commands, but if they appear+in your history again, historian will again consider them "interesting" (it's+for this reason that historian truncates the history after it runs).++Some of the regexes will inevitably be uninteresting, but you should generalise+them so that they don't show up again. Interesting commands should be+categorised and described, so that you can refer to them later.++An example interesting_history is contained in the EXAMPLE file.
+ Setup.lhs view
@@ -0,0 +1,4 @@+#! /usr/bin/env runhaskell

> import Distribution.Simple
> main = defaultMain
#! /usr/bin/env runhaskell++> import Distribution.Simple+> main = defaultMain
+ historian.cabal view
@@ -0,0 +1,35 @@+Name:           historian+Version:        0.0+Cabal-Version:  >= 1.2+Synopsis:       Extract the interesting bits from shell history+Description:    Extract interesting commands and add them to a text file.+                \"Interesting\" means not matching any regular expression in the+                file. This allows one to keep a textual database of commands.++                Never again say \"I wish I remembered what arguments to give+                wibble to make it flibber the gibbet\" three months after you+                looked it up.+                +                WARNING: historian truncates ~/.bash_history.+License:        BSD3+License-file:   LICENSE+Author:         Max Rabkin+Maintainer:     max.rabkin@gmail.com+Stability:      Experimental+Build-Type:     Simple+Category:       Console++Extra-Source-Files: EXAMPLE README++Executable historian+    Build-Depends:  base >= 3 && < 5,+                    process >= 1 && < 2,+                    directory >= 1 && < 2,+                    filepath >= 1 && < 2,+                    regex-posix >= 0.94 && < 0.95,+                    regex-compat >= 0.92 && < 0.93,+                    containers >= 0.1 && < 0.3++    Executable:     historian+    Main-Is:        historian.hs+
+ historian.hs view
@@ -0,0 +1,49 @@+import qualified Data.Map as M+import Data.List (group, isPrefixOf, sort)+import Text.Regex+import Text.Regex.Posix+import Data.Char (isSpace)+import Control.Arrow (second)+import Control.Applicative ((<$>), liftA2)+import System.Cmd (rawSystem)+import System.FilePath ((</>))+import System.Directory (removeFile)+import System.Environment (getArgs, getEnv)++type PatternDB = M.Map String Pattern+type Pattern = String++extractPatterns :: String -> PatternDB+extractPatterns =   --M.map makeRegex+                    M.fromListWith (\x y -> x ++ '|':y) .+                    map (second (\x -> "(" ++ x ++ ")") . splitCmd . tail) .+                    filter (">" `isPrefixOf`) .+                    lines++splitCmd :: String -> (String, String)+splitCmd = second (dropWhile isSpace) . break isSpace . dropWhile isSpace++extractInteresting :: PatternDB -> [String] -> [String]+extractInteresting db = filter (not . liftA2 (||) (`inDB` db) ("#" `isPrefixOf`))++inDB :: String -> PatternDB -> Bool+cmd `inDB` db = let (prog, args) = splitCmd cmd in+                    case M.lookup prog db of+                        Just pat -> args =~ pat+                        Nothing -> False++main = do+        homeDir <- catch (getEnv "HOME") (const . return $ ".")+        editor <- catch (getEnv "EDITOR") (const . return $ "nano")+        args <- getArgs+        let fn = case args of+                    [] -> homeDir </> "interesting_history"+                    [x] -> x++        let histfile = homeDir </> ".bash_history"+        boring <- extractPatterns <$> readFile fn+        history <- readFile $ histfile+        let interesting = map head . group . sort . extractInteresting boring . lines $ history+        boring `seq` (appendFile fn . unlines . map ("> " ++) $ interesting)+        interesting `seq` writeFile histfile "# history has been rewritten"+        rawSystem editor [fn]