示例#1
0
 public Parser(string file)
 {
     SourceFile       = file;
     Header           = new GettextBlock();
     HeaderFirstLines = 0;
     Data             = new GettextBlockList();
 }
示例#2
0
        public bool Parse()
        {
            if (!File.Exists(SourceFile))
            {
                return(false);
            }
            try
            {
                var    rx_regions         = new Regex("^#(region|endregion|[1-9]).*$");
                var    rx_strings         = new Regex("^(?<type>msgctxt|msgid|msgid_plural|msgstr|msgstr\\[(?<index>\\d)\\])\\s\"(?<string>.*)\"$");
                var    rx_srings_continue = new Regex("^\"(?<string>.*)\"$");
                var    rx_error           = new Regex("^(msgid\\s\"|(#[,:.\\|]))");
                var    block = new GettextBlock();
                string str = String.Empty;
                bool   end = false, close_block = false, keep_line = false;
                bool   header = true;
                Match  m;

                var sr = new StreamReader(SourceFile);
                for (int line = 0; !end; line++)
                {
                    end = sr.EndOfStream;
                    if (keep_line)
                    {
                        line--;
                    }
                    else
                    {
                        str = (end ? string.Empty : sr.ReadLine().Trim());
                    }
                    keep_line = false;

                    if ((close_block = (str.Length == 0)) == false)
                    {
                        bool is_data = false;

                        //UNDONE: Хреновенько, но пока хоть так, чтоб строки не удалял.
                        if (block.ID != null && rx_error.IsMatch(str))
                        {
                            close_block = keep_line = true;
                        }

                        #region Комментарии
                        else if (str.StartsWith("#"))
                        {
                            if (rx_regions.IsMatch(str))
                            {
                                close_block = true;
                            }
                            else
                            {
                                is_data = true;

                                if (str.StartsWith("#,"))
                                {
                                    block.Flags.Add(str);
                                }
                                else if (str.StartsWith("#:"))
                                {
                                    block.Links.Add(str.Substring(2));
                                }
                                else if (str.StartsWith("#."))
                                {
                                    block.AutoComments.Add(str);
                                }
                                else if (str.StartsWith("#|"))                                  // TODO: Сделать поддержку форматирования предыдущих ID
                                {
                                    block.PrevIDs.Add(str);
                                }
                                else if (str.StartsWith("#*"))
                                {
                                    block.AltStrings.Add(str);
                                }
                                else
                                {
                                    block.Comments.Add(str);
                                }
                            }
                        }
                        #endregion

                        #region Строки
                        else if ((m = rx_strings.Match(str)).Success)
                        {
                            keep_line = true;
                            if (block.StartLine < 0)
                            {
                                block.StartLine = line;
                            }
                            string gs        = String.Empty;
                            var    breaks    = new List <int>();
                            bool   add_break = false;
                            Match  gm        = m;

                            // Добавления всех последующих обрамленных кавычками строк
                            do
                            {
                                if (add_break)
                                {
                                    breaks.Add(gs.Length);
                                }
                                gs += gm.Groups["string"].Value;
                                if ((end = sr.EndOfStream) == false)
                                {
                                    str = sr.ReadLine().Trim();
                                }
                                line++;
                                add_break = true;
                            }while(!end && (gm = rx_srings_continue.Match(str)).Success);
                            close_block = end;

                            switch (m.Groups["type"].Value)
                            {
                            case "msgctxt":
                                block.Context = gs;
                                break;

                            case "msgid":
                                block.ID        = gs;
                                block.ID_Breaks = breaks;
                                break;

                            case "msgid_plural":
                                block.IDPlural        = gs;
                                block.IDPlural_Breaks = breaks;
                                break;

                            case "msgstr":
                                block.Str        = gs;
                                block.Str_Breaks = breaks;
                                break;

                            default:
                                int ind = int.Parse(m.Groups["index"].Value);
                                if (block.StrInd.Length < ind + 1)
                                {
                                    Array.Resize(ref block.StrInd, ind + 1);
                                    Array.Resize(ref block.StrInd_Breaks, ind + 1);
                                }
                                block.StrInd[ind]        = gs;
                                block.StrInd_Breaks[ind] = breaks;
                                break;
                            }
                        }
                        #endregion

                        if (is_data && block.StartLine < 0)
                        {
                            block.StartLine = line;
                        }
                    }

                    #region Завершение блока
                    if (close_block)
                    {
                        if (block.ID != null)
                        {
                            block.LinesCount = line - block.StartLine;
                            if (block.ID.Length == 0)
                            {
                                block.Comments.InsertRange(0, Header.Comments);
                                Header = block;
                                if (HeaderFirstLines > Header.StartLine)
                                {
                                    HeaderFirstLines = Header.StartLine;
                                }
                            }
                            else
                            {
                                Data.Add(block);
                            }
                            header = false;
                        }
                        else if (header)
                        {
                            Header.Comments.AddRange(block.Comments);
                            if (str.Length == 0 && Header.ID == null)
                            {
                                Header.Comments.Add(string.Empty);
                            }
                            HeaderFirstLines = line + 1;
                        }
                        block = new GettextBlock();
                    }
                    #endregion
                }

                sr.Close();
                return(true);
            }
            catch
            {
                return(false);
            }
        }
