twidge (empty) → 0.99.0
raw patch · 25 files changed
+3495/−0 lines, 25 filesdep +Cabaldep +ConfigFiledep +HSHsetup-changed
Dependencies added: Cabal, ConfigFile, HSH, HaXml, MissingH, base, directory, hslogger, mtl, network, parsec, regex-posix, unix
Files
- COPYING +340/−0
- COPYRIGHT +26/−0
- Commands.hs +70/−0
- Commands/Ls.hs +342/−0
- Config.hs +79/−0
- Download.hs +76/−0
- FeedParser.hs +70/−0
- INSTALL +10/−0
- Setup.lhs +7/−0
- Types.hs +46/−0
- Utils.hs +119/−0
- doc/SConstruct +30/−0
- doc/local.dsl +41/−0
- doc/man.twidge.sgml +21/−0
- doc/printlocal.dsl +25/−0
- doc/sgml-common/COPYING +342/−0
- doc/sgml-common/COPYRIGHT +39/−0
- doc/sgml-common/ChangeLog +265/−0
- doc/sgml-common/Makefile.common +229/−0
- doc/sgml-common/SConstruct +208/−0
- doc/sgml-common/ps2epsi +77/−0
- doc/twidge-manpage.sgml +872/−0
- doc/twidge.sgml +20/−0
- twidge.cabal +52/−0
- twidge.hs +89/−0
+ COPYING view
@@ -0,0 +1,340 @@+ GNU GENERAL PUBLIC LICENSE+ Version 2, June 1991++ Copyright (C) 1989, 1991 Free Software Foundation, Inc.+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++ Preamble++ The licenses for most software are designed to take away your+freedom to share and change it. By contrast, the GNU General Public+License is intended to guarantee your freedom to share and change free+software--to make sure the software is free for all its users. This+General Public License applies to most of the Free Software+Foundation's software and to any other program whose authors commit to+using it. (Some other Free Software Foundation software is covered by+the GNU Library General Public License instead.) You can apply it to+your programs, too.++ When we speak of free software, we are referring to freedom, not+price. Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+this service if you wish), that you receive source code or can get it+if you want it, that you can change the software or use pieces of it+in new free programs; and that you know you can do these things.++ To protect your rights, we need to make restrictions that forbid+anyone to deny you these rights or to ask you to surrender the rights.+These restrictions translate to certain responsibilities for you if you+distribute copies of the software, or if you modify it.++ For example, if you distribute copies of such a program, whether+gratis or for a fee, you must give the recipients all the rights that+you have. You must make sure that they, too, receive or can get the+source code. And you must show them these terms so they know their+rights.++ We protect your rights with two steps: (1) copyright the software, and+(2) offer you this license which gives you legal permission to copy,+distribute and/or modify the software.++ Also, for each author's protection and ours, we want to make certain+that everyone understands that there is no warranty for this free+software. If the software is modified by someone else and passed on, we+want its recipients to know that what they have is not the original, so+that any problems introduced by others will not reflect on the original+authors' reputations.++ Finally, any free program is threatened constantly by software+patents. We wish to avoid the danger that redistributors of a free+program will individually obtain patent licenses, in effect making the+program proprietary. To prevent this, we have made it clear that any+patent must be licensed for everyone's free use or not licensed at all.++ The precise terms and conditions for copying, distribution and+modification follow.++ GNU GENERAL PUBLIC LICENSE+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++ 0. This License applies to any program or other work which contains+a notice placed by the copyright holder saying it may be distributed+under the terms of this General Public License. The "Program", below,+refers to any such program or work, and a "work based on the Program"+means either the Program or any derivative work under copyright law:+that is to say, a work containing the Program or a portion of it,+either verbatim or with modifications and/or translated into another+language. (Hereinafter, translation is included without limitation in+the term "modification".) Each licensee is addressed as "you".++Activities other than copying, distribution and modification are not+covered by this License; they are outside its scope. The act of+running the Program is not restricted, and the output from the Program+is covered only if its contents constitute a work based on the+Program (independent of having been made by running the Program).+Whether that is true depends on what the Program does.++ 1. You may copy and distribute verbatim copies of the Program's+source code as you receive it, in any medium, provided that you+conspicuously and appropriately publish on each copy an appropriate+copyright notice and disclaimer of warranty; keep intact all the+notices that refer to this License and to the absence of any warranty;+and give any other recipients of the Program a copy of this License+along with the Program.++You may charge a fee for the physical act of transferring a copy, and+you may at your option offer warranty protection in exchange for a fee.++ 2. You may modify your copy or copies of the Program or any portion+of it, thus forming a work based on the Program, and copy and+distribute such modifications or work under the terms of Section 1+above, provided that you also meet all of these conditions:++ a) You must cause the modified files to carry prominent notices+ stating that you changed the files and the date of any change.++ b) You must cause any work that you distribute or publish, that in+ whole or in part contains or is derived from the Program or any+ part thereof, to be licensed as a whole at no charge to all third+ parties under the terms of this License.++ c) If the modified program normally reads commands interactively+ when run, you must cause it, when started running for such+ interactive use in the most ordinary way, to print or display an+ announcement including an appropriate copyright notice and a+ notice that there is no warranty (or else, saying that you provide+ a warranty) and that users may redistribute the program under+ these conditions, and telling the user how to view a copy of this+ License. (Exception: if the Program itself is interactive but+ does not normally print such an announcement, your work based on+ the Program is not required to print an announcement.)++These requirements apply to the modified work as a whole. If+identifiable sections of that work are not derived from the Program,+and can be reasonably considered independent and separate works in+themselves, then this License, and its terms, do not apply to those+sections when you distribute them as separate works. But when you+distribute the same sections as part of a whole which is a work based+on the Program, the distribution of the whole must be on the terms of+this License, whose permissions for other licensees extend to the+entire whole, and thus to each and every part regardless of who wrote it.++Thus, it is not the intent of this section to claim rights or contest+your rights to work written entirely by you; rather, the intent is to+exercise the right to control the distribution of derivative or+collective works based on the Program.++In addition, mere aggregation of another work not based on the Program+with the Program (or with a work based on the Program) on a volume of+a storage or distribution medium does not bring the other work under+the scope of this License.++ 3. You may copy and distribute the Program (or a work based on it,+under Section 2) in object code or executable form under the terms of+Sections 1 and 2 above provided that you also do one of the following:++ a) Accompany it with the complete corresponding machine-readable+ source code, which must be distributed under the terms of Sections+ 1 and 2 above on a medium customarily used for software interchange; or,++ b) Accompany it with a written offer, valid for at least three+ years, to give any third party, for a charge no more than your+ cost of physically performing source distribution, a complete+ machine-readable copy of the corresponding source code, to be+ distributed under the terms of Sections 1 and 2 above on a medium+ customarily used for software interchange; or,++ c) Accompany it with the information you received as to the offer+ to distribute corresponding source code. (This alternative is+ allowed only for noncommercial distribution and only if you+ received the program in object code or executable form with such+ an offer, in accord with Subsection b above.)++The source code for a work means the preferred form of the work for+making modifications to it. For an executable work, complete source+code means all the source code for all modules it contains, plus any+associated interface definition files, plus the scripts used to+control compilation and installation of the executable. However, as a+special exception, the source code distributed need not include+anything that is normally distributed (in either source or binary+form) with the major components (compiler, kernel, and so on) of the+operating system on which the executable runs, unless that component+itself accompanies the executable.++If distribution of executable or object code is made by offering+access to copy from a designated place, then offering equivalent+access to copy the source code from the same place counts as+distribution of the source code, even though third parties are not+compelled to copy the source along with the object code.++ 4. You may not copy, modify, sublicense, or distribute the Program+except as expressly provided under this License. Any attempt+otherwise to copy, modify, sublicense or distribute the Program is+void, and will automatically terminate your rights under this License.+However, parties who have received copies, or rights, from you under+this License will not have their licenses terminated so long as such+parties remain in full compliance.++ 5. You are not required to accept this License, since you have not+signed it. However, nothing else grants you permission to modify or+distribute the Program or its derivative works. These actions are+prohibited by law if you do not accept this License. Therefore, by+modifying or distributing the Program (or any work based on the+Program), you indicate your acceptance of this License to do so, and+all its terms and conditions for copying, distributing or modifying+the Program or works based on it.++ 6. Each time you redistribute the Program (or any work based on the+Program), the recipient automatically receives a license from the+original licensor to copy, distribute or modify the Program subject to+these terms and conditions. You may not impose any further+restrictions on the recipients' exercise of the rights granted herein.+You are not responsible for enforcing compliance by third parties to+this License.++ 7. If, as a consequence of a court judgment or allegation of patent+infringement or for any other reason (not limited to patent issues),+conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License. If you cannot+distribute so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you+may not distribute the Program at all. For example, if a patent+license would not permit royalty-free redistribution of the Program by+all those who receive copies directly or indirectly through you, then+the only way you could satisfy both it and this License would be to+refrain entirely from distribution of the Program.++If any portion of this section is held invalid or unenforceable under+any particular circumstance, the balance of the section is intended to+apply and the section as a whole is intended to apply in other+circumstances.++It is not the purpose of this section to induce you to infringe any+patents or other property right claims or to contest validity of any+such claims; this section has the sole purpose of protecting the+integrity of the free software distribution system, which is+implemented by public license practices. Many people have made+generous contributions to the wide range of software distributed+through that system in reliance on consistent application of that+system; it is up to the author/donor to decide if he or she is willing+to distribute software through any other system and a licensee cannot+impose that choice.++This section is intended to make thoroughly clear what is believed to+be a consequence of the rest of this License.++ 8. If the distribution and/or use of the Program is restricted in+certain countries either by patents or by copyrighted interfaces, the+original copyright holder who places the Program under this License+may add an explicit geographical distribution limitation excluding+those countries, so that distribution is permitted only in or among+countries not thus excluded. In such case, this License incorporates+the limitation as if written in the body of this License.++ 9. The Free Software Foundation may publish revised and/or new versions+of the General Public License from time to time. Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++Each version is given a distinguishing version number. If the Program+specifies a version number of this License which applies to it and "any+later version", you have the option of following the terms and conditions+either of that version or of any later version published by the Free+Software Foundation. If the Program does not specify a version number of+this License, you may choose any version ever published by the Free Software+Foundation.++ 10. If you wish to incorporate parts of the Program into other free+programs whose distribution conditions are different, write to the author+to ask for permission. For software which is copyrighted by the Free+Software Foundation, write to the Free Software Foundation; we sometimes+make exceptions for this. Our decision will be guided by the two goals+of preserving the free status of all derivatives of our free software and+of promoting the sharing and reuse of software generally.++ NO WARRANTY++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,+REPAIR OR CORRECTION.++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE+POSSIBILITY OF SUCH DAMAGES.++ END OF TERMS AND CONDITIONS++ How to Apply These Terms to Your New Programs++ If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++ To do so, attach the following notices to the program. It is safest+to attach them to the start of each source file to most effectively+convey the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++ <one line to give the program's name and a brief idea of what it does.>+ Copyright (C) <year> <name of author>++ This program is free software; you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation; either version 2 of the License, or+ (at your option) any later version.++ This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License for more details.++ You should have received a copy of the GNU General Public License+ along with this program; if not, write to the Free Software+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+++Also add information on how to contact you by electronic and paper mail.++If the program is interactive, make it output a short notice like this+when it starts in an interactive mode:++ Gnomovision version 69, Copyright (C) year name of author+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+ This is free software, and you are welcome to redistribute it+ under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License. Of course, the commands you use may+be called something other than `show w' and `show c'; they could even be+mouse-clicks or menu items--whatever suits your program.++You should also get your employer (if you work as a programmer) or your+school, if any, to sign a "copyright disclaimer" for the program, if+necessary. Here is a sample; alter the names:++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program+ `Gnomovision' (which makes passes at compilers) written by James Hacker.++ <signature of Ty Coon>, 1 April 1989+ Ty Coon, President of Vice++This General Public License does not permit incorporating your program into+proprietary programs. If your program is a subroutine library, you may+consider it more useful to permit linking proprietary applications with the+library. If this is what you want to do, use the GNU Library General+Public License instead of this License.
+ COPYRIGHT view
@@ -0,0 +1,26 @@+Copyright (C) 2006-2008 John Goerzen <jgoerzen@complete.org>++All code, documentation, and build scripts are under the following+license unless otherwise noted:++ This program is free software; you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation; either version 2 of the License, or+ (at your option) any later version.++ This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License for more details.++ You should have received a copy of the GNU General Public License+ along with this program; if not, write to the Free Software+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA++The GNU General Public License is available in the file COPYING in the source+distribution. Debian GNU/Linux users may find this in+/usr/share/common-licenses/GPL-2.++If the GPL is unacceptable for your uses, please e-mail me; alternative+terms can be negotiated for your project.+
+ Commands.hs view
@@ -0,0 +1,70 @@+{-+Copyright (C) 2006-2008 John Goerzen <jgoerzen@complete.org>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+-}++{- |+ Module : Commands+ Copyright : Copyright (C) 2006-2008 John Goerzen+ License : GNU GPL, version 2 or above++ Maintainer : John Goerzen <jgoerzen@complete.org>+ Stability : provisional+ Portability: portable++Written by John Goerzen, jgoerzen\@complete.org++-}+module Commands where++import Text.Printf+import Utils+import Types+import Config++import qualified Commands.Follow+import qualified Commands.Ls+import qualified Commands.Setup+import qualified Commands.Update++--allCommands :: [(String, Command)]+allCommands = + [Commands.Update.dmsend,+ Commands.Follow.follow,+ Commands.Ls.lsarchive,+ lscommands,+ Commands.Ls.lsdm,+ Commands.Ls.lsdmarchive,+ Commands.Ls.lsfollowers,+ Commands.Ls.lsfollowing,+ Commands.Ls.lsrecent,+ Commands.Ls.lsreplies,+ Commands.Setup.setup,+ Commands.Follow.unfollow,+ Commands.Update.update+ ]++lscommands = + simpleCmd "lscommands" "Display a list of all available commands" ""+ [] lscommands_worker++lscommands_worker _ _ _ =+ do putStrLn "All available commands:"+ printf "%-20s %s\n" "Name" "Description"+ putStrLn "-------------------- -------------------------------------------------------"+ mapM_ (\(_, x) -> printf "%-20s %s\n" (cmdname x) (cmddescrip x))+ allCommands+
+ Commands/Ls.hs view
@@ -0,0 +1,342 @@+{-+Copyright (C) 2006-2008 John Goerzen <jgoerzen@complete.org>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+-}++module Commands.Ls(lsrecent, lsreplies, lsfollowing, lsfollowers, lsarchive, lsdm, lsdmarchive) where+import Utils+import System.Log.Logger+import Types+import Text.Printf+import System.Console.GetOpt+import Data.List+import Text.XML.HaXml hiding (when)+import Download+import FeedParser+import Data.ConfigFile+import Data.String.Utils(strip)+import Config+import Data.Either.Utils(forceEither)+import Control.Monad(when)+import Distribution.Simple.Utils(wrapText)+import HSH+import System.Console.GetOpt.Utils++i = infoM "ls"++stdopts = [Option "a" ["all"] (NoArg ("a", "")) + "Show ALL results, not just 1st page\n\+ \WARNING: may generate excessive traffic. \+ \Use with caution!",+ Option "l" ["long"] (NoArg ("l", "")) + "Long format output -- more info and \+ \tab-separated columns"]++sinceopts = [+ Option "e" ["exec"] (ReqArg (stdRequired "e") "COMMAND")+ "Suppress normal output, and instead call COMMAND\n\+ \once for each output item. The command will be\n\+ \passed exactly four arguments: update ID,\n\+ \username, suggested Message-ID, and update\n\+ \content. These arguments may contain shell\n\+ \metacharacters.",+ Option "m" ["mailto"] (ReqArg (stdRequired "m") "ADDRESS")+ "Suppress normal output, and instead generate an\n\+ \email with the data and send it to ADDRESS.",+ Option "s" ["saveid"] (NoArg ("s", ""))+ "Save topmost ID for future use with --unseen.\n\+ \Will write the ID to your config file.",+ Option "u" ["unseen"] (NoArg ("u", ""))+ "Show only items since the last use of --saveid"]++paginated workerfunc cppath cp (args, remainder)+ | lookup "a" args == Nothing = + do workerfunc cppath cp (args, remainder) 1+ return ()+ | otherwise = paginateloop 1+ where paginateloop page =+ do r <- workerfunc cppath cp (args, remainder) page+ if null r+ then return ()+ else paginateloop (page + 1)++maybeSaveList section cpath cp args [] = return ()+maybeSaveList section cpath cp args newids =+ do debugM section $ "maybeSaveList called: " ++ show args ++ " " ++ show newids+ maybeSave section cpath cp args theid+ where theid = maximum . map (read::String -> Integer) $ newids++maybeSave section cpath cp args newid =+ case (lookup "s" args, get cp section "lastid") of+ (Nothing, _) -> return ()+ (_, Left _) -> saveid+ (_, Right x) ->+ if (read x) < (newid::Integer)+ then return ()+ else saveid+ where saveid = writeCP cpath newcp+ newcp = forceEither $+ do cp2 <- if (has_section cp section)+ then return cp+ else add_section cp section+ cp2 <- set cp2 section "lastid" (show newid)+ return cp2++sinceArgs section cp args =+ case (lookup "u" args, get cp section "lastid") of+ (Nothing, _) -> []+ (_, Left _) -> []+ (_, Right a) -> + [("since_id", strip a)]++--------------------------------------------------+-- lsrecent+--------------------------------------------------++lsrecent = simpleCmd "lsrecent" "List recent updates from those you follow"+ lsrecent_help+ (stdopts ++ sinceopts) (paginated (statuses_worker "lsrecent"+ "/statuses/friends_timeline"))++lsreplies = simpleCmd "lsreplies" "List recent replies to you"+ lsreplies_help+ (stdopts ++ sinceopts) (paginated (statuses_worker "lsreplies" + "/statuses/replies"))++lsarchive = simpleCmd "lsarchive" "List recent status updates you posted yourself"+ lsarchive_help+ (stdopts ++ sinceopts) (paginated (statuses_worker "lsarchive"+ "/statuses/user_timeline"))++lsdm = simpleCmd "lsdm" "List recent direct messages to you"+ lsdm_help+ (stdopts ++ sinceopts) (paginated (dm_worker "lsdm" + "/direct_messages"))++lsdmarchive = simpleCmd "lsdmarchive" "List recent direct messages you sent"+ lsdmarchive_help+ (stdopts ++ sinceopts) (paginated (dm_worker "lsdmarchive"+ "/direct_messages/sent"))++statuses_worker = generic_worker handleStatus+dm_worker = generic_worker handleDM++generic_worker procfunc section command cpath cp (args, _) page =+ do xmlstr <- sendAuthRequest cp (command ++ ".xml")+ (("page", show page) : sinceArgs section cp args)+ []+ debugM section $ "Got doc: " ++ xmlstr+ results <- procfunc section cp args xmlstr+ when (page == 1) $+ maybeSaveList section cpath cp args (map sId results)+ return results++lsrecent_help =+ "Usage: twidge lsrecent [options]\n\n\+ \You can see the 20 most recent items from your friends with:\n\n\+ \ twidge lsrecent\n\n\+ \To see items that you haven't seen yet, and remember this for the future,\n\+ \use:\n\n\+ \ twidge lsrecent -su\n\n\+ \After running that once, you may want to use -asu in the future to get all\n\+ \unseen messages, even if there are more than 20. Don't use -a until\n\+ \you've used -s at least once.\n"++lsreplies_help =+ "Usage: twidge lsreplies [options]\n\n\+ \You can see the 20 most recent @replies from others to you with:\n\n\+ \ twidge lsreplies\n\n\+ \For more examples, including how to see only unseen replies, please\n\+ \refer to the examples under twidge lsrecent --help, which also pertain\n\+ \to lsreplies.\n"++lsarchive_help =+ "Usage: twidge lsarchive [options]\n\n\+ \You can see the 20 most recent updates you posted with:\n\n\+ \ twidge lsarchive\n\n\+ \For more examples, including how to see only unseen updates, please\n\+ \refer to the examples under twidge lsrecent --help, which also pertain\n\+ \to lsarchive.\n"++lsdm_help =+ "Usage: twidge lsdm [options]\n\n\+ \You can see the 20 most recent direct messages to you with:\n\n\+ \ twidge lsdm\n\n\+ \For more examples, including how to see only unseen updates, please\n\+ \refer to the examples under twidge lsrecent --help, which also pertain\n\+ \to lsdm.\n"+ +lsdmarchive_help =+ "Usage: twidge lsdmarchive [options]\n\n\+ \You can see the 20 most recent direct messages you sent with:\n\n\+ \ twidge lsdmarchive\n\n\+ \For more examples, including how to see only unseen updates, please\n\+ \refer to the examples under twidge lsrecent --help, which also pertain\n\+ \to lsdmarchive.\n"++handleStatus = handleGeneric (map procStatuses . getStatuses) printStatus+handleDM = handleGeneric (map procDM . getDMs) printDM++handleGeneric pfunc printfunc section cp args xmlstr = + let doc = getContent . xmlParse section . stripUnicodeBOM $ xmlstr+ statuses = pfunc doc+ in do mapM_ (printfunc section cp args) statuses+ return statuses++procStatuses :: Content -> Message+procStatuses item = + Message {sId = s (tag "id") item,+ sSender = s (tag "user" /> tag "screen_name") item,+ sRecipient = "",+ sText = s (tag "text") item,+ sDate = s (tag "created_at") item}++s f item = sanitize $ contentToString (keep /> f /> txt $ item)++procDM :: Content -> Message+procDM item =+ Message {sId = s (tag "id") item,+ sSender = s (tag "sender_screen_name") item,+ sRecipient = s (tag "recipient_screen_name") item,+ sText = s (tag "text") item,+ sDate = s (tag "created_at") item}++getStatuses = tag "statuses" /> tag "status"+getDMs = tag "direct-messages" /> tag "direct_message"++longStatus :: Message -> String+longStatus m = printf "%s\t%s\t%s\t%s\t%s\t\n"+ (sId m) (sSender m) (sRecipient m) (sText m) (sDate m)+shortStatus :: Message -> String+shortStatus m = + (printf "%-22s %s\n" ("<" ++ sSender m ++ ">")+ (head wrappedtext)) +++ concatMap (printf "%-22s %s\n" "") (tail wrappedtext)+ where wrappedtext = wrapText (80 - 22 - 2) (words (sText m))++shortDM :: Message -> String+shortDM m =+ (printf "%-22s %-22s %s\n" ("<" ++ sSender m ++ ">")+ ("<" ++ sRecipient m ++ ">")+ (head wrappedtext)) +++ concatMap (printf "%-22s %-22s %s\n" "" "") (tail wrappedtext)+ where wrappedtext = wrapText (80 - 22 - 22 - 3) (words (sText m))++printStatus section cp args m = + printGeneric shortStatus longStatus section cp args m++printDM section cp args m =+ printGeneric shortDM longStatus section cp args m++printGeneric shortfunc longfunc section cp args m =+ case (lookup "m" args) of+ Nothing -> + case (lookup "e" args, lookup "l" args) of+ (Just cmd, _) ->+ runIO $ (cmd, [sId m, sSender m, sRecipient m, + sText m, sDate m])+ (Nothing, Nothing) -> putStr (shortfunc m)+ (Nothing, Just _) -> putStr (longfunc m)+ Just recipient -> mailto section cp args m recipient+ where msgid = genMsgId section m cp++mailto section cp args m recipient =+ runIO $ echo (message ++ "\n") -|- (sendmail, ["-t"])+ where sendmail = (forceEither $ get cp section "sendmail")::String+ msgid = genMsgId section m cp+ subject = take 30 (sText m) ++ "... (twidge " ++ section ++ ")"+ message = unlines $ + (case get cp section "mailfrom" of+ Left _ -> ["Subject: " ++ (sSender m) ++ ": " ++ subject]+ Right x -> ["From: " ++ (sSender m) ++ " <" ++ x ++ ">",+ "Subject: " ++ subject]+ ) ++ + ["Message-ID: " ++ msgid,+ "X-Twidge-urlbase: " ++ forceEither (get cp "DEFAULT" "urlbase"),+ "X-Twidge-server-base: " ++ serverHost cp,+ "X-Twidge-command: " ++ section,+ "X-Twidge-update-id: " ++ sId m,+ "X-Twidge-update-sender: " ++ sSender m,+ "X-Twidge-update-recipient: " ++ sRecipient m,+ "To: " ++ recipient,+ "",+ sText m,+ "",+ "(from " ++ sSender m ++ ")"]++--------------------------------------------------+-- lsfollowing+--------------------------------------------------++lsfollowing = simpleCmd "lsfollowing" "List people you are following"+ lsfollowing_help+ stdopts (paginated lsfollowing_worker)++lsfollowing_worker _ cp (args, user) page =+ do xmlstr <- sendAuthRequest cp url [("page", show page)] []+ debugM "lsfollowing" $ "Got doc: " ++ xmlstr+ let doc = getContent . xmlParse "lsfollowing" . stripUnicodeBOM $ xmlstr+ let users = map procUsers . getUsers $ doc+ mapM_ (printUser args) users+ return users+ + where url = case user of+ [] -> "/statuses/friends.xml"+ [x] -> "/statuses/friends/" ++ x ++ ".xml"+ _ -> error "Invalid args to lsfollowing; see twidge lsfollowing --help"++printUser args (name, userid) = + case lookup "l" args of+ Nothing -> putStrLn name+ Just _ -> printf "%s\t%s\n" userid name++getUsers = tag "users" /> tag "user"++procUsers :: Content -> (String, String)+procUsers item =+ (sanitize $ contentToString (keep /> tag "screen_name" /> txt $ item),+ sanitize $ contentToString (keep /> tag "id" /> txt $ item))++lsfollowing_help =+ "Usage: twidge lsfollowing [options] [username]\n\n\+ \If username is given, list the twitter accounts that user is following.\n\+ \Otherwise, list the twitter accounts your user is following.\n"++--------------------------------------------------+-- lsfollowers+--------------------------------------------------++lsfollowers = simpleCmd "lsfollowers" "List people that follow you"+ lsfollowers_help+ stdopts (paginated lsfollowers_worker)++lsfollowers_worker _ cp (args, user) page =+ do xmlstr <- sendAuthRequest cp url [("page", show page)] []+ debugM "lsfollowers" $ "Got doc: " ++ xmlstr+ let doc = getContent . xmlParse "lsfollowers" . stripUnicodeBOM $ xmlstr+ let users = map procUsers . getUsers $ doc+ mapM_ (printUser args) users+ return users+ + where url = case user of+ [] -> "/statuses/followers.xml"+ [x] -> "/statuses/followers/" ++ x ++ ".xml"+ _ -> error "Invalid args to lsfollowers; see twidge lsfollowers --help"++lsfollowers_help =+ "Usage: twidge lsfollowers [options] [username]\n\n\+ \If username is given, list the twitter accounts that follow the user.\n\+ \Otherwise, list the twitter accounts that follow you.\n"
+ Config.hs view
@@ -0,0 +1,79 @@+{- hpodder component+Copyright (C) 2006-2008 John Goerzen <jgoerzen@complete.org>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+-}++{- |+ Module : Config+ Copyright : Copyright (C) 2006-2008 John Goerzen+ License : GNU GPL, version 2 or above++ Maintainer : John Goerzen <jgoerzen@complete.org>+ Stability : provisional+ Portability: portable++Written by John Goerzen, jgoerzen\@complete.org++-}+module Config where++import System.Directory+import Data.ConfigFile+import Control.Monad+import Data.Either.Utils+import Data.String.Utils(strip, split)+import System.Posix.Files(rename)++getDefaultCP =+ do return $ forceEither $ + do cp <- set startingcp "DEFAULT" "urlbase" "https://twitter.com"+ cp <- set cp "DEFAULT" "sendmail" "/usr/sbin/sendmail"+ cp <- set cp "DEFAULT" "shortenurls" "yes"+ return cp++startingcp = emptyCP {accessfunc = interpolatingAccess 10}++getCPName =+ do appdir <- getUserDocumentsDirectory+ return $ appdir ++ "/.twidgerc"++loadCP cpgiven = + do cpname <- case cpgiven of+ Nothing -> getCPName+ Just x -> return x+ defaultcp <- getDefaultCP+ dfe <- doesFileExist cpname+ if dfe+ then do cp <- readfile defaultcp cpname+ return $ forceEither cp+ else do fail $ "No config file found at " ++ cpname ++ + "\nRun twidge setup to configure twidge for use."++writeCP cpgiven cp =+ do cpname <- case cpgiven of+ Nothing -> getCPName+ Just x -> return x+ let tempname = cpname ++ ".write.tmp"+ writeFile tempname (to_string cp)+ rename tempname cpname++getList :: ConfigParser -> String -> String -> Maybe [String]+getList cp sect key = + case get cp sect key of+ Right x -> Just (splitit x)+ Left _ -> Nothing+ where splitit x = filter (/= "") . map strip . split "," $ x+
+ Download.hs view
@@ -0,0 +1,76 @@+{- hpodder component+Copyright (C) 2006-2007 John Goerzen <jgoerzen@complete.org>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+-}++{- |+ Module : Download+ Copyright : Copyright (C) 2006-2008 John Goerzen+ License : GNU GPL, version 2 or above++ Maintainer : John Goerzen <jgoerzen@complete.org>+ Stability : provisional+ Portability: portable++Written by John Goerzen, jgoerzen\@complete.org++-}++module Download(sendAuthRequest, simpleDownload) where+import System.Log.Logger+import Data.ConfigFile+import HSH+import Data.Either.Utils(forceEither)+import Network.URI+import Data.List+import Control.Exception(evaluate)++d = debugM "download"+i = infoM "download"++curl = "curl"+curlopts = ["-A", "twidge v1.0.0; Haskell; GHC", -- Set User-Agent+ "-s", -- Silent mode+ "-S", -- Still show error messages+ "-L", -- Follow redirects+ "-y", "60", "-Y", "1", -- Timeouts+ "--retry", "2", -- Retry twice+ "-f" -- Fail on server errors+ ]++simpleDownload :: String -> IO String+simpleDownload url = run (curl, curlopts ++ [url])++sendAuthRequest :: ConfigParser -> String -> [(String, String)] -> [(String, String)] -> IO String+sendAuthRequest cp url getopts postoptlist =+ do -- Force this to be evaluated in the parent process+ authopts <- evaluate (getAuthOpts cp)+ run (curl, curlopts ++ authopts ++ postopts ++ [urlbase ++ url ++ optstr])+ where urlbase = forceEither $ get cp "DEFAULT" "urlbase"+ optstr = case getopts of+ [] -> ""+ _ -> "?" ++ (concat . intersperse "&" . map conv $ getopts)+ conv (k, v) = k ++ "=" ++ escapeURIString isUnreserved v+ postopts = concatMap postopt postoptlist+ postopt (k, v) = ["-d", escapeURIString isUnreserved k ++ "=" +++ escapeURIString isUnreserved v]++getAuthOpts :: ConfigParser -> [String]+getAuthOpts cp =+ case (get cp "DEFAULT" "username", get cp "DEFAULT" "password") of+ (Right user, Right pass) ->+ ["--user", user ++ ":" ++ pass]+ _ -> error "Missing username or password option in config file"
+ FeedParser.hs view
@@ -0,0 +1,70 @@+{- +Copyright (C) 2006-2008 John Goerzen <jgoerzen@complete.org>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+-}++{- |+ Module : FeedParser+ Copyright : Copyright (C) 2006-2008 John Goerzen+ License : GNU GPL, version 2 or above++ Maintainer : John Goerzen <jgoerzen@complete.org>+ Stability : provisional+ Portability: portable++Written by John Goerzen, jgoerzen\@complete.org++-}+module FeedParser where++import Text.XML.HaXml+import Data.Char+import Data.List+import Data.String.Utils(strip)++{- | Convert [Content] to a printable string, taking care to unescape it.++An implementation without unescaping would simply be:++> contentToString = concatMap (show . content)++Because HaXml's unescaping only works on Elements, we must make sure that+whatever Content we have is wrapped in an Element, then use txt to+pull the insides back out. -}+contentToString :: [Content] -> String+contentToString = + concatMap procContent+ where procContent x = + verbatim $ keep /> txt $ CElem (unesc (fakeElem x))++ fakeElem :: Content -> Element+ fakeElem x = Elem "fake" [] [x]++ unesc :: Element -> Element+ unesc = xmlUnEscape stdXmlEscaper++stripUnicodeBOM :: String -> String+stripUnicodeBOM ('\xef':'\xbb':'\xbf':x) = x+stripUnicodeBOM x = x++{- | Removes potentially problematic or malicious stuff -}+sanitize :: String -> String+sanitize = strip . map sanitizer+ where sanitizer c + | c `elem` "\n\r\0\t" = ' '+ | otherwise = c++getContent (Document _ _ e _) = CElem e
+ INSTALL view
@@ -0,0 +1,10 @@+Sorry, need more here...++Try:++ghc --make -o setup Setup.lhs+./setup configure+./setup build+./setup install++To run, you will need to have curl installed
+ Setup.lhs view
@@ -0,0 +1,7 @@+#!/usr/bin/env runhugs+arch-tag: Main setup script++> import Distribution.Simple++> main = defaultMain+
+ Types.hs view
@@ -0,0 +1,46 @@+{- hpodder component+Copyright (C) 2006-2007 John Goerzen <jgoerzen@complete.org>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+-}++{- |+ Module : Types+ Copyright : Copyright (C) 2006-2007 John Goerzen+ License : GNU GPL, version 2 or above++ Maintainer : John Goerzen <jgoerzen@complete.org>+ Stability : provisional+ Portability: portable++Written by John Goerzen, jgoerzen\@complete.org++-}+module Types where+import Data.ConfigFile++data Command =+ Command {cmdname :: String,+ cmddescrip :: String,+ execcmd :: [String] -> Maybe FilePath -> ConfigParser -> IO ()}++data Message = Message {+ sId :: String,+ sSender :: String,+ sRecipient :: String,+ sText :: String,+ sDate :: String+ } deriving (Eq, Read, Show, Ord)+
+ Utils.hs view
@@ -0,0 +1,119 @@+{-+Copyright (C) 2006-2008 John Goerzen <jgoerzen@complete.org>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+-}++{- |+ Module : Utils+ Copyright : Copyright (C) 2006-2008 John Goerzen+ License : GNU GPL, version 2 or above++ Maintainer : John Goerzen <jgoerzen@complete.org>+ Stability : provisional+ Portability: portable++Written by John Goerzen, jgoerzen\@complete.org++-}++module Utils where+import System.Console.GetOpt+import Types+import System.Exit+import System.IO+import Data.ConfigFile+import Text.Regex.Posix+import Data.Either.Utils(forceEither)+import Network.URI+import Data.Maybe.Utils+import Text.Printf++simpleCmd :: String -- ^ Command name+ -> String -- ^ Command description+ -> String -- ^ Command help text+ -> [OptDescr (String, String)] -- ^ Option descriptions+ -> (Maybe String -> ConfigParser -> ([(String, String)], [String]) -> IO ()) -- ^ Function to call + -> (String, Command)+simpleCmd name descrip helptext optionsinp func =+ (name, Command {cmdname = name, cmddescrip = descrip,+ execcmd = worker})+ where options =+ optionsinp ++ [Option "" ["help"] (NoArg ("help", "")) "Display this help"]+ worker argv cpath gi =+ case getOpt RequireOrder options argv of+ (o, n, []) -> + if (lookup "help" o == Just "") + then usageerror []+ else func cpath gi (o, n)+ (_, _, errors) -> usageerror (concat errors)+ usageerror errormsg =+ do putStrLn $ "Error processing arguments for command " ++ + name ++ ":"+ putStrLn errormsg+ putStrLn (usageInfo header options)+ putStrLn helptext+ exitFailure+ header = "Available command-options for " ++ name ++ " are:\n"+ +{-+lock func =+ do appdir <- getAppDir+ lockh <- openFile (appdir ++ "/.lock") WriteMode+ lockfd <- handleToFd lockh+ catch (placelock lockfd) errorhandler+ r <- finally func (releaselock lockfd)+ return r++ where placelock lockfd = setLock lockfd (WriteLock, AbsoluteSeek, 0, 0)+ releaselock lockfd = do+ setLock lockfd (Unlock, AbsoluteSeek, 0, 0)+ closeFd lockfd+ errorhandler _ =+ do putStrLn "Aborting because another twidge is already running"+ exitFailure+-}++ex_tempfail = 75+ex_permfail = 69++permFail :: String -> IO a+permFail msg =+ do hPutStrLn stderr msg+ exitWith (ExitFailure ex_permfail)++serverHost cp = host+ where urlbase = forceEither $ get cp "DEFAULT" "urlbase"+ uri = forceMaybeMsg "genMsgId parseURI" $ parseURI urlbase+ host = uriRegName . forceMaybeMsg "genMsgId uriauth" . + uriAuthority $ uri++genMsgId :: String -> Message -> ConfigParser -> String+genMsgId section m cp =+ printf "<%s.%s.%s@%s.%s.twidge>" (sId m) (sSender m) (sRecipient m)+ section (serverHost cp) +-- FIXME: escape periods in serverHost++{- | Parses a message id, returning (Message, host, section).+The sText and sDate fiels will be empty. -}+parseMsgId :: String -> Maybe (Message, String, String)+parseMsgId msgid =+ case msgid =~ repat of+ [[_, id, sender, recipient, section, host]] -> + Just (Message {sId = id, sSender = sender, sRecipient = recipient, + sText = "", sDate = ""},+ host, section)+ _ -> Nothing+ where repat = "^<([^.@]+)\\.([^.@]+)\\.([^@.]*)@([^.]+)\\.(.+)\\.twidge>"
+ doc/SConstruct view
@@ -0,0 +1,30 @@+# Copyright (C) 2004-2006 John Goerzen <jgoerzen@complete.org>+# <jgoerzen@complete.org>+#+# This program is free software; you can redistribute it and/or modify+# it under the terms of the GNU General Public License as published by+# the Free Software Foundation; either version 2 of the License, or+# (at your option) any later version.+#+# This program is distributed in the hope that it will be useful,+# but WITHOUT ANY WARRANTY; without even the implied warranty of+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+# GNU General Public License for more details.+#+# You should have received a copy of the GNU General Public License+# along with this program; if not, write to the Free Software+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA++env = Environment()+env.Export("env")+env.Append(MASTERBASE = 'twidge', TOPNODE = 'twidge', DOINDEX = 1,+ PDFARGS = '-s local=printlocal')++execfile('sgml-common/SConstruct')++manpages = []+for manpage in ['twidge']:+ manpages.append(env.MAN('%s.1' % manpage, 'man.%s.sgml' % manpage))+env.Alias('manpages', manpages)++
+ doc/local.dsl view
@@ -0,0 +1,41 @@+<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [+<!ENTITY dbstyle PUBLIC "-//GtkViaAlcove//DOCUMENT Gtk-doc HTML Stylesheet//EN" CDATA DSSSL>+]>++<style-sheet>+<style-specification use="gtk">+<style-specification-body>++(define (toc-depth nd)+ (if (string=? (gi nd) (normalize "book"))+ 1+ 1))+(define %generate-article-toc% #t)++;; Don't split up the doc as much.+(define (chunk-element-list)+ (list (normalize "preface")+ (normalize "chapter")+ (normalize "appendix")+ (normalize "article")+ (normalize "glossary")+ (normalize "bibliography")+ (normalize "index")+ (normalize "colophon")+ (normalize "setindex")+ (normalize "reference")+ (normalize "refentry")+ (normalize "part")+ (normalize "book") ;; just in case nothing else matches...+ (normalize "set") ;; sets are definitely chunks...+ ))+++</style-specification-body>+</style-specification>+<external-specification id="gtk" document="dbstyle">+</style-sheet>++<!--+# arch-tag: web stylesheet for documentation+-->
+ doc/man.twidge.sgml view
@@ -0,0 +1,21 @@+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [+<!ENTITY twidge "<application>twidge</application>">+<!ENTITY man.twidge SYSTEM "twidge-manpage.sgml">++ ]>++ <reference>+ <title>twidge Manual</title>+ + &man.twidge;++ </reference>+++ <!--+ Local Variables:+ mode: sgml+ sgml-set-face: T+ End:++ -->
+ doc/printlocal.dsl view
@@ -0,0 +1,25 @@+<!DOCTYPE style-sheet PUBLIC "-//James Clark//DTD DSSSL Style Sheet//EN" [+<!ENTITY dbstyle PUBLIC "-//Norman Walsh//DOCUMENT DocBook Print Stylesheet//EN" CDATA DSSSL>+]>++<style-sheet>+<style-specification use="docbook">+<style-specification-body>++(define tex-backend #t)+(define bop-footnotes #t)+(define %two-side% #t)+(define %footnote-ulinks% #t)++; (declare-characteristic heading-level+; "UNREGISTERED::James Clark//Characteristic::heading-level" 4)+++</style-specification-body>+</style-specification>+<external-specification id="docbook" document="dbstyle">+</style-sheet>++<!--+# arch-tag: print stylesheet for manual+-->
+ doc/sgml-common/COPYING view
@@ -0,0 +1,342 @@+ GNU GENERAL PUBLIC LICENSE+ Version 2, June 1991++ Copyright (C) 1989, 1991 Free Software Foundation, Inc.+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++ Preamble++ The licenses for most software are designed to take away your+freedom to share and change it. By contrast, the GNU General Public+License is intended to guarantee your freedom to share and change free+software--to make sure the software is free for all its users. This+General Public License applies to most of the Free Software+Foundation's software and to any other program whose authors commit to+using it. (Some other Free Software Foundation software is covered by+the GNU Library General Public License instead.) You can apply it to+your programs, too.++ When we speak of free software, we are referring to freedom, not+price. Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+this service if you wish), that you receive source code or can get it+if you want it, that you can change the software or use pieces of it+in new free programs; and that you know you can do these things.++ To protect your rights, we need to make restrictions that forbid+anyone to deny you these rights or to ask you to surrender the rights.+These restrictions translate to certain responsibilities for you if you+distribute copies of the software, or if you modify it.++ For example, if you distribute copies of such a program, whether+gratis or for a fee, you must give the recipients all the rights that+you have. You must make sure that they, too, receive or can get the+source code. And you must show them these terms so they know their+rights.++ We protect your rights with two steps: (1) copyright the software, and+(2) offer you this license which gives you legal permission to copy,+distribute and/or modify the software.++ Also, for each author's protection and ours, we want to make certain+that everyone understands that there is no warranty for this free+software. If the software is modified by someone else and passed on, we+want its recipients to know that what they have is not the original, so+that any problems introduced by others will not reflect on the original+authors' reputations.++ Finally, any free program is threatened constantly by software+patents. We wish to avoid the danger that redistributors of a free+program will individually obtain patent licenses, in effect making the+program proprietary. To prevent this, we have made it clear that any+patent must be licensed for everyone's free use or not licensed at all.++ The precise terms and conditions for copying, distribution and+modification follow.++ GNU GENERAL PUBLIC LICENSE+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++ 0. This License applies to any program or other work which contains+a notice placed by the copyright holder saying it may be distributed+under the terms of this General Public License. The "Program", below,+refers to any such program or work, and a "work based on the Program"+means either the Program or any derivative work under copyright law:+that is to say, a work containing the Program or a portion of it,+either verbatim or with modifications and/or translated into another+language. (Hereinafter, translation is included without limitation in+the term "modification".) Each licensee is addressed as "you".++Activities other than copying, distribution and modification are not+covered by this License; they are outside its scope. The act of+running the Program is not restricted, and the output from the Program+is covered only if its contents constitute a work based on the+Program (independent of having been made by running the Program).+Whether that is true depends on what the Program does.++ 1. You may copy and distribute verbatim copies of the Program's+source code as you receive it, in any medium, provided that you+conspicuously and appropriately publish on each copy an appropriate+copyright notice and disclaimer of warranty; keep intact all the+notices that refer to this License and to the absence of any warranty;+and give any other recipients of the Program a copy of this License+along with the Program.++You may charge a fee for the physical act of transferring a copy, and+you may at your option offer warranty protection in exchange for a fee.++ 2. You may modify your copy or copies of the Program or any portion+of it, thus forming a work based on the Program, and copy and+distribute such modifications or work under the terms of Section 1+above, provided that you also meet all of these conditions:++ a) You must cause the modified files to carry prominent notices+ stating that you changed the files and the date of any change.++ b) You must cause any work that you distribute or publish, that in+ whole or in part contains or is derived from the Program or any+ part thereof, to be licensed as a whole at no charge to all third+ parties under the terms of this License.++ c) If the modified program normally reads commands interactively+ when run, you must cause it, when started running for such+ interactive use in the most ordinary way, to print or display an+ announcement including an appropriate copyright notice and a+ notice that there is no warranty (or else, saying that you provide+ a warranty) and that users may redistribute the program under+ these conditions, and telling the user how to view a copy of this+ License. (Exception: if the Program itself is interactive but+ does not normally print such an announcement, your work based on+ the Program is not required to print an announcement.)++These requirements apply to the modified work as a whole. If+identifiable sections of that work are not derived from the Program,+and can be reasonably considered independent and separate works in+themselves, then this License, and its terms, do not apply to those+sections when you distribute them as separate works. But when you+distribute the same sections as part of a whole which is a work based+on the Program, the distribution of the whole must be on the terms of+this License, whose permissions for other licensees extend to the+entire whole, and thus to each and every part regardless of who wrote it.++Thus, it is not the intent of this section to claim rights or contest+your rights to work written entirely by you; rather, the intent is to+exercise the right to control the distribution of derivative or+collective works based on the Program.++In addition, mere aggregation of another work not based on the Program+with the Program (or with a work based on the Program) on a volume of+a storage or distribution medium does not bring the other work under+the scope of this License.++ 3. You may copy and distribute the Program (or a work based on it,+under Section 2) in object code or executable form under the terms of+Sections 1 and 2 above provided that you also do one of the following:++ a) Accompany it with the complete corresponding machine-readable+ source code, which must be distributed under the terms of Sections+ 1 and 2 above on a medium customarily used for software interchange; or,++ b) Accompany it with a written offer, valid for at least three+ years, to give any third party, for a charge no more than your+ cost of physically performing source distribution, a complete+ machine-readable copy of the corresponding source code, to be+ distributed under the terms of Sections 1 and 2 above on a medium+ customarily used for software interchange; or,++ c) Accompany it with the information you received as to the offer+ to distribute corresponding source code. (This alternative is+ allowed only for noncommercial distribution and only if you+ received the program in object code or executable form with such+ an offer, in accord with Subsection b above.)++The source code for a work means the preferred form of the work for+making modifications to it. For an executable work, complete source+code means all the source code for all modules it contains, plus any+associated interface definition files, plus the scripts used to+control compilation and installation of the executable. However, as a+special exception, the source code distributed need not include+anything that is normally distributed (in either source or binary+form) with the major components (compiler, kernel, and so on) of the+operating system on which the executable runs, unless that component+itself accompanies the executable.++If distribution of executable or object code is made by offering+access to copy from a designated place, then offering equivalent+access to copy the source code from the same place counts as+distribution of the source code, even though third parties are not+compelled to copy the source along with the object code.++ 4. You may not copy, modify, sublicense, or distribute the Program+except as expressly provided under this License. Any attempt+otherwise to copy, modify, sublicense or distribute the Program is+void, and will automatically terminate your rights under this License.+However, parties who have received copies, or rights, from you under+this License will not have their licenses terminated so long as such+parties remain in full compliance.++ 5. You are not required to accept this License, since you have not+signed it. However, nothing else grants you permission to modify or+distribute the Program or its derivative works. These actions are+prohibited by law if you do not accept this License. Therefore, by+modifying or distributing the Program (or any work based on the+Program), you indicate your acceptance of this License to do so, and+all its terms and conditions for copying, distributing or modifying+the Program or works based on it.++ 6. Each time you redistribute the Program (or any work based on the+Program), the recipient automatically receives a license from the+original licensor to copy, distribute or modify the Program subject to+these terms and conditions. You may not impose any further+restrictions on the recipients' exercise of the rights granted herein.+You are not responsible for enforcing compliance by third parties to+this License.++ 7. If, as a consequence of a court judgment or allegation of patent+infringement or for any other reason (not limited to patent issues),+conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License. If you cannot+distribute so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you+may not distribute the Program at all. For example, if a patent+license would not permit royalty-free redistribution of the Program by+all those who receive copies directly or indirectly through you, then+the only way you could satisfy both it and this License would be to+refrain entirely from distribution of the Program.++If any portion of this section is held invalid or unenforceable under+any particular circumstance, the balance of the section is intended to+apply and the section as a whole is intended to apply in other+circumstances.++It is not the purpose of this section to induce you to infringe any+patents or other property right claims or to contest validity of any+such claims; this section has the sole purpose of protecting the+integrity of the free software distribution system, which is+implemented by public license practices. Many people have made+generous contributions to the wide range of software distributed+through that system in reliance on consistent application of that+system; it is up to the author/donor to decide if he or she is willing+to distribute software through any other system and a licensee cannot+impose that choice.++This section is intended to make thoroughly clear what is believed to+be a consequence of the rest of this License.++ 8. If the distribution and/or use of the Program is restricted in+certain countries either by patents or by copyrighted interfaces, the+original copyright holder who places the Program under this License+may add an explicit geographical distribution limitation excluding+those countries, so that distribution is permitted only in or among+countries not thus excluded. In such case, this License incorporates+the limitation as if written in the body of this License.++ 9. The Free Software Foundation may publish revised and/or new versions+of the General Public License from time to time. Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++Each version is given a distinguishing version number. If the Program+specifies a version number of this License which applies to it and "any+later version", you have the option of following the terms and conditions+either of that version or of any later version published by the Free+Software Foundation. If the Program does not specify a version number of+this License, you may choose any version ever published by the Free Software+Foundation.++ 10. If you wish to incorporate parts of the Program into other free+programs whose distribution conditions are different, write to the author+to ask for permission. For software which is copyrighted by the Free+Software Foundation, write to the Free Software Foundation; we sometimes+make exceptions for this. Our decision will be guided by the two goals+of preserving the free status of all derivatives of our free software and+of promoting the sharing and reuse of software generally.++ NO WARRANTY++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,+REPAIR OR CORRECTION.++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE+POSSIBILITY OF SUCH DAMAGES.++ END OF TERMS AND CONDITIONS++ How to Apply These Terms to Your New Programs++ If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++ To do so, attach the following notices to the program. It is safest+to attach them to the start of each source file to most effectively+convey the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++ <one line to give the program's name and a brief idea of what it does.>+ Copyright (C) <year> <name of author>++ This program is free software; you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation; either version 2 of the License, or+ (at your option) any later version.++ This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License for more details.++ You should have received a copy of the GNU General Public License+ along with this program; if not, write to the Free Software+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+++Also add information on how to contact you by electronic and paper mail.++If the program is interactive, make it output a short notice like this+when it starts in an interactive mode:++ Gnomovision version 69, Copyright (C) year name of author+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+ This is free software, and you are welcome to redistribute it+ under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License. Of course, the commands you use may+be called something other than `show w' and `show c'; they could even be+mouse-clicks or menu items--whatever suits your program.++You should also get your employer (if you work as a programmer) or your+school, if any, to sign a "copyright disclaimer" for the program, if+necessary. Here is a sample; alter the names:++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program+ `Gnomovision' (which makes passes at compilers) written by James Hacker.++ <signature of Ty Coon>, 1 April 1989+ Ty Coon, President of Vice++This General Public License does not permit incorporating your program into+proprietary programs. If your program is a subroutine library, you may+consider it more useful to permit linking proprietary applications with the+library. If this is what you want to do, use the GNU Library General+Public License instead of this License.++# arch-tag: License for sgml-common
+ doc/sgml-common/COPYRIGHT view
@@ -0,0 +1,39 @@+Copyright for all code except ps2epsi+-------------------------------------+# Copyright (C) 2002, 2003 John Goerzen+# <jgoerzen@complete.org>+#+# This program is free software; you can redistribute it and/or modify+# it under the terms of the GNU General Public License as published by+# the Free Software Foundation; either version 2 of the License, or+# (at your option) any later version.+#+# This program is distributed in the hope that it will be useful,+# but WITHOUT ANY WARRANTY; without even the implied warranty of+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+# GNU General Public License for more details.+#+# You should have received a copy of the GNU General Public License+# along with this program; if not, write to the Free Software+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA++Copyright for ps2epsi+---------------------+This program is free software; you can redistribute it and/or modify it+under the terms of the GNU General Public License as published by the+Free Software Foundation; either version 2, or (at your option) any+later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, 59 Temple Place - Suite 330,+Boston, MA 02111-1307, USA.++My local changes were to the page size.++# arch-tag: Copyright statements and information for sgml-common
+ doc/sgml-common/ChangeLog view
@@ -0,0 +1,265 @@+# do not edit -- automatically generated by arch changelog+# arch-tag: automatic-ChangeLog--jgoerzen@complete.org--projects/sgml-common--head--1.0+#++2004-05-21 14:28:00 GMT John Goerzen <jgoerzen@complete.org> patch-20++ Summary:+ Fixed text target+ Revision:+ sgml-common--head--1.0--patch-20+++ modified files:+ ChangeLog SConstruct+++2004-02-27 15:22:59 GMT John Goerzen <jgoerzen@complete.org> patch-19++ Summary:+ Added manpage generation support+ Revision:+ sgml-common--head--1.0--patch-19+++ modified files:+ ChangeLog SConstruct+++2004-02-03 19:50:11 GMT John Goerzen <jgoerzen@complete.org> patch-18++ Summary:+ More clearing up of REs+ Revision:+ sgml-common--head--1.0--patch-18+++ modified files:+ ChangeLog SConstruct+++2004-02-03 19:40:22 GMT John Goerzen <jgoerzen@complete.org> patch-17++ Summary:+ Tightened up re for finding image tags+ Revision:+ sgml-common--head--1.0--patch-17+++ modified files:+ ChangeLog SConstruct+++2004-02-03 19:28:03 GMT John Goerzen <jgoerzen@complete.org> patch-16++ Summary:+ More changes to support scanner+ Revision:+ sgml-common--head--1.0--patch-16++ Removed outdated code and made more bugfixes relevant to documents without+ images or with only pre-generated images.++ new files:+ ChangeLog++ modified files:+ SConstruct+++2004-02-03 18:41:51 GMT John Goerzen <jgoerzen@complete.org> patch-15++ Summary:+ HTML gen now basically functional with scanning+ Revision:+ sgml-common--head--1.0--patch-15+++ modified files:+ SConstruct+++2004-02-03 17:41:51 GMT John Goerzen <jgoerzen@complete.org> patch-14++ Summary:+ Auto-scanning is now close for PDFs.+ Revision:+ sgml-common--head--1.0--patch-14+++ modified files:+ SConstruct+++2004-02-03 16:59:02 GMT John Goerzen <jgoerzen@complete.org> patch-13++ Summary:+ Scanners starting to work+ Revision:+ sgml-common--head--1.0--patch-13+++ modified files:+ SConstruct+++2004-02-03 16:22:51 GMT John Goerzen <jgoerzen@complete.org> patch-12++ Summary:+ Cleaned up HTML situation+ Revision:+ sgml-common--head--1.0--patch-12+++ modified files:+ SConstruct+++2004-02-02 22:33:50 GMT John Goerzen <jgoerzen@complete.org> patch-11++ Summary:+ SConstruct file now working+ Revision:+ sgml-common--head--1.0--patch-11+++ modified files:+ SConstruct+++2004-02-02 22:07:27 GMT John Goerzen <jgoerzen@complete.org> patch-10++ Summary:+ Fixed nasty PNG gen bug+ Revision:+ sgml-common--head--1.0--patch-10+++ modified files:+ SConstruct+++2004-02-02 21:57:32 GMT John Goerzen <jgoerzen@complete.org> patch-9++ Summary:+ Checkpointing some more...+ Revision:+ sgml-common--head--1.0--patch-9+++ modified files:+ SConstruct+++2004-02-02 21:37:29 GMT John Goerzen <jgoerzen@complete.org> patch-8++ Summary:+ Checkpointing some more...+ Revision:+ sgml-common--head--1.0--patch-8+++ modified files:+ SConstruct+++2004-02-02 20:19:02 GMT John Goerzen <jgoerzen@complete.org> patch-7++ Summary:+ Checkpointing+ Revision:+ sgml-common--head--1.0--patch-7+++ modified files:+ SConstruct+++2004-02-02 19:18:40 GMT John Goerzen <jgoerzen@complete.org> patch-6++ Summary:+ Added Plucker+ Revision:+ sgml-common--head--1.0--patch-6+++ modified files:+ SConstruct+++2004-02-02 19:09:16 GMT John Goerzen <jgoerzen@complete.org> patch-5++ Summary:+ Added cleanup rules+ Revision:+ sgml-common--head--1.0--patch-5+++ modified files:+ SConstruct+++2004-02-02 18:58:11 GMT John Goerzen <jgoerzen@complete.org> patch-4++ Summary:+ sources now checks only chapters/ to prevent dep cycle with index+ Revision:+ sgml-common--head--1.0--patch-4+++ modified files:+ Makefile.common SConstruct {arch}/=tagging-method+++2004-02-02 17:51:27 GMT John Goerzen <jgoerzen@complete.org> patch-3++ Summary:+ Experimental SCons conversion+ Revision:+ sgml-common--head--1.0--patch-3+++ new files:+ SConstruct+++2003-10-21 20:24:04 GMT John Goerzen <jgoerzen@complete.org> patch-2++ Summary:+ Added plain text generation target+ Revision:+ sgml-common--head--1.0--patch-2++ Added plain text generation target+ ++ modified files:+ ./Makefile.common+++2003-09-10 14:27:58 GMT John Goerzen <jgoerzen@complete.org> patch-1++ Summary:+ Minor updates to PNG generation and gtk-doc icon locations+ Revision:+ sgml-common--head--1.0--patch-1+++ modified files:+ Makefile.common+++2003-09-10 14:24:24 GMT John Goerzen <jgoerzen@complete.org> base-0++ Summary:+ initial import+ Revision:+ sgml-common--head--1.0--base-0++ + (automatically generated log message)++ new files:+ COPYING COPYRIGHT Makefile.common ps2epsi++
+ doc/sgml-common/Makefile.common view
@@ -0,0 +1,229 @@+# -*- Mode: makefile; -*-+# arch-tag: Primary sgml-common top-level Makefile+# Common Makefile for SGML documents+#+# Copyright (C) 2002, 2003 John Goerzen+# <jgoerzen@complete.org>+#+# This program is free software; you can redistribute it and/or modify+# it under the terms of the GNU General Public License as published by+# the Free Software Foundation; either version 2 of the License, or+# (at your option) any later version.+#+# This program is distributed in the hope that it will be useful,+# but WITHOUT ANY WARRANTY; without even the implied warranty of+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+# GNU General Public License for more details.+#+# You should have received a copy of the GNU General Public License+# along with this program; if not, write to the Free Software+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA++# The following variables should be set:+# MASTERBASE -- basename of master file -- example: my-guide+# BASICDEPS -- various dependencies of the master file. For instance,+# this might include files included in the SGML. It could also be empty.+# TOPNODE -- Basename of top id for HTML link.++MASTER := $(MASTERBASE).sgml+FIGUREDIRS := $(wildcard figures/*)+DOINDEX ?= yes++######################################################################+# Index generation+######################################################################++ifeq ($(DOINDEX), yes)++INDEXSGMLFILE := index/index.sgml+INDEXDATAFILE := index/HTML.index++$(INDEXSGMLFILE): $(INDEXDATAFILE)+ @echo " *** Generating SGML index from index list"+ collateindex.pl -i ch.index -g -o index/index.sgml index/HTML.index++$(INDEXDATAFILE): $(MASTER) $(BASICDEPS)+# jade -t sgml -d docbook.dsl -V html-index $(MASTER)+# jade -t sgml -V html-index $(MASTER)+ @echo " *** Generating index list from document"+ -rm -r index+ mkdir index+ collateindex.pl -i ch.index -N -o index/index.sgml+ #mkdir html-temp+ #docbook2html --output html-temp -V html-index $(MASTER)+ docbook-2-html -O -V -O html-index $(HTMLARGS) $(MASTER)+ mv $(MASTERBASE)-html/HTML.index index/+ rm -r $(MASTERBASE)-html+endif # DOINDEX++######################################################################+# Text generation+######################################################################+$(MASTERBASE).txt: $(MASTER) $(BASICDEPS) $(INDEXSGMLFILE)+ @echo " *** Generating text output"+ docbook2txt $(MASTER)++######################################################################+# PostScript generation+######################################################################++$(MASTERBASE).ps: $(MASTER) $(BASICDEPS) $(INDEXSGMLFILE) $(EPSFILES)+ @echo " *** Generating PostScript output"+# This works too: docbook2ps -V paper-size=Letter $(MASTER)+ docbook-2-ps -q -O -V -O paper-size=Letter $(PSARGS) $(MASTER)++######################################################################+# Figure generation+######################################################################++%_1.epi: %.ps+ $(get-epi)+%_2.epi: %.ps+ $(get-epi)+%_3.epi: %.ps+ $(get-epi)+%_4.epi: %.ps+ $(get-epi)+%_5.epi: %.ps+ $(get-epi)+%_6.epi: %.ps+ $(get-epi)+%_7.epi: %.ps+ $(get-epi)+%_8.epi: %.ps+ $(get-epi)+%_9.epi: %.ps+ $(get-epi)+%_10.epi: %.ps+ $(get-epi)+%_11.epi: %.ps+ $(get-epi)+%_12.epi: %.ps+ $(get-epi)++%_1_l.epi: %.ps+ $(get-epil)+%_2_l.epi: %.ps+ $(get-epil)+%_3_l.epi: %.ps+ $(get-epil)+%_4_l.epi: %.ps+ $(get-epil)+%_5_l.epi: %.ps+ $(get-epil)+%_6_l.epi: %.ps+ $(get-epil)+%_7_l.epi: %.ps+ $(get-epil)+%_8_l.epi: %.ps+ $(get-epil)+%_9_l.epi: %.ps+ $(get-epil)+%_10_l.epi: %.ps+ $(get-epil)+%_11_l.epi: %.ps+ $(get-epil)+%_12_l.epi: %.ps+ $(get-epil)++%.png: %_l.epi+ @echo " *** Generating PNG image for $<"+ gs -q -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -r90 -dBATCH -dNOPAUSE \+ -dSAFER -sOutputFile=$@ -sDEVICE=png16m $< -c showpage++%.ps: %.pdf+ pdftops $<++######################################################################+# HTML generation+######################################################################++define copy-figures-worker+mkdir html/figures+for DIRECTORY in $(FIGUREDIRS); do mkdir html/$$DIRECTORY; cp -v $$DIRECTORY/*.png html/$$DIRECTORY/; done+endef++define copy-figures+$(if $(FIGUREDIRS),$(copy-figures-worker))+endef++html/index.html: $(MASTER) $(BASICDEPS) $(INDEXSGMLFILE) $(PNGFILES)+ @echo " *** Generating HTML output"+ -rm -r html+ mkdir html+ #docbook2html --output html $(MASTER)+ docbook-2-html $(HTMLARGS) $(MASTER)+ mv $(MASTERBASE)-html/* html/+ rmdir $(MASTERBASE)-html+ $(copy-figures)+# tidy -m html/*.html+ ln -s $(TOPNODE).html html/index.html+ -cp -v /usr/share/gtk-doc/data/*.png html/++######################################################################+# Cleaning+######################################################################++clean:+ -rm -f `find . -name "*~"` `find . -name "*.png"` `find . -name "*.epi"`+ -rm -r html-temp html index $(MASTERBASE).txt+ -rm *.aux *.log *.dvi *.tex *.jtex *.ps *.html *.log *.out jadetex.cfg+ -rm *.ps html/*.html figures/topology/*.epi figures/topology/*.png+ -rm *.log *.pdb+ -rm `find . -name ".ps"` `find . -name "*.epi"` *.pdf+ -rm `find . -name "*.png"`++######################################################################+# Utility functions+######################################################################++GETPAGE=$(shell echo $(1) | sed -e "s/^.*_\([0-9]*\).epi/\\1/g")+define get-epi+@echo " *** Generating EPI image for $<"+psselect -q $(call GETPAGE,$@) $< temp.ps+psresize -w 6.375in -h 8.25in temp.ps temp2.ps+../sgml-common/ps2epsi temp2.ps $@+rm temp.ps temp2.ps+endef++GETPAGEL=$(shell echo $(1) | sed -e "s/^.*_\([0-9]*\)_l.epi/\\1/g")+define get-epil+@echo " *** Generating large EPI image for $<"+psselect -q $(call GETPAGEL,$@) $< temp.ps+psresize -w 8.5in -h 11in temp.ps temp2.ps+../sgml-common/ps2epsi temp2.ps $@+rm temp.ps temp2.ps+endef+++pdf: $(MASTERBASE).pdf++$(MASTERBASE).pdf: $(MASTERBASE).ps+ ps2pdf14 $(MASTERBASE).ps++plucker: $(MASTERBASE).pdb+$(MASTERBASE).pdb: html+ plucker-build --bpp=4 --compression=zlib --doc-name="$(MASTERBASE)" \+ -H file:`pwd`/html/index.html -M 5 \+ --maxheight=320 --maxwidth=310 \+ --staybelow=file:`pwd`/html --title="$(MASTERBASE)" -p . \+ -f $(MASTERBASE)++###########################################################################+# These are obsolete but should still work.+###########################################################################+++$(MASTERBASE).dvi: $(MASTERBASE).tex+ @echo " *** Generating DVI file."+ jadetex unix-guide.tex+ jadetex unix-guide.tex+ jadetex unix-guide.tex++$(MASTERBASE).tex: $(MASTER) $(BASICDEPS) $(INDEXSGMLFILE)+ @echo " *** Generating TeX files."+ docbook2tex -V paper-size=Letter $(MASTER)+# jade -t tex -V tex-backend -d \+# /usr/share/sgml/docbook/stylesheet/dsssl/modular/print/docbook.dsl \+# $(MASTER)+
+ doc/sgml-common/SConstruct view
@@ -0,0 +1,208 @@+# vim: set filetype=python :+# arch-tag: general-purpose SCons build file for sgml-common++from glob import glob+import os, re++############################################################+# Setup+############################################################++SConsignFile('.sconsign-master')+#Import('env')+d = env.Dictionary()+if not 'JADE' in d:+ d['JADE'] = 'jade'+if not 'INDEXNODE' in d:+ d['INDEXNODE'] = 'ch.index'+if not 'GTKIMGPATH' in d:+ d['GTKIMGPATH'] = '/usr/share/gtk-doc/data'+if not 'PS2EPSI' in d:+ d['PS2EPSI'] = '../sgml-common/ps2epsi'++def removeindex(l):+ while 'index/index.sgml' in l:+ l.remove('index/index.sgml')++master = d['MASTERBASE'] +mastersgml = master + '.sgml'+sources = [mastersgml] + glob('*/*.sgml') + glob('*/*/*.sgml')+removeindex(sources)+db2htmlcmd = 'docbook-2-html -D $JADE ${HTMLARGS} ${SOURCE}'+db2htmlindexcmd = 'docbook-2-html -D $JADE -O -V -O html-index ${HTMLARGS} ${SOURCE}'++##################################################+# SCANNERS+##################################################+def recursescan(scanner, node, env):+ result = scanner(node, env) + retval = []+ for item in result:+ retval.append(item)+ retval.extend(recursescan(scanner, item, env))+ return retval++SGML_includes_re = re.compile(r'<!ENTITY[^>]+SYSTEM[^>]+"(.+)"', re.M)+def SGML_includes_scan(node, env, path):+ ret = SGML_includes_re.findall(node.get_contents())+ removeindex(ret)+ return ret++SGML_includes_scanner = Scanner(name = 'SGML_includes',+ function = SGML_includes_scan, recursive = 1, skeys = ['.sgml', '.ent'])++SGML_image_pdf_re = re.compile(r'<(graphic|imagedata).+?fileref="([^"]+\.pdf)"', re.S)+SGML_image_png_re = re.compile(r'<(graphic|imagedata).+?fileref="([^"]+\.png)"', re.S)+def SGML_image_scanner(node, env, path, arg):+ root, ext = os.path.splitext(str(node))+ contents = node.get_contents()+ return SGML_includes_scan(node, env, path) + \+ [os.getcwd() + '/' + x[1] for x in arg.findall(contents)]++SGML_pdf_scanner = Scanner(name = 'SGML_pdf',+ function = SGML_image_scanner, argument = SGML_image_pdf_re,+ recursive = 1)+SGML_png_scanner = Scanner(name = 'SGML_png',+ function = SGML_image_scanner, argument = SGML_image_png_re,+ recursive = 1)++##################################################+# BUILDERS+##################################################++#### PLAIN TEXT+Btxt = Builder(action="docbook2txt $SOURCE", src_suffix='.sgml', suffix='.txt')++#### PDF / POSTSCRIPT+Bpdf = Builder(action="docbook-2-pdf -D ${JADE} -q -O -V -O paper-size=Letter ${PDFARGS} ${SOURCE}",+ src_suffix='.sgml', suffix='.pdf')+Bpdf2ps = Builder(action="pdftops ${SOURCE}", src_suffix='.pdf', suffix='.ps')++#### MAN PAGES+# FIXME: test this+Bman = Builder(action="docbook2man $SOURCE", src_suffix='.sgml', suffix='.1')++#### HTML+Bhtml = Builder(action = [ \+ 'if test -d ${TARGET.dir} ; then rm -r ${TARGET.dir} ; fi',+ 'mkdir ${TARGET.dir}',+ db2htmlcmd,+ 'mv ${MASTERBASE}-html/* ${TARGET.dir}/',+ 'rmdir ${MASTERBASE}-html',+ 'ln -s ${TOPNODE}.html ${TARGET.dir}/index.html',+ 'cp ${GTKIMGPATH}/*.png ${TARGET.dir}/'])++#### PNG+Bepip2png = Builder(action = 'gs -q -dTextAlphaBits=4 -dGraphicsAlphaBits=4 ' +\+ '-r90 -dBATCH -dNOPAUSE -dSAFER -sOutputFile=$TARGET ' + \+ '-sDEVICE=png16m $SOURCE -c showpage', suffix='.png', src_suffix='.pngepi')++#### EPI from PS+def getpagenumfromname(target, source, env, for_signature):+ return re.search('^.*_(\d+)\.(png){0,1}epi$', str(target[0])).group(1)+d['GETPAGE'] = getpagenumfromname++Aps2epi = Action(['psselect -q ${GETPAGE} $SOURCE temp.ps',+ 'psresize -w ${WIDTH} -h ${HEIGHT} temp.ps temp2.ps',+ '$PS2EPSI temp2.ps $TARGET',+ 'rm temp.ps temp2.ps'])+Bps2epi = Builder(action=Aps2epi, src_suffix='.ps', suffix='.epi')+Bps2epip = Builder(action=Aps2epi, src_suffix='.ps', suffix='.pngepi')+Bepi2pdf = Builder(action="epstopdf -o=${TARGET} ${SOURCE}", suffix='.pdf',+ src_suffix='.epi')++#### PLUCKER+Bplucker = Builder(action = 'plucker-build --bpp=4 --compression=zlib ' + \+ '--doc-name="${MASTERBASE}" -H file:${SOURCE.abspath} -M 5 ' + \+ '--maxheight=320 --maxwidth=310 --staybelow=file:`pwd`/${SOURCE.dir} ' + \+ '--title="${MASTERBASE}" -p . -f ${MASTERBASE}')++##################################################+# General setup+##################################################++env.Append(BUILDERS = {'Text': Btxt, 'PDF2PS': Bpdf2ps, 'PDF': Bpdf, 'HTML': Bhtml,+ 'Plucker': Bplucker, 'PS2EPI': Bps2epi, 'PS2EPIP': Bps2epip,+ 'EPI2PDF': Bepi2pdf, 'EPIP2PNG': Bepip2png, 'MAN': Bman})++#### INDEX GENERATION+if 'DOINDEX' in d:+ Bindex = Builder(action = ['if test -d ${TARGET.dir} ; then rm -r ${TARGET.dir} ; fi',+ "mkdir ${TARGET.dir}",+ "collateindex.pl -i $INDEXNODE -N -o $TARGET",+ db2htmlindexcmd,+ "mv ${MASTERBASE}-html/HTML.index ${TARGET.dir}/",+ "rm -r ${MASTERBASE}-html",+ "collateindex.pl -i $INDEXNODE -g -o $TARGET ${TARGET.dir}/HTML.index"])+ env['BUILDERS']['Index'] = Bindex+ index = env.Index('index/index.sgml', mastersgml)+ env.Depends(index, sources)+ env.Clean(index, 'index')+ deps = sources + [index]+else:+ deps = sources++##################################################+# BUILD RULES+###################################################+# Text+text = env.Text(mastersgml)+env.Depends(text, deps)+env.Alias('text', text)++# PDF+pdfsgml = File(mastersgml)+pdf = env.PDF(pdfsgml)+figsindoc = [x for x in recursescan(SGML_pdf_scanner, pdfsgml, env) if str(x).endswith('.pdf')]+epipdf = []+for file in figsindoc:+ pdfname = re.sub('_\d+\.pdf$', '.pdf', str(file))+ if pdfname == str(file):+ # This is not a filename that fits our pattern; add unmodified.+ epipdf.append(file)+ continue+ psfile = env.PDF2PS(source = pdfname)+ epifile = env.PS2EPI(str(file).replace(".pdf", ".epi"), psfile,+ WIDTH='6.375in', HEIGHT='8.25in')+ epipdf.append(env.EPI2PDF(source = epifile))++env.Depends(pdf, deps)+env.Depends(pdf, epipdf)+env.Alias('pdf', pdf)+env.Clean(pdf, ['jadetex.cfg', '${MASTERBASE}.aux', '${MASTERBASE}.dvi',+ '${MASTERBASE}.jtex', '${MASTERBASE}.log', '${MASTERBASE}.out',+ 'jade-out.fot'])++# PS+ps = env.PDF2PS(source = pdf)+env.Alias('ps', ps)++# HTML+htmlsgml = File(mastersgml)+buildhtml = env.HTML('html/index.html', htmlsgml)+figsindoc = [x for x in recursescan(SGML_png_scanner, htmlsgml, env) if str(x).endswith('.png')]+epipng = []+for file in figsindoc:+ pdfname = re.sub('_\d+\.png$', '.pdf', str(file))+ if pdfname == str(file):+ # This is not a filename that fits our pattern; add unmodified. + epipng.append(file)+ continue+ psfile = env.PDF2PS(source = pdfname)+ epifile = env.PS2EPIP(str(file).replace(".png", ".pngepi"), psfile,+ WIDTH='8.5in', HEIGHT='11in')+ epipng.append(env.EPIP2PNG(source = epifile))++env.Depends(buildhtml, epipng)+env.Depends(buildhtml, deps)+pnginstalls = env.InstallAs(['html/' + str(x) for x in epipng], epipng)+env.Depends(pnginstalls, buildhtml)+html = env.Alias('html', buildhtml)+html = env.Alias('html', pnginstalls)+env.Clean(buildhtml, 'html')++# Plucker+plucker = env.Plucker(master + '.pdb', 'html/index.html')+env.Alias('plucker', plucker)++env.Default(html)
+ doc/sgml-common/ps2epsi view
@@ -0,0 +1,77 @@+#!/bin/sh+# $RCSfile: ps2epsi,v $ $Revision: 1.4.2.2 $+# arch-tag: ps2epsi customized for sgml-common++tmpfile=/tmp/ps2epsi$$++export outfile++if [ $# -lt 1 -o $# -gt 2 ]; then+ echo "Usage: `basename $0` file.ps [file.epsi]" 1>&2+ exit 1+fi++infile=$1;++if [ $# -eq 1 ]+then+ case "${infile}" in+ *.ps) base=`basename ${infile} .ps` ;;+ *.cps) base=`basename ${infile} .cps` ;;+ *.eps) base=`basename ${infile} .eps` ;;+ *.epsf) base=`basename ${infile} .epsf` ;;+ *) base=`basename ${infile}` ;;+ esac+ outfile=${base}.epsi+else+ outfile=$2+fi++ls -l ${infile} |+awk 'F==1 {+ cd="%%CreationDate: " $6 " " $7 " " $8;+ t="%%Title: " $9;+ f="%%For:" U " " $3;+ c="%%Creator: Ghostscript ps2epsi from " $9;+ next;+ }+ /^%!/ {next;}+ /^%%Title:/ {t=$0; next;}+ /^%%Creator:/ {c=$0; next;}+ /^%%CreationDate:/ {cd=$0; next;}+ /^%%For:/ {f=$0; next;}+ !/^%/ {+ print "/ps2edict 30 dict def";+ print "ps2edict begin";+ print "/epsititle (" t "\\n) def";+ print "/epsicreator (" c "\\n) def";+ print "/epsicrdt (" cd "\\n) def";+ print "/epsifor (" f "\\n) def";+ print "end";+ exit(0);+ }+ ' U="$USERNAME$LOGNAME" F=1 - F=2 ${infile} >$tmpfile++gs -q -dNOPAUSE -dSAFER -dDELAYSAFER -r72 -sDEVICE=bit -sOutputFile=/dev/null $tmpfile ps2epsi.ps $tmpfile <${infile} 1>&2+rm -f $tmpfile++(+cat << BEGINEPS+save countdictstack mark newpath /showpage {} def /setpagedevice {pop} def+%%EndProlog+%%Page 1 1+BEGINEPS++cat ${infile} |+sed -e '/^%%BeginPreview:/,/^%%EndPreview[^!-~]*$/d' -e '/^%!PS-Adobe/d'\+ -e '/^%%[A-Za-z][A-Za-z]*[^!-~]*$/d' -e '/^%%[A-Za-z][A-Za-z]*: /d'++cat << ENDEPS+%%Trailer+cleartomark countdictstack exch sub { end } repeat restore+%%EOF+ENDEPS++) >> ${outfile}++exit 0
+ doc/twidge-manpage.sgml view
@@ -0,0 +1,872 @@+ <refentry id="twidge">+ <indexterm><primary>twidge</><secondary>Reference For</></>+ <refentryinfo>+ <address><email>jgoerzen@complete.org</email></address>+ <author><firstname>John</firstname><surname>Goerzen</surname></author>+ </refentryinfo>++ <refmeta>+ <refentrytitle>twidge</refentrytitle>+ <manvolnum>1</manvolnum>+ <refmiscinfo>John Goerzen</refmiscinfo>+ </refmeta>++ <refnamediv>+ <refname>twidge</refname>+ <refpurpose>Microblogging client for Twitter, Identica</refpurpose>+ </refnamediv>++ <refsynopsisdiv>+ <cmdsynopsis>+ <command>twidge</command>+ <arg choice="opt">-d</arg>+ <arg choice="opt">-c <replaceable>FILE</replaceable></arg>+ <arg choice="plain"><replaceable>command</replaceable></arg>+ <arg choice="opt"><replaceable>command_args</replaceable></arg>+ </cmdsynopsis>+ <cmdsynopsis>+ <command>twidge</command>+ <arg choice="plain">--help</arg>+ </cmdsynopsis>+ </refsynopsisdiv>++ <refsect1 id="twidge.description">+ <title>Description</title>+ <para>+ &twidge; is a client for microblogging sites such as + <ulink url="http://twitter.com/">Twitter</ulink> and+ <ulink url="http://identi.ca/">Identica</ulink> (identi.ca).+ Microblogging sites let you post short one-paragraph updates,+ follow the updates that your friends post, and interact with+ everyone in the site in a conversation style.+ </para>+ <para>+ &twidge; is a client to make working with microblogging sites+ faster and easier. It is extremely versatile, and can be+ customized to work the way you want to work, and combined with+ other tools to do just about anything.+ </para>+ <para>+ &twidge; can be used quite nicely interactively from the shell.+ It is useful directly as-is, and with simple shell aliases can+ make a highly efficient system to do exactly what you want. It+ is perfectly capable of being your only client for+ microblogging.+ </para>+ <para>+ &twidge; also can be used in an automated way, via+ <command>cron(1)</command>, or it can even integrate with your+ email system.+ </para>+ <para>+ A full list of &twidge; features, along with numerous+ suggestions on how to use it, can be found at the &twidge;+ website at <ulink+ url="http://software.complete.org/twidge"></ulink>.+ </para>+ + <para>+ But, if you'd like to get going RIGHT NOW, skip to the Quick+ Start section below. For now, I'll summarize a few &twidge;+ features; a more comprehensive list is on the website.+ </para>++ <refsect2 id="twidge.features">+ <title>Feature List</title>+ <itemizedlist>+ <listitem><para>Convenient, easy to learn, and fast command-line+ interface (it's simple to do simple things, and+ advanced things are possible)</para>+ </listitem>++ <listitem><para>This extensive manual, and numerous examples+ on the website</para></listitem>++ <listitem><para>Compatible with any microblogging service that+ implements the Twitter API. Tested with Twitter and+ Identica (identi.ca). Should be compatible with any other+ system.+ </para></listitem>++ <listitem><para>Full support for reading the activity of your+ friends, replies to you, and your own+ activity.</para></listitem>++ <listitem><para>Optional capability to remember what you have+ seen already and suppress those updates in future+ runs.</para></listitem>++ <listitem><para>Optional automatic shortening of long URLs via tinyurl.com</para></listitem>+ + <listitem><para>Optional integration with your email system --+ send and receive updates via email.</para></listitem>++ <listitem><para>Specifically designed to be friendly to use in+ shell scripts.</para></listitem>++ <listitem><para>Shell scripting makes it easy to do many+ things, such as scheduling future updates (with+ <command>at</command>), ignoring certain updates+ (with <command>grep</command>), etc.</para></listitem>+ + <listitem><para>Easy use of multiple accounts by having+ multiple configuration profiles. Mechanism lends itself+ to shell aliases and tools.</para></listitem>++ <listitem><para>Small, minimalist footprint</para>+ </listitem>++ <listitem><para>Output formats are easily parsed. Input+ formats are easily generated. Configuration file format is+ liberal and easy to generate.+ </para></listitem>++ <listitem><para>Robust error detection and recovery+ throughout.+ </para></listitem>+ </itemizedlist>+ </refsect2>++ </refsect1>++ <refsect1 id="twidge.quickstart">+ <title>Quick Start</title>+ <para>+ This section will describe how a first-time &twidge; user can+ get up and running quickly. It assumes you already have+ &twidge; compiled or installed on your system. If not,+ please follow the instructions in the+ <filename>INSTALL</filename>+ file in the+ source distribution.+ </para>+ <para>+ To get started, simply run <command>twidge setup</command> at your+ shell prompt. &twidge; will lead you through the first-time+ configuration -- which is only two questions and completely+ self-explanatory!+ </para>+ <para>+ Now, let's start exploring. <command>twidge lsrecent+ -su</command> will show you the 20 most recent updates from the+ people you follow. After the first time, it will remember what+ you've seen and only show you new updates. In place of+ <command>lsrecent</command>, you could substitue+ <command>lsreplies</command> to replies to you. You can also+ run <command>twidge lsrecent --help</command>, or refer to this+ document, for more details on the command. In short, -s tells+ the system to save what you've seen, and -u tells it to only+ show you unseen items.+ </para>+ <para>+ You can subscribe to updates from friends by running+ <command>twidge follow+ <replaceable>nick</replaceable></command>. To subscribe to+ updates for &twidge; itself, you'd run <command>twidge follow+ unixtwidge</command>. If you've had enough of updates from+ someone, just use the <command>twidge unfollow</command> command.+ </para>+ <para>+ Now, how about posting your own updates? Just type+ <command>twidge update</command>. Type your update, and press+ Enter when done. Your update may scroll past the end of the+ screen; don't worry about it. Just don't hit Enter until you're+ done. You can also pass your update on the command line, taking+ care to quote it if it contains spaces or shell characters.+ </para>+ <para>+ That's the quick tour. For many more examples, refer to the+ website.+ </para>+ </refsect1>++ <refsect1 id="twidge.options">+ <indexterm><primary>Options (command-line)</primary></indexterm>+ <title>Options</title>+ <para>+ &twidge; always is invoked with the name of a specific+ operation, such as <option>update</option> or+ <option>lsrecent</option>. In &twidge;, these operations are+ called <emphasis>commands</emphasis>. Each command has its+ own options, which are given after the command on the+ &twidge; command line. A full summary of each command's+ options is given later in this manual.+ </para>+ + <para>+ You may obtain a list of all commands with <command>twidge+ lscommands</command>. Help is available for any individual+ command with <command>twidge <replaceable>command</replaceable>+ --help</command>. Global help is available with+ <command>twidge --help</command>.+ </para>+ <refsect2 id="twidge.options.global">+ <title>Global Options</title>+ <para>+ These options may be specified <emphasis>before</emphasis> any+ command.+ </para>+ <variablelist>+ <varlistentry><term>-c <replaceable>FILE</replaceable></term>+ <term>--config=<replaceable>FILE</replaceable></term>+ <listitem><para>+ By default, &twidge; uses+ <filename>~/.twidgerc</filename> for configuration.+ With this option, you can specify an alternate file.+ &twidge; will read configuration information+ from it. In certain cases, &twidge; will also write to+ it, such as with the <command>twidge setup</command>+ command, or the -s option to one of the ls commands.+ </para>+ </listitem>+ </varlistentry>+ <varlistentry><term>-d</term><term>--debug</term>+ <listitem><para>+ Enables debugging output. This verbose output helps you+ learn what &twidge; is doing every step of the way and+ diagnose any problems you may encounter.+ </para>+ </listitem>+ </varlistentry>+ </variablelist>+ </refsect2>++ </refsect1>++ <refsect1 id="twidge.commands">+ <indexterm><primary>Commands</primary></indexterm>+ <title>Commands in Twidge</title>+ <para>+ &twidge; has many different commands. You must specify a+ command when using &twidge;.+ This section will discuss each command in+ detail. Note that all commands are case-sensitive and should be+ <emphasis>given in lowercase</emphasis>.+ </para>+ <para>+ All commands support the option <option>--help</option>. Running+ <command>twidge <replaceable>command</replaceable>+ --help</command> will display information about the command and+ its options. Since all commands support this, it won't be+ explicitly listed for each command below.+ </para>++ </refsect1>+ <refsect1 id="twidge.commands.updatedisplay">+ <title>Commands to Display Updates</title>+ <cmdsynopsis>+ <command>twidge ls<replaceable>*</replaceable></command>+ <arg choice="opt">-a</arg>+ <arg choice="opt">-l</arg>+ <arg choice="opt">-s</arg>+ <arg choice="opt">-u</arg>+ </cmdsynopsis>+ <para>+ Several commands can display updates from yourself or others.+ They all share a common syntax and common set of options. The+ commands are <command>lsarchive</command>,+ <command>lsdm</command>, <command>lsdmarchive</command>,+ <command>lsrecent</command>, and <command>lsreplies</command>.+ Here are the common options:+ </para>+ + <variablelist>+ <varlistentry><term>-a</term>+ <term>--all</term>+ <listitem><para>+ Normally, microblogging sites return one "page" of results+ -- typically, 20 or 100 results, depending on the+ operation. Specifying --all requests &twidge; to+ continually send requests to the microblogging site until+ it receives an entire set of information. Normally this+ is a bad idea, but when used in combination with -u --+ especially if you have used -s before -- it can be a+ useful way to poll for all new updates.+ </para>+ <para>+ If not used carefully, this command can generate many+ requests to the server and can use a significant amount of+ bandwidth. Microblogging sites have traffic limits, and+ will not take kindly to this. Be careful when you use+ --all.+ </para>+ </listitem>+ </varlistentry>++ <varlistentry><term>-e <replaceable>command</replaceable></term>+ <term>--exec=<replaceable>command</replaceable></term>+ <listitem><para>+ Causes any normal output to be suppressed. Instead, for+ each item that is retrieved, call the given command. The+ command will be passed exactly four arguments. Care+ should be exercised when using them in shell scripts due+ to the likelihood of the presence of shell+ metacharacters. The arguments are:+ </para>+ <orderedlist>+ <listitem><para>+ The update ID for the given update.+ </para></listitem>+ <listitem><para>+ The username that created the update</para></listitem>+ <listitem><para>+ A suggested Message-ID for representing the update in+ email. Contains the enclosing angle brackets.+ </para></listitem>+ <listitem><para>+ The update text itself. Likely contains spaces and+ other shell metacharacters.+ </para></listitem>+ </orderedlist>+ </listitem>+ </varlistentry>++ <varlistentry><term>-l</term>+ <term>--long</term>+ <listitem><para>+ The default output format shows a nickname and a message,+ formatted nicely for display. Using this option causes+ output to include these columns: message ID, sender nick,+ recipient nick (empty unless a direct message), update+ text, and date created.+ The output format is suitable for machine parsing. + horizontal tab character \t separates the columns,+ and is guaranteed to appear nowhere else. It is also+ guaranteed that \n will appear nowhere within a line when+ using -l.+ </para>+ <para>+ The columns as presented are anticipated to remain+ stable. However, additional columns could be added to the+ right of these columns in future versions of &twidge;.+ Well-behaved parsers should be prepared to discard any+ surplus columns to the right of those specified in this+ document.+ </para>+ </listitem>+ </varlistentry>++ <varlistentry>+ <term>-m <replaceable>address</replaceable></term>+ <term>--mailto=<replaceable>address</replaceable></term>+ <listitem><para>+ Causes any normal output to be suppressed. Instead, for+ each item that is retrieved, generate an email and send it+ to the given address. The subject line will contain the+ sender nickname and the first 30 characters of the text.+ The body will contain+ the entire text. The message is sent by using the program+ listed as sendmail in the configuration file. If mailfrom+ is listed in the configuration file, it is listed as the+ from address and the name of the sender is listed as the+ from comment.+ </para>+ <para>+ A Message-ID designed to uniquely identify this update is+ generated and included. In addition, headers beginning+ with X-Twidge- will be added, with various metadata.+ </para>+ <para>+ It should be noted that a simple script could be used with+ --exec to achieve this same purpose, but with greater+ flexibility.+ The functionality is built into &twidge; as well for+ convenience.+ </para>+ </listitem>+ </varlistentry>++ <varlistentry><term>-s</term>+ <term>--saveid</term>+ <listitem><para>+ Saves the ID of the most recent fetched message for future+ use with -u. Requires write access to your configuration+ file.+ </para></listitem>+ </varlistentry>++ <varlistentry><term>-u</term>+ <term>--unseen</term>+ <listitem><para>+ Causes the command to show only items since the last use+ of -s with this particular command. If -s has never+ before been used with this command, has no effect.+ </para>+ <para>+ As of September 2008, Identi.ca does not support the+ since_id parameter that is required for this option to be+ effective. A future version of &twidge; may implement a+ workaround.+ </para>+ </listitem>+ </varlistentry>+ </variablelist>++ <para>+ Some of these options don't make sense together; for instance,+ --long, --exec, and --mailto are mutually exclusive. Results+ are undefined if you use such options simultaneously.+ </para>++ <refsect2 id="twidge.commands.lsarchive">+ <title>lsarchive</title>+ <para>+ Lists your own posts.+ </para>+ </refsect2>++ <refsect2 id="twidge.commands.lsdm">+ <title>lsdm</title>+ <para>+ Lists direct messages sent to you. Note: identi.ca does not+ support direct messages, and this will cause an error with+ that service.+ </para>+ </refsect2>++ <refsect2 id="twidge.commands.lsdmarchive">+ <title>lsdmarchive</title>+ <para>+ Lists direct messages you have sent. Note: identi.ca does not+ support direct messages, and this command will cause an error+ with that service.+ </para>+ </refsect2>++ <refsect2 id="twidge.commands.lsrecent">+ <title>lsrecent</title>+ <para>+ Lists recent posts made by you or the people you follow.+ </para>+ </refsect2>++ <refsect2 id="twidge.commands.lsreplies">+ <title>lsreplies</title>+ <para>+ Lists recent replies made by anyone on the microblogging site+ to you.+ </para>+ </refsect2>+ </refsect1>++ <refsect1 id="twidge.commands.displayinfo">+ <title>Commands to Display Other Information</title>+ <para>+ These commands honor --all and --long like the other commands,+ but do not honor --saveid or --unseen, as these options make no+ sense.+ </para>++ <refsect2 id="twidge.commands.lsfollowers">+ <title>lsfollowers</title>+ <cmdsynopsis>+ <command>twidge lsfollowers</command>+ <arg choice="opt"><replaceable>options</replaceable></arg>+ <arg choice="opt"><replaceable>username</replaceable></arg>+ </cmdsynopsis>+ <para>+ Will slow a list of people following you. If given an+ optional username, shows the people that follow that user. If+ given --long, shows the IDs for each person. You may need to+ use --all to get a complete list, but again this may generate+ significant traffic.+ </para>+ </refsect2>++ <refsect2 id="twidge.commands.lsfollowing">+ <title>lsfollowing</title>+ <cmdsynopsis>+ <command>twidge lsfollowing</command>+ <arg choice="opt"><replaceable>options</replaceable></arg>+ <arg choice="opt"><replaceable>username</replaceable></arg>+ </cmdsynopsis>+ <para>+ Shows a list of the people you follow. Arguments and actions+ are the same as with lsfollowers.+ </para>+ </refsect2>+ </refsect1>++ <refsect1 id="twidge.commands.action">+ <title>Action Commands</title>+ <para>+ These commands perform an action on the server.+ </para>+++ <refsect2 id="twidge.commands.dmsend">+ <title>dmsend</title>+ <cmdsynopsis>+ <command>twidge dmsend</command>+ <arg choice="plain"><replaceable>recipient</replaceable></arg>+ <arg choice="opt"><replaceable>status</replaceable></arg>+ </cmdsynopsis>+ <para>+ Causes &twidge; to send a new direct message to the designated+ recipient. If a+ status is given on the command line, it must be presented as a+ single argument to &twidge; by the use of shell quoting if+ needed. If no status is given on the command line, a single+ line will be read from stdin and used as the status.+ </para>+ <para>+ The maximum length of updates on various microblogging sites+ is 140 characters. Twidge will abort with an error if your+ update attempt exceeds that length.+ </para>+ <para>+ By default, Twidge will attempt to shorten URLs in your+ updates via the TinyURL.com service. You can disable this by+ setting shortenurls = no in the [DEFAULT] or [dmsend] section of your+ configuration file.+ </para>+ </refsect2>++ <refsect2 id="twidge.commands.follow">+ <title>follow</title>+ <cmdsynopsis>+ <command>twidge follow</command>+ <arg choice="plain"><replaceable>username</replaceable></arg>+ </cmdsynopsis>+ <para>+ This command will cause &twidge; to request that the+ microblogging site add the given username to the list of+ people you follow. It is considered an error to attempt to+ add someone you already follow.+ </para>+ </refsect2>++ <refsect2 id="twidge.commands.setop">+ <title>setup</title>+ <cmdsynopsis><command>twidge setup</command></cmdsynopsis>+ <para>+ Enters the interactive first-time setup tool.+ </para>+ </refsect2>++ <refsect2 id="twidge.commands.unfollow">+ <title>unfollow</title>+ <cmdsynopsis>+ <command>twidge unfollow</command>+ <arg choice="plain"><replaceable>username</replaceable></arg>+ </cmdsynopsis>+ <para>+ This command will cause &twidge; to request that the+ microblogging site remove the given username from the list of+ people you follow. It is considered an error to attempt to+ remove someone you do not follow.+ </para>+ </refsect2>++ <refsect2 id="twidge.commands.update">+ <title>update</title>+ <cmdsynopsis>+ <command>twidge update</command>+ <arg choice="opt"><replaceable>status</replaceable></arg>+ </cmdsynopsis>+ <cmdsynopsis>+ <command>twidge update -r</command>+ </cmdsynopsis>+ <para>+ Causes &twidge; to post a new status to the server. If a+ status is given on the command line, it must be presented as a+ single argument to &twidge; by the use of shell quoting if+ needed. If no status is given on the command line, a single+ line will be read from stdin and used as the status.+ </para>+ <para>+ The maximum length of updates on various microblogging sites+ is 140 characters. Twidge will abort with an error if your+ update attempt exceeds that length.+ </para>+ <para>+ By default, Twidge will attempt to shorten URLs in your+ updates via the TinyURL.com service. You can disable this by+ setting shortenurls = no in the [DEFAULT] or [update] section of your+ configuration file.+ </para>+ <para>+ When -r is given, &twidge; expects to read an RFC2822 email+ message in stdin. The body of the message will be used as the+ content of the update. The References header of the message+ will be briefly scanned, and if appropriate, the reply-to+ attribute of the update will reflect the Message-ID referred+ to therein. This way, if you use <command>twidge lsrecent+ --mailto</command> to email recent items to you, then use your+ email reply button to reply to them, &twidge; will link the+ two on Twitter. This linkage can be done even if you omit+ @reply, but will likely confuse many people because most other+ clients can't do this. You should still include @reply.+ </para>+ <para>+ It should be noted that, in an effort to minimize size and+ complexity, &twidge; has an extremely simple email parser.+ You should send it only plain text messages. Do not use HTML,+ RTF, attachments, or anything that would cause MIME headers to+ appear in the RFC2822 body. You probably want to turn off+ your signature as well. &twidge; will convert newline+ characters to spaces when processing your message body. + </para>+ </refsect2>+ </refsect1>++ <refsect1 id="twidge.commands.other">+ <title>Other Command</title>+ + <refsect2 id="twidge.commands.lscommands">+ <indexterm><primary>Commands</><secondary>lscommands</></>+ <title>lscommands</title>+ <cmdsynopsis><command>twidge lscommands</command></cmdsynopsis>+ <para>+ This command will display a list of all available &twidge;+ commands along with a brief description of each.+ </para>+ </refsect2>+ </refsect1>++ <refsect1 id="twidge.config">+ <title>twidge Configuration File</title>+ <para>+ &twidge; has a configuration file in which you can set various+ options. This file normally lives under+ <filename>~/.twidgerc</filename>.+ </para>+ <para>+ The configuration file has multiple sections. Each section has+ a name and is introduced with the name in brackets. Each+ section has one or more options.+ </para>+ <para>+ The section named DEFAULT is special in that it provides+ defaults that will be used whenever an option can't be found+ under a different section. If you specify no section names,+ DEFAULT is the assumed section. Some items, such as username,+ password, and urlbase are assumed to be in DEFAULT.+ </para>+ <para>+ Let's start by looking at an example file, and then proceed to+ examine all the options that are available.+ </para>+ <programlisting><![CDATA[+[DEFAULT]++; Username and password+username = ilovetwidge++password = secret++; If your password contains a percent sign (%), list it twice (%%)++; Path to server API interface -- no trailing slash+urlbase = https://twitter.com++shortenurls = yes++; Last IDs seen by different commands. Written to with -s.++[lsarchive]+lastid = 917383569++[lsrecent]+lastid = 914881241+]]></programlisting>+ <para>+ Whenever &twidge; looks for information about a particular+ option, it first checks to see if it can find that option in a+ section for that option. If not, it checks the+ <option>DEFAULT</option> section. If it still doesn't find an+ answer, it consults its built-in defaults. The only built-in+ default at present is urlbase.+ </para>+ <refsect2 id="twidge.config.general">+ <title>General Options</title>+ <para>These are specified in the <option>DEFAULT</option>+ section.+ </para>+ <variablelist>+ <varlistentry><term>username</term>+ <listitem><para>+ Your username on the microblogging site. No default.+ </para></listitem>+ </varlistentry>+ <varlistentry><term>password</term>+ <listitem><para>+ Your password on the microblogging site. No default.+ </para></listitem>+ </varlistentry>+ <varlistentry><term>urlbase</term>+ <listitem><para>+ The URL to access the API of the microblogging site.+ The default, <literal>https://twitter.com</literal> is+ for Twitter. To use Identica, you would specify+ <literal>http://identi.ca/api</literal>. Do not put a+ trailing slash on this option.+ </para></listitem>+ </varlistentry>+ </variablelist>+ </refsect2> ++ <refsect2 id="twidge.config.options">+ <title>Per-Command Options</title>+ <para>+ These options may be specified in <option>DEFAULT</option> or+ in a per-option section. If placed in+ <option>DEFAULT</option>, they will apply to all relevant options+ unless overridden.+ </para>+ <variablelist>+ <varlistentry><term>lastid</term>+ <listitem><para>+ Stores the last ID seen for commands that support -s or+ -u.+ </para></listitem>+ </varlistentry>++ <varlistentry><term>mailfrom</term>+ <listitem><para>+ Gives the email address to use for the From: header on+ messages generated by &twidge;. Normally specified in+ [DEFAULT] so as to impact all commands. If not given, + &twidge; specifies no From: line, leaving the system's+ mail transport to assign a default one.+ </para>+ <para>+ Should contain a bare email address only -- no brackets,+ parens, quotes, or comments.+ </para>+ <para>+ When given, Twidge uses the nickname and this address+ for the From line. When not given, the nickname is+ prepended to the Subject line.+ </para>+ </listitem>+ </varlistentry>++ <varlistentry><term>sendmail</term>+ <listitem><para>+ Stores the path to the sendmail executable on your+ system, used for sending mail. Normally specified in+ [DEFAULT] so as to impact all commands. Defaults to+ /usr/sbin/sendmail.+ </para></listitem>+ </varlistentry>+ + <varlistentry><term>shortenurls</term>+ <listitem>+ <para>+ You may specify <literal>shortenurls</literal> in the+ <literal>[update]</literal> section. It defaults to yes. If+ set to no, will cause &twidge; to omit its attempt to shorten+ URLs in your updates via <literal>tinyurl.com</literal>.+ </para>+ </listitem>+ </varlistentry>++ </variablelist>++ </refsect2>++ </refsect1>+ ++ <refsect1 id="twidge.tips">+ <title>Tips & Hints</title>+ <para>+ Here are a few tips and hints to make &twidge; more pleasant+ for you.+ </para>+ <refsect2 id="twidge.tips.proxy">+ <title>Going Through a Proxy</title>+ <para>+ If your connections must go through a proxy, you'll need to+ set an environment variable.+ If you use an+ environment variable, your settings may will also impact other+ applications -- and that's probably what you want. See the+ Environment section later for tips on doing that.+ </para>+ </refsect2>++ </refsect1>++ <refsect1 id="twidge.environment">+ <title>Environment</title>+ <para>+ &twidge; does not read any environment variables directly.+ However, it does pass on the environment to the+ programs it calls, such as Curl. This can be useful for+ specifying proxies. Please see+ <application>curl</application>(1) for more details.+ </para>+ </refsect1>++ <refsect1 id="twidge.conforming">+ <title>Conforming To</title>+ <itemizedlist>+ <listitem><para>The <ulink+ url="http://www.w3.org/XML/">Extensible Markup Language+ (XML)</ulink> standard (W3C)</para></listitem>+ </itemizedlist>+ </refsect1>++ <refsect1 id="twidge.copyright">+ <title>Copyright</title>+ <indexterm><primary>Copyright</></>+ <para>+ &twidge;, all code, documentation, files, and build scripts are+ Copyright © 2006-2008 John Goerzen. All code, documentation,+ sripts, and files are under the following license unless+ otherwise noted:+ </para>+ <para>+ This program is free software; you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation; either version 2 of the License, or+ (at your option) any later version.+ </para>+ + <para>+ This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License for more details.+ </para>+ + <para>+ You should have received a copy of the GNU General Public License+ along with this program; if not, write to the Free Software+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+ </para>+ <para>+ The GNU General Public License is available in the file COPYING+ in the source distribution. Debian GNU/Linux users may find this in+ /usr/share/common-licenses/GPL-2.+ </para>+ <para>+ If the GPL is unacceptable for your uses, please e-mail me; alternative+ terms can be negotiated for your project.+ </para>+ </refsect1>+ + <refsect1 id="twidge.author">+ <title>Author</title>+ <para>+ &twidge;, its modules, documentation, executables, and all+ included files, except where noted, was written by+ John Goerzen <email>jgoerzen@complete.org</email> and+ copyright is held as stated in the COPYRIGHT section.+ </para>+ </refsect1>++ <refsect1 id="twidge.seealso">+ <title>See Also</title>+ <para>+ <application>curl</application>(1)+ </para>+ <para>+ The &twidge; homepage at <ulink+ url="http://software.complete.org/twidge"></>.+ </para>+ </refsect1>+ + </refentry>
+ doc/twidge.sgml view
@@ -0,0 +1,20 @@+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [+ <!ENTITY index SYSTEM "index/index.sgml">+ <!ENTITY man.twidge SYSTEM "twidge-manpage.sgml">+ <!ENTITY twidge "<application>twidge</application>">++]>++ <reference>+ <title>twidge Manual</title>+ &man.twidge;+ </reference>++<!--+Local Variables:+mode: sgml+sgml-set-face: T+End:++-->+
+ twidge.cabal view
@@ -0,0 +1,52 @@+Name: twidge+Version: 0.99.0+License: GPL+Maintainer: John Goerzen <jgoerzen@complete.org>+Author: John Goerzen+Stability: Stable+Copyright: Copyright (c) 2006-2008 John Goerzen+license-file: COPYRIGHT+extra-source-files: COPYING, INSTALL, doc/SConstruct,+ doc/twidge-manpage.sgml, doc/twidge.sgml, doc/local.dsl,+ doc/man.twidge.sgml, doc/printlocal.dsl, doc/sgml-common/COPYING,+ doc/sgml-common/COPYRIGHT, doc/sgml-common/ChangeLog,+ doc/sgml-common/Makefile.common, doc/sgml-common/SConstruct,+ doc/sgml-common/ps2epsi+homepage: http://software.complete.org/twidge+Build-type: Simple+Category: Network+Synopsis: Unix Command-Line Twitter and Identica Client+Description: twidge is a client for microblogging sites such as Twitter and+ Identica (identi.ca). Microblogging sites let you post short+ one-paragraph updates, follow the updates that your friends post, and+ interact with everyone in the site in a conversation style.+ .+ twidge is a client to make working with microblogging sites faster+ and easier. It is extremely versatile, and can be customized to work+ the way you want to work, and combined with other tools to do just+ about anything.+ .+ twidge can be used quite nicely interactively from the shell. It is+ useful directly as-is, and with simple shell aliases can make a+ highly efficient system to do exactly what you want. It is perfectly+ capable of being your only client for microblogging.+ .+ twidge also can be used in an automated way, via cron(1), or it can+ even integrate with your email system.+ .+ A full list of twidge features, along with numerous suggestions on+ how to use it, can be found at the twidge website at+ http://software.complete.org/twidge.++Build-Depends: network, unix, parsec, MissingH>=1.0.0,+ mtl, base, HaXml>=1.13.2, HaXml<1.19, hslogger,+ ConfigFile, directory, HSH, Cabal, regex-posix++Executable: twidge+Main-Is: twidge.hs+Other-Modules: Commands, Config, Download, FeedParser,+ Types, Utils, + Commands.Ls+GHC-Options: -O2+Extensions: ExistentialQuantification, OverlappingInstances,+ UndecidableInstances
+ twidge.hs view
@@ -0,0 +1,89 @@+{- component+Copyright (C) 2006-2008 John Goerzen <jgoerzen@complete.org>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA+-}++{- |+ Module : Main+ Copyright : Copyright (C) 2006-2008 John Goerzen+ License : GNU GPL, version 2 or above++ Maintainer : John Goerzen <jgoerzen@complete.org>+ Stability : provisional+ Portability: portable++Written by John Goerzen, jgoerzen\@complete.org++-}++import Config+import System.Log.Logger+import System.Log.Handler.Simple+import System.Console.GetOpt.Utils+import System.Console.GetOpt+import System.Environment+import Data.List+import System.Exit+import Commands+import Types+import Control.Monad+import Data.ConfigFile(emptyCP)+import System.IO+import Paths_twidge(version)+import Data.Version++main = + do updateGlobalLogger "" (setLevel INFO)+ argv <- getArgs+ + case getOpt RequireOrder options argv of+ (o, n, []) -> worker o n+ (_, _, errors) -> usageerror (concat errors) -- ++ usageInfo header options)+ +options = [Option "d" ["debug"] (NoArg ("d", "")) "Enable debugging",+ Option "c" ["config"] (ReqArg (stdRequired "c") "FILE")+ "Use specified config file",+ Option "" ["help"] (NoArg ("help", "")) "Display this help"]++worker args commandargs =+ do when (lookup "help" args == Just "") $ usageerror ""+ when (lookup "d" args == Just "") + (updateGlobalLogger "" (setLevel DEBUG))+ handler <- streamHandler stderr DEBUG -- stdout has issues with HSH+ updateGlobalLogger "" (setHandlers [handler])+ let commandname = head cmdargs+ case lookup commandname allCommands of+ Just command -> + do cp <- if commandname `elem` ["lscommands", "setup"] -- no config file needed+ then return emptyCP+ else loadCP (lookup "c" args)+ execcmd command (tail cmdargs) (lookup "c" args) cp+ Nothing -> usageerror ("Invalid command name " ++ commandname)+ where cmdargs = case commandargs of+ [] -> ["help"]+ x -> x++usageerror errormsg =+ do putStrLn errormsg+ putStrLn (usageInfo header options)+ putStrLn "Run \"twidge lscommands\" for a list of available commands.\n\+ \Run \"twidge command --help\" for help on a particular command.\n"+ putStr $ "This is Twidge, version " ++ showVersion version+ putStrLn $ ". Copyright (c) 2008 John Goerzen"+ exitFailure++header = "Usage: twidge [global-options] command [command-options]\n\n\+ \Available global-options are:\n"