commit ghc-ClustalParser for openSUSE:Factory
Hello community, here is the log from the commit of package ghc-ClustalParser for openSUSE:Factory checked in at 2017-03-31 15:07:29 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-ClustalParser (Old) and /work/SRC/openSUSE:Factory/.ghc-ClustalParser.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "ghc-ClustalParser" Fri Mar 31 15:07:29 2017 rev:2 rq:482169 version:1.2.1 Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-ClustalParser/ghc-ClustalParser.changes 2017-03-16 09:35:54.446564427 +0100 +++ /work/SRC/openSUSE:Factory/.ghc-ClustalParser.new/ghc-ClustalParser.changes 2017-03-31 15:07:30.301201240 +0200 @@ -1,0 +2,5 @@ +Sun Feb 12 14:12:30 UTC 2017 - psimons@suse.com + +- Update to version 1.2.1 with cabal2obs. + +------------------------------------------------------------------- Old: ---- ClustalParser-1.1.4.tar.gz New: ---- ClustalParser-1.2.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-ClustalParser.spec ++++++ --- /var/tmp/diff_new_pack.cekxdv/_old 2017-03-31 15:07:30.837125473 +0200 +++ /var/tmp/diff_new_pack.cekxdv/_new 2017-03-31 15:07:30.841124908 +0200 @@ -19,10 +19,10 @@ %global pkg_name ClustalParser %bcond_with tests Name: ghc-%{pkg_name} -Version: 1.1.4 +Version: 1.2.1 Release: 0 Summary: Libary for parsing Clustal tools output -License: GPL-3.0 +License: GPL-3.0+ Group: Development/Languages/Other Url: https://hackage.haskell.org/package/%{pkg_name} Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz @@ -32,6 +32,7 @@ BuildRequires: ghc-either-unwrap-devel BuildRequires: ghc-parsec-devel BuildRequires: ghc-rpm-macros +BuildRequires: ghc-text-devel BuildRequires: ghc-vector-devel BuildRoot: %{_tmppath}/%{name}-%{version}-build %if %{with tests} ++++++ ClustalParser-1.1.4.tar.gz -> ClustalParser-1.2.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ClustalParser-1.1.4/ClustalParser.cabal new/ClustalParser-1.2.1/ClustalParser.cabal --- old/ClustalParser-1.1.4/ClustalParser.cabal 2016-05-30 11:45:48.000000000 +0200 +++ new/ClustalParser-1.2.1/ClustalParser.cabal 2017-02-06 19:20:52.000000000 +0100 @@ -5,7 +5,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change -version: 1.1.4 +version: 1.2.1 synopsis: Libary for parsing Clustal tools output description: Currently contains parsers and datatypes for: clustalw2, clustalo, mlocarna, cmalign . @@ -18,7 +18,7 @@ Cmalign is a multiple sequence alignment program based on RNA family models and produces ,among others, clustal output. It is part of infernal <http://infernal.janelia.org/>. -license: GPL +license: GPL-3.0 license-file: LICENSE author: Florian Eggenhofer maintainer: egg@tbi.univie.ac.at @@ -36,8 +36,8 @@ source-repository this type: git - location: https://github.com/eggzilla/ClustalParser/tree/1.1.4 - tag: 1.1.4 + location: https://github.com/eggzilla/ClustalParser/tree/1.2.1 + tag: 1.2.1 library -- Modules exported by the library. @@ -45,7 +45,7 @@ other-modules: Bio.ClustalData -- Other library packages from which modules are imported. - build-depends: base >=4.5 && <5, parsec>=3.1.9, vector + build-depends: base >=4.5 && <5, parsec>=3.1.9, vector, text -- compiler options ghc-options: -Wall -O2 -fno-warn-unused-do-bind -- Directories containing source files. @@ -58,7 +58,7 @@ ghc-options: -Wall -O2 test-suite hspec - build-depends: base, parsec, ClustalParser, hspec >= 1.8 + build-depends: base, parsec, ClustalParser, hspec >= 1.8, text hs-source-dirs: test-suite main-is: Spec.hs type: exitcode-stdio-1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ClustalParser-1.1.4/ClustalParserTest.hs new/ClustalParser-1.2.1/ClustalParserTest.hs --- old/ClustalParser-1.1.4/ClustalParserTest.hs 2016-05-30 11:45:48.000000000 +0200 +++ new/ClustalParser-1.2.1/ClustalParserTest.hs 2017-02-06 19:20:52.000000000 +0100 @@ -1,7 +1,9 @@ +--runghc -package-db --ghc-arg=.cabal-sandbox/x86_64-linux-ghc-8.0.1-packages.conf.d ClustalParserTest.hs struct-multiline.mlocarna module Main where import System.Environment (getArgs) import Bio.ClustalParser +--import Data.Either.Unwrap main :: IO () main = do @@ -10,4 +12,5 @@ -- read Clustal outputfile parsedinput <- readStructuralClustalAlignment input_file print parsedinput + --print $ structuralAlignmentEntries (fromRight parsedinput) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ClustalParser-1.1.4/changelog new/ClustalParser-1.2.1/changelog --- old/ClustalParser-1.1.4/changelog 2016-05-30 11:45:48.000000000 +0200 +++ new/ClustalParser-1.2.1/changelog 2017-02-06 19:20:52.000000000 +0100 @@ -1,4 +1,8 @@ -*-change-log-*- +1.2.1 Florian Eggenhofer <egg@cs.uni-freiburg.de> 06. February 2017 + * Structural alignment parser now works with multiline consensus structures +1.2.0 Florian Eggenhofer <egg@cs.uni-freiburg.de> 07. January 2017 + * Changed datastructures for sequence identifers and sequences to Data.Text 1.1.4 Florian Eggenhofer <egg@cs.uni-freiburg.de> 30. May 2016 * Fixed a bug in output of clustal alignments with sequence length of 60 1.1.3 Florian Eggenhofer <florian.eggenhofer@univie.ac.at> 4. July 2015 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ClustalParser-1.1.4/src/Bio/ClustalData.hs new/ClustalParser-1.2.1/src/Bio/ClustalData.hs --- old/ClustalParser-1.1.4/src/Bio/ClustalData.hs 2016-05-30 11:45:48.000000000 +0200 +++ new/ClustalParser-1.2.1/src/Bio/ClustalData.hs 2017-02-06 19:20:52.000000000 +0100 @@ -3,26 +3,27 @@ module Bio.ClustalData where import qualified Data.Vector as V - +import qualified Data.Text as T + -- | Data type for clustal summary, containing information about the alignment process, usually printed to STDOUT data ClustalSummary = ClustalSummary { - clustalw2version :: String, - sequenceFormat :: String, + clustalw2version :: T.Text, + sequenceFormat :: T.Text, parametersOfInputSequences :: [SequenceParameters], pairwiseAlignmentSummaries :: [PairwiseAlignmentSummary], - guideTreeFileName :: String, + guideTreeFileName :: T.Text, groupNumber :: Int, groupSummaries :: [GroupSummary], alignmentScore :: Int, - alignmentFileName :: String + alignmentFileName :: T.Text } deriving (Show, Eq) data SequenceParameters = SequenceParameters { inputSequenceIndex :: Int, - inputSequenceIdentifier :: String, + inputSequenceIdentifier :: T.Text, inputSequenceLength :: Int } deriving (Show, Eq) @@ -47,7 +48,7 @@ data ClustalAlignment = ClustalAlignment { alignmentEntries :: [ClustalAlignmentEntry], - conservationTrack :: String + conservationTrack :: T.Text } deriving (Eq) @@ -56,30 +57,30 @@ | not (null _alignmentEntries) = header ++ alignmentString | otherwise = header where header = "CLUSTAL W (1.8) multiple sequence alignment\n\n\n" - longestSequenceIdLength = (maximum (map length (map entrySequenceIdentifier _alignmentEntries))) + 1 - totalSequenceLength = length (entryAlignedSequence (head _alignmentEntries)) + longestSequenceIdLength = (maximum (map T.length (map entrySequenceIdentifier _alignmentEntries))) + 1 + totalSequenceLength = T.length (entryAlignedSequence (head _alignmentEntries)) alignmentString = showAlignment totalSequenceLength longestSequenceIdLength 0 _alignmentEntries _conservationTrack -showAlignment :: Int -> Int -> Int -> [ClustalAlignmentEntry] -> String -> String +showAlignment :: Int -> Int -> Int -> [ClustalAlignmentEntry] -> T.Text -> String showAlignment totalSequenceLength longestSequenceIdLength currentWindowPosition _alignmentEntries _conservationTrack | totalSequenceLength == 0 = [] | currentWindowPosition < totalSequenceLength = showAlignmentBlock longestSequenceIdLength currentWindowPosition _alignmentEntries _conservationTrack ++ (showAlignment totalSequenceLength longestSequenceIdLength (currentWindowPosition + 60) _alignmentEntries _conservationTrack) | currentWindowPosition == totalSequenceLength = [] - | otherwise = "" + | otherwise = "" -showAlignmentBlock :: Int -> Int -> [ClustalAlignmentEntry] -> String -> String +showAlignmentBlock :: Int -> Int -> [ClustalAlignmentEntry] -> T.Text -> String showAlignmentBlock longestSequenceIdLength currentWindowPosition _alignmentEntries _conservationTrack = blockString where blockString = entries ++ extraTrack ++ "\n" entries = concatMap (showAlignmentLine longestSequenceIdLength currentWindowPosition) _alignmentEntries - extraTrack = concat (replicate longestSequenceIdLength " ") ++ V.toList (V.slice currentWindowPosition 60 (V.fromList _conservationTrack)) ++ "\n" + extraTrack = concat (replicate longestSequenceIdLength " ") ++ V.toList (V.slice currentWindowPosition 60 (V.fromList (T.unpack _conservationTrack))) ++ "\n" showAlignmentLine :: Int -> Int -> ClustalAlignmentEntry -> String -showAlignmentLine longestSequenceIdLength currentWindowPosition _alignmentEntry = (entrySequenceIdentifier _alignmentEntry) ++ concat (replicate (longestSequenceIdLength - length (entrySequenceIdentifier _alignmentEntry)) " ") ++ V.toList (V.slice currentWindowPosition 60 (V.fromList (entryAlignedSequence _alignmentEntry))) ++ "\n" +showAlignmentLine longestSequenceIdLength currentWindowPosition _alignmentEntry = T.unpack (entrySequenceIdentifier _alignmentEntry) ++ concat (replicate (longestSequenceIdLength - T.length (entrySequenceIdentifier _alignmentEntry)) " ") ++ V.toList (V.slice currentWindowPosition 60 (V.fromList (T.unpack (entryAlignedSequence _alignmentEntry)))) ++ "\n" data ClustalAlignmentEntry = ClustalAlignmentEntry { - entrySequenceIdentifier :: String, - entryAlignedSequence :: String + entrySequenceIdentifier :: T.Text, + entryAlignedSequence :: T.Text } deriving (Show, Eq) @@ -91,18 +92,18 @@ deriving (Show, Eq) data ClustalAlignmentEntrySlice = ClustalAlignmentEntrySlice - { - entrySequenceSliceIdentifier :: String, - entryAlignedSliceSequence :: String, - spacerLength :: Int - } - deriving (Show, Eq) + { + entrySequenceSliceIdentifier :: String, + entryAlignedSliceSequence :: String, + spacerLength :: Int + } + deriving (Show, Eq) -- | Data structure for structural Clustal alignment format data StructuralClustalAlignment = StructuralClustalAlignment { structuralAlignmentEntries :: [ClustalAlignmentEntry], - secondaryStructureTrack :: String, + secondaryStructureTrack :: T.Text, energy :: Double } deriving (Eq) @@ -112,15 +113,15 @@ | not (null _alignmentEntries) = header ++ alignmentString | otherwise = header where header = "CLUSTAL W \n\n" - longestSequenceIdLength = (maximum (map length (map entrySequenceIdentifier _alignmentEntries))) + 1 - totalSequenceLength = length (entryAlignedSequence (head _alignmentEntries)) + longestSequenceIdLength = (maximum (map T.length (map entrySequenceIdentifier _alignmentEntries))) + 1 + totalSequenceLength = T.length (entryAlignedSequence (head _alignmentEntries)) alignmentString = showAlignment totalSequenceLength longestSequenceIdLength 0 _alignmentEntries _secondaryStructureTrack -data StructuralClustalAlignmentSlice = StructuralClustalAlignmentSlice - { - structuralEntrySlices :: [StructuralClustalAlignmentEntrySlice] - } - deriving (Show, Eq) +-- data StructuralClustalAlignmentSlice = StructuralClustalAlignmentSlice +-- { +-- structuralEntrySlices :: [StructuralClustalAlignmentEntrySlice] +-- } +-- deriving (Show, Eq) data StructuralClustalAlignmentEntrySlice = StructuralClustalAlignmentEntrySlice { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ClustalParser-1.1.4/src/Bio/ClustalParser.hs new/ClustalParser-1.2.1/src/Bio/ClustalParser.hs --- old/ClustalParser-1.1.4/src/Bio/ClustalParser.hs 2016-05-30 11:45:48.000000000 +0200 +++ new/ClustalParser-1.2.1/src/Bio/ClustalParser.hs 2017-02-06 19:20:52.000000000 +0100 @@ -14,7 +14,7 @@ import Text.ParserCombinators.Parsec import Control.Monad import Data.List - +import qualified Data.Text as T readDouble :: String -> Double readDouble = read @@ -69,7 +69,7 @@ newline newline eof - return $ ClustalSummary version sequenceFormat' sequenceParametersList pairwiseAlignmentSummaryList guideTreeFileName' (readInt numberOfGroups) groupSummaryList (readInt alignmentScore') alignmentFileName' + return $ ClustalSummary (T.pack version) (T.pack sequenceFormat') sequenceParametersList pairwiseAlignmentSummaryList (T.pack guideTreeFileName') (readInt numberOfGroups) groupSummaryList (readInt alignmentScore') (T.pack alignmentFileName') genParserGroupSummary :: GenParser Char st GroupSummary genParserGroupSummary = do @@ -109,7 +109,7 @@ space string "bp" newline - return $ SequenceParameters (readInt sequenceIndexParam) sequenceIdentifierParam (readInt sequenceLengthParam) + return $ SequenceParameters (readInt sequenceIndexParam) (T.pack sequenceIdentifierParam) (readInt sequenceLengthParam) -- | Parse the input as ClustalAlignment datatype genParserClustalAlignment :: GenParser Char st ClustalAlignment @@ -123,18 +123,17 @@ mergealignmentSlices :: [ClustalAlignmentSlice] -> ClustalAlignment mergealignmentSlices slices = alignment - where entrySlicesList = map entrySlices slices -- list of lists of entry slices - sequenceIdentifiers = nub (map entrySequenceSliceIdentifier (head entrySlicesList)) - alignmentEntriesListBySlice = map (map entryAlignedSliceSequence) entrySlicesList - transposedAlignmentEntriesListbySlice = transpose alignmentEntriesListBySlice - mergedAlignmentSequenceEntries = map concat transposedAlignmentEntriesListbySlice - mergedAlignmentEntries = map constructAlignmentEntries (zip sequenceIdentifiers mergedAlignmentSequenceEntries) - conservationTrackSlices = map conservationTrackSlice slices - mergedConservationTrack = concat conservationTrackSlices - alignment = ClustalAlignment mergedAlignmentEntries mergedConservationTrack - -constructAlignmentEntries :: (String, String) -> ClustalAlignmentEntry -constructAlignmentEntries (entryIdentifier,entrySequence) = ClustalAlignmentEntry entryIdentifier entrySequence + where entrySlicesList = concatMap entrySlices slices -- list of lists of entry slices + sequenceIdentifiers = nub (map entrySequenceSliceIdentifier entrySlicesList) + mergedAlignmentEntries = map (constructAlignmentEntries entrySlicesList) sequenceIdentifiers + mergedConservationTrack = concatMap conservationTrackSlice slices + alignment = ClustalAlignment mergedAlignmentEntries (T.pack mergedConservationTrack) + +constructAlignmentEntries :: [ClustalAlignmentEntrySlice] -> String -> ClustalAlignmentEntry +constructAlignmentEntries slices entryIdentifier= entry + where currentSlices = filter (\a -> entrySequenceSliceIdentifier a == entryIdentifier) slices + entrySequence = concatMap entryAlignedSliceSequence currentSlices + entry = ClustalAlignmentEntry (T.pack entryIdentifier) (T.pack entrySequence) genParserClustalAlignmentSlice :: GenParser Char st ClustalAlignmentSlice genParserClustalAlignmentSlice = do @@ -165,16 +164,21 @@ secondaryStructure <- genSecondaryStructure energy' <- genParseEnergy eof - return (mergeStructuralAlignmentSlices alignmentSlices secondaryStructure energy') + return (mergeStructuralAlignmentSlices (concat alignmentSlices) secondaryStructure energy') genSecondaryStructure :: GenParser Char st String genSecondaryStructure = do string "alifold" - many1 space - secondaryStructure <- many1 (oneOf ".()") - space - return secondaryStructure + secondaryStructure <- many1 (try genSecondaryStructureSlice) + return (concat secondaryStructure) +genSecondaryStructureSlice :: GenParser Char st String +genSecondaryStructureSlice = do + many1 space + secondaryStructureSlice <- many1 (try (oneOf ".()")) + choice [try (string "\n"),try (string " ")] + return secondaryStructureSlice + genParseEnergy :: GenParser Char st Double genParseEnergy = do string "(" @@ -203,24 +207,23 @@ many1 newline return "" -mergeStructuralAlignmentSlices :: [StructuralClustalAlignmentSlice] -> String -> Double -> StructuralClustalAlignment +mergeStructuralAlignmentSlices :: [StructuralClustalAlignmentEntrySlice] -> String -> Double -> StructuralClustalAlignment mergeStructuralAlignmentSlices slices secondaryStructure energy' = alignment - where entrySlicesList = map structuralEntrySlices slices -- list of lists of entry slices - sequenceIdentifiers = (map structuralEntrySequenceSliceIdentifier (head entrySlicesList)) - alignmentEntriesListBySlice = map (map structuralEntryAlignedSliceSequence) entrySlicesList - transposedAlignmentEntriesListbySlice = transpose alignmentEntriesListBySlice - mergedAlignmentSequenceEntries = map concat transposedAlignmentEntriesListbySlice - mergedAlignmentEntries = map constructStructuralAlignmentEntries (zip sequenceIdentifiers mergedAlignmentSequenceEntries) - alignment = StructuralClustalAlignment mergedAlignmentEntries secondaryStructure energy' - -constructStructuralAlignmentEntries :: (String, String) -> ClustalAlignmentEntry -constructStructuralAlignmentEntries (entryIdentifier,entrySequence) = ClustalAlignmentEntry entryIdentifier entrySequence + where sequenceIdentifiers = nub (map structuralEntrySequenceSliceIdentifier slices) + mergedAlignmentEntries = map (constructStructuralAlignmentEntries slices) sequenceIdentifiers + alignment = StructuralClustalAlignment mergedAlignmentEntries (T.pack secondaryStructure) energy' + +constructStructuralAlignmentEntries :: [StructuralClustalAlignmentEntrySlice] -> String -> ClustalAlignmentEntry +constructStructuralAlignmentEntries slices entryIdentifier= entry + where currentSlices = filter (\a -> structuralEntrySequenceSliceIdentifier a == entryIdentifier) slices + entrySequence = concatMap structuralEntryAlignedSliceSequence currentSlices + entry = ClustalAlignmentEntry (T.pack entryIdentifier) (T.pack entrySequence) -genParserStructuralClustalAlignmentSlice :: GenParser Char st StructuralClustalAlignmentSlice +genParserStructuralClustalAlignmentSlice :: GenParser Char st [StructuralClustalAlignmentEntrySlice] genParserStructuralClustalAlignmentSlice = do entrySlices' <- many1 (try genParserStructuralClustalEntrySlice) optional newline - return $ StructuralClustalAlignmentSlice entrySlices' + return entrySlices' genParserStructuralClustalEntrySlice :: GenParser Char st StructuralClustalAlignmentEntrySlice genParserStructuralClustalEntrySlice = do @@ -237,30 +240,30 @@ parseClustalAlignment = parse genParserClustalAlignment "genParserClustalAlignment" -- | Parse Clustal alignment (.aln) from filehandle -readClustalAlignment :: String -> IO (Either ParseError ClustalAlignment) +readClustalAlignment :: String -> IO (Either ParseError ClustalAlignment) readClustalAlignment = parseFromFile genParserClustalAlignment -- | Parse Clustal alignment (.aln) with secondary structure in dot-bracket notation from String (as produced by mlocarna) -parseStructuralClustalAlignment :: String -> Either ParseError StructuralClustalAlignment +parseStructuralClustalAlignment :: String -> Either ParseError StructuralClustalAlignment parseStructuralClustalAlignment = parse genParserStructuralClustalAlignment "genParserStructuralClustalAlignment" -- | Parse Clustal alignment (.aln) with secondary structure in dot-bracket notation from filehandle (as produced by mlocarna) -readStructuralClustalAlignment :: String -> IO (Either ParseError StructuralClustalAlignment) +readStructuralClustalAlignment :: String -> IO (Either ParseError StructuralClustalAlignment) readStructuralClustalAlignment = parseFromFile genParserStructuralClustalAlignment -- | Parse Clustal summary (printed to STDOUT) from String -parseClustalSummary :: String -> Either ParseError ClustalSummary +parseClustalSummary :: String -> Either ParseError ClustalSummary parseClustalSummary = parse genParserClustalSummary "genParserClustalSummary" -- | Parse Clustal summary (printed to STDOUT) from file -readClustalSummary :: String -> IO (Either ParseError ClustalSummary) +readClustalSummary :: String -> IO (Either ParseError ClustalSummary) readClustalSummary = parseFromFile genParserClustalSummary -- | Parse nucleotide sequence. Allowed letters according to IUPAC -parseNucleotideSequence :: GenParser Char st String -parseNucleotideSequence = do - nucleotideSequence <- many1 (oneOf "RYSWKMBDHVNATUGCryswkmbdhvnatugc") - return $ nucleotideSequence +--parseNucleotideSequence :: GenParser Char st String +--parseNucleotideSequence = do +-- nucleotideSequence <- many1 (oneOf "RYSWKMBDHVNATUGCryswkmbdhvnatugc") +-- return $ nucleotideSequence -- | Parse nucleotide alignment entry. Allowed letters according to IUPAC and commonly used gap characters parseNucleotideAlignmentEntry :: GenParser Char st String @@ -269,13 +272,13 @@ return $ entry -- | Parse protein amino acid code sequence. Allowed letters according to IUPAC -parseProteinSequence :: GenParser Char st String -parseProteinSequence = do - proteinSequence <- many1 (oneOf "ABCDEFGHIKLMNPQRSTVWXYZabcdefghiklmnpqrstvwxyz") - return $ proteinSequence +--parseProteinSequence :: GenParser Char st String +--parseProteinSequence = do +-- proteinSequence <- many1 (oneOf "ABCDEFGHIKLMNPQRSTVWXYZabcdefghiklmnpqrstvwxyz") +-- return $ proteinSequence -- | Parse protein amino acid code alignment entry. Allowed letters according to IUPAC and commonly used gap characters -parseProteinAlignmentEntry :: GenParser Char st String -parseProteinAlignmentEntry = do - entry <- many1 (oneOf "~_-.ABCDEFGHIKLMNPQRSTVWXYZabcdefghiklmnpqrstvwxyz") - return $ entry +--parseProteinAlignmentEntry :: GenParser Char st String +--parseProteinAlignmentEntry = do +-- entry <- many1 (oneOf "~_-.ABCDEFGHIKLMNPQRSTVWXYZabcdefghiklmnpqrstvwxyz") +-- return $ entry
participants (1)
-
root@hilbert.suse.de