示例#3
0
        void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            #region Обработка файлов
            if (FilesError == 0)
            {
                for (int progress = 0; progress < Files.Count; progress++)
                {
                    var file = Files[progress];
                    FilesError = (Stop ? EF_Canceled : 0);

                    string file_src = file.Source, file_upd = file.Update, file_dest = file.Target;
                    bool   upd = (file_upd.Length > 0);
                    FilesUpdated = (FilesUpdated || upd);
                    Parser parser_src = new Parser(file_src), paser_upd = new Parser(file_upd);
                    if (FilesError == 0 && !parser_src.Parse())
                    {
                        FilesError = EF_ParserSrc;
                    }
                    if (FilesError == 0 && upd && !paser_upd.Parse())
                    {
                        FilesError = EF_ParserUpd;
                    }

                    var data = new List <string>();

                    #region Отладка парсера
                                        #if DebugSourceParser
                    try
                    {
                        var sr = new StreamReader(file_src);
                        data.AddRange(sr.ReadToEnd().Replace("\r\n", "\n").Split('\n'));
                        sr.Close();
                        Directory.CreateDirectory(SplitPath(file_dest)[0]);
                        var sw = new StreamWriter(file_dest + "~dbg.txt");
                        for (int bl = 0; bl < parser_src.Data.Count; bl++)
                        {
                            var block = parser_src.Data[bl];
                            sw.WriteLine(String.Format("——————————— Block {0} ———————————", bl));
                            for (int ln = 0; ln < block.LinesCount; ln++)
                            {
                                sw.WriteLine(data[block.StartLine + ln]);
                            }
                        }
                        sw.Close();
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Trace.WriteLine(ex.ToString());
                    }
                    data.Clear();
                                        #endif
                    #endregion

                    #region Применение изменений
                    bool wri_prev = !RemPrevIDs, wri_strings = !RemStrings, wri_alt = !RemAltStrings, wri_com = !RemComments, wri_autocom = !RemAutoComments, wri_links = !RemLinks, wri_flags = !RemFlags;
                    bool upd_header = (upd && UpdHeader), upd_prev = (upd && UpdPrevIDs), upd_strings = (upd && UpdStrings), upd_alt = (upd && UpdAltStrings), upd_com = (upd && UpdComments), upd_autocom = (upd && UpdAutoComments), upd_links = (upd && UpdLinks), upd_flags = (upd && UpdFlags);
                    if (FilesError == 0)
                    {
                        try
                        {
                            var sr = new StreamReader(file_src);
                            data.AddRange(sr.ReadToEnd().Replace("\r\n", "\n").Split('\n'));
                            sr.Close();
                            for (int isrc = parser_src.Data.Count - 1; isrc >= 0; isrc--)
                            {
                                var bsrc  = parser_src.Data[isrc];
                                int iupd  = paser_upd.Data.IndexOf(bsrc.ID);
                                var bupd  = (iupd < 0 ? null : paser_upd.Data[iupd]);
                                var block = new List <string>();
                                if (wri_com)
                                {
                                    block.AddRange(((upd_com && iupd >= 0 ? bupd : bsrc) as GettextBlock).Comments);
                                }
                                if (wri_autocom)
                                {
                                    block.AddRange(((upd_autocom && iupd >= 0 ? bupd : bsrc) as GettextBlock).AutoComments);
                                }
                                if (wri_links)
                                {
                                    block.AddRange(((upd_links && iupd >= 0 ? bupd : bsrc) as GettextBlock).FormatLinks(FormatLinks));
                                }
                                if (wri_flags)
                                {
                                    block.AddRange(((upd_flags && iupd >= 0 ? bupd : bsrc) as GettextBlock).Flags);
                                }
                                if (wri_prev)
                                {
                                    block.AddRange(((upd_prev && iupd >= 0 ? bupd : bsrc) as GettextBlock).PrevIDs);
                                }
                                // TODO: Добавить обновление контекста
                                if (!string.IsNullOrEmpty(bsrc.Context))
                                {
                                    block.Add(bsrc.FormatContext());
                                }
                                block.AddRange(bsrc.FormatMsgID(FormatIDs));
                                if (bsrc.IDPlural != null)
                                {
                                    block.AddRange(bsrc.FormatMsgIDPlural(FormatIDs));
                                }
                                GettextBlock buse = (upd_strings && iupd >= 0 ? bupd : bsrc);
                                if (buse.StrInd.Length == 0)
                                {
                                    if (wri_strings)
                                    {
                                        block.AddRange(buse.FormatMsgStr(FormatStrings));
                                    }
                                    else
                                    {
                                        block.Add("msgstr \"\"");
                                    }
                                }
                                else
                                {
                                    for (int i = 0; i < buse.StrInd.Length; i++)
                                    {
                                        if (wri_strings)
                                        {
                                            block.AddRange(buse.FormatMsgStrInd(i, FormatStrings));
                                        }
                                        else
                                        {
                                            block.Add("msgstr \"[" + i + "]\"");
                                        }
                                    }
                                }
                                if (wri_alt)
                                {
                                    block.AddRange(((upd_alt && iupd >= 0 ? bupd : bsrc) as GettextBlock).AltStrings);
                                }

                                data.RemoveRange(bsrc.StartLine, bsrc.LinesCount);
                                data.InsertRange(bsrc.StartLine, block);
                            }
                            if (upd_header)
                            {
                                data.RemoveRange(parser_src.Header.StartLine, parser_src.Header.LinesCount);
                                data.RemoveRange(0, parser_src.HeaderFirstLines);
                                data.InsertRange(0, paser_upd.Header.Comments);
                                int cur = paser_upd.Header.Comments.Count;
                                data.Insert(cur++, "msgid \"\"");
                                data.InsertRange(cur, paser_upd.Header.FormatMsgStr(2));
                            }
                            if (RemRegions)
                            {
                                var rx = new Regex("^#(region|endregion|[1-9])");
                                for (int i = data.Count - 1; i >= 0; i--)
                                {
                                    if (rx.IsMatch(data[i]))
                                    {
                                        data.RemoveAt(i);
                                    }
                                }
                            }
                        }
                        catch                         //(Exception ex)
                        {
                            FilesError = EF_Process;
                            //System.Diagnostics.Debug.WriteLine(ex.ToString());
                        }
                    }
                    #endregion

                    #region Запись нового файла
                    if (FilesError == 0)
                    {
                        try
                        {
                            Directory.CreateDirectory(SplitPath(file_dest)[0]);
                            var sw = new StreamWriter(file_dest + ".tmp");
                            sw.Write(String.Join("\r\n", data.ToArray()));
//							foreach (string s in data)
//								sw.WriteLine(s);
                            sw.Close();
                            // Net нормально понимает и просто реплейс для любых ситуаций. Mono - нифига.
                            if (File.Exists(file_dest))
                            {
                                File.Replace(file_dest + ".tmp", file_dest, !BackupFiles ? null : file_dest + ".bak");
                            }
                            else
                            {
                                File.Move(file_dest + ".tmp", file_dest);
                            }
                        }
                        catch
                        {
                            FilesError = EF_Write;
                        }
                    }
                    #endregion

                    file.Error = FilesError;
                    if (Files.Count > 1)
                    {
                        FilesError = 0;
                    }
                    backgroundWorker.ReportProgress(progress + 1);
                }
            }
            #endregion
        }