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 +23/−0
- LICENSE +30/−0
- README +30/−0
- Setup.lhs +4/−0
- historian.cabal +35/−0
- historian.hs +49/−0
+ 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]