From 82ae133e81dfc80a4a226bc8d2dcec32cbebeafa Mon Sep 17 00:00:00 2001 From: Andrey Astafyev Date: Sun, 2 Jun 2019 00:08:41 +0300 Subject: [PATCH] =?UTF-8?q?asciidoc=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=20markdown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + pelicanconf-ascii.py | 116 ++ pelicanconf-f.py | 116 ++ pelicanconf-full.py | 70 +- pelicanconf.py | 66 +- plugins/official | 2 +- wiki/Latex/Висячие строки.adoc | 12 + wiki/Latex/Висячие строки.md | 14 - wiki/Latex/ЕСПД в LyX.adoc | 87 ++ wiki/Latex/ЕСПД в LyX.md | 69 - wiki/Latex/Защита команд.adoc | 12 + wiki/Latex/Защита команд.md | 15 - wiki/Latex/{Лигатуры.md => Лигатуры.adoc} | 15 +- wiki/Latex/Многостраничные таблицы в LyX.adoc | 28 + wiki/Latex/Многостраничные таблицы в LyX.md | 32 - wiki/Latex/Переносы.adoc | 7 + wiki/Latex/Переносы.md | 11 - wiki/Latex/Русский в PDF.adoc | 19 + wiki/Latex/Русский в PDF.md | 22 - ...я в PostgreSQL.md => Авторизация в PostgreSQL.adoc} | 27 +- wiki/Linux/{CUPS.md => CUPS.adoc} | 43 +- wiki/Linux/DPKG/{APT.md => APT.adoc} | 14 +- ...помощью GnuPG.md => Шифрование файлов с помощью GnuPG.adoc} | 39 +- wiki/Linux/Hardware/GPE.adoc | 28 + wiki/Linux/Hardware/GPE.md | 28 - wiki/Linux/LXC/DNS в контейнере LXC.adoc | 15 + wiki/Linux/LXC/DNS в контейнере LXC.md | 17 - wiki/Linux/Runit/{runit.md => runit.adoc} | 59 +- ...альной сети.md => Сервер NTP в локальной сети.adoc} | 26 +- ...л Rxvt-Unicode.md => Терминал Rxvt-Unicode.adoc} | 19 +- wiki/Linux/Ссылки.adoc | 8 + wiki/Linux/Ссылки.md | 10 - wiki/Misc/Libgen.adoc | 31 + wiki/Misc/Libgen.md | 30 - wiki/Misc/Windows/OOShutUp.adoc | 22 + wiki/Misc/Windows/OOShutUp.md | 22 - ...ие проектом.md => CMake управление проектом.adoc} | 493 +++--- .../Development/Intel Parallel Studio.adoc | 38 + .../Prog/Development/Intel Parallel Studio.md | 22 - .../{PVS-Studio.md => PVS-Studio.adoc} | 98 +- .../Подбор ключей компиляции GCC.adoc | 36 + .../Подбор ключей компиляции GCC.md | 35 - .../Prog/Development/Профилирование кода.adoc | 77 + wiki/Prog/Development/Профилирование кода.md | 79 - ...ий анализ кода.md => Статический анализ кода.adoc} | 122 +- .../Построение профиля местности в QGis.adoc | 49 + .../Построение профиля местности в QGis.md | 51 - ...81886ef1b8d31cdb2b865473bbeb2cf9.png.cache | 1 + ...e76d88ee3db613b3f806d8c773281fdc.png.cache | 1 + ...втоматическое сохранение в репозиторий.adoc | 29 + ...автоматическое сохранение в репозиторий.md | 27 - ...са подмодуля.md => Git замена адреса подмодуля.adoc} | 20 +- wiki/Prog/Git/Git основные команды.adoc | 391 +++++ wiki/Prog/Git/Git основные команды.md | 311 ---- wiki/Prog/Git/Git распаковка объекта.adoc | 10 + wiki/Prog/Git/Git распаковка объекта.md | 14 - ... устройстве.md => Git репозиторий на переносном устройстве.adoc} | 18 +- .../Git/Git частичная копия репозитория.adoc | 29 + .../Git/Git частичная копия репозитория.md | 31 - .../Git/Gitlab выполнение по расписанию.adoc | 38 + .../Git/Gitlab выполнение по расписанию.md | 36 - ... GitLab в LXC.md => Установка и настройка GitLab в LXC.adoc} | 82 +- .../CPP/Проверка именования в Clang Tidy.adoc | 1364 +++++++++++++++++ .../CPP/Проверка именования в Clang Tidy.md | 1227 --------------- wiki/Prog/Links/Библиотеки C CPP.adoc | 29 + wiki/Prog/Links/Библиотеки C CPP.md | 30 - .../Prog/Time/Работа с датами и временем.adoc | 156 ++ wiki/Prog/Time/Работа с датами и временем.md | 159 -- wiki/Vim/Vimdiff.adoc | 18 + wiki/Vim/Vimdiff.md | 19 - wiki/Vim/Замена выделенного блока.adoc | 21 + wiki/Vim/Замена выделенного блока.md | 23 - ...calLeader.md => Клавиши Leader и LocalLeader.adoc} | 34 +- ... и PageDown.md => Клавиши PageUp и PageDown.adoc} | 17 +- ...одировка файла.md => Кодировка файла.adoc} | 15 +- wiki/Vim/Комментирование кода.adoc | 25 + wiki/Vim/Комментирование кода.md | 26 - ... плагинов Plug.md => Менеджер плагинов Plug.adoc} | 35 +- ...ция easymotion.md => Навигация easymotion.adoc} | 21 +- wiki/Vim/Навигация по буферам.adoc | 14 + wiki/Vim/Навигация по буферам.md | 16 - ...умерация строк.md => Нумерация строк.adoc} | 18 +- ...рка орфографии.md => Проверка орфографии.adoc} | 17 +- wiki/Vim/Ссылки.adoc | 10 + wiki/Vim/Ссылки.md | 12 - wiki/Vim/Управление окнами.adoc | 19 + wiki/Vim/Управление окнами.md | 21 - .../diag-81886ef1b8d31cdb2b865473bbeb2cf9.png | Bin 0 -> 40071 bytes .../diag-e76d88ee3db613b3f806d8c773281fdc.png | Bin 0 -> 32488 bytes 89 files changed, 3514 insertions(+), 3122 deletions(-) create mode 100644 pelicanconf-ascii.py create mode 100644 pelicanconf-f.py create mode 100644 wiki/Latex/Висячие строки.adoc delete mode 100644 wiki/Latex/Висячие строки.md create mode 100644 wiki/Latex/ЕСПД в LyX.adoc delete mode 100644 wiki/Latex/ЕСПД в LyX.md create mode 100644 wiki/Latex/Защита команд.adoc delete mode 100644 wiki/Latex/Защита команд.md rename wiki/Latex/{Лигатуры.md => Лигатуры.adoc} (58%) create mode 100644 wiki/Latex/Многостраничные таблицы в LyX.adoc delete mode 100644 wiki/Latex/Многостраничные таблицы в LyX.md create mode 100644 wiki/Latex/Переносы.adoc delete mode 100644 wiki/Latex/Переносы.md create mode 100644 wiki/Latex/Русский в PDF.adoc delete mode 100644 wiki/Latex/Русский в PDF.md rename wiki/Linux/Astra/{Авторизация в PostgreSQL.md => Авторизация в PostgreSQL.adoc} (55%) rename wiki/Linux/{CUPS.md => CUPS.adoc} (62%) rename wiki/Linux/DPKG/{APT.md => APT.adoc} (63%) rename wiki/Linux/GnuPG/{Шифрование файлов с помощью GnuPG.md => Шифрование файлов с помощью GnuPG.adoc} (52%) create mode 100644 wiki/Linux/Hardware/GPE.adoc delete mode 100644 wiki/Linux/Hardware/GPE.md create mode 100644 wiki/Linux/LXC/DNS в контейнере LXC.adoc delete mode 100644 wiki/Linux/LXC/DNS в контейнере LXC.md rename wiki/Linux/Runit/{runit.md => runit.adoc} (64%) rename wiki/Linux/System/{Сервер NTP в локальной сети.md => Сервер NTP в локальной сети.adoc} (63%) rename wiki/Linux/Xorg/{Терминал Rxvt-Unicode.md => Терминал Rxvt-Unicode.adoc} (89%) create mode 100644 wiki/Linux/Ссылки.adoc delete mode 100644 wiki/Linux/Ссылки.md create mode 100644 wiki/Misc/Libgen.adoc delete mode 100644 wiki/Misc/Libgen.md create mode 100644 wiki/Misc/Windows/OOShutUp.adoc delete mode 100644 wiki/Misc/Windows/OOShutUp.md rename wiki/Prog/Development/{CMake управление проектом.md => CMake управление проектом.adoc} (64%) create mode 100644 wiki/Prog/Development/Intel Parallel Studio.adoc delete mode 100644 wiki/Prog/Development/Intel Parallel Studio.md rename wiki/Prog/Development/{PVS-Studio.md => PVS-Studio.adoc} (62%) create mode 100644 wiki/Prog/Development/Подбор ключей компиляции GCC.adoc delete mode 100644 wiki/Prog/Development/Подбор ключей компиляции GCC.md create mode 100644 wiki/Prog/Development/Профилирование кода.adoc delete mode 100644 wiki/Prog/Development/Профилирование кода.md rename wiki/Prog/Development/{Статический анализ кода.md => Статический анализ кода.adoc} (56%) create mode 100644 wiki/Prog/GIS/Построение профиля местности в QGis.adoc delete mode 100644 wiki/Prog/GIS/Построение профиля местности в QGis.md create mode 100644 wiki/Prog/Git/.asciidoctor/diagram/diag-81886ef1b8d31cdb2b865473bbeb2cf9.png.cache create mode 100644 wiki/Prog/Git/.asciidoctor/diagram/diag-e76d88ee3db613b3f806d8c773281fdc.png.cache create mode 100644 wiki/Prog/Git/Git автоматическое сохранение в репозиторий.adoc delete mode 100644 wiki/Prog/Git/Git автоматическое сохранение в репозиторий.md rename wiki/Prog/Git/{Git замена адреса подмодуля.md => Git замена адреса подмодуля.adoc} (55%) create mode 100644 wiki/Prog/Git/Git основные команды.adoc delete mode 100644 wiki/Prog/Git/Git основные команды.md create mode 100644 wiki/Prog/Git/Git распаковка объекта.adoc delete mode 100644 wiki/Prog/Git/Git распаковка объекта.md rename wiki/Prog/Git/{Git репозиторий на переносном устройстве.md => Git репозиторий на переносном устройстве.adoc} (77%) create mode 100644 wiki/Prog/Git/Git частичная копия репозитория.adoc delete mode 100644 wiki/Prog/Git/Git частичная копия репозитория.md create mode 100644 wiki/Prog/Git/Gitlab выполнение по расписанию.adoc delete mode 100644 wiki/Prog/Git/Gitlab выполнение по расписанию.md rename wiki/Prog/Git/{Установка и настройка GitLab в LXC.md => Установка и настройка GitLab в LXC.adoc} (79%) create mode 100644 wiki/Prog/Lang/CPP/Проверка именования в Clang Tidy.adoc delete mode 100644 wiki/Prog/Lang/CPP/Проверка именования в Clang Tidy.md create mode 100644 wiki/Prog/Links/Библиотеки C CPP.adoc delete mode 100644 wiki/Prog/Links/Библиотеки C CPP.md create mode 100644 wiki/Prog/Time/Работа с датами и временем.adoc delete mode 100644 wiki/Prog/Time/Работа с датами и временем.md create mode 100644 wiki/Vim/Vimdiff.adoc delete mode 100644 wiki/Vim/Vimdiff.md create mode 100644 wiki/Vim/Замена выделенного блока.adoc delete mode 100644 wiki/Vim/Замена выделенного блока.md rename wiki/Vim/{Клавиши Leader и LocalLeader.md => Клавиши Leader и LocalLeader.adoc} (85%) rename wiki/Vim/{Клавиши PageUp и PageDown.md => Клавиши PageUp и PageDown.adoc} (78%) rename wiki/Vim/{Кодировка файла.md => Кодировка файла.adoc} (92%) create mode 100644 wiki/Vim/Комментирование кода.adoc delete mode 100644 wiki/Vim/Комментирование кода.md rename wiki/Vim/{Менеджер плагинов Plug.md => Менеджер плагинов Plug.adoc} (60%) rename wiki/Vim/{Навигация easymotion.md => Навигация easymotion.adoc} (82%) create mode 100644 wiki/Vim/Навигация по буферам.adoc delete mode 100644 wiki/Vim/Навигация по буферам.md rename wiki/Vim/{Нумерация строк.md => Нумерация строк.adoc} (73%) rename wiki/Vim/{Проверка орфографии.md => Проверка орфографии.adoc} (74%) create mode 100644 wiki/Vim/Ссылки.adoc delete mode 100644 wiki/Vim/Ссылки.md create mode 100644 wiki/Vim/Управление окнами.adoc delete mode 100644 wiki/Vim/Управление окнами.md create mode 100644 wiki/images/diag-81886ef1b8d31cdb2b865473bbeb2cf9.png create mode 100644 wiki/images/diag-e76d88ee3db613b3f806d8c773281fdc.png diff --git a/.gitignore b/.gitignore index da8c2c0..62a1265 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ cache/* +cache-ascii/* cache-full/* cache-html/* output/* diff --git a/pelicanconf-ascii.py b/pelicanconf-ascii.py new file mode 100644 index 0000000..8f174b7 --- /dev/null +++ b/pelicanconf-ascii.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- # +from __future__ import unicode_literals +import os + +class i18n(object): + # looks for translations in + # {LOCALE_DIR}/{LANGUAGE}/LC_MESSAGES/{DOMAIN}.mo + # if not present, falls back to default + + DOMAIN = 'messages' + LOCALE_DIR = '{THEME}/translations' + LANGUAGES = ['ru'] + NEWSTYLE = True + + __name__ = 'i18n' + + def register(self): + from pelican.signals import generator_init + generator_init.connect(self.install_translator) + + def install_translator(self, generator): + import gettext + try: + translator = gettext.translation( + self.DOMAIN, + self.LOCALE_DIR.format(THEME=THEME), + self.LANGUAGES) + except (OSError, IOError): + translator = gettext.NullTranslations() + generator.env.install_gettext_translations(translator, self.NEWSTYLE) + +# ABOUT_ME = ' ' +AUTHOR = 'Андрей Астафьев' +SITENAME = 'ДСП' +SITEURL = 'https://dsp.246060.ru' + +PATH = 'wiki' +CACHE_PATH = 'cache-ascii' + +TIMEZONE = 'Europe/Moscow' + +DEFAULT_LANG = 'ru' + +# Generation time +CACHE_CONTENT = True +LOAD_CONTENT_CACHE = True + +# Feed generation is usually not desired when developing +FEED_ALL_ATOM = None +CATEGORY_FEED_ATOM = None +TRANSLATION_FEED_ATOM = None +AUTHOR_FEED_ATOM = None +AUTHOR_FEED_RSS = None +USE_FOLDER_AS_CATEGORY = True +DEFAULT_DATE = 'fs' +STATIC_PATHS = [ 'images', 'files', 'extras' ] + +EXTRA_PATH_METADATA = { + 'extras/favicon.ico': {'path': 'favicon.ico'}, +} + +DISPLAY_CATEGORIES_ON_MENU = False +DISPLAY_CATEGORIES_ON_SIDEBAR = True +DISPLAY_TAGS_ON_SIDEBAR = True + +THEME = 'themes/bootstrap4' +BOOTSTRAP_THEME = 'litera' + +I18N_TEMPLATES_LANG = 'ru' +I18N_GETTEXT_NEWSTYLE = True +I18N_GETTEXT_LOCALEDIR = 'themes/bootstrap4/translations' +I18N_GETTEXT_DOMAIN = 'messages' +JINJA_ENVIRONMENT = {'extensions': ['jinja2.ext.i18n']} + +PLUGIN_PATHS = ["plugins/official", "plugins/thirdparty"] +PLUGINS = [i18n(), "pelican-css", "pelidoc", "series", "subcategory", "tag_cloud", "tipue_search", "replacer", "asciidoctor"] + +PDF_PROCESSOR = True + +ASCIIDOCTOR_CMD = "asciidoctor" +ASCIIDOCTOR_IMAGES_PATH = '{}/wiki/images'.format(os.getcwd()) +ASCIIDOCTOR_EXTRA_OPTIONS = [ + '--require', 'asciidoctor-diagram', + '--attribute=imagesdir='+ASCIIDOCTOR_IMAGES_PATH, +] + +REPLACES = ( + ('{}/wiki/'.format(os.getcwd()), u''), +) + +YUICOMPRESSOR_EXECUTABLE = "yui-compressor" +YUICOMPRESSOR_EXTRA_OPTIONS = ["--nomunge"] +#PLUGINS += ["yuicompressor-opt"] + +DIRECT_TEMPLATES = ('index', 'categories', 'authors', 'archives', 'search') + +# Blogroll +LINKS = () +# LINKS = (('Pelican', 'http://getpelican.com/'), +# ('Python.org', 'http://python.org/'), +# ('Jinja2', 'http://jinja.pocoo.org/'), +# ('You can modify those links in your config file', '#'),) + +# Social widget +SOCIAL = () +# SOCIAL = (('You can add links in your config file', '#'), +# ('Another social link', '#'),) + +PYGMENTS_STYLE='pastie' + +DEFAULT_PAGINATION = 20 + +# Uncomment following line if you want document-relative URLs when developing +RELATIVE_URLS = True + diff --git a/pelicanconf-f.py b/pelicanconf-f.py new file mode 100644 index 0000000..8f174b7 --- /dev/null +++ b/pelicanconf-f.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- # +from __future__ import unicode_literals +import os + +class i18n(object): + # looks for translations in + # {LOCALE_DIR}/{LANGUAGE}/LC_MESSAGES/{DOMAIN}.mo + # if not present, falls back to default + + DOMAIN = 'messages' + LOCALE_DIR = '{THEME}/translations' + LANGUAGES = ['ru'] + NEWSTYLE = True + + __name__ = 'i18n' + + def register(self): + from pelican.signals import generator_init + generator_init.connect(self.install_translator) + + def install_translator(self, generator): + import gettext + try: + translator = gettext.translation( + self.DOMAIN, + self.LOCALE_DIR.format(THEME=THEME), + self.LANGUAGES) + except (OSError, IOError): + translator = gettext.NullTranslations() + generator.env.install_gettext_translations(translator, self.NEWSTYLE) + +# ABOUT_ME = ' ' +AUTHOR = 'Андрей Астафьев' +SITENAME = 'ДСП' +SITEURL = 'https://dsp.246060.ru' + +PATH = 'wiki' +CACHE_PATH = 'cache-ascii' + +TIMEZONE = 'Europe/Moscow' + +DEFAULT_LANG = 'ru' + +# Generation time +CACHE_CONTENT = True +LOAD_CONTENT_CACHE = True + +# Feed generation is usually not desired when developing +FEED_ALL_ATOM = None +CATEGORY_FEED_ATOM = None +TRANSLATION_FEED_ATOM = None +AUTHOR_FEED_ATOM = None +AUTHOR_FEED_RSS = None +USE_FOLDER_AS_CATEGORY = True +DEFAULT_DATE = 'fs' +STATIC_PATHS = [ 'images', 'files', 'extras' ] + +EXTRA_PATH_METADATA = { + 'extras/favicon.ico': {'path': 'favicon.ico'}, +} + +DISPLAY_CATEGORIES_ON_MENU = False +DISPLAY_CATEGORIES_ON_SIDEBAR = True +DISPLAY_TAGS_ON_SIDEBAR = True + +THEME = 'themes/bootstrap4' +BOOTSTRAP_THEME = 'litera' + +I18N_TEMPLATES_LANG = 'ru' +I18N_GETTEXT_NEWSTYLE = True +I18N_GETTEXT_LOCALEDIR = 'themes/bootstrap4/translations' +I18N_GETTEXT_DOMAIN = 'messages' +JINJA_ENVIRONMENT = {'extensions': ['jinja2.ext.i18n']} + +PLUGIN_PATHS = ["plugins/official", "plugins/thirdparty"] +PLUGINS = [i18n(), "pelican-css", "pelidoc", "series", "subcategory", "tag_cloud", "tipue_search", "replacer", "asciidoctor"] + +PDF_PROCESSOR = True + +ASCIIDOCTOR_CMD = "asciidoctor" +ASCIIDOCTOR_IMAGES_PATH = '{}/wiki/images'.format(os.getcwd()) +ASCIIDOCTOR_EXTRA_OPTIONS = [ + '--require', 'asciidoctor-diagram', + '--attribute=imagesdir='+ASCIIDOCTOR_IMAGES_PATH, +] + +REPLACES = ( + ('{}/wiki/'.format(os.getcwd()), u''), +) + +YUICOMPRESSOR_EXECUTABLE = "yui-compressor" +YUICOMPRESSOR_EXTRA_OPTIONS = ["--nomunge"] +#PLUGINS += ["yuicompressor-opt"] + +DIRECT_TEMPLATES = ('index', 'categories', 'authors', 'archives', 'search') + +# Blogroll +LINKS = () +# LINKS = (('Pelican', 'http://getpelican.com/'), +# ('Python.org', 'http://python.org/'), +# ('Jinja2', 'http://jinja.pocoo.org/'), +# ('You can modify those links in your config file', '#'),) + +# Social widget +SOCIAL = () +# SOCIAL = (('You can add links in your config file', '#'), +# ('Another social link', '#'),) + +PYGMENTS_STYLE='pastie' + +DEFAULT_PAGINATION = 20 + +# Uncomment following line if you want document-relative URLs when developing +RELATIVE_URLS = True + diff --git a/pelicanconf-full.py b/pelicanconf-full.py index 39ff68e..5c7d830 100644 --- a/pelicanconf-full.py +++ b/pelicanconf-full.py @@ -1,6 +1,7 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # from __future__ import unicode_literals +import os class i18n(object): # looks for translations in @@ -35,7 +36,7 @@ SITENAME = 'ДСП' SITEURL = 'https://dsp.246060.ru' PATH = 'wiki' -CACHE_PATH = 'cache-full' +CACHE_PATH = 'cache-ascii' TIMEZONE = 'Europe/Moscow' @@ -54,23 +55,12 @@ AUTHOR_FEED_RSS = None USE_FOLDER_AS_CATEGORY = True DEFAULT_DATE = 'fs' STATIC_PATHS = [ 'images', 'files', 'extras' ] +DIRECT_TEMPLATES = ('index', 'categories', 'authors', 'archives', 'search') EXTRA_PATH_METADATA = { 'extras/favicon.ico': {'path': 'favicon.ico'}, } -MARKDOWN = { - 'extension_configs': { - 'markdown.extensions.codehilite': {'css_class': 'highlight'}, - 'markdown.extensions.extra': {}, - 'markdown.extensions.meta': {}, - 'markdown.extensions.toc': { - 'title': 'Содержание' - }, - } , - 'output_format': 'html5', -} - DISPLAY_CATEGORIES_ON_MENU = False DISPLAY_CATEGORIES_ON_SIDEBAR = True DISPLAY_TAGS_ON_SIDEBAR = True @@ -85,50 +75,30 @@ I18N_GETTEXT_DOMAIN = 'messages' JINJA_ENVIRONMENT = {'extensions': ['jinja2.ext.i18n']} PLUGIN_PATHS = ["plugins/official", "plugins/thirdparty"] -PLUGINS = [i18n(), "pandoc_reader", "pelican-css", "pelidoc", "series", "subcategory", "tag_cloud", "tipue_search", "plantuml", "replacer"] -#PLUGINS = ["better_tables", "just_table"] +PLUGINS = [i18n(), "pelican-css", "pelidoc", "series", "subcategory", "tag_cloud", "tipue_search", "replacer", "asciidoctor"] -PDF_PROCESSOR = True -PANDOC_OUTPUTS = { - 'pdf': 'pdf', -} - -PANDOC_ARGS = [ - "--variable=documentclass:extarticle", - "--variable=toc-title:Содержание", - "--filter=skip-toc-tag", - "--filter=pandoc_plantuml_filter.py", - "--highlight-style=tango", - "--template=wiki", - "--resource-path=wiki:." +ASCIIDOCTOR_CMD = "asciidoctor" +ASCIIDOCTOR_EXTRA_OPTIONS = [ + '--require', 'asciidoctor-diagram', + '--attribute=imagesdir={}/wiki/images'.format(os.getcwd()), + '--attribute=source-highlighter=pygments', + '--attribute=pygments-style=manni', + '--attribute=pygments-css=class', + '--attribute=lang=ru', + '--attribute=figure-caption=Рис.', + '--attribute=experimental', ] -PANDOC_EXTRA_OPTIONS = PANDOC_ARGS + [ "--pdf-engine=xelatex" ] - -PANDOC_MARKDOWN_EXTENSIONS = [ - "+smart", - "+backtick_code_blocks", - "+fenced_code_blocks", - "+fenced_code_attributes", - "+fenced_divs", - "+native_divs", - "+bracketed_spans", - "+native_spans" -] - -PANDOC_EXTENSIONS = PANDOC_MARKDOWN_EXTENSIONS - REPLACES = ( - (u'output/images/', u'images/'), + ('{}/wiki/'.format(os.getcwd()), u''), ) - -YUICOMPRESSOR_EXECUTABLE = "yui-compressor" -YUICOMPRESSOR_EXTRA_OPTIONS = ["--nomunge"] +#YUICOMPRESSOR_EXECUTABLE = "yui-compressor" +#YUICOMPRESSOR_EXTRA_OPTIONS = ["--nomunge"] PLUGINS += ["yuicompressor-opt"] -DIRECT_TEMPLATES = ('index', 'categories', 'authors', 'archives', 'search') +PDF_PROCESSOR = True # Blogroll LINKS = () @@ -142,7 +112,7 @@ SOCIAL = () # SOCIAL = (('You can add links in your config file', '#'), # ('Another social link', '#'),) -PYGMENTS_STYLE='pastie' +PYGMENTS_STYLE='asciidoctor-pastie' DEFAULT_PAGINATION = 20 diff --git a/pelicanconf.py b/pelicanconf.py index a80ac5f..241ad74 100644 --- a/pelicanconf.py +++ b/pelicanconf.py @@ -1,6 +1,7 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # from __future__ import unicode_literals +import os class i18n(object): # looks for translations in @@ -35,7 +36,7 @@ SITENAME = 'ДСП' SITEURL = 'https://dsp.246060.ru' PATH = 'wiki' -CACHE_PATH = 'cache-html' +CACHE_PATH = 'cache-ascii' TIMEZONE = 'Europe/Moscow' @@ -54,23 +55,12 @@ AUTHOR_FEED_RSS = None USE_FOLDER_AS_CATEGORY = True DEFAULT_DATE = 'fs' STATIC_PATHS = [ 'images', 'files', 'extras' ] +DIRECT_TEMPLATES = ('index', 'categories', 'authors', 'archives', 'search') EXTRA_PATH_METADATA = { 'extras/favicon.ico': {'path': 'favicon.ico'}, } -MARKDOWN = { - 'extension_configs': { - 'markdown.extensions.codehilite': {'css_class': 'highlight'}, - 'markdown.extensions.extra': {}, - 'markdown.extensions.meta': {}, - 'markdown.extensions.toc': { - 'title': 'Содержание' - }, - } , - 'output_format': 'html5', -} - DISPLAY_CATEGORIES_ON_MENU = False DISPLAY_CATEGORIES_ON_SIDEBAR = True DISPLAY_TAGS_ON_SIDEBAR = True @@ -85,50 +75,30 @@ I18N_GETTEXT_DOMAIN = 'messages' JINJA_ENVIRONMENT = {'extensions': ['jinja2.ext.i18n']} PLUGIN_PATHS = ["plugins/official", "plugins/thirdparty"] -PLUGINS = [i18n(), "pandoc_reader", "pelican-css", "pelidoc", "series", "subcategory", "tag_cloud", "tipue_search", "plantuml", "replacer"] -#PLUGINS = ["better_tables", "just_table"] +PLUGINS = [i18n(), "pelican-css", "pelidoc", "series", "subcategory", "tag_cloud", "tipue_search", "replacer", "asciidoctor"] -#PDF_PROCESSOR = True -PANDOC_OUTPUTS = { - 'pdf': 'pdf', -} - -PANDOC_ARGS = [ - "--variable=documentclass:extarticle", - "--variable=toc-title:Содержание", - "--filter=skip-toc-tag", - "--filter=pandoc_plantuml_filter.py", - "--highlight-style=tango", - "--template=wiki", - "--resource-path=wiki:." +ASCIIDOCTOR_CMD = "asciidoctor" +ASCIIDOCTOR_EXTRA_OPTIONS = [ + '--require', 'asciidoctor-diagram', + '--attribute=imagesdir={}/wiki/images'.format(os.getcwd()), + '--attribute=source-highlighter=pygments', + '--attribute=pygments-style=manni', + '--attribute=pygments-css=class', + '--attribute=lang=ru', + '--attribute=figure-caption=Рис.', + '--attribute=experimental', ] -PANDOC_EXTRA_OPTIONS = PANDOC_ARGS + [ "--pdf-engine=xelatex" ] - -PANDOC_MARKDOWN_EXTENSIONS = [ - "+smart", - "+backtick_code_blocks", - "+fenced_code_blocks", - "+fenced_code_attributes", - "+fenced_divs", - "+native_divs", - "+bracketed_spans", - "+native_spans" -] - -PANDOC_EXTENSIONS = PANDOC_MARKDOWN_EXTENSIONS - REPLACES = ( - (u'output/images/', u'images/'), + ('{}/wiki/'.format(os.getcwd()), u''), ) - YUICOMPRESSOR_EXECUTABLE = "yui-compressor" YUICOMPRESSOR_EXTRA_OPTIONS = ["--nomunge"] #PLUGINS += ["yuicompressor-opt"] -DIRECT_TEMPLATES = ('index', 'categories', 'authors', 'archives', 'search') +#PDF_PROCESSOR = True # Blogroll LINKS = () @@ -142,7 +112,7 @@ SOCIAL = () # SOCIAL = (('You can add links in your config file', '#'), # ('Another social link', '#'),) -PYGMENTS_STYLE='pastie' +PYGMENTS_STYLE='asciidoctor-pastie' DEFAULT_PAGINATION = 20 diff --git a/plugins/official b/plugins/official index cfc7a3f..8cea2c6 160000 --- a/plugins/official +++ b/plugins/official @@ -1 +1 @@ -Subproject commit cfc7a3f224f1743063b034561f89a6a712d13587 +Subproject commit 8cea2c6492f98e11341c48556978da7f6756f8a0 diff --git a/wiki/Latex/Висячие строки.adoc b/wiki/Latex/Висячие строки.adoc new file mode 100644 index 0000000..c1040f1 --- /dev/null +++ b/wiki/Latex/Висячие строки.adoc @@ -0,0 +1,12 @@ += LaTeX: висячие строки +:category: LaTeX +:tags: LaTeX, текст, + + +Пакет https://www.ctan.org/pkg/nowidow[`nowidow`] используется для +изменения алгоритма размещения висячих строк. Пример: + +[source,latex] +---- +\usepackage[defaultlines=3,all]{nowidow} +---- diff --git a/wiki/Latex/Висячие строки.md b/wiki/Latex/Висячие строки.md deleted file mode 100644 index 040115e..0000000 --- a/wiki/Latex/Висячие строки.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "LaTeX: висячие строки" -category: LaTeX -tags: LaTeX, текст, -summary: -... - -Пакет [`nowidow`](https://www.ctan.org/pkg/nowidow) используется для -изменения алгоритма размещения висячих строк. Пример: - -```latex -\usepackage[defaultlines=3,all]{nowidow} -``` - diff --git a/wiki/Latex/ЕСПД в LyX.adoc b/wiki/Latex/ЕСПД в LyX.adoc new file mode 100644 index 0000000..b1f28a0 --- /dev/null +++ b/wiki/Latex/ЕСПД в LyX.adoc @@ -0,0 +1,87 @@ += LyX: редактирование ЕСПД +:category: LaTeX +:tags: LaTeX, текст, LyX, + + +Установить пакеты: + +[source,sh] +---- +sudo apt-get install lyx texlive-xetex +---- + +Установить стили LaTeX для ЕСПД: + +[source,sh] +---- +git clone https://git.246060.ru/f1x1t/latex-style-esdpx ~/texmf/tex/latex/espdx +---- + +Установить шаблоны для LyX: + +[source,sh] +---- +git clone https://git.246060.ru:/f1x1t/lyx-layout-espdx.git ~/.lyx/layouts +---- + +Запустить LyX и в меню выбрать menu:Инструменты[Обновить конфигурацию] и +перезапустить программу. + +Скачать link:files/espdx-template.lyx[шаблон] для LyX, открыть файл +*espdx-template.lyx* и в меню выбрать menu:Документ[Настройки…]. +В появившемся окне нажать кнопку btn:[Сохранить как параметры +документа по умолчанию]. + +Пример настройки: + +.Класс документа +image::lyx-espdx/01.png[Класс документа] + +.Модули +image::lyx-espdx/02.png[Модули] + +.Шрифты +image::lyx-espdx/03.png[Шрифты] + +.Макет текста +image::lyx-espdx/04.png[Макет текста] + +.Макет страницы +image::lyx-espdx/05.png[Макет страницы] + +.Поля страницы +image::lyx-espdx/06.png[Поля страницы] + +.Язык +image::lyx-espdx/07.png[Язык] + +.Нумерация и содержание +image::lyx-espdx/08.png[Нумерация и содержание] + +.Библиография +image::lyx-espdx/09.png[Библиография] + +.Предметный указатель +image::lyx-espdx/10.png[Предметный указатель] + +.Свойства PDF / Общие +image::lyx-espdx/11.png[Свойства PDF / Общие] + +.Свойства PDF / Гиперссылки +image::lyx-espdx/12.png[Свойства PDF / Гиперссылки] + +.Свойства PDF / Закладки +image::lyx-espdx/13.png[Свойства PDF / Закладки] + +.Параметры математики +image::lyx-espdx/14.png[Параметры математики] + +.Размещение плавающих объектов +image::lyx-espdx/15.png[Размещение плавающих объектов] + +.Форматы +image::lyx-espdx/16.png[Форматы] + +.Преамбула LaTeX +image::lyx-espdx/17.png[Преамбула LaTeX] + diff --git a/wiki/Latex/ЕСПД в LyX.md b/wiki/Latex/ЕСПД в LyX.md deleted file mode 100644 index 43dee5a..0000000 --- a/wiki/Latex/ЕСПД в LyX.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: "LyX: редактирование ЕСПД" -category: LaTeX -tags: LaTeX, текст, LyX, -summary: -... - - -Установить пакеты: - -```sh -sudo apt-get install lyx texlive-xetex -``` - -Установить стили LaTeX для ЕСПД: - -``` -git clone https://git.246060.ru/f1x1t/latex-style-esdpx ~/texmf/tex/latex/espdx -``` - -Установить шаблоны для LyX: - -``` -git clone https://git.246060.ru:/f1x1t/lyx-layout-espdx.git ~/.lyx/layouts -``` - -Запустить LyX и в меню __Инструменты__ выбрать __Обновить конфигурацию__ -и перезапустить программу. - -Скачать [шаблон](files/espdx-template.lyx) для LyX, открыть файл -**espdx-template.lyx** и в меню выбрать __Документ / Настройки...__. -В появившемся окне нажать кнопку __Сохранить как параметры документа по умолчанию__. - -Пример настройки: - -![Класс документа](images/lyx-espdx/01.png) - -![Модули](images/lyx-espdx/02.png) - -![Шрифты](images/lyx-espdx/03.png) - -![Макет текста](images/lyx-espdx/04.png) - -![Макет страницы](images/lyx-espdx/05.png) - -![Поля страницы](images/lyx-espdx/06.png) - -![Язык](images/lyx-espdx/07.png) - -![Нумерация и содержание](images/lyx-espdx/08.png) - -![Библиография](images/lyx-espdx/09.png) - -![Предметный указатель](images/lyx-espdx/10.png) - -![Свойства PDF / Общие](images/lyx-espdx/11.png) - -![Свойства PDF / Гиперссылки](images/lyx-espdx/12.png) - -![Свойства PDF / Закладки](images/lyx-espdx/13.png) - -![Параметры математики](images/lyx-espdx/14.png) - -![Размещение плавающих объектов](images/lyx-espdx/15.png) - -![Форматы](images/lyx-espdx/16.png) - -![Преамбула LaTeX](images/lyx-espdx/17.png) - diff --git a/wiki/Latex/Защита команд.adoc b/wiki/Latex/Защита команд.adoc new file mode 100644 index 0000000..d0bb628 --- /dev/null +++ b/wiki/Latex/Защита команд.adoc @@ -0,0 +1,12 @@ += LaTeX: защита команд +:category: LaTeX +:tags: LaTeX, текст, + +Команда `\protect` используется для защиты инструкций внутри хрупких +команд. Например, для защиты команды переноса строки внутри команды +`section` нужно написать: + +[source,latex] +---- +\section{Первая строка\protect\\Вторая строка} +---- diff --git a/wiki/Latex/Защита команд.md b/wiki/Latex/Защита команд.md deleted file mode 100644 index e90c7d5..0000000 --- a/wiki/Latex/Защита команд.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: "LaTeX: защита команд" -category: LaTeX -tags: LaTeX, текст, -summary: -... - -Команда `\protect` используется для защиты инструкций внутри -хрупких команд. Например, для защиты команды переноса строки -внутри команды `section` нужно написать: - -```latex -\section{Первая строка\protect\\Вторая строка} -``` - diff --git a/wiki/Latex/Лигатуры.md b/wiki/Latex/Лигатуры.adoc similarity index 58% rename from wiki/Latex/Лигатуры.md rename to wiki/Latex/Лигатуры.adoc index d9562f6..5a1aeec 100644 --- a/wiki/Latex/Лигатуры.md +++ b/wiki/Latex/Лигатуры.adoc @@ -1,14 +1,11 @@ ---- -title: "LaTeX: лигатуры" -category: LaTeX -tags: LaTeX, шрифты, -summary: -... += LaTeX: лигатуры +:category: LaTeX +:tags: LaTeX, шрифты, Команды для запрета использования лигатур: -```latex +[source,latex] +---- \usepackage{microtype} \DisableLigatures[f]{encoding = *, family = *} -``` - +---- diff --git a/wiki/Latex/Многостраничные таблицы в LyX.adoc b/wiki/Latex/Многостраничные таблицы в LyX.adoc new file mode 100644 index 0000000..7e9e65a --- /dev/null +++ b/wiki/Latex/Многостраничные таблицы в LyX.adoc @@ -0,0 +1,28 @@ += LyX: многостраничные таблицы +:category: LaTeX +:tags: LaTeX, текст, LyX, таблицы, + +* Создать таблицу как минимум с четырьмя строками. +* Щелкнуть правой кнопкой мыши на таблице, выбрать во всплывающем меню +*Длинная таблица*. +* Щелкнуть правой кнопкой мыши на таблице, выбрать во всплывающем меню +*Настройки*. +* Установить курсор на первой строке таблицы, в окне настроек перейти на +вкладку *Длинная таблица*. +* Выбрать *Подпись* и *Первый заголовок*. +* Нажать *Применить*. +* Установить курсор на второй строке таблицы, в окне настроек перейти на +вкладку *Длинная таблица*. +* Выбрать *Подпись* и *Заголовок*. +* Нажать *Применить*. +* Установить курсор на третьей строке таблицы, в окне настроек перейти +на вкладку *Длинная таблица*. +* Выбрать *Заголовок* и *Первый заколовок*. +* Нажать *Применить*. +* Щелкнуть правой кнопкой мыши на второй строке таблицы, выбрать в меню +*Подпись (Ненумерованный)*. +* На первой строке таблицы установить метку и ввести текст подписи к +таблице на начальной странице. +* На второй строке таблицы сформировать текст подписи к таблице, который +будет использоваться на последующих страницах. +* На третьей строке нужно сформировать заголовок таблицы. diff --git a/wiki/Latex/Многостраничные таблицы в LyX.md b/wiki/Latex/Многостраничные таблицы в LyX.md deleted file mode 100644 index 033f385..0000000 --- a/wiki/Latex/Многостраничные таблицы в LyX.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "LyX: многостраничные таблицы" -category: LaTeX -tags: LaTeX, текст, LyX, таблицы, -summary: -... - -- Создать таблицу как минимум с четырьмя строками. -- Щелкнуть правой кнопкой мыши на таблице, выбрать во всплывающем -меню **Длинная таблица**. -- Щелкнуть правой кнопкой мыши на таблице, выбрать во всплывающем -меню **Настройки**. -- Установить курсор на первой строке таблицы, в окне настроек перейти -на вкладку **Длинная таблица**. -- Выбрать **Подпись** и **Первый заголовок**. -- Нажать **Применить**. -- Установить курсор на второй строке таблицы, в окне настроек перейти -на вкладку **Длинная таблица**. -- Выбрать **Подпись** и **Заголовок**. -- Нажать **Применить**. -- Установить курсор на третьей строке таблицы, в окне настроек перейти -на вкладку **Длинная таблица**. -- Выбрать **Заголовок** и **Первый заколовок**. -- Нажать **Применить**. -- Щелкнуть правой кнопкой мыши на второй строке таблицы, выбрать в меню -**Подпись (Ненумерованный)**. -- На первой строке таблицы установить метку и ввести текст подписи к -таблице на начальной странице. -- На второй строке таблицы сформировать текст подписи к таблице, -который будет использоваться на последующих страницах. -- На третьей строке нужно сформировать заголовок таблицы. - diff --git a/wiki/Latex/Переносы.adoc b/wiki/Latex/Переносы.adoc new file mode 100644 index 0000000..f145671 --- /dev/null +++ b/wiki/Latex/Переносы.adoc @@ -0,0 +1,7 @@ += LaTeX: переносы строк +:category: LaTeX +:tags: LaTeX, текст, + +Текст между командами `\sloppy` и `\fussy` или внутри блока +`\begin{sloppypar} ... \end{sloppypar}` будет переноситься сразу при +достижении края бокса. diff --git a/wiki/Latex/Переносы.md b/wiki/Latex/Переносы.md deleted file mode 100644 index 0a96ff5..0000000 --- a/wiki/Latex/Переносы.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: "LaTeX: переносы строк" -category: LaTeX -tags: LaTeX, текст, -summary: -... - -Текст между командами `\sloppy` и `\fussy` или внутри блока -`\begin{sloppypar} ... \end{sloppypar}` будет переноситься -сразу при достижении края бокса. - diff --git a/wiki/Latex/Русский в PDF.adoc b/wiki/Latex/Русский в PDF.adoc new file mode 100644 index 0000000..0a545c7 --- /dev/null +++ b/wiki/Latex/Русский в PDF.adoc @@ -0,0 +1,19 @@ += LaTeX: русский язык в выходном PDF +:category: LaTeX +:tags: LaTeX, текст, PDF, + +Данный метод используется только в LaTeX, в XeTeX (XeLaTeX) генерация +PDF работает изначально. + +Для поиска в файле PDF и копирования текста с правильной кодировкой +нужно использовать пакет https://www.ctan.org/pkg/cmap[`cmap`]. Включать +использование пакета нужно как можно раньше, чтобы правильно +формировалась служебная информация и титульные листы. + +[source,latex] +---- +\usepackage{cmap} +---- + +Полезная http://s.arboreus.com/2007/07/pdf-latex.html[информация] о +выводе из LaTeX в PDF. diff --git a/wiki/Latex/Русский в PDF.md b/wiki/Latex/Русский в PDF.md deleted file mode 100644 index 66b7b18..0000000 --- a/wiki/Latex/Русский в PDF.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: "LaTeX: русский язык в выходном PDF" -category: LaTeX -tags: LaTeX, текст, PDF, -summary: -... - -Данный метод используется только в LaTeX, в XeTeX (XeLaTeX) генерация PDF -работает изначально. - -Для поиска в файле PDF и копирования текста с правильной кодировкой -нужно использовать пакет [`cmap`](https://www.ctan.org/pkg/cmap). -Включать использование пакета нужно как можно раньше, чтобы правильно -формировалась служебная информация и титульные листы. - -```latex -\usepackage{cmap} -``` - -Полезная [информация](http://s.arboreus.com/2007/07/pdf-latex.html) -о выводе из LaTeX в PDF. - diff --git a/wiki/Linux/Astra/Авторизация в PostgreSQL.md b/wiki/Linux/Astra/Авторизация в PostgreSQL.adoc similarity index 55% rename from wiki/Linux/Astra/Авторизация в PostgreSQL.md rename to wiki/Linux/Astra/Авторизация в PostgreSQL.adoc index e23006c..d2b60de 100644 --- a/wiki/Linux/Astra/Авторизация в PostgreSQL.md +++ b/wiki/Linux/Astra/Авторизация в PostgreSQL.adoc @@ -1,26 +1,25 @@ ---- -title: "Astra: авторизация в PostgreSQL через PAM" -category: Linux -tags: Linux, Astra, postgresql, базы данных, -summary: -... += Astra: авторизация в PostgreSQL через PAM +:category: Linux +:tags: Linux, Astra, postgresql, базы данных, + Для обеспечения авторизации пользователей через PAM системному -пользователю `postgres`, с правами которого выполняется сервер -базы данных, необходимо выдать права на чтение информации из базы -данных пользователей и сведений о мандатных метках и привилегиях: +пользователю `postgres`, с правами которого выполняется сервер базы +данных, необходимо выдать права на чтение информации из базы данных +пользователей и сведений о мандатных метках и привилегиях: -```sh +[source,sh] +---- usermod -a -G shadow postgres setfacl -d -m u:postgres:r /etc/parsec/macdb setfacl -R -m u:postgres:r /etc/parsec/macdb setfacl -m u:postgres:rx /etc/parsec/macdb -``` +---- Для обеспечения возможности авторизации пользователя `user`, зарегистрированного в системе PAM, нужно выполнить команду -```sh +[source,sh] +---- usermac -c 0:0 -l 0:0 user -``` - +---- diff --git a/wiki/Linux/CUPS.md b/wiki/Linux/CUPS.adoc similarity index 62% rename from wiki/Linux/CUPS.md rename to wiki/Linux/CUPS.adoc index eac88af..eb186f1 100644 --- a/wiki/Linux/CUPS.md +++ b/wiki/Linux/CUPS.adoc @@ -1,42 +1,45 @@ ---- -title: "CUPS: команды" -category: Linux -tags: Linux, печать, CUPS -... += CUPS: команды +:category: Linux +:tags: Linux, печать, CUPS, -Текущее состояние принтера (см. также [lpstat](http://cheat.sh/lpstat)): +Текущее состояние принтера (см. также http://cheat.sh/lpstat[lpstat]): -```sh +[source,sh] +---- lpstat -h hostname -p printer_name -``` +---- Возобновить работу принтера: -```sh +[source,sh] +---- lpadmin -h hostname -p printer_name -E -``` +---- -Печать (см. также [lp](http://cheat.sh/lp)): +Печать (см. также http://cheat.sh/lp[lp]): -```sh +[source,sh] +---- lp -h hostname -d printer_name file.pdf -``` +---- Просмотр очереди: -```sh +[source,sh] +---- lpq -h hostname -p printer_name -``` +---- Удаление задания job-id из очереди: -```sh +[source,sh] +---- lprm -h hostname -p printer_name job-id -``` +---- Удаление всех заданий из очереди: -```sh +[source,sh] +---- lprm -h hostname -p printer_name - -``` - +---- diff --git a/wiki/Linux/DPKG/APT.md b/wiki/Linux/DPKG/APT.adoc similarity index 63% rename from wiki/Linux/DPKG/APT.md rename to wiki/Linux/DPKG/APT.adoc index f86fce3..cb90454 100644 --- a/wiki/Linux/DPKG/APT.md +++ b/wiki/Linux/DPKG/APT.adoc @@ -1,12 +1,10 @@ ---- -title: "APT" -category: Linux -tags: linux, ubuntu, debian, apt, -summary: -... += APT +:category: Linux +:tags: linux, ubuntu, debian, apt, Запрет загрузки переводов описаний пакетов: -```sh +[source,sh] +---- echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/99translations -``` +---- diff --git a/wiki/Linux/GnuPG/Шифрование файлов с помощью GnuPG.md b/wiki/Linux/GnuPG/Шифрование файлов с помощью GnuPG.adoc similarity index 52% rename from wiki/Linux/GnuPG/Шифрование файлов с помощью GnuPG.md rename to wiki/Linux/GnuPG/Шифрование файлов с помощью GnuPG.adoc index 6cc3ed2..cada6d4 100644 --- a/wiki/Linux/GnuPG/Шифрование файлов с помощью GnuPG.md +++ b/wiki/Linux/GnuPG/Шифрование файлов с помощью GnuPG.adoc @@ -1,32 +1,35 @@ ---- -title: "GnuPG: шифрование файлов" -category: Linux -tags: Linux, GnuPG, безопасность -... += GnuPG: шифрование файлов +:category: Linux +:tags: Linux, GnuPG, безопасность -Для шифрования файлов с использованием публичного ключа адресата можно выполнить команду: +Для шифрования файлов с использованием публичного ключа адресата можно +выполнить команду: -```sh +[source,sh] +---- tar cp files_list | pv | gpg -e --recipient user@domain.tld > archive.tar.gpg -``` +---- -По умолчанию во время шифрования данные сжимаются компрессорами `zip` или `gzip`, -поэтому сжимать данные до `gpg` не нужно. Можно отключить стандартный алгоритм сжатия и -использовать собственный компрессор, например `xz`: +По умолчанию во время шифрования данные сжимаются компрессорами `zip` +или `gzip`, поэтому сжимать данные до `gpg` не нужно. Можно отключить +стандартный алгоритм сжатия и использовать собственный компрессор, +например `xz`: -```sh +[source,sh] +---- tar cp files_list | pv | xz -9 | gpg -e --compress-algo none --recipient user@domain.tld > archive.tar.xz.gpg -``` +---- Для шифрования с использованием пароля: -```sh +[source,sh] +---- tar cf files_list | pv | gpg -c > archive.tar.gpg -``` +---- Для расшифровки нужно выполнить команду: -```sh +[source,sh] +---- gpg -d archive.tar.gpg --output archive.tar -``` - +---- diff --git a/wiki/Linux/Hardware/GPE.adoc b/wiki/Linux/Hardware/GPE.adoc new file mode 100644 index 0000000..ccef71e --- /dev/null +++ b/wiki/Linux/Hardware/GPE.adoc @@ -0,0 +1,28 @@ += Прерывания GPE +:category: Linux +:tags: Linux, hardware, железо, + +Неисправная аппаратура может генерировать большое количество прерываний, +что приводит к заметному ухудшению отзывчивости системы. Проверить +наличие подобной ситуации можно командой + +[source,sh] +---- +find /sys/firmware/acpi/interrupts | sort | while read i; do echo "$i:"; cat $i; done +---- + +Если в выводе будет присутствовать очень большое число, то значит +проявляется именно данная проблема. Для временного исправления можно +заблокировать прерывание, выполнив команду + +[source,sh] +---- +echo 0 > /sys/firmware/acpi/interrupts/gpeXX 2>/dev/null +---- + +где XX номер прерывания, для которого зафиксировано большое число +срабатываний. Для полного исправления проблемы нужно разбираться с +аппаратурой. + +https://unix.stackexchange.com/questions/242013/disable-gpe-acpi-interrupts-on-boot[См. +также] diff --git a/wiki/Linux/Hardware/GPE.md b/wiki/Linux/Hardware/GPE.md deleted file mode 100644 index 7883866..0000000 --- a/wiki/Linux/Hardware/GPE.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Прерывания GPE" -category: Linux -tags: Linux, hardware, железо, -summary: -... - -Неисправная аппаратура может генерировать большое количество прерываний, -что приводит к заметному ухудшению отзывчивости системы. Проверить -наличие подобной ситуации можно командой - -```sh -find /sys/firmware/acpi/interrupts | sort | while read i; do echo "$i:"; cat $i; done -``` - -Если в выводе будет присутствовать очень большое число, то значит проявляется -именно данная проблема. Для временного исправления можно заблокировать прерывание, -выполнив команду - -```sh -echo 0 > /sys/firmware/acpi/interrupts/gpeXX 2>/dev/null -``` - -где XX номер прерывания, для которого зафиксировано большое число срабатываний. -Для полного исправления проблемы нужно разбираться с аппаратурой. - -[См. также](https://unix.stackexchange.com/questions/242013/disable-gpe-acpi-interrupts-on-boot) - diff --git a/wiki/Linux/LXC/DNS в контейнере LXC.adoc b/wiki/Linux/LXC/DNS в контейнере LXC.adoc new file mode 100644 index 0000000..cc90934 --- /dev/null +++ b/wiki/Linux/LXC/DNS в контейнере LXC.adoc @@ -0,0 +1,15 @@ += DNS в контейнере LXC +:category: Linux +:tags: lxc, контейнеры, ubuntu, linux, dns, + +В системе Ubuntu 18.04 работающей внутри контейнера LXC по умолчанию не +работает разрешение имён. Чтобы использовать DNS-сервер `8.8.8.8`, нужно +внутри контейнера выполнить команды: + +[source,sh] +---- +sed -i 's/#DNS=/DNS=8.8.8.8/' /etc/systemd/resolved.conf +systemctl restart systemd-resolved +rm /etc/resolv.conf +ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf +---- diff --git a/wiki/Linux/LXC/DNS в контейнере LXC.md b/wiki/Linux/LXC/DNS в контейнере LXC.md deleted file mode 100644 index 8bbe329..0000000 --- a/wiki/Linux/LXC/DNS в контейнере LXC.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: "DNS в контейнере LXC" -category: Linux -tags: lxc, контейнеры, ubuntu, linux, dns, -summary: -... - -В системе Ubuntu 18.04 работающей внутри контейнера LXC по умолчанию -не работает разрешение имён. Чтобы использовать DNS-сервер `8.8.8.8`, -нужно внутри контейнера выполнить команды: - -```sh -sed -i 's/#DNS=/DNS=8.8.8.8/' /etc/systemd/resolved.conf -systemctl restart systemd-resolved -rm /etc/resolv.conf -ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf -``` diff --git a/wiki/Linux/Runit/runit.md b/wiki/Linux/Runit/runit.adoc similarity index 64% rename from wiki/Linux/Runit/runit.md rename to wiki/Linux/Runit/runit.adoc index 31ff5aa..6357747 100644 --- a/wiki/Linux/Runit/runit.md +++ b/wiki/Linux/Runit/runit.adoc @@ -1,28 +1,27 @@ ---- -title: "runit: система инициализации" -category: Linux -tags: Debian, Ubuntu, Linux, инициализация, runit, -summary: -... += runit: система инициализации +:category: Linux +:tags: Debian, Ubuntu, Linux, инициализация, runit, -### Установка +== Установка -[runit](http://smarden.org/runit/) — это система инициализации со +http://smarden.org/runit/[runit] — это система инициализации со встроенными средствами контроля за процессами. Установка в Ubuntu: -```sh +[source,sh] +---- sudo apt-get install runit runit-systemd -``` +---- -### Запуск сервисов от непривилегированного пользователя +== Запуск сервисов от непривилегированного пользователя Чтобы разрешить непривилегированному пользователю `user` управлять собственной конфигурацией для runit, нужно с правами суперпользователя выполнить: -```sh +[source,sh] +---- mkdir -p /etc/service/run-user/supervise cat > /etc/service/run-user/run << EOF #!/bin/sh @@ -31,17 +30,18 @@ exec 2>&1 exec chpst -u user runsvdir /home/user/sv EOF chmod +x /etc/service/run-user/run -``` +---- В результате в каталоге `/home/user/sv` пользователь `user` сможет создавать собственные правила управления сервисами. -### Пример сервиса +== Пример сервиса Для запуска сервера Redis пользователем `user` нужно создать файл конфигурации `/home/user/redis/etc/redis.conf`: -``` +[source,text] +---- daemonize no port 5079 tcp-backlog 128 @@ -56,33 +56,36 @@ client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 4mb 1mb 60 client-output-buffer-limit pubsub 4mb 1mb 60 maxclients 50 -``` +---- -Запускаемый сервер должен запускаться не в фоновом режиме, чтобы -runit мог контролировать его состояние. +Запускаемый сервер должен запускаться не в фоновом режиме, чтобы `runit` +мог контролировать его состояние. -Скрипт `/home/user/sv/redis/run`, который `runit` использует для -запуска процесса: +Скрипт `/home/user/sv/redis/run`, который `runit` использует для запуска +процесса: -```sh -#!/bin/sh +[source,sh] +---- +#!/bin/sh -e WORKDIR=/home/user/redis cd "${WORKDIR}" || exit 1 exec 2>&1 exec redis-server etc/redis.conf -``` +---- -Журналирование выполняется с помощью входящей в состав пакета -runit программы `svlogd`. Скрипт для его запуска должен находиться -в подкаталоге `log` (`/home/user/sv/redis/log/run`): +Журналирование выполняется с помощью входящей в состав пакета runit +программы `svlogd`. Скрипт для его запуска должен находиться в +подкаталоге `log` (`/home/user/sv/redis/log/run`): -```sh +[source,sh] +---- #!/bin/sh -e LOGDIR=/home/user/redis/log mkdir -p "${LOGDIR}" exec svlogd -tt "${LOGDIR}"" -``` +---- + diff --git a/wiki/Linux/System/Сервер NTP в локальной сети.md b/wiki/Linux/System/Сервер NTP в локальной сети.adoc similarity index 63% rename from wiki/Linux/System/Сервер NTP в локальной сети.md rename to wiki/Linux/System/Сервер NTP в локальной сети.adoc index 5ecaa31..d4f9c9f 100644 --- a/wiki/Linux/System/Сервер NTP в локальной сети.md +++ b/wiki/Linux/System/Сервер NTP в локальной сети.adoc @@ -1,16 +1,14 @@ ---- -title: "Сервер времени NTP в локальной сети" -category: Linux -tags: Linux, NTP, время, -summary: -... += Сервер времени NTP в локальной сети +:category: Linux +:tags: Linux, NTP, время, Если в локальной сети необходимо синхронизировать время, не имея -авторитетного источника времени, то можно использовать локальные -часы сервера в качестве базовых. В этом случае файл настройки -`/etc/ntp.conf` на сервере `192.168.0.1` будет выглядеть так: +авторитетного источника времени, то можно использовать локальные часы +сервера в качестве базовых. В этом случае файл настройки `/etc/ntp.conf` +на сервере `192.168.0.1` будет выглядеть так: -``` +[source,text] +---- driftfile /var/lib/ntp/ntp.drift logfile /var/log/ntp.log tinker panic 0 @@ -19,11 +17,12 @@ server 127.127.1.0 minpoll 4 maxpoll 7 fudge 127.127.1.0 stratum 8 restrict 192.168.0.0 mask 255.255.255.0 restrict default nomodify notrap -``` +---- Файл `/etc/ntp.conf` на клиенте из подсети `192.168.0.0/24` имеет вид: -``` +[source,text] +---- driftfile /var/lib/ntp/ntp.drift logfile /var/log/ntp.log tinker panic 0 @@ -32,5 +31,4 @@ server 127.127.1.0 minpoll 4 maxpoll 7 fudge 127.127.1.0 stratum 12 server 192.168.0.1 minpoll 4 maxpoll 7 iburst restrict default nomodify nopeer -``` - +---- diff --git a/wiki/Linux/Xorg/Терминал Rxvt-Unicode.md b/wiki/Linux/Xorg/Терминал Rxvt-Unicode.adoc similarity index 89% rename from wiki/Linux/Xorg/Терминал Rxvt-Unicode.md rename to wiki/Linux/Xorg/Терминал Rxvt-Unicode.adoc index b2589d4..3b95907 100644 --- a/wiki/Linux/Xorg/Терминал Rxvt-Unicode.md +++ b/wiki/Linux/Xorg/Терминал Rxvt-Unicode.adoc @@ -1,20 +1,19 @@ ---- -title: "Терминал rxvt-unicode" -category: Linux -tags: Linux, Xorg, rxvt, терминал, -summary: -... += Терминал rxvt-unicode +:category: Linux +:tags: Linux, Xorg, rxvt, терминал, Скачать скрипт для динамического изменения размера шрифта -```sh +[source,sh] +---- curl -fLo $HOME/.urxvt/ext/font-size --create-dirs \ https://raw.githubusercontent.com/majutsushi/urxvt-font-size/master/font-size -``` +---- Добавить в файл `$HOME/.Xresources`: -``` +[source,text] +---- URxvt.background: White URxvt.foreground: Black URxvt.saveLines: 8192 @@ -40,5 +39,5 @@ URxvt.keysym.C-S-KP_Subtract: perl:font-size:decglobal ! Запрет печати URxvt.print-pipe: "cat > /dev/null" -``` +---- diff --git a/wiki/Linux/Ссылки.adoc b/wiki/Linux/Ссылки.adoc new file mode 100644 index 0000000..84f9ae1 --- /dev/null +++ b/wiki/Linux/Ссылки.adoc @@ -0,0 +1,8 @@ += Linux: полезные ссылки +:category: Linux +:tags: Linux, ссылки, + +* https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html[Параметры +загрузки ядра] +* http://cheat.sh/[Примеры команд] +* https://m.opennet.ru/[Новости] diff --git a/wiki/Linux/Ссылки.md b/wiki/Linux/Ссылки.md deleted file mode 100644 index 8d31290..0000000 --- a/wiki/Linux/Ссылки.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: "Linux: полезные ссылки" -category: Linux -tags: Linux, ссылки, -... - -* [Параметры загрузки ядра](https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html) -* [Примеры команд](http://cheat.sh/) -* [Новости](https://m.opennet.ru/) - diff --git a/wiki/Misc/Libgen.adoc b/wiki/Misc/Libgen.adoc new file mode 100644 index 0000000..c6a2196 --- /dev/null +++ b/wiki/Misc/Libgen.adoc @@ -0,0 +1,31 @@ += Libgen: локальная база данных для Windows +:category: Windows +:tags: windows, libgen, библиотеки, книги, + +Программа http://libruslib.ucoz.com/index/libgen_bibliotekar/0-5[LibGen +- Библиотекарь] позволяет просматривать локальную копию базы данных +сервера http://libgen.io/[Libgen]. Архив базы данных можно скачать +http://gen.lib.rus.ec/dbdumps/[здесь]. В архиве базы с именем вида +`libgen_YYYY-MM-DD.rar` содержится полная информация для полнотекстового +поиска по описаниям книг, а в архиве с именем вида +`libgen-compact_YYYY-MM-DD.rar` описания удалены. + +Для обработки полного архива потребуется около 30 ГБ свободного +пространства. Последовательность действий: + +[arabic] +* https://yadi.sk/d/j_ToPE7D3SHGN6[Скачать] и распаковать программу +Libgen. +* Скачать архив базы данных, распаковать его в каталог `upload` и +переименовать SQL-скрипт в `backup_ba.sql`. +* https://yadi.sk/d/psnuXFJM3SHGR8[Скачать] архив со скриптами для +преобразования базы данных и распаковать его в каталог `upload`. +* Запустить программу `libgen.exe`. +* Выбрать в меню menu:Databases[Update book database]. +* Перечень настроек должен быть таким: +** [ ] Download from the Internet +** [ ] Unpack +** [x] Prepare for import to the database +* Нажать кнопку btn:[Start]. +* После завершения работы нажать кнопку btn:[Done]. +* Удалить из каталога `upload` файл `backup_ba1.sql`. diff --git a/wiki/Misc/Libgen.md b/wiki/Misc/Libgen.md deleted file mode 100644 index 65402b2..0000000 --- a/wiki/Misc/Libgen.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "Libgen: локальная база данных для Windows" -category: Windows -tags: windows, libgen, библиотеки, книги, -summary: -... - -Программа [LibGen - Библиотекарь](http://libruslib.ucoz.com/index/libgen_bibliotekar/0-5) -позволяет просматривать локальную копию базы данных сервера [Libgen](http://libgen.io/). -Архив базы данных можно скачать [здесь](http://gen.lib.rus.ec/dbdumps/). -В архиве базы с именем вида `libgen_YYYY-MM-DD.rar` содержится полная информация -для полнотекстового поиска по описаниям книг, а в архиве с именем вида -`libgen-compact_YYYY-MM-DD.rar` описания удалены. - -Для обработки полного архива потребуется около 25 Гб свободного пространства. -Последовательность действий: - -1. [Скачать](https://yadi.sk/d/j_ToPE7D3SHGN6) и распаковать программу Libgen. -2. Скачать архив базы данных, распаковать его в каталог `upload` -и переименовать SQL-скрипт в `backup_ba.sql`. -3. [Скачать](https://yadi.sk/d/psnuXFJM3SHGR8) архив со скриптами для преобразования -базы данных и распаковать его в каталог `upload`. -4. Запустить программу `libgen.exe`. -5. Выбрать в меню **Databases | Update book database**. -6. Убрать галочки **Download from the Internet** и **Unpack** и поставить -**Prepare for import to the database**. -7. Нажать кнопку **Start**. -8. После завершения работы нажать кнопку **Done**. -9. Удалить из каталога `upload` файл `backup_ba1.sql`. - diff --git a/wiki/Misc/Windows/OOShutUp.adoc b/wiki/Misc/Windows/OOShutUp.adoc new file mode 100644 index 0000000..944717f --- /dev/null +++ b/wiki/Misc/Windows/OOShutUp.adoc @@ -0,0 +1,22 @@ += Настройка Windows в O&O ShutUp10 +:category: Misc +:tags: Windows, настройка, программы, + +Программа https://www.oo-software.com/en/shutup10[O&O ShutUp10] +используется для быстрой настроки большого количества параметров +Windows{nbsp}10. Пример приведён ниже: + +.Экран 1 +image::oo-shutup/1.jpg[1] + +.Экран 2 +image::oo-shutup/2.jpg[2] + +.Экран 3 +image::oo-shutup/3.jpg[3] + +.Экран 4 +image::oo-shutup/4.jpg[4] + +.Экран 5 +image::oo-shutup/5.jpg[5] diff --git a/wiki/Misc/Windows/OOShutUp.md b/wiki/Misc/Windows/OOShutUp.md deleted file mode 100644 index a83690f..0000000 --- a/wiki/Misc/Windows/OOShutUp.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: "Настройка Windows в O&O ShutUp10" -category: Misc -tags: Windows, настройка, программы, -summary: -... - -Программа [O&O ShutUp10](https://www.oo-software.com/en/shutup10) -используется для быстрой настроки большого количества параметров Windows 10. -Пример приведён ниже: - -![1](images/oo-shutup/1.jpg) - -![2](images/oo-shutup/2.jpg) - -![3](images/oo-shutup/3.jpg) - -![4](images/oo-shutup/4.jpg) - -![5](images/oo-shutup/5.jpg) - - diff --git a/wiki/Prog/Development/CMake управление проектом.md b/wiki/Prog/Development/CMake управление проектом.adoc similarity index 64% rename from wiki/Prog/Development/CMake управление проектом.md rename to wiki/Prog/Development/CMake управление проектом.adoc index 8913ac5..594aa78 100644 --- a/wiki/Prog/Development/CMake управление проектом.md +++ b/wiki/Prog/Development/CMake управление проектом.adoc @@ -1,38 +1,20 @@ ---- -title: "CMake: управление проектом" -category: Программирование -tags: программирование, cmake, -summary: -toc: yes -monofontoptions: -- Scale=0.6 -... += CMake: управление проектом +:category: Программирование +:tags: программирование, cmake, - +:toc: -[TOC] +== Полезные ссылки +* https://github.com/onqtam/awesome-cmake[Каталог ссылок] +* https://cgold.readthedocs.io/en/latest/index.html[CGold: The +Hitchhiker’s Guide to the CMake] -### Полезные ссылки - -* [Каталог ссылок](https://github.com/onqtam/awesome-cmake) -* [CGold: The Hitchhiker’s Guide to the CMake](https://cgold.readthedocs.io/en/latest/index.html) - - -### Структура каталогов проекта +== Структура каталогов проекта Файлы проекта и результаты компиляции размещаются в каталогах: -``` +.... └── cmex ├── _build │ ├── Debug @@ -54,68 +36,72 @@ thead th:nth-child(2) { │ └── lib ├── thirdparty └── tools -``` +.... Назначение каталогов приведено в таблице. -Каталог | Назначение --------------------------|---------------------------------------------- -`cmex/_build` | Результаты компиляции -`cmex/_build/Debug` | Результаты компиляции в режиме отладки -`cmex/_build/Release` | Результаты компиляции в режиме выпуска -`cmex/.git` | Репозиторий git -`cmex/cmake` | Файлы с дополнительными функциями для CMake -`cmex/cmake/cmlib` | Библиотека функций для CMake -`cmex/cmake/find` | Модули CMake для поиска внешних программ и библиотек -`cmex/cmake/etc` | Файлы настроек, используемые в CMake -`cmex/cmake/generators` | Генераторы проектов -`cmex/doc` | Документация для проекта -`cmake/files` | Каталог для дополнительных файлов -`cmake/files/etc` | Каталог для файлов настроек проекта -`cmake/files/share` | Каталог для неизменяемых файлов -`cmake/files/var` | Каталог для изменяемых файлов -`cmex/l10n` | Файлы переводов -`cmex/src` | Исходные тексты -`cmex/src/app` | Исходные тексты программ -`cmex/src/lib` | Исходные тексты библиотек -`cmex/thirdparty` | Исходные тексты сторонних проектов -`cmex/tools` | Дополнительные утилиты - +[cols=",",options="header",] +|=== +|Каталог |Назначение +|`cmex/_build` |Результаты компиляции +|`cmex/_build/Debug` |Результаты компиляции в режиме отладки +|`cmex/_build/Release` |Результаты компиляции в режиме выпуска +|`cmex/.git` |Репозиторий git +|`cmex/cmake` |Файлы с дополнительными функциями для CMake +|`cmex/cmake/cmlib` |Библиотека функций для CMake +|`cmex/cmake/find` |Модули CMake для поиска внешних программ и библиотек +|`cmex/cmake/etc` |Файлы настроек, используемые в CMake +|`cmex/cmake/generators` |Генераторы проектов +|`cmex/doc` |Документация для проекта +|`cmake/files` |Каталог для дополнительных файлов +|`cmake/files/etc` |Каталог для файлов настроек проекта +|`cmake/files/share` |Каталог для неизменяемых файлов +|`cmake/files/var` |Каталог для изменяемых файлов +|`cmex/l10n` |Файлы переводов +|`cmex/src` |Исходные тексты +|`cmex/src/app` |Исходные тексты программ +|`cmex/src/lib` |Исходные тексты библиотек +|`cmex/thirdparty` |Исходные тексты сторонних проектов +|`cmex/tools` |Дополнительные утилиты +|=== Каталог `_build` создаётся, чтобы избежать попадания получаемых во время -сборки файлов в иерархию основного проекта. -Запись результатов сборки проекта внутрь иерархии каталогов с исходными текстами -приводит к засорению формируемыми на этапе сборки файлами, которые затрудняют -разработку, поиск в оригинальных файлах и мешают ориентироваться в проекте. -При работе с несколькими типами сборки, например, отладка и выпуск, появляется -необходимость корректного полного удаления результатов предыдущего тип сборки. +сборки файлов в иерархию основного проекта. Запись результатов сборки +проекта внутрь иерархии каталогов с исходными текстами приводит к +засорению формируемыми на этапе сборки файлами, которые затрудняют +разработку, поиск в оригинальных файлах и мешают ориентироваться в +проекте. При работе с несколькими типами сборки, например, отладка и +выпуск, появляется необходимость корректного полного удаления +результатов предыдущего тип сборки. - -### Начало проекта +== Начало проекта В каталоге `cmex` нужно создать файл `CMakeLists.txt`: -```cmake +[source,cmake] +---- # Минимальная версия Cmake cmake_minimum_required(VERSION 3.3) cmake_policy(VERSION 3.0.2..3.7) # Название и версия проекта и используемые языки программирования project(cmex VERSION 0.2.0 LANGUAGES C CXX) -``` +---- Значение версии следует формировать согласно правилам -[семантического версионирования](https://semver.org/lang/ru/). +https://semver.org/lang/ru/[семантического версионирования]. -В каталог `cmake/cmlib` установить субмодуль CMLib, содержащий функции для CMake: +В каталог `cmake/cmlib` установить субмодуль CMLib, содержащий функции +для CMake: -``` +.... git submodule add ssh://git@gitlab-server/root/cmlib cmake/cmlib -``` +.... и подключить в файле `CMakeLists.txt`: -```cmake +[source,cmake] +---- # В каталоге cmake/cmlib находятся файлы с библиотечными функциями if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/cmlib) list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/cmlib) @@ -125,19 +111,19 @@ endif() list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/find) include(CMLibCommon) -``` +---- -В файле `cmake/etc/organization.txt` записать название -организации, которой принадлежит проект: +В файле `cmake/etc/organization.txt` записать название организации, +которой принадлежит проект: -``` +.... ORG, Inc. -``` +.... -В файле `cmake/etc/cpack_ignore.txt` перечислить шаблоны -для исключения из архива, создаваемого целью `dist`. Например: +В файле `cmake/etc/cpack_ignore.txt` перечислить шаблоны для исключения +из архива, создаваемого целью `dist`. Например: -``` +.... cmake/lib/.git$ .git$ files/var @@ -146,82 +132,86 @@ CMakeLists.txt.user \\\\..*\\\\.bak$ \\\\..*\\\\.tmp$ \\\\..*\\\\.swp$ -``` +.... +Чтобы проверить корректность файла `CMakeLists.txt`, нужно создать +каталог `_build` в каталоге `cmex`, перейти в него и выполнить команды: -Чтобы проверить корректность файла `CMakeLists.txt`, нужно создать каталог -`_build` в каталоге `cmex`, перейти в него и выполнить команды: - -```sh +[source,sh] +---- cmake .. make -``` +---- - -### Поиск системных библиотек +== Поиск системных библиотек Системные библиотеки можно искать с помощью программы `pkgconfig`, которая хранит базу данных параметров, включающую пути к заголовочным -файлами и перечни библиотек, необходимых для компоновки. -Сначала производится наличие модуля `PkgConfig`, в котором определена -функция `pkg_check_modules`, которая и осуществляет поиск. Например, -для поиска библиотек `gsl`, `fftw3` и `udev` можно написать: +файлами и перечни библиотек, необходимых для компоновки. Сначала +производится наличие модуля `PkgConfig`, в котором определена функция +`pkg_check_modules`, которая и осуществляет поиск. Например, для поиска +библиотек `gsl`, `fftw3` и `udev` можно написать: -```cmake +[source,cmake] +---- # Поиск библиотек с помощью pkgconfig find_package(PkgConfig) pkg_check_modules(GSL REQUIRED gsl) pkg_check_modules(FFTW3 REQUIRED fftw3) pkg_check_modules(UDEV udev) -``` +---- -Если системная библиотека поставляется без файла описания для `pkgconfig`, -то для её поиска может быть написан специальный модуль для `CMake`, -который вызывается функцией `find_package`. Кроме того функция `find_package` -может возвращать дополнительные значения, например, пути к исполняемым файлам. +Если системная библиотека поставляется без файла описания для +`pkgconfig`, то для её поиска может быть написан специальный модуль для +`CMake`, который вызывается функцией `find_package`. Кроме того функция +`find_package` может возвращать дополнительные значения, например, пути +к исполняемым файлам. -```cmake +[source,cmake] +---- # Поиск с помощью функции find_package find_package(LibXml2) find_package(CURL) -``` +---- Если для библиотеки нет модуля, выполняющего её поиск, то можно произвести поиск с помощью функции `find_library`. Например, -```cmake +[source,cmake] +---- # Поиск библиотеки с помощью функции find_library find_library(MATHGL mgl PATHS /usr/lib /usr/lib/x86_64-linux-gnu) find_library(MATHGLQT5 mgl-qt5 PATHS /usr/lib /usr/lib/x86_64-linux-gnu) -``` +---- - -### Автоматически генерируемый заголовочный файл +== Автоматически генерируемый заголовочный файл На этапе конфигурирования проекта можно создать файл, в который будут записаны параметры, полученные на данной стадии. В библиотеке CMLib присутствует функция `cmlib_config_hpp_generate()`, создающая файл `${CMAKE_BUILD_DIR}/include/config.hpp`, в который записывается -информация о имени и версии проекта, дате и типе сборки. +информация о имени и версии проекта, дате и типе сборки. -```cmake +[source,cmake] +---- # Автоматически генерируемый заголовочный файл cmlib_config_hpp_generate() -``` +---- +== Базовая библиотека -### Базовая библиотека +В файле `cmex/CMakeLists.txt` должна быть строка, включающая поиск файла +`CMakeLists.txt` в подкаталоге `src/lib`: -В файле `cmex/CMakeLists.txt` должна быть строка, включающая -поиск файла `CMakeLists.txt` в подкаталоге `src/lib`: - -```cmake +[source,cmake] +---- add_subdirectory(src/libcmex) -``` +---- В каталоге `cmex/src/libcmex` нужно создать файл `cmex.hpp`: -```cpp +[source,cpp] +---- #ifndef LIBCMEX_CMEX_HPP_ #define LIBCMEX_CMEX_HPP_ @@ -230,21 +220,23 @@ add_subdirectory(src/libcmex) int32_t cmex_init(int32_t i); #endif // LIBCMEX_CMEX_HPP_ -``` +---- файл `cmex.cpp`: -```cpp +[source,cpp] +---- #include "cmex.hpp" int32_t cmex_init(int32_t i = 0) { - return i; + return i; } -``` +---- и файл `CMakeLists.txt`: -```cmake +[source,cmake] +---- # Название основной цели и имя библиотеки в текущем каталоге set(current_target cmex) @@ -274,21 +266,22 @@ if(BUILD_SHARED_LIBS) endif() install(FILES ${CMAKE_BINARY_DIR}/include/config.hpp ${current_target_headers} COMPONENT headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${current_target}) -``` +---- +== Базовое приложение -### Базовое приложение +В файле `cmex/CMakeLists.txt` должна быть строка, включающая поиск файла +`CMakeLists.txt` в подкаталоге `src/cmex`: -В файле `cmex/CMakeLists.txt` должна быть строка, включающая поиск файла `CMakeLists.txt` -в подкаталоге `src/cmex`: - -```cmake +[source,cmake] +---- add_subdirectory(src/cmex) -``` +---- В каталоге `cmex/src/cmex` нужно создать файл `main.cpp`: -```cpp +[source,cpp] +---- #include "compiler_features.hpp" #include "config.hpp" @@ -297,18 +290,18 @@ add_subdirectory(src/cmex) #include "cmex.hpp" int main(int argc, char **argv) { - std::cout << CMEX_COMPILER_VERSION_MAJOR << std::endl; // Значение из compiler_features.hpp - std::cout << BUILD_TYPE << std::endl; // Значение из config.hpp - std::cout << CMEX_VERSION_STR << std::endl; // Значение из config.hpp - std::cout << cmex_init(4) << std::endl; // Функция из внутренней библиотеки - return 0; + std::cout << CMEX_COMPILER_VERSION_MAJOR << std::endl; // Значение из compiler_features.hpp + std::cout << BUILD_TYPE << std::endl; // Значение из config.hpp + std::cout << CMEX_VERSION_STR << std::endl; // Значение из config.hpp + std::cout << cmex_init(4) << std::endl; // Функция из внутренней библиотеки + return 0; } - -``` +---- и файл `CMakeLists.txt`: -```cmake +[source,cmake] +---- # Название основной цели в текущем каталоге set(current_target cmex_app) @@ -343,15 +336,15 @@ target_link_libraries(${current_target} cmex_static) # Правила для установки install(TARGETS ${current_target} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -``` +---- - -### Подключение внешнего проекта +== Подключение внешнего проекта В каталоге `cmex/thirdparty` нужно создать каталог `cmext` с проектом, состоящим из файлов `cmext.hpp`: -```c +[source,c] +---- #ifndef CMEXT_CMEXT_HPP_ #define CMEXT_CMEXT_HPP_ @@ -360,21 +353,23 @@ install(TARGETS ${current_target} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) int32_t cmext_init(int32_t i); #endif -``` +---- `cmext.cpp`: -```c +[source,c] +---- #include "cmext.hpp" int32_t cmext_init(int32_t i = 0) { - return i; + return i; } -``` +---- и `CMakeLists.txt`: -```cmake +[source,cmake] +---- cmake_minimum_required(VERSION 3.3) project(cmext) @@ -382,13 +377,14 @@ include(GNUInstallDirs) add_library(cmext cmext.cpp) install(TARGETS cmext ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES cmext.hpp COMPONENT headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME}) -``` +---- В файле `cmex/CMakeLists.txt` нужно подключить стандартный модуль `ExternalProject` и описать правила для его загрузки, настройки, компиляции и установки для сопряжения с текущим проектом: -```cmake +[source,cmake] +---- # Подключение внешних проектов include(ExternalProject) @@ -400,36 +396,41 @@ ExternalProject_Add(cmext BUILD_BYPRODUCTS /lib/libcmext.a CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_BUILD_TYPE=Release ) -``` +---- -Вызовы этих функций нужно сделать до функций `add_subdirectories`, -чтобы в подключенных подкаталогах можно было использовать цель `cmext` -для определения зависимостей. +Вызовы этих функций нужно сделать до функций `add_subdirectories`, чтобы +в подключенных подкаталогах можно было использовать цель `cmext` для +определения зависимостей. -В файле `cmex/src/cmex/CMakeLists.txt` нужно подключить внешний проект `cmext`: +В файле `cmex/src/cmex/CMakeLists.txt` нужно подключить внешний проект +`cmext`: -```cmake +[source,cmake] +---- # Зависимость от библиотеки из внешнего проекта проекта add_dependencies(${current_target} cmext) -``` +---- -```cmake +[source,cmake] +---- # Добавление каталога, в который устанавливаются заголовочные файлы от внешнего # проекта cmext, к списку путей для поиска заголовочных файлов target_include_directories(${current_target} PUBLIC $) -``` +---- -```cmake +[source,cmake] +---- # Библиотека из внешнего проекта cmext target_link_libraries(${current_target} ${CMAKE_BINARY_DIR}/lib/libcmext.a) -``` +---- -Для проверки работоспособности в файле `cmex/src/cmex/main.cpp` нужно вызвать -функцию `cmext_init` из библиотеки, предоставляемой внешним проектом. -Например: +Для проверки работоспособности в файле `cmex/src/cmex/main.cpp` нужно +вызвать функцию `cmext_init` из библиотеки, предоставляемой внешним +проектом. Например: -```cpp +[source,cpp] +---- #include "compiler_features.hpp" #include "config.hpp" @@ -456,43 +457,44 @@ int main(int argc, char **argv) { // Функция из внешней библиотеки qStdOut() << QObject::tr("libcmext function call: ") << cmext_init(9) << endl; - return 0; + return 0; } -``` +---- +== Qt5 -### Qt5 +Для поиска необходимых компонентов Qt5 нужно в файл +`cmex/CMakeLists.txt` добавить строки: -Для поиска необходимых компонентов Qt5 нужно в файл `cmex/CMakeLists.txt` -добавить строки: - -```cmake +[source,cmake] +---- find_package(Qt5 COMPONENTS Core Network Gui Widgets DBus Concurrent Sql REQUIRED) -``` +---- -Библиотека CMLib автоматически подключает вызов препроцессора `moc` -и компилятора ресурсов `rcc`, если цель использует модуль `Core`, и +Библиотека CMLib автоматически подключает вызов препроцессора `moc` и +компилятора ресурсов `rcc`, если цель использует модуль `Core`, и вызывает компилятор файлов описания интерфейса, если цель использует модуль `Widgets`. - -### Консольное приложение +== Консольное приложение В файл `cmex/src/cmex/CMakeLists.txt` добавить строки: -```cmake +[source,cmake] +---- # Qt5 qt_translation(TARGET ${current_target} TS_DIR ${CMAKE_SOURCE_DIR}/l10n LANGUAGES ru_RU) target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Core_INCLUDE_DIRS}) target_compile_options(${current_target} PUBLIC "${Qt5Core_EXECUTABLE_COMPILE_FLAGS}") target_link_libraries(${current_target} Qt5::Core) -``` +---- -Для проверки работоспособности подключения Qt5 файл `cmex/src/cmex/main.cpp` -нужно заменить на: +Для проверки работоспособности подключения Qt5 файл +`cmex/src/cmex/main.cpp` нужно заменить на: -```cpp +[source,cpp] +---- #include "compiler_features.hpp" #include "config.hpp" @@ -509,13 +511,13 @@ QTextStream& qStdOut() } int main(int argc, char **argv) { - QCoreApplication app(argc, argv); - QTranslator translator; + QCoreApplication app(argc, argv); + QTranslator translator; - if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm"))) - { - app.installTranslator(&translator); - } + if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm"))) + { + app.installTranslator(&translator); + } // Значение из compiler_features.hpp qStdOut() << QObject::tr("Compiler version: ") << CMEX_COMPILER_VERSION_MAJOR << endl; // Значение из config.hpp @@ -527,30 +529,32 @@ int main(int argc, char **argv) { // Функция из внешней библиотеки qStdOut() << QObject::tr("libcmext function call: ") << cmext_init(9) << endl; - return 0; + return 0; } -``` +---- -После сборки проекта в каталоге `cmex/l10n` появится файл `cmex_app_ru_RU.ts`, -в котором нужно отредактировать переводы с помощью программы `linguist`. -После сохранения переводов проект нужно пересобрать, файл переводов в -скопилированном виде будет встроен в исполняемый файл `cmex`, а доступ -к нему будет осуществляться с помощью кода: +После сборки проекта в каталоге `cmex/l10n` появится файл +`cmex_app_ru_RU.ts`, в котором нужно отредактировать переводы с помощью +программы `linguist`. После сохранения переводов проект нужно +пересобрать, файл переводов в скопилированном виде будет встроен в +исполняемый файл `cmex`, а доступ к нему будет осуществляться с помощью +кода: -```cpp - if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm"))) - { - app.installTranslator(&translator); - } -``` +[source,cpp] +---- + if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm"))) + { + app.installTranslator(&translator); + } +---- +== Графическое приложение -### Графическое приложение +Для создания минимального графического приложения нужно создать файл +описания интерфейса `cmex/src/cmex/my_main_window.ui`: -Для создания минимального графического приложения нужно создать -файл описания интерфейса `cmex/src/cmex/my_main_window.ui`: - -```xml +[source,xml] +---- MyMainWindow @@ -571,11 +575,12 @@ int main(int argc, char **argv) { -``` +---- заголовочный файл `cmex/src/cmex/my_main_window.hpp`: -```cpp +[source,cpp] +---- #ifndef CMEX_MY_MAIN_WINDOW_HPP_ #define CMEX_MY_MAIN_WINDOW_HPP_ @@ -583,18 +588,20 @@ int main(int argc, char **argv) { #include "ui_my_main_window.h" class MyMainWindow : public QWidget, private Ui::MyMainWindow { - Q_OBJECT - public: - MyMainWindow(QWidget* parent = 0); - virtual ~MyMainWindow(); + Q_OBJECT + public: + MyMainWindow(QWidget* parent = 0); + virtual ~MyMainWindow(); }; #endif /* CMEX_MY_MAIN_WINDOW_HPP_ */ -``` +---- -и файл с реализацией конструктора и деструктора `cmex/src/cmex/my_main_window.cpp`: +и файл с реализацией конструктора и деструктора +`cmex/src/cmex/my_main_window.cpp`: -```cpp +[source,cpp] +---- #include "my_main_window.hpp" MyMainWindow::MyMainWindow(QWidget* parent) { @@ -604,12 +611,13 @@ MyMainWindow::MyMainWindow(QWidget* parent) { MyMainWindow::~MyMainWindow() { } -``` +---- Для отображения графического окна нужно заменить файл `cmex/src/cmex/main.cpp` на: -```cpp +[source,cpp] +---- #include "compiler_features.hpp" #include "config.hpp" @@ -628,13 +636,13 @@ QTextStream& qStdOut() } int main(int argc, char **argv) { - QApplication app(argc, argv); - QTranslator translator; + QApplication app(argc, argv); + QTranslator translator; - if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm"))) - { - app.installTranslator(&translator); - } + if (translator.load(QLocale(), "cmex_app", QLatin1String("_"), QLatin1String(":/qm"))) + { + app.installTranslator(&translator); + } // Значение из compiler_features.hpp qStdOut() << QObject::tr("Compiler version: ") << CMEX_COMPILER_VERSION_MAJOR << endl; @@ -647,16 +655,17 @@ int main(int argc, char **argv) { // Функция из внешней библиотеки qStdOut() << QObject::tr("libcmext function call: ") << cmext_init(9) << endl; - MyMainWindow* mmw = new MyMainWindow(); - mmw->show(); - return app.exec(); + MyMainWindow* mmw = new MyMainWindow(); + mmw->show(); + return app.exec(); } -``` +---- -В файле `cmex/src/cmex/CMakeLists.txt` добавить новые файлы -к списку файлов, используемых для компиляции: +В файле `cmex/src/cmex/CMakeLists.txt` добавить новые файлы к списку +файлов, используемых для компиляции: -```cmake +[source,cmake] +---- set(current_target_sources main.cpp my_main_window.cpp @@ -665,51 +674,51 @@ set(current_target_sources set(current_target_uis my_main_window.ui ) -``` +---- -```cmake +[source,cmake] +---- # Цель для создания исполняемого файла add_executable(${current_target} ${current_target_sources} ${current_target_uis}) -``` +---- -и добавить строки для подключения графических библиотек Qt5 -и соответствующих им заголовочных файлов: +и добавить строки для подключения графических библиотек Qt5 и +соответствующих им заголовочных файлов: -```cmake +[source,cmake] +---- target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Gui_INCLUDE_DIRS}) target_include_directories(${current_target} SYSTEM PUBLIC ${Qt5Widgets_INCLUDE_DIRS}) target_link_libraries(${current_target} Qt5::Gui) target_link_libraries(${current_target} Qt5::Widgets) -``` +---- Во время сборки проекта в файл переводов `cmex/l10n/cmex_app_ru_RU.ts` -будут добавлены повые строки, их нужно перевести с помощью `linguist` -и снова скомпилировать проект. +будут добавлены повые строки, их нужно перевести с помощью `linguist` и +снова скомпилировать проект. - - -### Удаление установленных файлов +== Удаление установленных файлов В библиотеку CMLib добавлена цель `uninstall`, позволяющая удалить файлы, перечисленные в файле `${CMAKE_BUILD_DIR}/install_manifest.txt`. - -### Архивирование проекта +== Архивирование проекта Стандарный модуль `CPack` осуществляет архивирование проекта. В файле -`cproj/cmake/etc/cpack_ignore.txt` определён список типовых масок файлов для -исключения из архива: +`cproj/cmake/etc/cpack_ignore.txt` определён список типовых масок файлов +для исключения из архива: -``` +.... .git$ files/var CMakeLists.txt.user ~$ -\\\\..*\\\\.bak$ \\\\..*\\\\.tmp$ +\\\\..*\\\\.bak$ \\\\..*\\\\.swp$ -``` +\\\\..*\\\\.o$ +.... -По умолчанию цель для упаковки проекта называется `package_source`. -В библиотеке CMLib определены значения основных параметров, а также +По умолчанию цель для упаковки проекта называется `package_source`. В +библиотеке CMLib определены значения основных параметров, а также дополнительная цель `dist`. diff --git a/wiki/Prog/Development/Intel Parallel Studio.adoc b/wiki/Prog/Development/Intel Parallel Studio.adoc new file mode 100644 index 0000000..57851a3 --- /dev/null +++ b/wiki/Prog/Development/Intel Parallel Studio.adoc @@ -0,0 +1,38 @@ += Intel Parallel Studio: установка в образ для чтения +:category: Linux/Программы +:tags: Linux, Intel, компилятор, C++, + +Для установки и использования Intel Parallel Studio в сжатом образе +доступном только для чтения необходимо: + +[arabic] +. Скачать +https://software.intel.com/en-us/parallel-studio-xe[дистрибутив] и +распаковать его. +. Скачать файл link:files/parallel-studio/silent.cfg[`silent.cfg`] и +скопировать его в полученный каталог. +. Если есть файл лицензии `parallel_studio.lic`, скопировать его в +каталог `/opt/intel/licenses`. +. Добавить полномочия для сбора статистики: + +[source,sh] +---- +sudo setcap cap_sys_ptrace=eip /opt/intel/vtune_amplifier/bin64/amplxe-cl +sudo setcap cap_sys_ptrace=eip /opt/intel/vtune_amplifier/bin64/amplxe-perf +---- + +[arabic, start=5] +. От суперпользователя установить в каталог `/opt/intel` командой +`sudo ./install.sh -s silent.cfg`. +. Создать образ +`mksquashfs /opt/intel/* /home/user/intel.sfs -comp xz -Xbcj x86 -all-root -b 512K` +. Удалить содержимое каталога `/opt/intel`. +. Подмонтировать образ: +`mount -t squashfs /home/user/intel.sfs /opt/intel` +. Добавить в файл `/home/user/.bashrc` строки: + +[source,sh] +---- +source /opt/intel/bin/compilervars.sh intel64 +source /opt/intel/vtune_amplifier/amplxe-vars.sh +---- diff --git a/wiki/Prog/Development/Intel Parallel Studio.md b/wiki/Prog/Development/Intel Parallel Studio.md deleted file mode 100644 index 3e7452a..0000000 --- a/wiki/Prog/Development/Intel Parallel Studio.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: "Intel Parallel Studio: установка в образ для чтения" -category: Linux/Программы -tags: Linux, Intel, компилятор, C++ -summary: -... - -Для установки и использования Intel Parallel Studio -в сжатом образе доступном только для чтения необходимо: - -1. Скачать [дистрибутив](https://software.intel.com/en-us/parallel-studio-xe) и распаковать его. -2. Скачать файл [`silent.cfg`](files/parallel-studio/silent.cfg) и скопировать его в полученный каталог. -3. Если есть файл лицензии `parallel_studio.lic`, скопировать его в каталог `/opt/intel/licenses`. -4. От суперпользователя установить в каталог `/opt/intel` командой `sudo ./install.sh -s silent.cfg`. -5. Создать образ `mksquashfs /opt/intel/* /home/user/intel.sfs -comp xz -Xbcj x86 -all-root -b 512K` -6. Удалить содержимое каталога `/opt/intel`. -7. Подмонтировать образ: `mount -t squashfs /home/user/intel.sfs /opt/intel` -8. Добавить в файл `/home/user/.bashrc` строки: -```sh -source /opt/intel/bin/compilervars.sh intel64 -source /opt/intel/vtune_amplifier/amplxe-vars.sh -``` diff --git a/wiki/Prog/Development/PVS-Studio.md b/wiki/Prog/Development/PVS-Studio.adoc similarity index 62% rename from wiki/Prog/Development/PVS-Studio.md rename to wiki/Prog/Development/PVS-Studio.adoc index 03b5a55..86914c6 100644 --- a/wiki/Prog/Development/PVS-Studio.md +++ b/wiki/Prog/Development/PVS-Studio.adoc @@ -1,59 +1,62 @@ ---- -title: "PVS-Studio" -category: Программирование -tags: программирование, C, C++, отладка, -summary: -toc: yes -... += PVS-Studio +:category: Программирование +:tags: программирование, C, C++, отладка, -[TOC] +:toc: -### Информация и лицензия +== Информация и лицензия -[PVS-Studio](https://www.viva64.com/ru/pvs-studio/) — это инструмент для -статического анализа исходного кода программ, написанных на языках С, C++. +https://www.viva64.com/ru/pvs-studio/[PVS-Studio] — это инструмент для +статического анализа исходного кода программ, написанных на языках С, +C++. Для использования в Linux нужно чтобы в каталоге `~/.config/PVS-Studio` находился лицензионный ключ или в начале исходных файлов с расширениями -`*.c`, `*.cpp`, `*.cxx` и т.п. [присутствовали строки](https://www.viva64.com/ru/b/0457/) +`*.c`, `*.cpp`, `*.cxx` и т.п. +https://www.viva64.com/ru/b/0457/[присутствовали строки] -``` +.... // This is an independent project of an individual developer. Dear PVS-Studio, please check it. // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -``` +.... -### Настройка и компиляция проекта +== Настройка и компиляция проекта Полное руководство для работы в Linux находится -[здесь](https://www.viva64.com/ru/m/0036/), а ниже приведён список типовых команд. +https://www.viva64.com/ru/m/0036/[здесь], а ниже приведён список типовых +команд. Настройка проекта для CMake: -```sh +[source,sh] +---- cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=On -``` +---- Сборка проекта с помощью `make`: -```sh +[source,sh] +---- pvs-studio-analyzer trace -- make -j$(nproc) -``` +---- Настройка и сборка проекта с использованием Ninja: -```sh +[source,sh] +---- cmake -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=On ninja -t compdb -``` +---- -### Анализ проекта +== Анализ проекта -Для анализа проектов используется утилита `pvs-studio-analyzer`. По умолчанию -включены только диагностики общего назначения (General Analysis, GA). -Включить дополнительные правила можно с помощью опции `-a`: +Для анализа проектов используется утилита `pvs-studio-analyzer`. По +умолчанию включены только диагностики общего назначения (General +Analysis, GA). Включить дополнительные правила можно с помощью опции +`-a`: -``` +.... -a [MODE], --analysis-mode [MODE] MODE defines the type of warnings: 1 - 64-bit errors; @@ -64,45 +67,50 @@ ninja -t compdb 32 - MISRA. Modes can be combined by adding the values Default: 4 -``` +.... Выбор типов предупреждений осуществляется на основе побитовой маски из приведенных выше типов. Чтобы выполнить анализ, исключив проверки MISRA, нужно выполнить -```sh +[source,sh] +---- pvs-studio-analyzer analyze -a 29 -j$(nproc) -o pvs.log -``` +---- Составление отчёта для просмотра в Qt Creator: -```sh +[source,sh] +---- plog-converter -t tasklist -o pvs.tasks pvs.log -``` +---- -При составлении отчёта уровень детализации можно изменять с помощью ключа -`-a` (`--analyzer`), который производит фильтрацию предупреждений согласно -маске, которая имеет вид `MessageType:MessageLevels`, где `MessageType` -может принимать один из следующих типов: `GA`, `OP`, `64`, `CS`, `MISRA`, -а `MessageLevels` может принимать значения от `1` до `3`. +При составлении отчёта уровень детализации можно изменять с помощью +ключа `-a` (`--analyzer`), который производит фильтрацию предупреждений +согласно маске, которая имеет вид `MessageType:MessageLevels`, где +`MessageType` может принимать один из следующих типов: `GA`, `OP`, `64`, +`CS`, `MISRA`, а `MessageLevels` может принимать значения от `1` до `3`. Возможна комбинация разных масок через `;`. Например, при составлении отчёта для просмотра в формате HTML можно повысить уровень детализации: -```sh +[source,sh] +---- plog-converter -t fullhtml -a "GA:1,2,3;64:1;OP:1,2;CS:1,2" -o html pvs.log -``` +---- Составление отчёта для редактора Vim: -```sh +[source,sh] +---- plog-converter -a "GA:1,2" -t errorfile -o pvs.err pvs.log -``` +---- -Для просмотра отчёта в редакторе Vim нужно открыть файл `pvs.err` и выполнить команды: +Для просмотра отчёта в редакторе Vim нужно открыть файл `pvs.err` и +выполнить команды: -```vim +[source,vim] +---- :set makeprg=cat\ % " выбор программы для компиляции в текущей сессии :silent make " имитация сборки :cw " открытие результатов в нижнем окне -``` - +---- diff --git a/wiki/Prog/Development/Подбор ключей компиляции GCC.adoc b/wiki/Prog/Development/Подбор ключей компиляции GCC.adoc new file mode 100644 index 0000000..cbc4d77 --- /dev/null +++ b/wiki/Prog/Development/Подбор ключей компиляции GCC.adoc @@ -0,0 +1,36 @@ += Подбор ключей компиляции GCC +:category: Программирование +:tags: программирование, C, C++, отладка, оптимизация, + +Подбор ключей компиляции основан на измерениях характеристик во время +выполнения программы. На первом этапе создаётся исполняемый файл +`program`, в который включается информация для профилировки. Ключ +`-fprofile-generate=data/pgo` указывает, что нужно собирать информацию и +сохранять в каталог `data/pgo`. Компиляцию следует выполнять в +последовательном режиме. + +[source,sh] +---- +env CXXFLAGS='-fprofile-generate=data/pgo' cmake .. -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" +make -j1 +---- + +После компиляцию программу следует выполнить, придерживаясь типичного +сценария использования. + +[source,sh] +---- +./program +---- + +Скомпилировать программу с использованием полученной статистики. Для +многопоточной программы следует указать флаг `-fprofile-correction`, +чтобы скорректировать данные, которые могут неустойчивыми из-за +пропусков обновлений счётчиков. Компиляцию следует выполнять в +последовательном режиме. + +[source,sh] +---- +env CXXFLAGS='-fprofile-use=data/pgo -fprofile-correction' cmake .. -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" +make -j1 +---- diff --git a/wiki/Prog/Development/Подбор ключей компиляции GCC.md b/wiki/Prog/Development/Подбор ключей компиляции GCC.md deleted file mode 100644 index fbdb4c1..0000000 --- a/wiki/Prog/Development/Подбор ключей компиляции GCC.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Подбор ключей компиляции GCC" -category: Программирование -tags: программирование, C, C++, отладка, оптимизация, -summary: -... - -Подбор ключей компиляции основан на измерениях характеристик во -время выполнения программы. На первом этапе создаётся исполняемый -файл `program`, в который включается информация для профилировки. -Ключ `-fprofile-generate=data/pgo` указывает, что нужно собирать -информацию и сохранять в каталог `data/pgo`. Компиляцию следует -выполнять в последовательном режиме. - -```sh -env CXXFLAGS='-fprofile-generate=data/pgo' cmake .. -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" -make -j1 -``` - -После компиляцию программу следует выполнить, придерживаясь -типичного сценария использования. - -```sh -./program -``` - -Скомпилировать программу с использованием полученной статистики. -Для многопоточной программы следует указать флаг `-fprofile-correction`, -чтобы скорректировать данные, которые могут неустойчивыми из-за пропусков -обновлений счётчиков. Компиляцию следует выполнять в последовательном режиме. - -```sh -env CXXFLAGS='-fprofile-use=data/pgo -fprofile-correction' cmake .. -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" -make -j1 -``` diff --git a/wiki/Prog/Development/Профилирование кода.adoc b/wiki/Prog/Development/Профилирование кода.adoc new file mode 100644 index 0000000..9669e3f --- /dev/null +++ b/wiki/Prog/Development/Профилирование кода.adoc @@ -0,0 +1,77 @@ += Профилирование кода +:category: Программирование +:tags: программирование, отладка, производительность, профилирование, gprof, + +== Общее описание + +Чтобы профилировать приложения, компилируемые http://gcc.gnu.org[GCC], +необходимо добавлять флаг `-fno-omit-frame-pointer` и, желательно, `-g`. + +== quickstack + +Утилита для отслеживания стеков вызовов функций +https://github.com/yoshinorim/quickstack[quicktrack]. Пример +использования: + +[source,sh] +---- +quickstack -f -p $(pidof application) +---- + +== perf + +Утилита профилирования для ядра Linux (находится в дереве его исходных +текстов в каталоге `tools/perf`). + +[source,sh] +---- +perf record --call-graph dwarf -- ./application +perf report -g graph --no-children +---- + +Полезные ссылки: + +* https://perf.wiki.kernel.org/index.php/Main_Page[Официальная страница] +* https://stackoverflow.com/questions/1777556/alternatives-to-gprof/10958510#10958510[Примеры] +* http://www.brendangregg.com/perf.html[Примеры] + +== oprofile + +[source,sh] +---- +opcontrol --setup --vmlinux=/boot/vmlinux-`uname -r` +---- + +== Systemtap + +https://eax.me/systemtap/[Установка и простые примеры использования +SystemTap] + +== Valgrind + +https://eax.me/valgrind/[Хорошая статья] об использовании Valgrind для +поиска утечек, а также о взаимодействии с GDB. + +В версии 3.15 добавление инструмент профилирования кучи DHAT (Dynamic +Heap Analysis Tool), позволяющий отследить все запросы на распределения +памяти в куче и выявить утечки ресурсов, места излишне большой +активности при работе с кучей, неиспользованные выделения памяти, +краткосрочные выделения и неэффективное размещение данных в куче. + +[source,sh] +---- +valgrind --tool=dhat ./application +---- + +== gperftools + +== Разное + +* https://eax.me/c-cpp-profiling/[Профилирование кода на C/C++ в Linux и +FreeBSD] +* http://gernotklingler.com/blog/gprof-valgrind-gperftools-evaluation-tools-application-level-cpu-profiling-linux/[Примеры] + +== Графическое отображение + +* http://www.brendangregg.com/flamegraphs.html[Flame Graphs] +* https://github.com/jrfonseca/gprof2dot[gprof2dot] diff --git a/wiki/Prog/Development/Профилирование кода.md b/wiki/Prog/Development/Профилирование кода.md deleted file mode 100644 index 4a6b2b3..0000000 --- a/wiki/Prog/Development/Профилирование кода.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "Профилирование кода" -category: Программирование -tags: программирование, отладка, производительность, профилирование, gprof, -summary: -... - -## Общее описание - -Чтобы профилировать приложения, компилируемые [GCC](http://gcc.gnu.org), -необходимо добавлять флаг `-fno-omit-frame-pointer` и, желательно, `-g`. - -## quickstack - -Утилита для отслеживания стеков вызовов функций [quicktrack](https://github.com/yoshinorim/quickstack). -Пример использования: - -```sh -quickstack -f -p $(pidof application) -``` - -## perf - -Утилита профилирования для ядра Linux (находится в дереве его исходных текстов -в каталоге `tools/perf`). - -```sh -perf record --call-graph dwarf -- ./application -perf report -g graph --no-children -``` - -Полезные ссылки: - -* [Официальная страница](https://perf.wiki.kernel.org/index.php/Main_Page) -* [Примеры](https://stackoverflow.com/questions/1777556/alternatives-to-gprof/10958510#10958510) -* [Примеры](http://www.brendangregg.com/perf.html) - -## oprofile - -```sh -opcontrol --setup --vmlinux=/boot/vmlinux-`uname -r` -``` - -## Systemtap - -[Установка и простые примеры использования SystemTap](https://eax.me/systemtap/) - - -## Valgrind - - -[Хорошая статья](https://eax.me/valgrind/) об использовании Valgrind для поиска -утечек, а также о взаимодействии с GDB. - -В версии 3.15 добавление инструмент профилирования кучи DHAT (Dynamic -Heap Analysis Tool), позволяющий отследить все запросы на распределения -памяти в куче и выявить утечки ресурсов, места излишне большой активности -при работе с кучей, неиспользованные выделения памяти, краткосрочные -выделения и неэффективное размещение данных в куче. - -```sh -valgrind --tool=dhat ./application -``` - - -## gperftools - - -## Разное - -* [Профилирование кода на C/C++ в Linux и FreeBSD](https://eax.me/c-cpp-profiling/) -* [Примеры](http://gernotklingler.com/blog/gprof-valgrind-gperftools-evaluation-tools-application-level-cpu-profiling-linux/) - - -## Графическое отображение - -* [Flame Graphs](http://www.brendangregg.com/flamegraphs.html) -* [gprof2dot](https://github.com/jrfonseca/gprof2dot) - diff --git a/wiki/Prog/Development/Статический анализ кода.md b/wiki/Prog/Development/Статический анализ кода.adoc similarity index 56% rename from wiki/Prog/Development/Статический анализ кода.md rename to wiki/Prog/Development/Статический анализ кода.adoc index a4a00fa..ef5b8e3 100644 --- a/wiki/Prog/Development/Статический анализ кода.md +++ b/wiki/Prog/Development/Статический анализ кода.adoc @@ -1,33 +1,33 @@ ---- -title: "Статический анализ кода" -category: Программирование -tags: программирование, отладка, cppcheck, iwyu, clang-tidy, cpplint, clazy, -summary: -... += Статический анализ кода +:category: Программирование +:tags: программирование, отладка, cppcheck, iwyu, clang-tidy, cpplint, clazy, -## Общее описание +== Общее описание -Ниже приведены утилиты для проверки кода на C++ и примеры их настройки и использования -совместно с [CMake](https://cmake.org/). +Ниже приведены утилиты для проверки кода на C++ и примеры их настройки и +использования совместно с https://cmake.org/[CMake]. -### [clang-tidy](http://clang.llvm.org/extra/clang-tidy/) +=== http://clang.llvm.org/extra/clang-tidy/[clang-tidy] Установка: -```sh +[source,sh] +---- sudo apt-get install clang-tidy-6.0 -``` +---- Использование: -```sh +[source,sh] +---- cmake "-DCMAKE_CXX_CLANG_TIDY=/usr/bin/clang-tidy-6.0" path/to/source -``` +---- -В каталоге проекта нужно создать файл `.clang-tidy` в формате YAML со списком -выполняемых проверок. Например: +В каталоге проекта нужно создать файл `.clang-tidy` в формате YAML со +списком выполняемых проверок. Например: -```yaml +[source,yaml] +---- --- Checks: '-*, clang-diagnostic-*, @@ -42,91 +42,97 @@ CheckOptions: - key: readability-identifier-naming.ClassMemberCase value: camelBack ... -``` +---- -Пример файла `.clang-tidy`, в котором перечислены все правила для проверки -именования идентификаторов приведён [здесь](https://git.246060.ru/f1x1t/clang-tidy-readability-identifier-naming). +Пример файла `.clang-tidy`, в котором перечислены все правила для +проверки именования идентификаторов приведён +https://git.246060.ru/f1x1t/clang-tidy-readability-identifier-naming[здесь]. - -### CppCheck +=== CppCheck Установка: -```sh +[source,sh] +---- sudo apt-get install cppcheck -``` +---- Использование: -```sh +[source,sh] +---- cmake "-DCMAKE_CXX_CPPCHECK=/usr/bin/cppcheck;--std=c++11" path/to/source -``` +---- -This will run /usr/bin/cppcheck;–std=c++11″ –source=/path/to/source/file.cxx on each c++ file in the project being built. +This will run /usr/bin/cppcheck;–std=c++11″ +–source=/path/to/source/file.cxx on each c++ file in the project being +built. - -### CppLint +=== CppLint Установка: -```sh +[source,sh] +---- sudo apt-get install python3-cpplint -``` +---- Использование: -```sh +[source,sh] +---- cmake "-DCMAKE_CXX_CPPLINT=/usr/bin/cpplint;--linelength=79" path/to/source -``` +---- -```sh +[source,sh] +---- make -j24 2>&1 1>/dev/null | ../cpplint2tasks.pl > 222.tasks -``` +---- -This will run /usr/local/bin/cpplint –linelength=79 on each c++ file in the project being built. +This will run /usr/local/bin/cpplint –linelength=79 on each c++ file in +the project being built. - -### IWYU +=== IWYU Установка: -```sh +[source,sh] +---- sudo apt-get install iwyu -``` +---- Использование: - -```sh +[source,sh] +---- cmake "-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=/usr/bin/iwyu;--transitive_includes_only" .. -``` +---- +This will run /usr/bin/iwyu –transitive_includes_only on each c++ file +in the project being built. -This will run /usr/bin/iwyu –transitive_includes_only on each c++ file in the project being built. +=== LWYU - -### LWYU - -```sh +[source,sh] +---- cmake -DCMAKE_LINK_WHAT_YOU_USE=TRUE .. -``` - -### Clazy +---- +=== Clazy Установка: -```sh +[source,sh] +---- sudo apt-get install clazy clang-6.0 -``` +---- Использование: -```sh +[source,sh] +---- CLAZY_CHECKS=level2 cmake -DCMAKE_CXX_COMPILER=clazy .. CLANGXX=clang++-6.0 make -``` - - -### PVS-Studio +---- +=== PVS-Studio diff --git a/wiki/Prog/GIS/Построение профиля местности в QGis.adoc b/wiki/Prog/GIS/Построение профиля местности в QGis.adoc new file mode 100644 index 0000000..5fd4068 --- /dev/null +++ b/wiki/Prog/GIS/Построение профиля местности в QGis.adoc @@ -0,0 +1,49 @@ += Построение профиля местности в QGis +:category: Картография +:tags: картография, qgis, sxf, shp, gdal, + +[arabic] +. В главном меню QGis *Слой* — *Добавить слой* — *Добавить векторный +слой* выбрать и открыть файл с векторным слоем, например, `map.sxf`. +. Среди слоёв выбрать слой с рельефом местности и типом геометрии +`LineString`. + +image:qgis-heights/1.png[Слои карты] + +[arabic, start=3] +. На панели *Панель слоёв* правой кнопкой мыши щелкнуть на слое, +содержащем данные о высотах, и выбрать *Фильтр…*. +. Построить выражение выбирающие только данные с высотами, например, +`"CLNAME" ILIKE '%ГОРИЗОНТАЛИ ОСНОВ%'` и нажить *OK*. +. На панели *Панель слоёв* правой кнопкой мыши щелкнуть на слое, +содержащем данные о высотах, и выбрать *Сохранить как…*. Появившийся +новый слой *heights* следует удалить. +. В появившемся диалоговом окне выбрать имя выходного файла, например, +`heights`. + +image:qgis-heights/2.png[Имя выходного файла] + +[arabic, start=7] +. В каталоге `/home/a/work/map` выполнить команду, которая в файле +`heights.shp` из слоя `heights` берёт данные о высотах из поля `SC_4` и +генерирует матрицу высот размером 2000 на 2000 в формате BMP. Настойки +алгоритма посторения матрицы можно изменять с помощью параметра `-a`: + +[source,sh] +---- +gdal_grid -a invdist:power=3.0:smoothing=1.0 -outsize 2000 2000 -of BMP -ot Byte -zfield SC_4 -l heights heights.shp heights.bmp +---- + +[arabic, start=8] +. После построения матрицы её можно импортировать в QGis как растровый +слой, для этого в главном меню QGis *Слой* — *Добавить слой* — *Добавить +растровый слой* нужно выбрать и открыть файл `heights.bmp`. В результате +на панели *Панель слоёв* появится растровый слой *heights*. +. С помощью модуля Profile Tool можно построить профиль местности. В +главном меню нужно выбрать *Модуль* — *Profile Tool* — *Terrain +profile*. +. На панели *Панель слоёв* нужно перенести растровый слой *heights* в +конец списка, выделить его и на панели *Profile Tool* нажать *Add +Layer*. После этого на карте можно строить профили местности. + +image:qgis-heights/3.png[Матрица высот] diff --git a/wiki/Prog/GIS/Построение профиля местности в QGis.md b/wiki/Prog/GIS/Построение профиля местности в QGis.md deleted file mode 100644 index af8c0c4..0000000 --- a/wiki/Prog/GIS/Построение профиля местности в QGis.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: "Построение профиля местности в QGis" -category: Картография -tags: картография, qgis, sxf, shp, gdal, -summary: -... - - -1) В главном меню QGis **Слой** — **Добавить слой** — **Добавить векторный слой** -выбрать и открыть файл с векторным слоем, например, `map.sxf`. - -2) Среди слоёв выбрать слой с рельефом местности и типом геометрии `LineString`. - -![Слои карты](images/qgis-heights/1.png) - -3) На панели **Панель слоёв** правой кнопкой мыши щелкнуть на слое, -содержащем данные о высотах, и выбрать **Фильтр...**. - -4) Построить выражение выбирающие только данные с высотами, например, -`"CLNAME" ILIKE '%ГОРИЗОНТАЛИ ОСНОВ%'` и нажить **OK**. - -5) На панели **Панель слоёв** правой кнопкой мыши щелкнуть на слое, -содержащем данные о высотах, и выбрать **Сохранить как...**. Появившийся -новый слой **heights** следует удалить. - -6) В появившемся диалоговом окне выбрать имя выходного файла, например, `heights`. - -![Имя выходного файла](images/qgis-heights/2.png) - -7) В каталоге `/home/a/work/map` выполнить команду, которая в файле -`heights.shp` из слоя `heights` берёт данные о высотах из поля `SC_4` -и генерирует матрицу высот размером 2000 на 2000 в формате BMP. -Настойки алгоритма посторения матрицы можно изменять с помощью параметра `-a`: - -```sh -gdal_grid -a invdist:power=3.0:smoothing=1.0 -outsize 2000 2000 -of BMP -ot Byte -zfield SC_4 -l heights heights.shp heights.bmp -``` - -8) После построения матрицы её можно импортировать в QGis как растровый -слой, для этого в главном меню QGis **Слой** — **Добавить слой** — -**Добавить растровый слой** нужно выбрать и открыть файл `heights.bmp`. -В результате на панели **Панель слоёв** появится растровый слой **heights**. - -9) С помощью модуля Profile Tool можно построить профиль местности. В главном -меню нужно выбрать **Модуль** — **Profile Tool** — **Terrain profile**. - -10) На панели **Панель слоёв** нужно перенести растровый слой **heights** -в конец списка, выделить его и на панели **Profile Tool** нажать **Add Layer**. -После этого на карте можно строить профили местности. - -![Матрица высот](images/qgis-heights/3.png) diff --git a/wiki/Prog/Git/.asciidoctor/diagram/diag-81886ef1b8d31cdb2b865473bbeb2cf9.png.cache b/wiki/Prog/Git/.asciidoctor/diagram/diag-81886ef1b8d31cdb2b865473bbeb2cf9.png.cache new file mode 100644 index 0000000..1c6e257 --- /dev/null +++ b/wiki/Prog/Git/.asciidoctor/diagram/diag-81886ef1b8d31cdb2b865473bbeb2cf9.png.cache @@ -0,0 +1 @@ +{"checksum":"81886ef1b8d31cdb2b865473bbeb2cf9","width":671,"height":550} \ No newline at end of file diff --git a/wiki/Prog/Git/.asciidoctor/diagram/diag-e76d88ee3db613b3f806d8c773281fdc.png.cache b/wiki/Prog/Git/.asciidoctor/diagram/diag-e76d88ee3db613b3f806d8c773281fdc.png.cache new file mode 100644 index 0000000..66ea5d8 --- /dev/null +++ b/wiki/Prog/Git/.asciidoctor/diagram/diag-e76d88ee3db613b3f806d8c773281fdc.png.cache @@ -0,0 +1 @@ +{"checksum":"e76d88ee3db613b3f806d8c773281fdc","width":685,"height":363} \ No newline at end of file diff --git a/wiki/Prog/Git/Git автоматическое сохранение в репозиторий.adoc b/wiki/Prog/Git/Git автоматическое сохранение в репозиторий.adoc new file mode 100644 index 0000000..584b500 --- /dev/null +++ b/wiki/Prog/Git/Git автоматическое сохранение в репозиторий.adoc @@ -0,0 +1,29 @@ += Git: автоматическое сохранение в репозиторий +:category: Программирование +:tags: программирование, git, + +Скрипт https://github.com/elnull/gitwatch[gitwatch] позволяет +отслеживать изменения в каталоге с помощью программы `inotifywait` и +фиксировать их в репозиторий. Для работы скрипта необходимо установить +пакет `inotify-tools`. Если нужно следить за каталогом `/home/user/dir` +и записывать историю изменений в `/home/user/repo/dir`, то нужно +инициализировать репозиторий: + +[source,sh] +---- +git init --bare /home/user/repo/dir +---- + +добавить шаблоны исключаемых файлов: + +[source,sh] +---- +printf '*.[oa]\n*.swp\n*~\n/.git' >> /home/user/repo/dir/info/exclude +---- + +и запустить скрипт: + +[source,sh] +---- +./gitwatch.sh -g /home/user/repo/dir /home/user/dir +---- diff --git a/wiki/Prog/Git/Git автоматическое сохранение в репозиторий.md b/wiki/Prog/Git/Git автоматическое сохранение в репозиторий.md deleted file mode 100644 index 2a9bdba..0000000 --- a/wiki/Prog/Git/Git автоматическое сохранение в репозиторий.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Git: автоматическое сохранение в репозиторий" -category: Программирование -tags: программирование, git, -... - -Скрипт [gitwatch](https://github.com/elnull/gitwatch) позволяет отслеживать -изменения в каталоге с помощью программы `inotifywait` и фиксировать их в -репозиторий. Для работы скрипта необходимо установить пакет `inotify-tools`. -Если нужно следить за каталогом `/home/user/dir` и записывать историю -изменений в `/home/user/repo/dir`, то нужно инициализировать репозиторий: - -```sh -git init --bare /home/user/repo/dir -``` - -добавить шаблоны исключаемых файлов: - -```sh -printf '*.[oa]\n*.swp\n*~\n/.git' >> /home/user/repo/dir/info/exclude -``` - -и запустить скрипт: - -```sh -./gitwatch.sh -g /home/user/repo/dir /home/user/dir -``` diff --git a/wiki/Prog/Git/Git замена адреса подмодуля.md b/wiki/Prog/Git/Git замена адреса подмодуля.adoc similarity index 55% rename from wiki/Prog/Git/Git замена адреса подмодуля.md rename to wiki/Prog/Git/Git замена адреса подмодуля.adoc index 4a1ee68..0ef6583 100644 --- a/wiki/Prog/Git/Git замена адреса подмодуля.md +++ b/wiki/Prog/Git/Git замена адреса подмодуля.adoc @@ -1,20 +1,16 @@ ---- -title: "Git: замена адреса подмодуля" -category: Программирование -tags: программирование, git, -monofontoptions: -- Scale=0.7 -... += Git: замена адреса подмодуля +:category: Программирование +:tags: программирование, git, Если у подмодуля, находящегося в каталоге `thirdparty/example` нужно -заменить адрес синхронизации и имя используемой ветки, то в каталоге -с файлом `.gitmodules`, в котором содержится информация об этом подмодуле, +заменить адрес синхронизации и имя используемой ветки, то в каталоге с +файлом `.gitmodules`, в котором содержится информация об этом подмодуле, нужно выполнить команды: -```sh +[source,sh] +---- git config --file=.gitmodules submodule.thirdparty/example.url https://github.com/username/ABC.git git config --file=.gitmodules submodule.thirdparty/example.branch new-branch-name git submodule sync --recursive git submodule update --init --recursive --remote -``` - +---- diff --git a/wiki/Prog/Git/Git основные команды.adoc b/wiki/Prog/Git/Git основные команды.adoc new file mode 100644 index 0000000..8d21b26 --- /dev/null +++ b/wiki/Prog/Git/Git основные команды.adoc @@ -0,0 +1,391 @@ += Git: основные команды +:category: Программирование +:tags: программирование, git + +== Ссылки + +* https://githowto.com/ru/changes_not_files[GitHowTo] +* https://git-scm.com/book/ru/v2[ProGit] +* https://github.com/maxliscia/git-pocket[Git Pocket Guide] + +== Установка + +В Debian/Ubuntu: + +[source,sh] +---- +sudo apt-get install git +---- + +== Термины + +[width="100%",cols="16%,17%,67%",options="header",] +|=== +|Термин |Англ |Определение +|Рабочий каталог |working tree, working directory |Набор файлов в +текущем каталоге + +|Репозиторий |repository, repo |Контейнер, хранящий историю изменений +файлов проекта + +|Индекс |index, staging area |Область между рабочим каталогом и +репозиторием, в которой осуществляется подготовка к фиксации + +|SHA-1 |SHA-1 |Уникальный идентификатор, отражающий информацию об +истории + +|Ветка |branch |Именованная последовательность в истории изменений + +|Фиксация (коммит) |commit |Набор файлов, записанных в историю +одновременно + +|`HEAD` |`HEAD` |Имя ссылки на последнюю фиксацию в текущей ветке + +|Метка |tag |Именованная ссылка на некоторую фиксацию в истории +|=== + +== Состояния + +Файлы в рабочем каталоге могут отслеживаться системой контроля версий +(tracked) или нет (untracked). Отслеживаемые файлы, которые на диаграмме +обозначены зелёным фоном, могут быть неизменёнными (unmodified), +изменёнными (modified) или подготовленными к фиксации (staged). + +[plantuml] +---- +@startuml +participant untracked as "Неотслеживамые\n(untracked)" +box "Отслеживаемые" +participant staged as "Подготовленные к фиксации\n(staged)" #55FF55 +participant unmodified as "Неизменённые\n(unmodified)" #99FF99 +participant modified as "Изменённые\n(modified)" #77FF77 +end box + +untracked -> staged : git add +staged -> unmodified : git commit +unmodified -> modified : редактирование +modified -> staged : git add +modified -> untracked: git rm --cached +unmodified -> untracked: git rm --cached +staged -> untracked: git rm --cached +@enduml +---- + +Основные команды, осуществляющие взаимодействие между рабочим каталогом, +индексом, локальным и удалённым репозиторием, приведены на диаграмме +ниже. + +[plantuml] +---- +@startuml +participant workspace as "Рабочий каталог\n(working dir)" +participant index as "Индекс\n(index)" #77FF77 +participant local as "Локальный репозиторий\n(local repository)" #FF7777 +participant remote as "Удалённый репозиторий\n(remote repository)" #7777FF + +workspace -> local : git commit -a +workspace -> index : git add (-u) +index -> local : git commit +local -> remote : git push + +== Обновление с сервера == + +remote -> workspace : git pull (rebase) +remote -> local : fetch + +== Откат изменений == +local -[#red]> workspace : git checkout HEAD +index -[#red]> workspace : git checkout + +== Сравнение == +local -[#blue]> workspace : git diff HEAD +index -[#blue]> workspace : git diff + +@enduml +---- + +== Настройка + +[width="100%",cols="16%,38%,46%",options="header",] +|=== +|Команда |Ключи |Описание +|`git config` |`--global user.name "John Doe"` |Имя текущего +пользователя + +|`git config` |`--global user.email "mail@example.com"` |Почта текущего +пользователя + +|`git config` |`--list` |Вывод текущей конфигурации + +|`git config` |`--global --list` |Вывод глобальной конфигурации +|=== + +== Инициализация + +[width="100%",cols="19%,27%,54%",options="header",] +|=== +|Команда |Ключи |Описание +|`git init` |`` |Создать пустой репозиторий в каталоге `` + +|`git clone` |`` `` |Создать в каталоге `` копию +репозитория, находящегося по адресу `` + +|`git clone` |`--recursive ` `` |Создать в каталоге `` +копию репозитория, находящегося по адресу ``, с учётом +подмодулей +|=== + +== Подмодули + +[width="100%",cols="19%,27%,54%",options="header",] +|=== +|Команда |Ключи |Описание +|`git submodule` |`add ` |Добавить в каталог `` +текущего рапозитория подмодуль, находящийся по адресу `` + +|`git submodule` |`update --recursive --remote` |Обновить подмодули + +|`git submodule` |`sync --recursive` |Заменить адреса подмодулей на +указанные в файле `.gitmodules` +|=== + +Удаление подмодуля: + +[source,sh] +---- +git submodule deinit +git rm +---- + +== Фиксация + +[width="100%",cols="19%,27%,54%",options="header",] +|=== +|Команда |Ключи |Описание +|`git add` |`` |Подготовить файл `` к фиксации +                     + +|`git commit` | |Зафиксировать подготовленные файлы + +|`git commit` |`-a` |Зафиксировать все отслеживаемые файлы, которые были +изменены + +|`git rm` |`` |Удалить файл из индекса и рабочего каталога + +|`git rm` |`-f ` |Force deletion of files from disk + +|`git rm` |`--cached ` |Untrack file (without deleting) +|=== + +== Информация + +[width="100%",cols="20%,20%,60%",options="header",] +|=== +|Команда |Ключи |Описание +|`git status` |`-s`            |Вывод информации о рабочем каталоге в +краткой форме + +|`git log` |`--oneline` |Вывод журнала изменений в краткой форме + +|`git ls-files` | |Вывод списка отслеживаемых и подготовленных файлов +|=== + +== $push branches (see tags for pushing tags) + +[cols=",,",options="header",] +|=== +|Команда |Ключи |Описание +|`git push` |` ` |Push branch to remote +|`git push` |` --all` |Push all branches to remote +|`git push` |`--d ` |`--delete` remote branch +|=== + +== $remote + +* Remote connections are like bookmarks named after remote repos +* `git clone` automatically creates a remote connection usually called +`origin` + +[width="100%",cols="36%,26%,38%",options="header",] +|=== +|Команда |Ключи |Описание +|`git remote` |`-v` |List remote repository endpoints + +|`git branch` |`-r` |List remote repository branches + +|`git remote` |`add ` |Create namespaced connection to a +remote repository + +|`git remote` |`rename ` |Rename connection + +|`git remote` |`rm ` |Remove connection + +|`git remote` |`add origin ` |Set remote origin +|=== + +Reference: https://git-scm.com/docs/git-remote + +*Remove remote origin:* + +[source,shell] +---- +# Remove `origin` settings from .git/config +git remote rm origin + +# Remove `FETCH_HEAD` which still points to remote +git rm .git/FETCH_HEAD +---- + +== $fetch-pull + +[cols=",,",options="header",] +|=== +|Команда |Ключи |Описание +|`git fetch` |`` |Fetch all branches from remote (without merge) +|`git fetch` |` ` |Fetch specific branch +|`git merge` |`/` |Merge fetched remote +|`git pull` |`` |Fetch and merge in one command +|=== + +Reference: https://git-scm.com/docs/git-fetch, +https://git-scm.com/docs/git-pull + +== $branch + +[cols=",,",options="header",] +|=== +|Команда |Ключи |Описание +|`git branch` | |List branches + +|`git branch` |`` |Create new branch + +|`git checkout` |`` |Switch to branch, or commit + +|`git branch` |`-m ` |Rename branch + +|`git merge` |`` |Merge changes from `` to +current branch + +|`git branch` |`-d ` |`--delete` branch +|=== + +Reference: https://git-scm.com/docs/git-branch + +== $diff + +[cols=",,",options="header",] +|=== +|Команда |Ключи |Описание +|`git diff` | |Compare *`working directory`* and *`index`* +| |`–-cached` |Compare *`index`* and *`latest commit`* +| |`HEAD` |Compare *`latest commit`* and *`working directory`* +| |`--stat` |Optional short format +| |` ` |2 points in time to compare +| |` | ` |Compare whole directory or limit to file +|=== + +Reference: https://git-scm.com/docs/git-diff + +*Examples:* + +[source,shell] +---- +## compare changes made to README.md between working tree (default) and latest commit (HEAD) +$ git diff --stat HEAD ./path/README.md + +## compare changes made to README.md between 2 specific points in time (e.g. 2 commits) +$ git diff --stat a649900 24bdd58 ./path/README.md +---- + +== $tag + +[width="100%",cols="36%,26%,38%",options="header",] +|=== +|Команда |Ключи |Описание +|`git tag` | |List tags + +|`git tag` |`` |Create tag, from latest commit, lightweight + +|`git tag` |`-a -m ""` |Create tag, with `--annotate`, +from latest commit + +|`git tag` |`-a -m "" ` |Create tag, with +`--annotate`, from specific commit + +|`git tag` |`-d ` |`--delete` tag + +|`git show` |`` |Show tag data and message + +|`git checkout` |`` |Switch to specific point tag (not editable) + +|`git push` |` ` |Push specific tag to `` +(recommended) + +|`git push` |` --tags` |Push all tags to `` (only if +necessary) +|=== + +Инициализация репозитория в каталоге `dir`: + +[source,sh] +---- +git init dir +---- + +Клонирование репозитория `repo`, принадлежащего пользователю `user`, с +сервера `gitlab.2` в каталог `dir`: + +[source,sh] +---- +git clone git@gitlab.2:user/repo.git dir +---- + +Просмотр состояния рабочего каталога и репозитория: + +[source,sh] +---- +git status +---- + +Краткая форма вывода состояния: + +[source,sh] +---- +git status -s +---- + +Добавление файла `README.md` под версионный контроль и подготовка к +фиксации: + +[source,sh] +---- +git add README.md +---- + +Удаление файла `README.md` из индекса репозитория: + +[source,sh] +---- +git rm --cached README.md +---- + +Зафиксировать файлы, подготовленные к фиксации: + +[source,sh] +---- +git commit +---- + +Зафиксировать все отслеживаемые файлы, которые были изменены: + +[source,sh] +---- +git commit -a +---- + +Отправить все ветки репозитория на сервер с меткой `origin`: + +[source,sh] +---- +git push origin +---- diff --git a/wiki/Prog/Git/Git основные команды.md b/wiki/Prog/Git/Git основные команды.md deleted file mode 100644 index f6469c3..0000000 --- a/wiki/Prog/Git/Git основные команды.md +++ /dev/null @@ -1,311 +0,0 @@ ---- -title: "Git: основные команды" -category: Программирование -tags: программирование, git -monofontoptions: -- Scale=0.8 -... - - - - -## Ссылки - -* [GitHowTo](https://githowto.com/ru/changes_not_files) -* [ProGit](https://git-scm.com/book/ru/v2) -* [Git Pocket Guide](https://github.com/maxliscia/git-pocket) - -## Установка - -В Debian/Ubuntu: - -```sh -sudo apt-get install git -``` - -## Термины - - -| Термин | Англ | Определение | -| ------ | ------ | ----------------------- | -| Рабочий каталог | working tree, working directory | Набор файлов в текущем каталоге | -| Репозиторий | repository, repo | Контейнер, хранящий историю изменений файлов проекта | -| Индекс | index, staging area | Область между рабочим каталогом и репозиторием, в которой осуществляется подготовка к фиксации | -| SHA-1 | SHA-1 | Уникальный идентификатор, отражающий информацию об истории | -| Ветка | branch | Именованная последовательность в истории изменений | -| Фиксация (коммит) | commit | Набор файлов, записанных в историю одновременно | -| `HEAD` | `HEAD` | Имя ссылки на последнюю фиксацию в текущей ветке | -| Метка | tag | Именованная ссылка на некоторую фиксацию в истории | - - -## Состояния - -Файлы в рабочем каталоге могут отслеживаться системой контроля версий -(tracked) или нет (untracked). Отслеживаемые файлы, которые на диаграмме -обозначены зелёным фоном, могут быть неизменёнными (unmodified), -изменёнными (modified) или подготовленными к фиксации (staged). - -```plantuml -@startuml -participant untracked as "Неотслеживамые\n(untracked)" -box "Отслеживаемые" -participant staged as "Подготовленные к фиксации\n(staged)" #55FF55 -participant unmodified as "Неизменённые\n(unmodified)" #99FF99 -participant modified as "Изменённые\n(modified)" #77FF77 -end box - -untracked -> staged : git add -staged -> unmodified : git commit -unmodified -> modified : редактирование -modified -> staged : git add -modified -> untracked: git rm --cached -unmodified -> untracked: git rm --cached -staged -> untracked: git rm --cached -@enduml -``` - -Основные команды, осуществляющие взаимодействие между рабочим каталогом, -индексом, локальным и удалённым репозиторием, приведены на диаграмме ниже. - -```plantuml -@startuml -participant workspace as "Рабочий каталог\n(working dir)" -participant index as "Индекс\n(index)" #77FF77 -participant local as "Локальный репозиторий\n(local repository)" #FF7777 -participant remote as "Удалённый репозиторий\n(remote repository)" #7777FF - -workspace -> local : git commit -a -workspace -> index : git add (-u) -index -> local : git commit -local -> remote : git push - -== Обновление с сервера == - -remote -> workspace : git pull (rebase) -remote -> local : fetch - -== Откат изменений == -local -[#red]> workspace : git checkout HEAD -index -[#red]> workspace : git checkout - -== Сравнение == -local -[#blue]> workspace : git diff HEAD -index -[#blue]> workspace : git diff - -@enduml -``` - - - -## Настройка - -| Команда | Ключи | Описание | -| ---- | ---------- | ------------ | -| `git config` | `--global user.name "John Doe"` | Имя текущего пользователя | -| `git config` | `--global user.email "mail@example.com"` | Почта текущего пользователя | -| `git config` | `--list` | Вывод текущей конфигурации | -| `git config` | `--global --list` | Вывод глобальной конфигурации | - - -## Инициализация - -| Команда | Ключи | Описание | -| ---- | ------ | ------------ | -| `git init` | `` | Создать пустой репозиторий в каталоге `` | -| `git clone` | `` `` | Создать в каталоге `` копию репозитория, находящегося по адресу `` | -| `git clone` | `--recursive ` `` | Создать в каталоге `` копию репозитория, находящегося по адресу ``, с учётом подмодулей | - - -## Подмодули - -| Команда | Ключи | Описание | -| ---- | ------ | ------------ | -| `git submodule` | `add ` | Добавить в каталог `` текущего рапозитория подмодуль, находящийся по адресу `` | -| `git submodule` | `update --recursive --remote` | Обновить подмодули | -| `git submodule` | `sync --recursive` | Заменить адреса подмодулей на указанные в файле `.gitmodules` | - - -Удаление подмодуля: - -```sh -git submodule deinit -git rm -``` - -## Фиксация - -| Команда | Ключи | Описание | -| ---- | ------ | ------------ | -| `git add` | `` | Подготовить файл `` к фиксации                     | -| `git commit` | | Зафиксировать подготовленные файлы | -| `git commit` | `-a` | Зафиксировать все отслеживаемые файлы, которые были изменены | -| `git rm` | `` | Удалить файл из индекса и рабочего каталога | -| `git rm` | `-f ` | Force deletion of files from disk | -| `git rm` | `--cached ` | Untrack file (without deleting) | - - -## Информация - -| Команда | Ключи | Описание | -| ---- | ---- | ------------ | -| `git status` | `-s`            | Вывод информации о рабочем каталоге в краткой форме | -| `git log` | `--oneline` | Вывод журнала изменений в краткой форме | -| `git ls-files` | | Вывод списка отслеживаемых и подготовленных файлов | - - -## $push branches (see tags for pushing tags) - -| Команда | Ключи | Описание | -| ---- | ------ | ------------ | -| `git push` | ` ` | Push branch to remote | -| `git push` | ` --all` | Push all branches to remote | -| `git push` | `--d ` | `--delete` remote branch | - -## $remote - -- Remote connections are like bookmarks named after remote repos -- `git clone` automatically creates a remote connection usually called `origin` - -| Команда | Ключи | Описание | -|---------|-------|----------| -| `git remote` | `-v` | List remote repository endpoints | -| `git branch` | `-r` | List remote repository branches | -| `git remote` | `add ` | Create namespaced connection to a remote repository | -| `git remote` | `rename ` | Rename connection | -| `git remote` | `rm ` | Remove connection | -| `git remote` | `add origin ` | Set remote origin | - -Reference: https://git-scm.com/docs/git-remote - -**Remove remote origin:** - -```shell -# Remove `origin` settings from .git/config -git remote rm origin - -# Remove `FETCH_HEAD` which still points to remote -git rm .git/FETCH_HEAD -``` - -## $fetch-pull - -| Команда | Ключи | Описание | -|---------|-------|----------| -| `git fetch` | `` | Fetch all branches from remote (without merge) | -| `git fetch` | ` ` | Fetch specific branch | -| `git merge` | `/` | Merge fetched remote | -| `git pull` | `` | Fetch and merge in one command | - -Reference: https://git-scm.com/docs/git-fetch, https://git-scm.com/docs/git-pull - - -## $branch - -| Команда | Ключи | Описание | -|---------|-------|----------| -| `git branch` | | List branches | -| `git branch` | `` | Create new branch | -| `git checkout` | `` | Switch to branch, or commit | -| `git branch` | `-m ` | Rename branch | -| `git merge` | `` | Merge changes from `` to current branch | -| `git branch` | `-d ` | `--delete` branch | - -Reference: https://git-scm.com/docs/git-branch - -## $diff - -| Команда | Ключи | Описание | -|---------|-------|----------| -| `git diff` | | Compare **`working directory`** and **`index`** | -| | `–-cached` | Compare **`index`** and **`latest commit`** | -| | `HEAD` | Compare **`latest commit`** and **`working directory`** | -| | `--stat` | Optional short format | -| | ` ` | 2 points in time to compare | -| | ` | ` | Compare whole directory or limit to file | - -Reference: https://git-scm.com/docs/git-diff - -**Examples:** - -```shell -## compare changes made to README.md between working tree (default) and latest commit (HEAD) -$ git diff --stat HEAD ./path/README.md - -## compare changes made to README.md between 2 specific points in time (e.g. 2 commits) -$ git diff --stat a649900 24bdd58 ./path/README.md -``` - -## $tag - -| Команда | Ключи | Описание | -|---------|-------|----------| -| `git tag` | | List tags | -| `git tag` | `` | Create tag, from latest commit, lightweight | -| `git tag` | `-a -m ""` | Create tag, with `--annotate`, from latest commit | -| `git tag` | `-a -m "" ` | Create tag, with `--annotate`, from specific commit | -| `git tag` | `-d ` | `--delete` tag | -| `git show` | `` | Show tag data and message | -| `git checkout` | `` | Switch to specific point tag (not editable) | -| `git push` | ` ` | Push specific tag to `` (recommended) | -| `git push` | ` --tags` | Push all tags to `` (only if necessary) | - - - - -Инициализация репозитория в каталоге `dir`: - -```sh -git init dir -``` - -Клонирование репозитория `repo`, принадлежащего пользователю `user`, -с сервера `gitlab.2` в каталог `dir`: - -```sh -git clone git@gitlab.2:user/repo.git dir -``` - -Просмотр состояния рабочего каталога и репозитория: - -```sh -git status -``` - -Краткая форма вывода состояния: - -```sh -git status -s -``` - -Добавление файла `README.md` под версионный контроль и подготовка -к фиксации: - -```sh -git add README.md -``` - -Удаление файла `README.md` из индекса репозитория: - -```sh -git rm --cached README.md -``` - -Зафиксировать файлы, подготовленные к фиксации: - -```sh -git commit -``` - -Зафиксировать все отслеживаемые файлы, которые были изменены: - -```sh -git commit -a -``` - -Отправить все ветки репозитория на сервер с меткой `origin`: - -```sh -git push origin -``` diff --git a/wiki/Prog/Git/Git распаковка объекта.adoc b/wiki/Prog/Git/Git распаковка объекта.adoc new file mode 100644 index 0000000..6c7ebc8 --- /dev/null +++ b/wiki/Prog/Git/Git распаковка объекта.adoc @@ -0,0 +1,10 @@ += Git: распаковка объекта +:category: Программирование +:tags: программирование, git, + +В случае повреждения репозитория можно восстановить отдельные объекты, +которые сохраняются в формате zlib. Пример команды: + +.... +perl -MCompress::Zlib -e 'undef $/; print uncompress(<>)' < 1234567890abcdef1234567890abcdef012345 > file +.... diff --git a/wiki/Prog/Git/Git распаковка объекта.md b/wiki/Prog/Git/Git распаковка объекта.md deleted file mode 100644 index 0bf9568..0000000 --- a/wiki/Prog/Git/Git распаковка объекта.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "Git: распаковка объекта" -category: Программирование -tags: программирование, git, -monofontoptions: -- Scale=0.7 -... - -В случае повреждения репозитория можно восстановить отдельные -объекты, которые сохраняются в формате zlib. Пример команды: - -``` -perl -MCompress::Zlib -e 'undef $/; print uncompress(<>)' < 1234567890abcdef1234567890abcdef012345 > file -``` diff --git a/wiki/Prog/Git/Git репозиторий на переносном устройстве.md b/wiki/Prog/Git/Git репозиторий на переносном устройстве.adoc similarity index 77% rename from wiki/Prog/Git/Git репозиторий на переносном устройстве.md rename to wiki/Prog/Git/Git репозиторий на переносном устройстве.adoc index 0a06677..0ffbdc1 100644 --- a/wiki/Prog/Git/Git репозиторий на переносном устройстве.md +++ b/wiki/Prog/Git/Git репозиторий на переносном устройстве.adoc @@ -1,26 +1,26 @@ ---- -title: "Git: репозиторий на переносном устройстве" -category: Программирование -tags: программирование, git, -... += Git: репозиторий на переносном устройстве +:category: Программирование +:tags: программирование, git, Создание репозитория для нового проекта: -```sh +[source,sh] +---- ln -s /media/user/usbdisk/git /home/user/work/usbdisk/git git --bare init /home/user/work/usbdisk/git/project.git cd /home/user/work/projects git clone /home/user/work/usbdisk/git/project.git cd project git remote set-url usb file:///home/user/work/usbdisk/git/project.git/ -``` +---- Добавление нового удалённого репозитория к существующему проекту: -```sh +[source,sh] +---- ln -s /media/user/usbdisk/git /home/user/work/usbdisk/git git --bare init /home/user/work/usbdisk/git/project.git cd /home/user/work/projects/project git remote add usb file:///home/user/work/usbdisk/git/project.git git push --set-upstream usb master -``` +---- diff --git a/wiki/Prog/Git/Git частичная копия репозитория.adoc b/wiki/Prog/Git/Git частичная копия репозитория.adoc new file mode 100644 index 0000000..425594a --- /dev/null +++ b/wiki/Prog/Git/Git частичная копия репозитория.adoc @@ -0,0 +1,29 @@ += Git: частичная копия репозитория +:category: Программирование +:tags: программирование, git, + +Если проект очень большой, а следить нужно только за малой его частью, +можно создать частичную копию репозитория. Допустим, по адресу +`git://localhost/project.git` находится большой проект, в котором +интересует только последнее состояние каталогов `src/driver` и +`include/driver`. Сначала нужно создать пустой репозиторий и подготовить +его для получения только необходимых файлов: + +[source,sh] +---- +git init project +cd project +git remote add origin git://localhost/project.git +git config core.sparsecheckout true +echo "src/driver/*" >> .git/info/sparse-checkout +echo "include/driver/*" >> .git/info/sparse-checkout +---- + +После этого можно получать частичную копию проекта, а, добавив ключ +`--depth=1`, указать, что синхронизироваться должно только текущее +состояние файлов без учёта истории. + +[source,sh] +---- +git pull --depth=1 origin master +---- diff --git a/wiki/Prog/Git/Git частичная копия репозитория.md b/wiki/Prog/Git/Git частичная копия репозитория.md deleted file mode 100644 index 1775e19..0000000 --- a/wiki/Prog/Git/Git частичная копия репозитория.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Git: частичная копия репозитория" -category: Программирование -tags: программирование, git, -summary: -... - -Если проект очень большой, а следить нужно только за малой -его частью, можно создать частичную копию репозитория. -Допустим, по адресу `git://localhost/project.git` находится -большой проект, в котором интересует только последнее -состояние каталогов `src/driver` и `include/driver`. -Сначала нужно создать пустой репозиторий и подготовить его -для получения только необходимых файлов: - -```sh -git init project -cd project -git remote add origin git://localhost/project.git -git config core.sparsecheckout true -echo "src/driver/*" >> .git/info/sparse-checkout -echo "include/driver/*" >> .git/info/sparse-checkout -``` - -После этого можно получать частичную копию проекта, -а, добавив ключ `--depth=1`, указать, что синхронизироваться -должно только текущее состояние файлов без учёта истории. - -```sh -git pull --depth=1 origin master -``` diff --git a/wiki/Prog/Git/Gitlab выполнение по расписанию.adoc b/wiki/Prog/Git/Gitlab выполнение по расписанию.adoc new file mode 100644 index 0000000..f30e2b7 --- /dev/null +++ b/wiki/Prog/Git/Gitlab выполнение по расписанию.adoc @@ -0,0 +1,38 @@ += GitLab: выполнение по расписанию +:category: Программирование +:tags: программирование, gitlab, git, + +После помещения изменений (push) на сервер следует выполнять только +задачи, не требующие много ресурсов. Ресурсоёмкие задачи можно отложить +на время минимальной нагрузки сервера. Для этого нужно: + +* в секциях файла `.gitlab-ci.yml`, запускающих задачи с высокой +нагрузкой, добавить + +[source,yaml] +---- +only: + - schedules +---- + +подробнее это описано +https://docs.gitlab.com/ee/ci/yaml/#only-and-except-simplified[здесь] + +* в веб-интерфейсе в меню *CI/CD* / *Расписания* добавить *Новое +расписание* и назначить исполнение задачи на время, когда нагрузка на +сервер минимальна. + +Для пропуска запланированной задачи в исполняемый скрипт нужно добавить +проверку условия запуска. Например, чтобы отменить запуск компиляции, +если за последний день (86400 секунд) не было изменений, можно оформить +`.gitlab-ci.yml` примерно так: + +[source,yaml] +---- +nightly-job: + only: + - schedules + script: + - "[ $(($(date +%s)-$(git log -1 --date=format:%s --format=%cd))) -gt 86400 ] && exit 0" + - make +---- diff --git a/wiki/Prog/Git/Gitlab выполнение по расписанию.md b/wiki/Prog/Git/Gitlab выполнение по расписанию.md deleted file mode 100644 index 72206e1..0000000 --- a/wiki/Prog/Git/Gitlab выполнение по расписанию.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "GitLab: выполнение по расписанию" -category: Программирование -tags: программирование, gitlab, git, -... - -После помещения изменений (push) на сервер следует выполнять только задачи, -не требующие много ресурсов. Ресурсоёмкие задачи можно отложить на время -минимальной нагрузки сервера. Для этого нужно: - -* в секциях файла `.gitlab-ci.yml`, запускающих задачи с высокой нагрузкой, -добавить - -```yaml -only: - - schedules -``` - - подробнее это описано [здесь](https://docs.gitlab.com/ee/ci/yaml/#only-and-except-simplified) - -* в веб-интерфейсе в меню **CI/CD** / **Расписания** добавить **Новое расписание** -и назначить исполнение задачи на время, когда нагрузка на сервер минимальна. - -Для пропуска запланированной задачи в исполняемый скрипт нужно добавить -проверку условия запуска. Например, чтобы отменить запуск компиляции, -если за последний день (86400 секунд) не было изменений, можно оформить -`.gitlab-ci.yml` примерно так: - -```yaml -nightly-job: - only: - - schedules - script: - - "[ $(($(date +%s)-$(git log -1 --date=format:%s --format=%cd))) -gt 86400 ] && exit 0" - - make -``` diff --git a/wiki/Prog/Git/Установка и настройка GitLab в LXC.md b/wiki/Prog/Git/Установка и настройка GitLab в LXC.adoc similarity index 79% rename from wiki/Prog/Git/Установка и настройка GitLab в LXC.md rename to wiki/Prog/Git/Установка и настройка GitLab в LXC.adoc index ea47599..0b3a2b4 100644 --- a/wiki/Prog/Git/Установка и настройка GitLab в LXC.md +++ b/wiki/Prog/Git/Установка и настройка GitLab в LXC.adoc @@ -1,33 +1,31 @@ ---- -title: "Установка и настройка GitLab в LXC" -category: Программирование -tags: программирование, gitlab, git, lxc, контейнеры, ubuntu, -summary: -toc: yes -... += Установка и настройка GitLab в LXC +:category: Программирование +:tags: программирование, gitlab, git, lxc, контейнеры, ubuntu, -[TOC] +:toc: Установка выполняется в операционной системе Ubuntu Bionic. -### LXC +== LXC Создание базового контейнера: -```sh +[source,sh] +---- lxc-create -t download -n bionic-base -- --dist ubuntu --release bionic --arch amd64 -``` +---- Создание контейнеров для GitLab и GitLab Runner: -```sh +[source,sh] +---- lxc-copy -n bionic-base -N gitlab-bionic -s lxc-copy -n bionic-base -N gitlab-runner-bionic -s -``` +---- Файл `/var/lib/lxc/gitlab-bionic/config`: -``` +.... # Distribution configuration lxc.include = /usr/share/lxc/config/common.conf @@ -50,11 +48,11 @@ lxc.autodev = 1 lxc.pty.max = 16384 lxc.cgroup.devices.allow = c 10:200 rwm lxc.mount.entry = /dev/net dev/net none bind,create=dir -``` +.... Файл `/var/lib/lxc/gitlab-runner-bionic/config`: -``` +.... # Distribution configuration lxc.include = /usr/share/lxc/config/common.conf @@ -82,65 +80,67 @@ lxc.autodev = 1 lxc.pty.max = 16384 lxc.cgroup.devices.allow = c 10:200 rwm lxc.mount.entry = /dev/net dev/net none bind,create=dir -``` +.... -### GitLab +== GitLab Установить GitLab: -```sh +[source,sh] +---- sudo lxc-start -n gitlab-bionic sudo lxc-attach -n gitlab-bionic sudo apt install curl curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash sudo apt install gitlab-ce -``` +---- -Отредактировать файл `/etc/locale.gen` и сгенерировать локали для системы: +Отредактировать файл `/etc/locale.gen` и сгенерировать локали для +системы: -```sh +[source,sh] +---- sudo locale-gen -``` +---- Отредактировать файл `/etc/gitlab/gitlab.rb` и выполнить: -```sh +[source,sh] +---- sudo gitlab-ctl reconfigure sudo gitlab-ctl restart -``` +---- - -### GitLab Runner и Docker +== GitLab Runner и Docker Установить GitLab Runner: -```sh +[source,sh] +---- sudo lxc-start -n runner-bionic sudo lxc-attach -n runner-bionic curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash sudo apt install gitlab-runner docker.io sudo gitlab-runner register -``` +---- Во время установки ввести токен приведённый на странице `admin/runners`, а в качестве исполнителя задач `docker`. Для работы Docker внутри контейнера нужно удалить AppArmor: -```sh +[source,sh] +---- sudo apt purge apparmor -``` +---- -Внутри контейнера для Docker желательно использовать драйвер `btrfs` -cat /etc/docker/daemon.json +Внутри контейнера для Docker желательно использовать драйвер `btrfs` cat +/etc/docker/daemon.json -{ - "storage-driver": "btrfs" -} +\{ ``storage-driver'': ``btrfs'' } +== Ссылки -### Ссылки - -* [GitLab Runner](https://docs.gitlab.com/runner/register/index.html) -* [Runners](https://docs.gitlab.com/ee/ci/runners/) -* [Gitlab-CI](https://habr.com/ru/company/southbridge/blog/306596/) +* https://docs.gitlab.com/runner/register/index.html[GitLab Runner] +* https://docs.gitlab.com/ee/ci/runners/[Runners] +* https://habr.com/ru/company/southbridge/blog/306596/[Gitlab-CI] diff --git a/wiki/Prog/Lang/CPP/Проверка именования в Clang Tidy.adoc b/wiki/Prog/Lang/CPP/Проверка именования в Clang Tidy.adoc new file mode 100644 index 0000000..0f36f8b --- /dev/null +++ b/wiki/Prog/Lang/CPP/Проверка именования в Clang Tidy.adoc @@ -0,0 +1,1364 @@ += Проверка именования в clang-tidy +:category: Программирование +:tags: C++, программирование, clang, clang-tidy, форматирование, + +:toc: + +Программа https://clang.llvm.org/extra/clang-tidy/[clang-tidy] может +проверить стилистику регистра идентификаторов, а также их префиксы и +суффиксы. Возможные варианты стилей: + +.... +lower_case +UPPER_CASE +camelBack +CamelCase +camel_Snake_Back +Camel_Snake_Case +aNy_CasE +.... + +Перечень вариантов идентификаторов приведён +https://clang.llvm.org/extra/clang-tidy/checks/readability-identifier-naming.html[здесь]. + +Для включения проверки именования идентификаторов нужно в находящемся в +корне проекта файле `.clang-tidy` включить данный тип диагностики (опция +`clang-diagnostic-*,readability-identifier-naming`), а затем указать +список выполняемых проверок и их параметры в формате YAML, например: + +[source,yaml] +---- +--- +Checks: 'clang-diagnostic-*,readability-identifier-naming' +CheckOptions: + - key: readability-identifier-naming.VariableCase + value: lower_case + - key: readability-identifier-naming.VariablePrefix + value: '' + - key: readability-identifier-naming.VariableSuffix + value: '' +... +---- + +https://git.246060.ru/f1x1t/clang-tidy-readability-identifier-naming[Проект] +с файлом `.clang-tidy`, в соответствии с которым проводятся проверки +именования идентификаторов. + +Перечень возможных параметров конфигурационного файла, их типовые +значения и примеры соответствующего кода приведены ниже. + +== Синтаксис + +=== AbstractClass (Абстрактный класс) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|AbstractClassCase |`CamelCase` +|AbstractClassPrefix |`''` +|AbstractClassSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ABSTRACT_CLASS { + public: + ABSTRACT_CLASS(); +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class AbstractClass { + public: + AbstractClass(); +}; +---- + +=== Class (Класс) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ClassCase |`CamelCase` +|ClassPrefix |`''` +|ClassSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class TEST_CLASS { + public: + TEST_CLASS(); + ~TEST_CLASS(); +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class TestClass { + public: + TestClass(); + ~TestClass(); +}; +---- + +=== Struct (Структура) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|StructCase |`CamelCase` +|StructPrefix |`''` +|StructSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +struct TEST_struct { + int a; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +struct TestStruct { + int a; +}; +---- + +=== Union (Объединение) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|UnionCase |`CamelCase` +|UnionPrefix |`''` +|UnionSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +union TEST_union { + int a; + char b; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +union TestUnion { + int a; + char b; +}; +---- + +=== Enum (Перечисление) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|EnumCase |`CamelCase` +|EnumPrefix |`''` +|EnumSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +enum TEST_enum { ONE, TWO }; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +enum TestEnum { ONE, TWO }; +---- + +=== EnumConstant (Значение в перечислении) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|EnumConstantCase |`UPPER_CASE` +|EnumConstantPrefix |`''` +|EnumConstantSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +enum TestEnum { one, TWO }; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +enum TestEnum { ONE, TWO }; +---- + +=== Namespace (Пространство имён) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|NamespaceCase |`lower_case` +|NamespacePrefix |`''` +|NamespaceSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +namespace TEST_ns { + +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +namespace test_ns { + +} +---- + +=== InlineNamespace (Вложенное пространство имён) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|InlineNamespaceCase |`lower_case` +|InlineNamespacePrefix |`''` +|InlineNamespaceSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +namespace test_ns { +inline namespace InlineNamespace { + +} +} // namespace test_ns +---- + +Пример кода после форматирования: + +[source,cpp] +---- +namespace test_ns { +inline namespace inline_namespace { + +} +} // namespace test_ns +---- + +=== TypeAlias (Псевдоним типа) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|TypeAliasCase |`lower_case` +|TypeAliasPrefix |`''` +|TypeAliasSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +struct MyStructure { + int a; +}; +using MY_STRUCT_TYPE = MyStructure; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +struct MyStructure { + int a; +}; +using MyStructType = MyStructure; +---- + +=== Typedef (Объявление типа) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|TypedefCase |`lower_case` +|TypedefPrefix |`''` +|TypedefSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +typedef int MY_INT; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +typedef int my_int; +---- + +== Переменные + +=== Variable (Переменная) ??? + +=== GlobalVariable (Глобальная переменная) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|GlobalVariableCase |`lower_case` +|GlobalVariablePrefix |`''` +|GlobalVariableSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +unsigned GlobalVariable; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +unsigned global_variable; +---- + +=== LocalVariable (Локальная переменная) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|LocalVariableCase |`camelBack` +|LocalVariablePrefix |`''` +|LocalVariableSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +int function() { + int LocalVariable = 0; + return LocalVariable; +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +int function() { + int localVariable = 0; + return localVariable; +} +---- + +=== StaticVariable (Статическая переменная) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|StaticVariableCase |`camelBack` +|StaticVariablePrefix |`''` +|StatucVariableSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +int functionWithStaticVariable() { + static int StaticVariable = 0; + return StaticVariable; +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +int functionWithStaticVariable() { + static int staticVariable = 0; + return staticVariable; +} +---- + +=== ConstexptVariable (Переменная constexpr) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ConstexprVariableCase |`lower_case` +|ConstexprVariablePrefix |`''` +|ConstexprVariableSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +constexpr int CONST_FIVE = 5; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +constexpr int const_five = 5; +---- + +=== GlobalPointer (Глобальный указатель) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|GlobalPointerCase |`lower_case` +|GlobalPointerPrefix |`''` +|GlobalPointerSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +void* globalPointer; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +void* global_pointer; +---- + +=== LocalPointer (Локальный указатель) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|LocalPointerCase |`camelBack` +|LocalPointerPrefix |`''` +|LocalPointerSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +void* function() { + void* LocalPointer = nullptr; + return LocalPointer; +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +void* function() { + void* localPointer = nullptr; + return localPointer; +} +---- + +=== Member (Член) ??? + +=== ClassMember (Член класса) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ClassMemberCase |`camelBack` +|ClassMemberPrefix |`''` +|ClassMemberSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithClassMember { + public: + static int CLASS_MEMBER; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithClassMember { + public: + static int classMember; +}; +---- + +=== ConstantMember (Константный член) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ConstantMemberCase |`lower_case` +|ConstantMemberPrefix |`''` +|ConstantMemberSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithConstantMember { + char const ConstMember[4] = "123"; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithConstantMember { + char const const_member[4] = "123"; +}; +---- + +=== PrivateMember (Приватный член) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|PrivateMemberCase |`camelBack` +|PrivateMemberPrefix |`'m_'` +|PrivateMemberSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithPrivateMember { + private: + int PrivateMember; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithPrivateMember { + private: + int m_privateMember; +}; +---- + +=== ProtectedMember (Защищённый член) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ProtectedMemberCase |`camelBack` +|ProtectedMemberPrefix |`''` +|ProtectedMemberSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithProtectedMember { + protected: + int ProtectedMember; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithProtectedMember { + protected: + int protectedMember; +}; +---- + +=== PublicMember (Публичный член) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|PublicMemberCase |`camelBack` +|PublicMemberPrefix |`''` +|PublicMemberSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithPublicMember { + public: + int PublicMember; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithPublicMember { + public: + int publicMember; +}; +---- + +== Константы + +=== Constant (Константа) ??? + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ConstantCase |`UPPER_CASE` +|ConstantPrefix |`''` +|ConstantSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +const int theOne = 1; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +const int THE_ONE = 1; +---- + +=== GlobalConstant (Глобальная константа) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|GlobalConstantCase |`UPPER_CASE` +|GlobalConstantPrefix |`''` +|GlobalConstantSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +const int theOne = 1; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +const int THE_ONE = 1; +---- + +=== LocalConstant (Локальная константа) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|LocalConstantCase |`camelBack` +|LocalConstantPrefix |`''` +|LocalConstantSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +int functionWithLocalConstant() { + const int LocalConstant = 0; + return LocalConstant; +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +int functionWithLocalConstant() { + const int localConstant = 0; + return localConstant; +} +---- + +=== StaticConstant (Статическая контстанта) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|StaticConstantCase |`camelBack` +|StaticConstantPrefix |`''` +|StaticConstantSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +int functionWithStaticConstant() { + const int StaticConstant = 0; + return StaticConstant; +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +int functionWithStaticConstant() { + const int staticConstant = 0; + return staticConstant; +} +---- + +=== ClassConstant (Константа класса) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ClassConstantCase |`UPPER_CASE` +|ClassConstantPrefix |`''` +|ClassConstantSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithClassConstant { + public: + static int const Class_Constant = 0; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithClassConstant { + public: + static int const CLASS_CONSTANT = 0; +}; +---- + +=== GlobalConstantPointer (Глобальный константный указатель) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|GlobalConstantPointerCase |`lower_case` +|GlobalConstantPointerPrefix |`''` +|GlobalConstantPointerSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +void* global_pointer; +void* const GlobalConstPointer = global_pointer; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +void* global_pointer; +void* const global_const_pointer = global_pointer; +---- + +=== LocalConstantPointer (Локальный константный указатель) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|LocalConstantPointerCase |`camelBack` +|LocalConstantPointerPrefix |`''` +|LocalConstantPointerSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +void* functionWithLocalConstPointer() { + void* pointer = nullptr; + void* const LocalConstPointer = pointer; + return LocalConstPointer; +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +void* functionWithLocalConstPointer() { + void* pointer = nullptr; + void* const localConstPointer = pointer; + return localConstPointer; +} +---- + +== Функции + +=== Function (Функция) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|FunctionCase |`camelBack` +|FunctionPrefix |`''` +|FunctionSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +static int static_function() { + return 0; +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +static int staticFunction() { + return 0; +} +---- + +=== GlobalFunction (Глобальная функция) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|GlobalFunctionCase |`camelBack` +|GlobalFunctionPrefix |`''` +|GlobalFunctionSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +int global_function() { + return 0; +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +int globalFunction() { + return 0; +} +---- + +=== ConstexprFunction (Функция constexpr) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ConstexprFunctionCase |`camelBack` +|ConstexprFunctionPrefix |`''` +|ConstexprFunctionSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +constexpr int get_five() { + return ( 5 ); +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +constexpr int getFive() { + return ( 5 ); +} +---- + +=== Method (Метод) ??? + +=== ClassMethod (Метод класса) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ClassMethodCase |`camelBack` +|ClassMethodPrefix |`''` +|ClassMethodSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithMethod { + public: + static int get_int() { return 0; }; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithMethod { + public: + static int getInt() { return 0; }; +}; +---- + +=== ConstexprMethod (Метод constexpr) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ConstexprMethodCase |`camelBack` +|ConstexprMethodPrefix |`''` +|ConstexprMethodSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithConstexprMethod { + private: + constexpr int get_int() { return 0; }; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithConstexprMethod { + private: + constexpr int getInt() { return 0; }; +}; +---- + +=== VirtualMethod (Виртуальный метод) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|VirtualMethodCase |`camelBack` +|VirtualMethodPrefix |`''` +|VirtualMethodSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithVirtualMethod { + private: + virtual int get_int() { return 0; }; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithVirtualMethod { + private: + virtual int getInt() { return 0; }; +}; +---- + +=== PrivateMethod (Приватный метод) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|PrivateMethodCase |`camelBack` +|PrivateMethodPrefix |`''` +|PrivateMethodSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithPrivateMethod { + private: + int get_int() { return 0; }; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithPrivateMethod { + private: + int getInt() { return 0; }; +}; +---- + +=== ProtectedMethod (Защищённый метод) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ProtectedMethodCase |`camelBack` +|ProtectedMethodPrefix |`''` +|ProtectedMethodSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithProtectedMethod { + protected: + int get_int() { return 0; }; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithProtectedMethod { + protected: + int getInt() { return 0; }; +}; +---- + +=== PublicMethod (Публичный метод) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|PublicMethodCase |`camelBack` +|PublicMethodPrefix |`''` +|PublicMethodSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +class ClassWithPublicMethod { + public: + int get_int() { return 0; }; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +class ClassWithPublicMethod { + public: + int getInt() { return 0; }; +}; +---- + +== Параметры + +=== Parameter (Параметр) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ParameterCase |`camelBack` +|ParameterPrefix |`''` +|ParameterSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +int returnInt(int return_Value) { + return return_Value; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +int returnInt(int returnValue) { + return returnValue; +}; +---- + +=== ConstantParameter (Константный параметр) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ConstantParameterCase |`camelBack` +|ConstantParameterPrefix |`''` +|ConstantParameterSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +char returnChar(const char return_Value) { + return return_Value; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +char returnChar(const char returnValue) { + return returnValue; +}; +---- + +=== ConstantPointerParameter (Константный указатель на параметр) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ConstantPointerParameterCase |`camelBack` +|ConstantPointerParameterPrefix |`''` +|ConstantPointerParameterSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +void* returnVoid(void* const return_Value) { + return return_Value; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +void* returnVoid(void* const returnValue) { + return returnValue; +}; +---- + +=== PointerParameter (Параметр типа указатель) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|PointerParameterCase |`camelBack` +|PointerParameterPrefix |`''` +|PointerParameterSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +void* returnPtr(void* return_Value) { + return return_Value; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +void* returnPtr(void* returnValue) { + return returnValue; +}; +---- + +== Шаблоны + +=== TemplateParameter (Параметр шаблона) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|TemplateParameterCase |`camelBack` +|TemplateParameterPrefix |`''` +|TemplateParameterSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +template int tFunction(TType t_value) { + return 0; +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +template int tFunction(TType tValue) { + return 0; +} +---- + +=== ParameterPack (Список параметров шаблона) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ParameterPackCase |`camelBack` +|ParameterPackPrefix |`''` +|ParameterPackSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +template void f(Types ... Parameters_Pack); +---- + +Пример кода после форматирования: + +[source,cpp] +---- +template void f(Types ... parametersPack); +---- + +=== TemplateTemplateParameter (Параметр шаблона шаблона) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|TemplateTemplateParameterCase |`camelBack` +|TemplateTemplateParameterPrefix |`''` +|TemplateTemplateParameterSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +template class TPL_TPL_Parameter> +class AllmightyClass { }; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +template class tplTplParameter> +class AllmightyClass { }; +---- + +=== TypeTemplateParameter (Типа параметра шаблона) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|TypeTemplateParameterCase |`CamelCase` +|TypeTemplateParameterPrefix |`''` +|TypeTemplateParameterSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +templateint tFunction(t_type value) { + return 0; +}; +---- + +Пример кода после форматирования: + +[source,cpp] +---- +templateint tFunction(TType value) { + return 0; +}; +---- + +=== ValueTemplateParameter (Значение параметра шаблона) + +[cols=",",options="header",] +|=== +|Параметр |Значение +|ValueTemplateParameterCase |`camelBack` +|ValueTemplateParameterPrefix |`''` +|ValueTemplateParameterSuffix |`''` +|=== + +Пример кода до форматирования: + +[source,cpp] +---- +template int tFunction(TType tValue) { + return 0; +} +---- + +Пример кода после форматирования: + +[source,cpp] +---- +template int tFunction(TType tValue) { + return 0; +} +---- diff --git a/wiki/Prog/Lang/CPP/Проверка именования в Clang Tidy.md b/wiki/Prog/Lang/CPP/Проверка именования в Clang Tidy.md deleted file mode 100644 index 28ff5f0..0000000 --- a/wiki/Prog/Lang/CPP/Проверка именования в Clang Tidy.md +++ /dev/null @@ -1,1227 +0,0 @@ ---- -title: "Проверка именования в clang-tidy" -category: Программирование -tags: C++, программирование, clang, clang-tidy, форматирование, -summary: -toc: yes -... - -[TOC] - -Программа [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) может -проверить стилистику регистра идентификаторов, а также их префиксы и суффиксы. -Возможные варианты стилей: - -``` -lower_case -UPPER_CASE -camelBack -CamelCase -camel_Snake_Back -Camel_Snake_Case -aNy_CasE -``` - -Перечень вариантов идентификаторов приведён -[здесь](https://clang.llvm.org/extra/clang-tidy/checks/readability-identifier-naming.html). - -Для включения проверки именования идентификаторов нужно в находящемся -в корне проекта файле `.clang-tidy` включить данный тип диагностики (опция -`clang-diagnostic-*,readability-identifier-naming`), а затем указать -список выполняемых проверок и их параметры в формате YAML, например: - -```yaml ---- -Checks: 'clang-diagnostic-*,readability-identifier-naming' -CheckOptions: - - key: readability-identifier-naming.VariableCase - value: lower_case - - key: readability-identifier-naming.VariablePrefix - value: '' - - key: readability-identifier-naming.VariableSuffix - value: '' -... -``` - -[Проект](https://git.246060.ru/f1x1t/clang-tidy-readability-identifier-naming) -с файлом `.clang-tidy`, в соответствии с которым проводятся проверки именования -идентификаторов. - -Перечень возможных параметров конфигурационного файла, их типовые значения -и примеры соответствующего кода приведены ниже. - - -## Синтаксис - -### AbstractClass (Абстрактный класс) - -Параметр | Значение --------------------------------|---------------- -AbstractClassCase | `CamelCase` -AbstractClassPrefix | `''` -AbstractClassSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ABSTRACT_CLASS { - public: - ABSTRACT_CLASS(); -}; -``` - -Пример кода после форматирования: - -```cpp -class AbstractClass { - public: - AbstractClass(); -}; -``` - -### Class (Класс) - -Параметр | Значение --------------------------------|---------------- -ClassCase | `CamelCase` -ClassPrefix | `''` -ClassSuffix | `''` - - -Пример кода до форматирования: - -```cpp -class TEST_CLASS { - public: - TEST_CLASS(); - ~TEST_CLASS(); -}; -``` - -Пример кода после форматирования: - -```cpp -class TestClass { - public: - TestClass(); - ~TestClass(); -}; -``` - -### Struct (Структура) - -Параметр | Значение --------------------------------|---------------- -StructCase | `CamelCase` -StructPrefix | `''` -StructSuffix | `''` - -Пример кода до форматирования: - -```cpp -struct TEST_struct { - int a; -}; - -``` - -Пример кода после форматирования: - -```cpp -struct TestStruct { - int a; -}; -``` - -### Union (Объединение) - -Параметр | Значение --------------------------------|---------------- -UnionCase | `CamelCase` -UnionPrefix | `''` -UnionSuffix | `''` - -Пример кода до форматирования: - -```cpp -union TEST_union { - int a; - char b; -}; -``` - -Пример кода после форматирования: - -```cpp -union TestUnion { - int a; - char b; -}; -``` - -### Enum (Перечисление) - -Параметр | Значение --------------------------------|---------------- -EnumCase | `CamelCase` -EnumPrefix | `''` -EnumSuffix | `''` - -Пример кода до форматирования: - -```cpp -enum TEST_enum { ONE, TWO }; -``` - -Пример кода после форматирования: - -```cpp -enum TestEnum { ONE, TWO }; -``` - - -### EnumConstant (Значение в перечислении) - -Параметр | Значение --------------------------------|---------------- -EnumConstantCase | `UPPER_CASE` -EnumConstantPrefix | `''` -EnumConstantSuffix | `''` - -Пример кода до форматирования: - -```cpp -enum TestEnum { one, TWO }; -``` - -Пример кода после форматирования: - -```cpp -enum TestEnum { ONE, TWO }; -``` - - -### Namespace (Пространство имён) - -Параметр | Значение --------------------------------|---------------- -NamespaceCase | `lower_case` -NamespacePrefix | `''` -NamespaceSuffix | `''` - -Пример кода до форматирования: - -```cpp -namespace TEST_ns { - -} -``` - -Пример кода после форматирования: - -```cpp -namespace test_ns { - -} -``` - - -### InlineNamespace (Вложенное пространство имён) - -Параметр | Значение --------------------------------|---------------- -InlineNamespaceCase | `lower_case` -InlineNamespacePrefix | `''` -InlineNamespaceSuffix | `''` - -Пример кода до форматирования: - -```cpp -namespace test_ns { -inline namespace InlineNamespace { - -} -} // namespace test_ns -``` - -Пример кода после форматирования: - -```cpp -namespace test_ns { -inline namespace inline_namespace { - -} -} // namespace test_ns -``` - - -### TypeAlias (Псевдоним типа) - -Параметр | Значение --------------------------------|---------------- -TypeAliasCase | `lower_case` -TypeAliasPrefix | `''` -TypeAliasSuffix | `''` - -Пример кода до форматирования: - -```cpp -struct MyStructure { - int a; -}; -using MY_STRUCT_TYPE = MyStructure; -``` - -Пример кода после форматирования: - -```cpp -struct MyStructure { - int a; -}; -using MyStructType = MyStructure; -``` - -### Typedef (Объявление типа) - -Параметр | Значение --------------------------------|---------------- -TypedefCase | `lower_case` -TypedefPrefix | `''` -TypedefSuffix | `''` - -Пример кода до форматирования: - -```cpp -typedef int MY_INT; -``` - -Пример кода после форматирования: - -```cpp -typedef int my_int; -``` - - -## Переменные - - -### Variable (Переменная) ??? - -### GlobalVariable (Глобальная переменная) - -Параметр | Значение --------------------------------|---------------- -GlobalVariableCase | `lower_case` -GlobalVariablePrefix | `''` -GlobalVariableSuffix | `''` - -Пример кода до форматирования: - -```cpp -unsigned GlobalVariable; -``` - -Пример кода после форматирования: - -```cpp -unsigned global_variable; -``` - - -### LocalVariable (Локальная переменная) - -Параметр | Значение --------------------------------|---------------- -LocalVariableCase | `camelBack` -LocalVariablePrefix | `''` -LocalVariableSuffix | `''` - -Пример кода до форматирования: - -```cpp -int function() { - int LocalVariable = 0; - return LocalVariable; -} -``` - -Пример кода после форматирования: - -```cpp -int function() { - int localVariable = 0; - return localVariable; -} -``` - -### StaticVariable (Статическая переменная) - -Параметр | Значение --------------------------------|---------------- -StaticVariableCase | `camelBack` -StaticVariablePrefix | `''` -StatucVariableSuffix | `''` - -Пример кода до форматирования: - -```cpp -int functionWithStaticVariable() { - static int StaticVariable = 0; - return StaticVariable; -} -``` - -Пример кода после форматирования: - -```cpp -int functionWithStaticVariable() { - static int staticVariable = 0; - return staticVariable; -} -``` - - -### ConstexptVariable (Переменная constexpr) - -Параметр | Значение --------------------------------|---------------- -ConstexprVariableCase | `lower_case` -ConstexprVariablePrefix | `''` -ConstexprVariableSuffix | `''` - -Пример кода до форматирования: - -```cpp -constexpr int CONST_FIVE = 5; -``` - -Пример кода после форматирования: - -```cpp -constexpr int const_five = 5; -``` - - -### GlobalPointer (Глобальный указатель) - -Параметр | Значение --------------------------------|---------------- -GlobalPointerCase | `lower_case` -GlobalPointerPrefix | `''` -GlobalPointerSuffix | `''` - -Пример кода до форматирования: - -```cpp -void* globalPointer; -``` - -Пример кода после форматирования: - -```cpp -void* global_pointer; -``` - -### LocalPointer (Локальный указатель) - -Параметр | Значение --------------------------------|---------------- -LocalPointerCase | `camelBack` -LocalPointerPrefix | `''` -LocalPointerSuffix | `''` - -Пример кода до форматирования: - -```cpp -void* function() { - void* LocalPointer = nullptr; - return LocalPointer; -} -``` - -Пример кода после форматирования: - -```cpp -void* function() { - void* localPointer = nullptr; - return localPointer; -} -``` - -### Member (Член) ??? - - -### ClassMember (Член класса) - -Параметр | Значение --------------------------------|---------------- -ClassMemberCase | `camelBack` -ClassMemberPrefix | `''` -ClassMemberSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithClassMember { - public: - static int CLASS_MEMBER; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithClassMember { - public: - static int classMember; -}; -``` - - -### ConstantMember (Константный член) - -Параметр | Значение --------------------------------|---------------- -ConstantMemberCase | `lower_case` -ConstantMemberPrefix | `''` -ConstantMemberSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithConstantMember { - char const ConstMember[4] = "123"; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithConstantMember { - char const const_member[4] = "123"; -}; -``` - -### PrivateMember (Приватный член) - -Параметр | Значение --------------------------------|---------------- -PrivateMemberCase | `camelBack` -PrivateMemberPrefix | `'m_'` -PrivateMemberSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithPrivateMember { - private: - int PrivateMember; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithPrivateMember { - private: - int m_privateMember; -}; -``` - - -### ProtectedMember (Защищённый член) - -Параметр | Значение --------------------------------|---------------- -ProtectedMemberCase | `camelBack` -ProtectedMemberPrefix | `''` -ProtectedMemberSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithProtectedMember { - protected: - int ProtectedMember; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithProtectedMember { - protected: - int protectedMember; -}; -``` - - -### PublicMember (Публичный член) - -Параметр | Значение --------------------------------|---------------- -PublicMemberCase | `camelBack` -PublicMemberPrefix | `''` -PublicMemberSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithPublicMember { - public: - int PublicMember; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithPublicMember { - public: - int publicMember; -}; -``` - - -## Константы - - -### Constant (Константа) ??? - -Параметр | Значение --------------------------------|---------------- -ConstantCase | `UPPER_CASE` -ConstantPrefix | `''` -ConstantSuffix | `''` - -Пример кода до форматирования: - -```cpp -const int theOne = 1; -``` - -Пример кода после форматирования: - -```cpp -const int THE_ONE = 1; -``` - - - -### GlobalConstant (Глобальная константа) - -Параметр | Значение --------------------------------|---------------- -GlobalConstantCase | `UPPER_CASE` -GlobalConstantPrefix | `''` -GlobalConstantSuffix | `''` - -Пример кода до форматирования: - -```cpp -const int theOne = 1; -``` - -Пример кода после форматирования: - -```cpp -const int THE_ONE = 1; -``` - - -### LocalConstant (Локальная константа) - -Параметр | Значение --------------------------------|---------------- -LocalConstantCase | `camelBack` -LocalConstantPrefix | `''` -LocalConstantSuffix | `''` - -Пример кода до форматирования: - -```cpp -int functionWithLocalConstant() { - const int LocalConstant = 0; - return LocalConstant; -} -``` - -Пример кода после форматирования: - -```cpp -int functionWithLocalConstant() { - const int localConstant = 0; - return localConstant; -} -``` - - -### StaticConstant (Статическая контстанта) - -Параметр | Значение --------------------------------|---------------- -StaticConstantCase | `camelBack` -StaticConstantPrefix | `''` -StaticConstantSuffix | `''` - -Пример кода до форматирования: - -```cpp -int functionWithStaticConstant() { - const int StaticConstant = 0; - return StaticConstant; -} -``` - -Пример кода после форматирования: - -```cpp -int functionWithStaticConstant() { - const int staticConstant = 0; - return staticConstant; -} -``` - -### ClassConstant (Константа класса) - -Параметр | Значение --------------------------------|---------------- -ClassConstantCase | `UPPER_CASE` -ClassConstantPrefix | `''` -ClassConstantSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithClassConstant { - public: - static int const Class_Constant = 0; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithClassConstant { - public: - static int const CLASS_CONSTANT = 0; -}; -``` - -### GlobalConstantPointer (Глобальный константный указатель) - -Параметр | Значение --------------------------------|---------------- -GlobalConstantPointerCase | `lower_case` -GlobalConstantPointerPrefix | `''` -GlobalConstantPointerSuffix | `''` - -Пример кода до форматирования: - -```cpp -void* global_pointer; -void* const GlobalConstPointer = global_pointer; -``` - -Пример кода после форматирования: - -```cpp -void* global_pointer; -void* const global_const_pointer = global_pointer; -``` - - -### LocalConstantPointer (Локальный константный указатель) - -Параметр | Значение --------------------------------|---------------- -LocalConstantPointerCase | `camelBack` -LocalConstantPointerPrefix | `''` -LocalConstantPointerSuffix | `''` - -Пример кода до форматирования: - -```cpp -void* functionWithLocalConstPointer() { - void* pointer = nullptr; - void* const LocalConstPointer = pointer; - return LocalConstPointer; -} -``` - -Пример кода после форматирования: - -```cpp -void* functionWithLocalConstPointer() { - void* pointer = nullptr; - void* const localConstPointer = pointer; - return localConstPointer; -} -``` - - - -## Функции - - -### Function (Функция) - -Параметр | Значение --------------------------------|---------------- -FunctionCase | `camelBack` -FunctionPrefix | `''` -FunctionSuffix | `''` - -Пример кода до форматирования: - -```cpp -static int static_function() { - return 0; -} -``` - -Пример кода после форматирования: - -```cpp -static int staticFunction() { - return 0; -} -``` - - -### GlobalFunction (Глобальная функция) - -Параметр | Значение --------------------------------|---------------- -GlobalFunctionCase | `camelBack` -GlobalFunctionPrefix | `''` -GlobalFunctionSuffix | `''` - -Пример кода до форматирования: - -```cpp -int global_function() { - return 0; -} -``` - -Пример кода после форматирования: - -```cpp -int globalFunction() { - return 0; -} -``` - - -### ConstexprFunction (Функция constexpr) - - -Параметр | Значение --------------------------------|---------------- -ConstexprFunctionCase | `camelBack` -ConstexprFunctionPrefix | `''` -ConstexprFunctionSuffix | `''` - -Пример кода до форматирования: - -```cpp -constexpr int get_five() { - return ( 5 ); -} -``` - -Пример кода после форматирования: - -```cpp -constexpr int getFive() { - return ( 5 ); -} -``` - - -### Method (Метод) ??? - - -### ClassMethod (Метод класса) - -Параметр | Значение --------------------------------|---------------- -ClassMethodCase | `camelBack` -ClassMethodPrefix | `''` -ClassMethodSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithMethod { - public: - static int get_int() { return 0; }; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithMethod { - public: - static int getInt() { return 0; }; -}; -``` - - -### ConstexprMethod (Метод constexpr) - -Параметр | Значение --------------------------------|---------------- -ConstexprMethodCase | `camelBack` -ConstexprMethodPrefix | `''` -ConstexprMethodSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithConstexprMethod { - private: - constexpr int get_int() { return 0; }; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithConstexprMethod { - private: - constexpr int getInt() { return 0; }; -}; -``` - -### VirtualMethod (Виртуальный метод) - -Параметр | Значение --------------------------------|---------------- -VirtualMethodCase | `camelBack` -VirtualMethodPrefix | `''` -VirtualMethodSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithVirtualMethod { - private: - virtual int get_int() { return 0; }; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithVirtualMethod { - private: - virtual int getInt() { return 0; }; -}; -``` - - -### PrivateMethod (Приватный метод) - -Параметр | Значение --------------------------------|---------------- -PrivateMethodCase | `camelBack` -PrivateMethodPrefix | `''` -PrivateMethodSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithPrivateMethod { - private: - int get_int() { return 0; }; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithPrivateMethod { - private: - int getInt() { return 0; }; -}; -``` - -### ProtectedMethod (Защищённый метод) - -Параметр | Значение --------------------------------|---------------- -ProtectedMethodCase | `camelBack` -ProtectedMethodPrefix | `''` -ProtectedMethodSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithProtectedMethod { - protected: - int get_int() { return 0; }; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithProtectedMethod { - protected: - int getInt() { return 0; }; -}; -``` - -### PublicMethod (Публичный метод) - -Параметр | Значение -----------------------------|---------------- -PublicMethodCase | `camelBack` -PublicMethodPrefix | `''` -PublicMethodSuffix | `''` - -Пример кода до форматирования: - -```cpp -class ClassWithPublicMethod { - public: - int get_int() { return 0; }; -}; -``` - -Пример кода после форматирования: - -```cpp -class ClassWithPublicMethod { - public: - int getInt() { return 0; }; -}; -``` - - -## Параметры - - -### Parameter (Параметр) - -Параметр | Значение --------------------------------|---------------- -ParameterCase | `camelBack` -ParameterPrefix | `''` -ParameterSuffix | `''` - -Пример кода до форматирования: - -```cpp -int returnInt(int return_Value) { - return return_Value; -}; -``` - -Пример кода после форматирования: - -```cpp -int returnInt(int returnValue) { - return returnValue; -}; -``` - - -### ConstantParameter (Константный параметр) - -Параметр | Значение --------------------------------|---------------- -ConstantParameterCase | `camelBack` -ConstantParameterPrefix | `''` -ConstantParameterSuffix | `''` - -Пример кода до форматирования: - -```cpp -char returnChar(const char return_Value) { - return return_Value; -}; -``` - -Пример кода после форматирования: - -```cpp -char returnChar(const char returnValue) { - return returnValue; -}; -``` - - -### ConstantPointerParameter (Константный указатель на параметр) - -Параметр | Значение --------------------------------|---------------- -ConstantPointerParameterCase | `camelBack` -ConstantPointerParameterPrefix | `''` -ConstantPointerParameterSuffix | `''` - -Пример кода до форматирования: - -```cpp -void* returnVoid(void* const return_Value) { - return return_Value; -}; -``` - -Пример кода после форматирования: - -```cpp -void* returnVoid(void* const returnValue) { - return returnValue; -}; -``` - -### PointerParameter (Параметр типа указатель) - -Параметр | Значение --------------------------------|---------------- -PointerParameterCase | `camelBack` -PointerParameterPrefix | `''` -PointerParameterSuffix | `''` - -Пример кода до форматирования: - -```cpp -void* returnPtr(void* return_Value) { - return return_Value; -}; -``` - -Пример кода после форматирования: - -```cpp -void* returnPtr(void* returnValue) { - return returnValue; -}; -``` - - -## Шаблоны - - -### TemplateParameter (Параметр шаблона) - -Параметр | Значение --------------------------------|---------------- -TemplateParameterCase | `camelBack` -TemplateParameterPrefix | `''` -TemplateParameterSuffix | `''` - -Пример кода до форматирования: - -```cpp -template int tFunction(TType t_value) { - return 0; -} -``` - -Пример кода после форматирования: - -```cpp -template int tFunction(TType tValue) { - return 0; -} -``` - - -### ParameterPack (Список параметров шаблона) - -Параметр | Значение --------------------------------|---------------- -ParameterPackCase | `camelBack` -ParameterPackPrefix | `''` -ParameterPackSuffix | `''` - -Пример кода до форматирования: - -```cpp -template void f(Types ... Parameters_Pack); -``` - -Пример кода после форматирования: - -```cpp -template void f(Types ... parametersPack); -``` - - -### TemplateTemplateParameter (Параметр шаблона шаблона) - -Параметр | Значение --------------------------------|---------------- -TemplateTemplateParameterCase | `camelBack` -TemplateTemplateParameterPrefix| `''` -TemplateTemplateParameterSuffix| `''` - -Пример кода до форматирования: - -```cpp -template class TPL_TPL_Parameter> -class AllmightyClass { }; -``` - -Пример кода после форматирования: - -```cpp -template class tplTplParameter> -class AllmightyClass { }; -``` - - -### TypeTemplateParameter (Типа параметра шаблона) - -Параметр | Значение --------------------------------|---------------- -TypeTemplateParameterCase | `CamelCase` -TypeTemplateParameterPrefix | `''` -TypeTemplateParameterSuffix | `''` - -Пример кода до форматирования: - -```cpp -templateint tFunction(t_type value) { - return 0; -}; -``` - -Пример кода после форматирования: - -```cpp -templateint tFunction(TType value) { - return 0; -}; -``` - - -### ValueTemplateParameter (Значение параметра шаблона) - -Параметр | Значение --------------------------------|---------------- -ValueTemplateParameterCase | `camelBack` -ValueTemplateParameterPrefix | `''` -ValueTemplateParameterSuffix | `''` - -Пример кода до форматирования: - -```cpp -template int tFunction(TType tValue) { - return 0; -} -``` - -Пример кода после форматирования: - -```cpp -template int tFunction(TType tValue) { - return 0; -} -``` - diff --git a/wiki/Prog/Links/Библиотеки C CPP.adoc b/wiki/Prog/Links/Библиотеки C CPP.adoc new file mode 100644 index 0000000..9b5575e --- /dev/null +++ b/wiki/Prog/Links/Библиотеки C CPP.adoc @@ -0,0 +1,29 @@ += Библиотеки для C, C++ +:category: Программирование +:tags: программирование, C, C++, Qt, + +:toc: + +== C + +* http://nanomsg.org[nanomsg]: сетевое взаимодействие +* https://noping.cc[oping]: работа с ICMP-пакетами +* https://github.com/xianyi/OpenBLAS[openblas]: оптимизированная версия +https://ru.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms[BLAS] + +== C++ + +* https://github.com/nlohmann/json[JSON] +* https://github.com/fmtlib/fmt[fmtlib]: форматирование строк +* https://github.com/gabime/spdlog[spdlog]: журналирование +* https://github.com/skystrife/cpptoml[cpptoml]: чтение +https://github.com/toml-lang/toml[TOML] +* https://github.com/martinmoene/gsl-lite/[gsl-lite]: реализация +рекомедаций https://github.com/isocpp/CppCoreGuidelines[C++ Core +Guidelines] +* http://www.holoborodko.com/pavel/mpfr[mpfrc++]: C++ интерфейс для +https://www.mpfr.org/[MPFR] + +== Qt + +* https://github.com/sjinks/qt_signalwatcher[Обработка сигналов UNIX] diff --git a/wiki/Prog/Links/Библиотеки C CPP.md b/wiki/Prog/Links/Библиотеки C CPP.md deleted file mode 100644 index 0887b77..0000000 --- a/wiki/Prog/Links/Библиотеки C CPP.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "Библиотеки для C, C++" -category: Программирование -tags: программирование, C, C++, Qt, -summary: -toc: yes -... - -[TOC] - -### C - -* [nanomsg](http://nanomsg.org): сетевое взаимодействие -* [oping](https://noping.cc): работа с ICMP-пакетами -* [openblas](https://github.com/xianyi/OpenBLAS): оптимизированная версия -[BLAS](https://ru.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms) - -### C++ - -* [JSON](https://github.com/nlohmann/json) -* [fmtlib](https://github.com/fmtlib/fmt): форматирование строк -* [spdlog](https://github.com/gabime/spdlog): журналирование -* [cpptoml](https://github.com/skystrife/cpptoml): чтение [TOML](https://github.com/toml-lang/toml) -* [gsl-lite](https://github.com/martinmoene/gsl-lite/): реализация рекомедаций [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) -* [mpfrc++](http://www.holoborodko.com/pavel/mpfr): C++ интерфейс для [MPFR](https://www.mpfr.org/) - -### Qt - -* [Обработка сигналов UNIX](https://github.com/sjinks/qt_signalwatcher) - diff --git a/wiki/Prog/Time/Работа с датами и временем.adoc b/wiki/Prog/Time/Работа с датами и временем.adoc new file mode 100644 index 0000000..a9b16fc --- /dev/null +++ b/wiki/Prog/Time/Работа с датами и временем.adoc @@ -0,0 +1,156 @@ += Работа с датами и временем +:category: Программирование +:tags: программирование, время, часы, дата, + +:toc: + +== Временные шкалы + +В идеале системы учёта времени должны обладать тремя характеристиками: + +[arabic] +. _точность_ (время базируется на атомном стандарте, каждая секунда +отсчитывается как секунда в системе СИ, нет високосных секунд, переводов +на зимнее или летнее время и т.п.); +. _простота_ (каждый '`день`' состоит из 86400 "`секунд`"); +. _календарные дни_ (дни календаря точно соответствуют вращению Земли). + +На практике есть возможность выбрать шкалу только с двумя +характеристиками из трёх. + +[arabic] +. точность и календарные дни. Примером такой шкалы является UTC, в +которой отсчёт дней и секунд ведётся разными методами (секунды +исчисляются по атомному стандарту, а дни по суточному вращению Земли), а +соответствие достигается вводом _секунды координации_; +. календарные дни и простота. Примером такой шкалы является POSIX (IEEE +Std 1003.1-1988), в которой день всегда равен 86400 секундам; +. точность и простота. Этими характеристиками обладают технические шкалы +(атомные часы, GPS), в которых не важен учёт дней. + +== Классы времени + +Время можно условно поделить на два класса: физическое и гражданское. + +[arabic] +. _Физическое_ время представляет собой точки на непрерывной шкале, +такую концепцию достаточно точно отражает UTC, если можно пренебречь +_секундой координации_ (дополнительная секунда, добавляемая к UTC 30 +июня или 31 декабря для согласования со средним солнечным временем UT1. +В этот момент время условно обозначается как 23:59:60, а на шкале UTC +две секунды отображаются как одна). +. _Гражданское_ время представляется полями (год, месяц, число, час, +минута, секунда, доли секунды, а также временная зона и календарь, +который по умолчанию считается Григорианским). + +Почти всегда существует возможность однозначно перевести физическое +время в гражданское и наоборот, но при этом следует различать их +свойства и применение (ближайшая аналогия — массивы байтов и символьные +строки). + +Основная проблема состоит в том, что в обычном употреблении не всегда +можно сделать вывод о том, какой класс времени подразумевается, и +гражданское время меняется на основании юридических актов (указов, +постановлений и т.п.), что приводит к неоднозначности при планировании +событий. + +== Обработка на компьютере + +=== Хранение и отображение + +Для ссылки на момент во времени необходимо использовать единую шкалу, на +которой нет разрывов, связанных с летним временем. Примером стандарта +времени с такой шкалой является UTC. Локальное или местное время для +таких целей не подходит, так как на его шкале имеются разрывы и +неоднозначности, связанные с переходами на летнее время и обратно. + +Если нужно сохранить значение локального времени, то необходимо +сохранить также смещение относительно UTC, чтобы временную отметку можно +было интерпретировать однозначно. Необходимо помнить, что местное время +может отличаться от UTC на интервал не кратный часу (например, в +Нидерландах с 1909-05-01 по 1937-06-30 смещение времени от UTC +составляло 19 минут и 32.13 секунд). + +Правила хранения и отображения времени: + +[arabic] +. Время всегда хранится в UTC. При необходимости дополнительно +сохраняется информация о временной зоне (смещение и/или название). +. Для вывода на экран время переводится в местное. +. При выводе на экран отличного от местного времени необходимо указывать +название часового пояса или типа исчисления (например, Юлианский +календарь). + +=== Системное время для администратора + +Системный администратор должен следить за тем, чтобы файлы базы данных +описания временных зон *tzdata* имели одну версию в рамках комплекса и +обновлялись регулярно, чтобы минимизировать расхождения с внешними +системами. Особенно это важно делать при издании новых правил учёта +зимнего или летнего времени. + +На серверах аппаратные часы всегда должны использовать UTC. Операционные +системы тоже должны использовать UTC, чтобы при возникновении проблем в +файлах журналов было указано время в едином формате. + +В рамках комплекса следует использовать синхронизацию времени, даже если +нет доверенного источника более высокого уровня. + +=== Клиентские приложения + +В общем случае нельзя доверять временным отметкам внешних клиентов, так +как невозможно гарантировать их корректность. Программа должна +самостоятельно ставить временные отметки для происходящих событий. +Исключением являются программные комплексы, в которых предусмотрено +наличие доверенных приложений, ответственных за установку временных +отметок. + +=== Postgresql + +Сервер базы данных должен использовать только временную зону UTC. Для +этого в файле настройки сервера `postgresql.conf` должна быть строка + +.... +timezone = 'UTC' +.... + +При создании таблиц необходимо использовать типы данных +`timestamp without time zone` и `time without time zone`. Если данные о +времени должны содержать информацию о временной зоне или смещении +относительно UTC, то нужно создать дополнительные столбцы, информацию из +которых должно обрабатывать клиентское приложение. Например, временные +отметки можно хранить в таком виде + +[source,sql] +---- +CREATE TABLE time_stamps ( + time_stamp time without time zone, -- временная отметка + time_zone character(12), -- текстовое название временной зоны + shift integer -- смещение локального времени относительно UTC в секундах +); +---- + +Смещение следует записывать в четырёхбайтное знаковое целое, так как оно +может быть как положительным, так и отрицательным, а его максимальное +значение может составлять 14 * 60 * 60 = 50400 секунд. Несмотря на +приведённый выше пример с временной зоной Нидерландов, микросекундами +можно пренебречь, так как современные временные зоны имеют смещения +кратные минутам, а точность до микросекунд в далёком прошлом обычно не +требуется. + +Чтобы клиентская программа могла получить выборку, привязанную к +некоторой временной зоне можно использовать оператор `AT TIME ZONE`, +например + +[source,sql] +---- +SELECT TIMESTAMP '2001-02-16 20:38:40Z' AT TIME ZONE 'MSK'; +---- + +В результате время будет преобразовано из временной зоны UTC в MSK. +Модификатор `Z` в записи времени указывает на принадлежность зоне UTC. + +=== Qt + +Класс `QTimeZone` предназначен для получения информации о временной зоне +и перевода времени из одной временной зоны в другую. diff --git a/wiki/Prog/Time/Работа с датами и временем.md b/wiki/Prog/Time/Работа с датами и временем.md deleted file mode 100644 index e28b121..0000000 --- a/wiki/Prog/Time/Работа с датами и временем.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -title: "Работа с датами и временем" -category: Программирование -tags: программирование, время, часы, дата, -summary: -toc: yes -toc-depth: 4 -... - -[TOC] - -### Временные шкалы - -В идеале системы учёта времени должны обладать тремя характеристиками: - -1. _точность_ (время базируется на атомном стандарте, каждая секунда -отсчитывается как секунда в системе СИ, нет високосных секунд, переводов -на зимнее или летнее время и т.п.); -2. _простота_ (каждый "день" состоит из 86400 "секунд"); -3. _календарные дни_ (дни календаря точно соответствуют вращению Земли). - -На практике есть возможность выбрать шкалу только с двумя характеристиками -из трёх. - -1. точность и календарные дни. Примером такой шкалы является UTC, -в которой отсчёт дней и секунд ведётся разными методами (секунды -исчисляются по атомному стандарту, а дни по суточному вращению Земли), -а соответствие достигается вводом _секунды координации_; - -2. календарные дни и простота. Примером такой шкалы является POSIX -(IEEE Std 1003.1-1988), в которой день всегда равен 86400 секундам; - -3. точность и простота. Этими характеристиками обладают технические -шкалы (атомные часы, GPS), в которых не важен учёт дней. - - -### Классы времени - -Время можно условно поделить на два класса: физическое и гражданское. - -1. _Физическое_ время представляет собой точки на непрерывной шкале, такую -концепцию достаточно точно отражает UTC, если можно пренебречь _секундой -координации_ (дополнительная секунда, добавляемая к UTC 30 июня или 31 декабря -для согласования со средним солнечным временем UT1. В этот момент время -условно обозначается как 23:59:60, а на шкале UTC две секунды отображаются -как одна). - -2. _Гражданское_ время представляется полями (год, месяц, число, час, минута, -секунда, доли секунды, а также временная зона и календарь, который по умолчанию -считается Григорианским). - -Почти всегда существует возможность однозначно перевести физическое время -в гражданское и наоборот, но при этом следует различать их свойства и -применение (ближайшая аналогия — массивы байтов и символьные строки). - -Основная проблема состоит в том, что в обычном употреблении не всегда можно -сделать вывод о том, какой класс времени подразумевается, и гражданское -время меняется на основании юридических актов (указов, постановлений и т.п.), -что приводит к неоднозначности при планировании событий. - -### Обработка на компьютере - -#### Хранение и отображение - -Для ссылки на момент во времени необходимо использовать единую шкалу, -на которой нет разрывов, связанных с летним временем. Примером стандарта -времени с такой шкалой является UTC. Локальное или местное время для таких -целей не подходит, так как на его шкале имеются разрывы и неоднозначности, -связанные с переходами на летнее время и обратно. - -Если нужно сохранить значение локального времени, то необходимо сохранить -также смещение относительно UTC, чтобы временную отметку можно было -интерпретировать однозначно. Необходимо помнить, что местное время может -отличаться от UTC на интервал не кратный часу (например, в Нидерландах -с 1909-05-01 по 1937-06-30 смещение времени от UTC составляло -19 минут и 32.13 секунд). - -Правила хранения и отображения времени: - -1. Время всегда хранится в UTC. При необходимости дополнительно сохраняется -информация о временной зоне (смещение и/или название). - -2. Для вывода на экран время переводится в местное. - -3. При выводе на экран отличного от местного времени необходимо указывать -название часового пояса или типа исчисления (например, Юлианский календарь). - - -#### Системное время для администратора - -Системный администратор должен следить за тем, чтобы файлы базы данных -описания временных зон **tzdata** имели одну версию в рамках комплекса -и обновлялись регулярно, чтобы минимизировать расхождения с внешними -системами. Особенно это важно делать при издании новых правил учёта -зимнего или летнего времени. - -На серверах аппаратные часы всегда должны использовать UTC. Операционные -системы тоже должны использовать UTC, чтобы при возникновении проблем -в файлах журналов было указано время в едином формате. - -В рамках комплекса следует использовать синхронизацию времени, даже -если нет доверенного источника более высокого уровня. - - -#### Клиентские приложения - -В общем случае нельзя доверять временным отметкам внешних клиентов, -так как невозможно гарантировать их корректность. Программа должна -самостоятельно ставить временные отметки для происходящих событий. -Исключением являются программные комплексы, в которых предусмотрено -наличие доверенных приложений, ответственных за установку временных отметок. - - -#### Postgresql - -Сервер базы данных должен использовать только временную зону UTC. Для этого -в файле настройки сервера `postgresql.conf` должна быть строка - -``` -timezone = 'UTC' -``` - -При создании таблиц необходимо использовать типы данных `timestamp without time zone` -и `time without time zone`. Если данные о времени должны содержать информацию -о временной зоне или смещении относительно UTC, то нужно создать дополнительные -столбцы, информацию из которых должно обрабатывать клиентское приложение. -Например, временные отметки можно хранить в таком виде - -```sql -CREATE TABLE time_stamps ( - time_stamp time without time zone, -- временная отметка - time_zone character(12), -- текстовое название временной зоны - shift integer -- смещение локального времени относительно UTC в секундах -); -``` - -Смещение следует записывать в четырёхбайтное знаковое целое, так как оно -может быть как положительным, так и отрицательным, а его максимальное -значение может составлять 14 * 60 * 60 = 50400 секунд. Несмотря на приведённый -выше пример с временной зоной Нидерландов, микросекундами можно пренебречь, -так как современные временные зоны имеют смещения кратные минутам, а точность -до микросекунд в далёком прошлом обычно не требуется. - -Чтобы клиентская программа могла получить выборку, привязанную к некоторой -временной зоне можно использовать оператор `AT TIME ZONE`, например - -```sql -SELECT TIMESTAMP '2001-02-16 20:38:40Z' AT TIME ZONE 'MSK'; -``` - -В результате время будет преобразовано из временной зоны UTC в MSK. -Модификатор `Z` в записи времени указывает на принадлежность зоне UTC. - - -#### Qt - -Класс `QTimeZone` предназначен для получения информации о временной зоне -и перевода времени из одной временной зоны в другую. - diff --git a/wiki/Vim/Vimdiff.adoc b/wiki/Vim/Vimdiff.adoc new file mode 100644 index 0000000..bdbb951 --- /dev/null +++ b/wiki/Vim/Vimdiff.adoc @@ -0,0 +1,18 @@ += Vim: сравнение файлов +:category: Vim +:tags: Vim, команды Vim, + +Команды режима `diff` для сравнения и слияния файлов: + +[cols="1,2",options="header",] +|=== +|Команда |Назначение +|`do` |Получить изменения из второго окна в текущее окно +|`dp` |Вставить изменения из текущего окна во второе окно +|`]c` |Перейти к следующему отличию +|`[c` |Перейти к предыдущему отличию +|`C-W` `C-W` |Переход между окнами +|=== + +http://vimcasts.org/episodes/fugitive-vim-resolving-merge-conflicts-with-vimdiff/[Видеоурок] +по трехпутевому слиянию. diff --git a/wiki/Vim/Vimdiff.md b/wiki/Vim/Vimdiff.md deleted file mode 100644 index 7534503..0000000 --- a/wiki/Vim/Vimdiff.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: "Vim: сравнение файлов" -category: Vim -tags: Vim, команды Vim, -summary: -... - -Команды режима `diff` для сравнения и слияния файлов: - -Команда | Назначение --------------|------------ -`do` | Получить изменения из второго окна в текущее окно -`dp` | Вставить изменения из текущего окна во второе окно -`]c` | Перейти к следующему отличию -`[c` | Перейти к предыдущему отличию -`C-W` `C-W` | Переход между окнами - -[Видеоурок](http://vimcasts.org/episodes/fugitive-vim-resolving-merge-conflicts-with-vimdiff/) -по трехпутевому слиянию. diff --git a/wiki/Vim/Замена выделенного блока.adoc b/wiki/Vim/Замена выделенного блока.adoc new file mode 100644 index 0000000..765aefb --- /dev/null +++ b/wiki/Vim/Замена выделенного блока.adoc @@ -0,0 +1,21 @@ += Vim: замена выделенного блока +:category: Vim +:tags: Vim, команды Vim, + +Замену блока, выделенного в режиме VISUAL, можно выполнить +последовательностью команд `y:%s/"/заменитель/g`. + +[cols="1,3",options="header",] +|=== +|Команда |Назначение +|`y` |Копирование в регистр " +|`:` |Перейти в командный режим +|`%` |Применить ко всему буферу +|`s` |Замена +|`Сtrl-r` |Вставка из регистра +|`"` |Имя регистра (будет предложено по умолчанию) +|`/` |Разделитель +|`заменитель` |Новый текст +|`/` |Разделитель +|`g` |Для всех вхождений в строке +|=== diff --git a/wiki/Vim/Замена выделенного блока.md b/wiki/Vim/Замена выделенного блока.md deleted file mode 100644 index 37af540..0000000 --- a/wiki/Vim/Замена выделенного блока.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "Vim: замена выделенного блока" -category: Vim -tags: Vim, команды Vim, -summary: -... - -Замену блока, выделенного в режиме VISUAL, можно выполнить -последовательностью команд `y:%s/"/заменитель/g`. - -Команда | Назначение ----------------|------------- -`y` | Копирование в регистр " -`:` | Перейти в командный режим -`%` | Применить ко всему буферу -`s` | Замена -`Сtrl-r` | Вставка из регистра -`"` | Имя регистра (будет предложено по умолчанию) -`/` | Разделитель -`заменитель` | Новый текст -`/` | Разделитель -`g` | Для всех вхождений в строке - diff --git a/wiki/Vim/Клавиши Leader и LocalLeader.md b/wiki/Vim/Клавиши Leader и LocalLeader.adoc similarity index 85% rename from wiki/Vim/Клавиши Leader и LocalLeader.md rename to wiki/Vim/Клавиши Leader и LocalLeader.adoc index cab91b5..6e794e5 100644 --- a/wiki/Vim/Клавиши Leader и LocalLeader.md +++ b/wiki/Vim/Клавиши Leader и LocalLeader.adoc @@ -1,39 +1,39 @@ ---- -title: "Vim: клавиши Leader и LocalLeader" -category: Vim -tags: Vim, команды Vim, -summary: -... += Vim: клавиши Leader и LocalLeader +:category: Vim +:tags: Vim, команды Vim, Клавиши `Leader` и `LocalLeader` представляют собой префиксы для команд. Их текущие значения можно посмотреть командами -```vim +[source,vim] +---- :echo mapleader :echo maplocalleader -``` +---- -Часто их значения переназначают в файле `$HOME/.vimrc`, например так +Часто их значения переназначают в файле `$HOME/.vim/vimrc`, например так -```vim +[source,vim] +---- let mapleader = "\" let maplocalleader = "," -``` +---- Новое значение команды генерируется с помощью текущих значений этих переменных, таким образом последовательность команд -```vim +[source,vim] +---- let mapleader = "," nnoremap a :echo "Hey there ," let mapleader = "\" nnoremap a :echo "Hey there space" -``` +---- приведёт к тому, что будут созданы две команды `,a` и `a`, следовательно для получения единообразных команд следует помещать -переназначения в начало файла `$HOME/.vimrc`. +переназначения в начало файла `$HOME/.vim/vimrc`. `LocalLeader` отличается от `Leader` тем, что действует только для текущего буфера, поэтому обычно используется в плагинах, загружаемых @@ -42,7 +42,7 @@ nnoremap a :echo "Hey there space" Таймауты для ввода команд, использующих клавиши `Leader` и `LocalLeader`, настраиваются командой -```vim +[source,vim] +---- set timeout timeoutlen=5000 ttimeoutlen=100 -``` - +---- diff --git a/wiki/Vim/Клавиши PageUp и PageDown.md b/wiki/Vim/Клавиши PageUp и PageDown.adoc similarity index 78% rename from wiki/Vim/Клавиши PageUp и PageDown.md rename to wiki/Vim/Клавиши PageUp и PageDown.adoc index 9996cd6..e998099 100644 --- a/wiki/Vim/Клавиши PageUp и PageDown.md +++ b/wiki/Vim/Клавиши PageUp и PageDown.adoc @@ -1,14 +1,12 @@ ---- -title: "Vim: клавиши PageUp и PageDown" -category: Vim -tags: Vim, команды Vim, -summary: -... += Vim: клавиши PageUp и PageDown +:category: Vim +:tags: Vim, команды Vim, Чтобы поведение клавиш `PageUp` и `PageDown` совпадало с более -привычным, можно добавить в `$HOME/.vimrc` следующий код: +привычным, можно добавить в `$HOME/.vim/vimrc` следующий код: -```vim +[source,vim] +---- " Более привычные PgUp / PgDown, когда курсор остаётся в той же строке, " " а не переносится вверх / вниз экрана, как при стандартном PgUp / PgDown. " " Поскольку по умолчанию прокрутка по C-U / C-D, при которой курсор остаётся @@ -18,5 +16,4 @@ nmap nmap imap imap -``` - +---- diff --git a/wiki/Vim/Кодировка файла.md b/wiki/Vim/Кодировка файла.adoc similarity index 92% rename from wiki/Vim/Кодировка файла.md rename to wiki/Vim/Кодировка файла.adoc index 265e3c5..0dbb9b9 100644 --- a/wiki/Vim/Кодировка файла.md +++ b/wiki/Vim/Кодировка файла.adoc @@ -1,15 +1,13 @@ ---- -title: "Vim: кодировка файла" -category: Vim -tags: Vim, -summary: -... += Vim: кодировка файла +:category: Vim +:tags: Vim, Для управления кодировкой файлов можно создать дополнительное меню, позволяющее открыть файл в выбранной кодировке, проверить её корректность и сохранить в нужном виде. Пример кода: -```vim +[source,vim] +---- " кодировка для чтения файла set encoding=utf-8 " кодировка терминала @@ -29,5 +27,4 @@ menu Encoding.Open\ as\ UCS-2LE :e ++enc=ucs-2le menu Encoding.Open\ as\ UTF-8 :e ++enc=utf-8 menu Encoding.Convert\ to\ UTF-8 :set fenc=utf-8 map :emenu Encoding. -``` - +---- diff --git a/wiki/Vim/Комментирование кода.adoc b/wiki/Vim/Комментирование кода.adoc new file mode 100644 index 0000000..bbdddd8 --- /dev/null +++ b/wiki/Vim/Комментирование кода.adoc @@ -0,0 +1,25 @@ += Vim: комментирование кода +:category: Vim +:tags: Vim, команды Vim, + +Отмена автоматического комментирования кода при вставке из буфера: + +[source,vim] +---- +autocmd FileType * setlocal formatoptions-=cro +---- + +Для управления комментированием можно использовать плагин +https://github.com/scrooloose/nerdcommenter[NerdCommenter]. Основные +команды: + +[cols="1,2",options="header",] +|=== +|Команда |Назначение +|`[n]cc` |комментировать блок +|`[n]cn` |комментировать с учётом вложенности +|`[n]cl` |символ комментария помещать в начало строки +|`[n]ci` |инвертирование комментариев +|`cA` |добавить комментарий в конец строки +|`[n]cu` |раскомментировать блок +|=== diff --git a/wiki/Vim/Комментирование кода.md b/wiki/Vim/Комментирование кода.md deleted file mode 100644 index ee765f0..0000000 --- a/wiki/Vim/Комментирование кода.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Vim: комментирование кода" -category: Vim -tags: Vim, команды Vim, -summary: -... - -Отмена автоматического комментирования кода при вставке из буфера: - -```Vim -autocmd FileType * setlocal formatoptions-=cro -``` - -Для управления комментированием можно использовать плагин -[NerdCommenter](https://github.com/scrooloose/nerdcommenter). -Основные команды: - -Команда | Назначение -----------------------|---------------------------- -`[n]cc` | комментировать блок -`[n]cn` | комментировать с учётом вложенности -`[n]cl` | символ комментария помещать в начало строки -`[n]ci` | инвертирование комментариев -`cA` | добавить комментарий в конец строки -`[n]cu` | раскомментировать блок - diff --git a/wiki/Vim/Менеджер плагинов Plug.md b/wiki/Vim/Менеджер плагинов Plug.adoc similarity index 60% rename from wiki/Vim/Менеджер плагинов Plug.md rename to wiki/Vim/Менеджер плагинов Plug.adoc index 3423668..43f5041 100644 --- a/wiki/Vim/Менеджер плагинов Plug.md +++ b/wiki/Vim/Менеджер плагинов Plug.adoc @@ -1,28 +1,28 @@ ---- -title: "Vim: менеджер плагинов Plug" -category: Vim -tags: Vim, плагины Vim, -summary: -... += Vim: менеджер плагинов Plug +:category: Vim +:tags: Vim, плагины Vim, -Автоматическое управление плагинами в Vim можно организовать -с помощью менеджера [Plug](https://github.com/junegunn/vim-plug), -установить который можно командой +Автоматическое управление плагинами в Vim можно организовать с помощью +менеджера https://github.com/junegunn/vim-plug[Plug], установить который +можно командой -```sh +[source,sh] +---- curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim -``` +---- -Чтобы использовать Plug, нужно добавить в `$HOME/.vimrc`: +Чтобы использовать Plug, нужно добавить в `$HOME/.vim/vimrc`: -1. Строку `call plug#begin('~/.vim/plugged')` -2. Список строк, начинающихся с команды `Plug`, для загрузки плагинов -3. Закончить список командой `call plug#end()` +[arabic] +* Строку `call plug#begin('~/.vim/plugged')` +* Список строк, начинающихся с команды `Plug`, для загрузки плагинов +* Закончить список командой `call plug#end()` Пример: -```vim +[source,vim] +---- " Обязательно использовать одиночные кавычки call plug#begin('~/.vim/plugged') @@ -40,5 +40,4 @@ Plug 'tpope/vim-fireplace', { 'for': 'clojure' } " Окончание списка плагинов call plug#end() -``` - +---- diff --git a/wiki/Vim/Навигация easymotion.md b/wiki/Vim/Навигация easymotion.adoc similarity index 82% rename from wiki/Vim/Навигация easymotion.md rename to wiki/Vim/Навигация easymotion.adoc index edde106..f35f6b6 100644 --- a/wiki/Vim/Навигация easymotion.md +++ b/wiki/Vim/Навигация easymotion.adoc @@ -1,15 +1,13 @@ ---- -title: "Vim: навигация по тексту с помощью easymotion" -category: Vim -tags: Vim, команды Vim, -summary: -... += Vim: навигация по тексту с помощью easymotion +:category: Vim +:tags: Vim, команды Vim, -Плагин [easymotion](https://github.com/easymotion/vim-easymotion) -предоставляет функции для удобного перемещения по тексту. -Пример настройки: +Плагин https://github.com/easymotion/vim-easymotion[easymotion] +предоставляет функции для удобного перемещения по тексту. Пример +настройки: -```vim +[source,vim] +---- " Не включать команды по умолчанию let g:EasyMotion_do_mapping = 0 @@ -49,5 +47,4 @@ omap / (easymotion-tn) " different highlight method and have some other features ) map n (easymotion-next) map N (easymotion-prev) -``` - +---- diff --git a/wiki/Vim/Навигация по буферам.adoc b/wiki/Vim/Навигация по буферам.adoc new file mode 100644 index 0000000..7d4585a --- /dev/null +++ b/wiki/Vim/Навигация по буферам.adoc @@ -0,0 +1,14 @@ += Vim: навигация по буферам +:category: Vim +:tags: Vim, команды Vim, + +[cols="1,2",options="header",] +|=== +|Команда |Назначение +|`:bn` |следующий буфер +|`:bp` |предыдущий буфер +|`:ls` |список открытых буферов +|`:bd` |закрыть текущий буфер +|`:b имя_буфера` |переключиться на буфер +|`:bdа имя_буфера` |удалить буфер по имени +|=== diff --git a/wiki/Vim/Навигация по буферам.md b/wiki/Vim/Навигация по буферам.md deleted file mode 100644 index a80c5e6..0000000 --- a/wiki/Vim/Навигация по буферам.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Vim: навигация по буферам" -category: Vim -tags: Vim, команды Vim, -summary: -... - -Команда | Назначение -------------------|----------------- -`:bn` | следующий буфер -`:bp` | предыдущий буфер -`:ls` | список открытых буферов -`:bd` | закрыть текущий буфер -`:b имя_буфера` | переключиться на буфер -`:bdа имя_буфера` | удалить буфер по имени - diff --git a/wiki/Vim/Нумерация строк.md b/wiki/Vim/Нумерация строк.adoc similarity index 73% rename from wiki/Vim/Нумерация строк.md rename to wiki/Vim/Нумерация строк.adoc index ae15507..11793ed 100644 --- a/wiki/Vim/Нумерация строк.md +++ b/wiki/Vim/Нумерация строк.adoc @@ -1,14 +1,12 @@ ---- -title: "Vim: нумерация строк" -category: Vim -tags: Vim, команды Vim, -summary: -... += Vim: нумерация строк +:category: Vim +:tags: Vim, команды Vim, -Для переключения режимов отображения слева столбца нумерации -строк можно добавить в `$HOME/.vimrc` следующий код: +Для переключения режимов отображения слева столбца нумерации строк можно +добавить в `$HOME/.vimrc` следующий код: -```vim +[source,vim] +---- " Нумерация строк включена set number " Нумерация строк абсолютная @@ -28,7 +26,7 @@ function! ChangeNumbering() endfunc map # :call ChangeNumbering() -``` +---- В результате по команде `#` будет осуществляться циклическое переключение между абсолютной, относительной нумерацией diff --git a/wiki/Vim/Проверка орфографии.md b/wiki/Vim/Проверка орфографии.adoc similarity index 74% rename from wiki/Vim/Проверка орфографии.md rename to wiki/Vim/Проверка орфографии.adoc index e5c3c2c..6094aa5 100644 --- a/wiki/Vim/Проверка орфографии.md +++ b/wiki/Vim/Проверка орфографии.adoc @@ -1,14 +1,12 @@ ---- -title: "Vim: проверка орфографии" -category: Vim -tags: Vim, команды Vim, словарь, орфография, -summary: -... += Vim: проверка орфографии +:category: Vim +:tags: Vim, команды Vim, словарь, орфография, -Код в `$HOME/.vimrc` для циклического переключения режимов проверки +Код в `$HOME/.vim/vimrc` для циклического переключения режимов проверки орфографии: два языка, английский, русский и без проверки: -```Vim +[source,vim] +---- " По умолчанию проверка орфографии для русского и английского. setlocal spell spelllang=ru,en set spellsuggest=9 @@ -35,5 +33,4 @@ map :call ChangeSpellLang() " выбор альтернатив imap z=i map z= -``` - +---- diff --git a/wiki/Vim/Ссылки.adoc b/wiki/Vim/Ссылки.adoc new file mode 100644 index 0000000..dc01a36 --- /dev/null +++ b/wiki/Vim/Ссылки.adoc @@ -0,0 +1,10 @@ += Vim: полезные ссылки +:category: Vim +:tags: Vim, + +* http://vim.org[Vim] +* http://usevim.com/[Usevim] +* http://nvie.com/posts/how-i-boosted-my-vim/[How I boosted my Vim] +* https://sheerun.net/2014/03/21/how-to-boost-your-vim-productivity/[How +to boost your Vim productivity] +* https://vimawesome.com/[Vim Awesome] diff --git a/wiki/Vim/Ссылки.md b/wiki/Vim/Ссылки.md deleted file mode 100644 index 631007b..0000000 --- a/wiki/Vim/Ссылки.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Vim: полезные ссылки" -category: Vim -tags: Vim, -summary: -... - -* [Vim](http://vim.org) -* [Usevim](http://usevim.com/) -* [How I boosted my Vim](http://nvie.com/posts/how-i-boosted-my-vim/) -* [How to boost your Vim productivity](https://sheerun.net/2014/03/21/how-to-boost-your-vim-productivity/) -* [Vim Awesome](https://vimawesome.com/) diff --git a/wiki/Vim/Управление окнами.adoc b/wiki/Vim/Управление окнами.adoc new file mode 100644 index 0000000..085954a --- /dev/null +++ b/wiki/Vim/Управление окнами.adoc @@ -0,0 +1,19 @@ += Vim: управление окнами +:category: Vim +:tags: Vim, команды Vim, + +[cols="1,2",options="header",] +|=== +|Команда |Назначение +|`:split filename` |открыть в новом окне (горизонтальное разделение) +|`:vsplit filename` |открыть в новом окне (вертикальное разделение) +|`` `` |перейти к следующему окну +|`` `q` |закрыть текущее окно +|`` `o` |развернуть окно полностью +|`` `pass:c[_]` |развернуть окно по высоте +|`` `\|` |развернуть окно по ширине +|`` `=` |выровнять размер окон +|`` `+` |увеличить окно на 1 строку +|`` `-` |уменьшить окно на 1 строку +|`` `стрелки` |перемещение между окнами +|=== diff --git a/wiki/Vim/Управление окнами.md b/wiki/Vim/Управление окнами.md deleted file mode 100644 index e9a2b19..0000000 --- a/wiki/Vim/Управление окнами.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Vim: управление окнами" -category: Vim -tags: Vim, команды Vim, -summary: -... - -Команда | Назначение ---------------------|------------------------- -`:split filename` | открыть в новом окне (горизонтальное разделение) -`:vsplit filename` | открыть в новом окне (вертикальное разделение) -`` `` | перейти к следующему окну -`` `q` | закрыть текущее окно -`` `o` | развернуть окно полностью -`` `_` | развернуть окно по высоте -`` `|` | развернуть окно по ширине -`` `=` | выровнять размер окон -`` `+` | увеличить окно на 1 строку -`` `-` | уменьшить окно на 1 строку -`` `стрелки` | перемещение между окнами - diff --git a/wiki/images/diag-81886ef1b8d31cdb2b865473bbeb2cf9.png b/wiki/images/diag-81886ef1b8d31cdb2b865473bbeb2cf9.png new file mode 100644 index 0000000000000000000000000000000000000000..35078e983754ceb8b95090b4fcf25b37be5c9d7f GIT binary patch literal 40071 zcmcG$byU=C+ct_Kq9ULmAT5HFlmgPAA}yhGgLF&H(1;QW0xI1lE!_+Qh;(-h3`jFD z43a~$FTCrypZELL-tQmVwOE7W%=NqSIFI8v&&v-gN-~7ksIKAQ;1J5mK6{CSb1?<{ zFkiU{-icR+%z+m+7bz_l6NlICwr1uoI5KATW=_T~W~O&ux!!R{uH5DjR-%Suhl<*)Z~E`Vm-5(6T7?1vuT3cxZh(iS2V?=G|xWwJ%T)j>$B zPv)pg)?Oed_52cM9iFlI9D!z~CNDM)^7nsS_n7V3iC?7V?S`9UkikzcUvzBsB{?@Z zW5x}_$fD$fp7`zj3iPa#33!_!OV=v4`XKc|cU<4nuov%G2eq>?*LS_Rp#}bEpLm8btL7nMomoKsocZpV7=X>j6C!&XFDm%H_ zSB|BrLt0?FSE~}Y2a~#AH&nBZrMI%K?DkJNVKo(K?8_M$4-}7h5PnH;F?d~+Yciyz zcA-BNH;3bK3xsyEK=iG&Gr{0430on$@SFWNNgAsUUMX$zTa_B^te+JT*~Qrba}3VL z*=@~Bh|#Y&Yw3MvOi!6_O-wmF#|t4CRee5TN;1^w!?=uI?$CRkSgP-{pK4u!kR6Q9 zD6?tNW}hT53%VoyGU^oG^W>Y>O4B2X!&o$5_VwX3MBcbY%vI(ZnNh8v)yKx{+*>6R z0i$KL70)VjSF8~&$1fvBt|Toq2EfS=aC>;Fy_ENF#Ngn(!I69RM9s|rope=;O#Q5l z`}GAgvS)fYcva67r6Q%CO_9C$^3bu%`v=~W7v&tDLsh2Rl7`5n2t!cuDka%*F{hFLlQ`6JdFmr)!{mEnu(X z6m#*-T{{1TmF5J};Cs@ViNwE2PL1_#V8igzek&p!aUZ>+aOIGxQTnTxPsd_04~Ea~Bm_npm6 zX_-al(jUd(jhJf$=2&h6!=$7n@BLr1^KIeFi;HCB zOe}jWGL+KO!w*SD-i<+Vb9HogPgU4xDk%}Ux<7g1S4~hbfN4$PM~CsK^T4Pj_KcwZ zxo;pZ6jQpN(xQmM9`Va`j-oEhv{VB%ZZH8wy8qRz?JcRZ8X(fF0rUFJSq4RxI ze~y9Pvsk1_?K|4OdweK_5^bQhA8LQMsr?NyRLEwW);RAC^5)Vtv+)z(GX?qw>4rZ7 zcWG$Q>u6iwBfETix`=1it1B@E@lNxt(+AsaeMutH0`CTKAp%R^My#;I#l-=iKMO=e zEJIiM1UQ}x;Jyvow98b11qEb|=8gE1uW)m&ne({!zqrdt!OSv)9=7t)8rMT!zd|Qn zsqQ-IJ)CnP{$;ri>&@%D@lY;>Y#soZLF#`kQXCB$&L;S6q1r`mF` zJ^ACumGsg%^FTS-&s%z7#P zd2A1cgM>8bk*!uZIkTciaF4&J81iU$%?mwF9zEOq;kkUG2=sXbbA4DCQMkmkOINhO zJ_fphQI@0BE;6vg$3G&X)frs8IP)w{;>cD=_jEO1UG0i4W`J>_X1TRwaVT3NUwf!T zJ)e2eo+OZGQrDp;gCG(Yf0Tk!950#6pZ{%|zScLL-MZH?{r#gH`g7lM?VI$IJ@SHz z8}Cx0#Zgsqm3x)OxyJD_5QpK6n+03lC!;&gHVdtqLB6W5o`q$==4b9vWI_xF;TjP- zkT6IEt_@Zn8RL-t@J9-PMHgIiCkrl3PjfQHRRqOaE>SWb2r5j-%6Vvdp zwXVDShpjT(c|-^HQ;*RBrC@Lq+Qmr}8p_Z~6)B+*1l}cP|yi zKFjcyuvSy{^|kQy>^$z{(sz5|vDTscQZ_OrWru-Dsjc7ds{l%RWL;_CtK8XT!lv=9 z{xleBSURkGRyTyJBIp;p5=LBB!|eNINJYxwh4n8|zM#Rlq6)RGxQkA*4|KfRXDFF-Ah z$VaA_*$kQMg^<5XN?h%y3<&Iv<6WN3D0t~gp3MCHe)Jb7ZYHLdiJIi3BuTgjZQ%8Z z7AzJ2s;BQ+^4?x=WQ{_M?^gQGXhc=n4T%O;l%#B8SQ@UJ14%&Ucv4#cfe4F|SE*T7 zE1GuSp+R4vM=d)HUkH7;D^>)5G&DN8*Pj-yy);oKb8s-y)9Z7#I`R#Vfcf))a`N#S zqq_-O-0d~DrltiPLSaX8xo_|Eh(KR2aS!dT9QnlMny7h?2QxGC%c{qcuy1-oGcyer zbbSsMQBxQa3q@B2McM*gapH(cF&^>$q7ZuL%1ubhZX1UVUA1FsKPKsHU?M+rto?-1 zVmeuf!zNahHhVnWWP;fqdrH3peeL*@e1oq+Rk0{u+1~wOE{~OIZ+mLTlR7@**nZ5; z%lbM^?n;i*BXqxtgg}*dpQy84>qoqsH<@ZwBUs85r|{`_Ha6ydJ{AcMh6~yunjz~t z9`0hXVhJpTtCM3h$Ry4)Lp8OEi6q+kT((!Z_=-DhITk|Q+^ zZU$RQX6`Xbg3Avk2)(GA$Vh~jWLHmu1Ztj?YpN41ZZk?>F8cbXbQ;qAc><(FANIk( zfYYMSr;+q%Pk#}E>5I-tKMkLRJ1_gH^nPZ<_9eP|ju&${DchpkY$GY3LR&Ir&a$~u#_-#Bs4@_irjtKF&R3;?M@b;k-9?a`JYra_fFjn;7*5s{Q zd}ht>9V~ikdA;`O@`zn8+?TISW?(3b=lgIoOP1#8oC^~XQ;FOy^D+@DTP$Xz!n#H& z?x9xXa=1i&Sy`EwlPNCe@`9J_a)W6HM|~88Uc8Q;bE;;W_Cx5cE`bUg?D$8@AL9>u z0tM_mLOItej>Zfd6i&0u^kHlEB$vDPI#?7E6Ro{ATXbtFgFBNi5?_U_A&N(Z$4epZxNmo_*TF4Z zRvM$@h#$4J2u)1#Dxg}Ck+(#s6V5_uyHuxFk+8TReBHuFFy5%aQUjA0m0`PU+aoQ= z+Jov^@|a|C#ZqW%+qNQ;XT1A1d`IJX?SR&?kOk3)xV)W-A?5RJz*Y*|VYr?|G- z=N8ERV6~3m)TyG2`}BIWwUz79BgJah_D|djr`b!#an|FQ+xM#!S z?7&A(XV{SXMMbUodFYlclTv(3so7Oks)i2%27mYLa93n!fwt3CXxQQ2EgQB&!A zM!e7LumPbJ?*5s7YdDX|Ja2GF*|#pD`g5=E5Er?hQ15eDR&M8ng=Q?8kTU=3j(GRh zMTuBWiFZZ)G2M8!;K7Pa!^{J& zDDBut7t0+>9k*dm-_WJj3hPby4nn_nAebILql8y~C-sT$fyP7OjzDf+SU8>c z`_iaAQ#p%LTALB;?$Q!e){V5LE~Kf&^5Yn`fq{*z)v}{RA>y@BJ7s><$eJR&HQn~f zldE1)OE5L_moJTLTt{uNj`LwJE3cAhR}rk;M$lQ2Z4Nqd(eYwqu~IdAOr|72oiaSaJIWNHhi znMk=OpLmh@GqMYL?|~z0U*9^H_bA|{-wm%GDRb0ca?;M%KV@YF2MX;pY1fLh3l^uPyRAM*@%1HAf84<1J~PsiBgbro)yLj` zChYe2|2S=bEO=I_r_+|AjEsO{2d4;k$RjB!_#Eoswl0?q_O3ux;MWL$|DiIA85a6+ z1VZA#^zzIDLBY@Y@6Xva?!B`Q^I^eZO--NJLZ>3XIK>PrwbFote`$vtqp&V5;_}l+qDEC5PCtdg};GQA2VQFLWL8WWVx)i#m*{+hG>{Q5Lg*46di=m3a?LmAYwfVz+EI(r1I&7eaBItiW9=@q;&XkoSs z=amrP_}C{C0)A^y`bG3w1zFn!eKSF`StS>dh+gMS@yOdB5V>${a`Y~9$S@6wdinD} zDQUda09KZhHu8nrb!Zo%Umenp8G83_O<2U2ghD1i@Z*T&asm1>7gzaf&!z5oopqb= zdc{;&%yh7vKs?V}yg-VE&WO`mE;h+s@*k`mBvhS9O1GQbp>5w6iV*;hB*~=3TtB$(ks!*)RS~#=lC1S~}Z~e>#m6z?vCd35Y zYRjCF)z!)`6{d6g9ll8mJD9<$`D6=hljz}g^1_;CqZCusmI|A+pq&!rz7>iWX5E9ssjHf`VkLA2L z*{DDIiKr+#+YG-ndt%mfV*)u*!>oU|Sp74S5HPxgxw1vyGfxQIqoPP}g46pN$1_OG z_~K{*ddwgJ_0y7Z@I+v!=U zAq<-M_j=eLnZ(q46$J&+z6%`X zB0VBD!@sT&BnUV!6_l9x{@UX@hXq;X)tuJO$-U-(yd z-;L?}KwFn820pi1V2-zWDcpm!s^lz%!Qsw70`({I7)ueXFQ@jm;OjvPr7x@s|W_gMm)5tEI2~)7{5m=jo||U zq%QD#y9D-Qi0SFR4pBbhsFmHirM2RNvA2xTG>Ch`m0cj3-4AHLz8xfc@1q;T+w9vW z&@Z*p^e$12yjY+7Doq7$5quG-FLrMTq1?cilu59jtP{CPu{h?WrBFGwYp8F-Unr$X zP56|$9UEF5<$dU~wQ20kPggthp0Q$>|5wj_du;mfFsnp^F{kd}R`33Pw1Gin%Feb2 z7PD~O9J)nVqvsY8Ki!91x3f#|^eFV$LGoVxu!@v2h3Zl#Fq*U$t4o4_Xfj#uUb}PO z)Wzxx3CY%SM$sp-nCZ*yN^L+BWFca*l$Sjz^MGW0QQ3&7u(7UCo7GHDcY86oJ6r+# z7qj<8mptJU$c%9<4dY4r+Itr6-=8nh_j7UN3y0EM)bxp~yaj|M<5O2aRoYcBR*xUF zlLJU(N>;&8w&5!jNmk@^GrPHsjq(_)_fetz$iWn{wH4AG%V<0Dse~%ZE5Oz^gj_ks zC!m{=i75c7(4J1>%5_pp1^+cV0$$AW^+i6#C$ZCz?Or<%+<;RF`ZuFwY0d+8-X!MA zcAy;Epym!N;;YmLxv>a;NDNz^J@gX6=jO>+4^DQ9F+o!_smt(`s0#{XjKhn6KBkYV|N+!LO^=coE2t7hnnOc~62yC_zi5 z2z@(-Dx!R$|NJ&^tS-P9yUB`SwHMF5CSzc(T?B^K{YX>n@p01hbTZI8g|OUU;}wl< zmgE&-*S!58Cq=R!L0D=5`#ZYP;{CA?N{&M|)UOMn#epNl;*ia@oYn7C#u8tVf-n#W zcPXctF72s)REv^soj0M|*zsaPy3hre9R*ko)g>kND#pFk+v|l41$y1nrDHAZ@<_5tNfOuBC-_w>0?ZI_#e@=CVJ1|TrZS%uNd{KNgo78XOUBaGtJ&-8 zNsHBkFFzu=^~M44`tGc-)F$N71){lZuB;o_@1RI~8%zzOcxsT@`ibVtMi$-SaD``N z>q)YRSWR%{?*R86I z(JVj>1&O-7eq&ebdf#(rMJw;+yUVW3&)vT44d$N}bougU6Fk&l*KKYZ>t_|D6JE zOeHB|(7<;R*{C|5ZJ3PF>#Nz85H1@jIipsfylhX?uHnhK(LyhjLETw;6g&-25clBI zbJWIH5Y4M&<=@@KAQRl(hWo8WMvMCBAKu@*;w}l|~5(~k@`L(UV$C`UiPO`zYyeJ&`jYNHBt#D?k)B9xS-!@??_ zJ~h9`l$bfe*(0v6N42xM%iL$RQnOT`8zcJV4X@8JH%SnwwA7l_$^a^mJz8h$E0TM4 z)Xu?SDG6g*qfMXSMP?9cDJcz7_2UYayE_hdgh z7|T7v`3duGR(FE{23Sa*Oo{KAaHlV3ilVkfgY~&RHu{IoWumJK`FCNH__8>+_*Ze%1OhKQd0D$YG&9@k>k* z+p>EH^VODdxI)a{hYykm*0Qo|zNgMQFLHO~runS}7Z%r3h05XZy#$Bp`&fpR<1}m0 z0QBkM8XNF>%*{@MvO~U7Q;dZ=q|Xm}!E;>ZFh7kNjDO^FBr)%}sHfRrC#$e8?hOr| zc0$fhvEt&>0HN~eT2MnNFR*0<@p=9o>zJ_?Zovn!MZxH4(L$k_XJZ$-+ZN322-iue zlZ{Yi^xcqMM>9x_4-gFc*Q)WWRfSv}KY8)SWwRv8rS7?#&+v*$-R>;)q>yN6{%KU- znZ&Z02EL&-m}(?jHg0Y zJK|Er#L-RE3VZgVMYw{KD=Ae~eLGu;lM7CC`{fwTP5`*VSb5<9pT6OB9E-AM0%p|i7_pjRd$|3K(uI2_4LGLb#d46 zI5zpS90Xy=ysrpnUZ)u^Fn}YP2;SeNMP0+rLC$7_T!f>4O}IR@+cr{v7^yh-m}6XI zTfM<wsCF*mZ#c6;mm zCYPejuz+k5*$=!ea$1%X%}W$BIH910DM*~}!KaMTe{DfKN2?arW#`#hyVYTap0Xyw z3H@4Dc!R*$=;YB^dOA@!B_rZ9oYyd^sz)~!(0gQhi%~ry2hE+OzM_o+d6z~_JV=bk zzh`TZEW=Mu=*N$geAR41t7J0!am-5q>0NITEbOaitsjLr5Ss%c+syTL1`i;H^w9r9T*q9Av`5a4PgT*f;Wdheg4q00fp!`1O6IT^%bE8`|>Z6y1 z!5GG&UTAEl!H>0saE*Rowk@s(dVu<`1z@k&SB@Z z3-s%O@XWA{J2&*KA)n!z*~Ce~G#qydd62h~C|VK z6{4Bc%(x(Rk3e!P1~8Jb+iuTl(-0WXrMM642wFT8h>8S3^X{92j}(iNlGa}M<(jQ?<<*=&;8DfS1qmHH zLhECnlWEc{0ec!+@<+;%HLGd2VH8oP@u9zxoL}DAHB{;ivgK!IkM&;Z)wsWN!^QZT z{$pTRl&182{#4kH;q#{Fw|)~6qIz;@FyGd;iy{>_3rOSd32lsWn5Ppf+D)Uw|oai@Z_dh!%d5yY#TpH11GHQf-rQQTam|)4QR7-VlrMT zNVrth8p7XrO&;GHwvCMR3~Y`R>bnZ4`!-_CfpUT6=Z9xx=#CW@t=fNKGlII}{qcEF?*WQ1G|zSE zI5PH+(hN`(QTPTq0<`A?3qlydBI-yZgotP^jgeHfRhr%zCEJBO@8^llhxSE}9S<7xKIUtu-J6Of4)d z%*_i88+9Y;xW?IXkx?HOOsN&p%##iD&Ok4UZ4nv9s!E_D2xPgMpFpoxCr- z*7af9VYXrZ;V16y?sN9{Lq=TAt9!IA-u7(NQ?va2`OWz@XD6o|z1r8Z_~f{*_^#Jn z30+mr%VZ`yU-2j9^p;(Y#%ZPFp&+C3Ox#*m(!8d2SN|dC(#Fe&HY^hNm0mvl>mdOF z0pKAD{4TF{`HC`=D#%pCXf5!J&~Y>$#Taw@$LAv*pzI-BGw8VOBtSs#C)Rfz_FWmNI#y9Dc1yx0Yi<3xe*&+Y;5pPhB zx7lyG(C|>)_AI>!!yS6Fq|Uk`XvD>{XNm{G&$`f)uhQ?>sAq)k2o6S{4u#~m$Thm8 zx|3ZKCWfn~m6&#$@LqBBb zJwZV?5Pjy<6q^2c(*x|!mMx^!0Y9kjQV|3FA%VV5l<*Z77DkMW@bmDzo+ve=3e8GQ zP1X8U5B2h@Te=y^ihvgv^E`Mk0P^!11v;cGN_DPl{?2m1T3AmCa~ z<}}pQ3RL1AJ1e_uW159}HLhzK@*jhPSI3GB4Gg9y$}C{6YtmgDyjBT`9zPrX5(FH= zKzQR~Yad-W1vOt|`I_8fV(_OEAHSs;oE~rYNd^(|+aY!`!o^7(@&!qH2skMJ-W3!n zf{t(3630R1R{+{)shhG>Ip7K@irtUI+1YtwHC*CUHviz@pd}OGbFw?8eTYHAtS>sEm#j@?`yv7UpBthP)1s}d&Bev#6&0z+0P_Vc zfU>W2fvVi+1sYwNXZ!QS?9OMWC!lqMDtlUmnJR~rvNGPjNA^?Il)UD}W{hQ&s*>zM z4OYG>?dFo4Q;Bdthv$$F5X1C^gA zKIW#q524^5T$GiTZVjatSV><96_{qlI(wM#4A(U_{pW(v(#+1zF8W~TsHqbY6OVs> zfA`Qcda%Lwti8QG#rO08JL79uVNG^41=J%~q>{8n3QR^urmS1qda~VCdQ?RgRJ4VL z_GlV^Fo+y>7f+#DPnTx-2>Pwb#Z zfkyt?(=UgSY^uk{$D(3lEQ;~X;&&Qe&tBAj;O6c=lB;Ub{Ql-K`~qWzo#`V+8`ihI zCHBZ#A|fJVV`Divxy2>?;CUsV?;Yxt*uv=RCOB`d`5{|uCo6k?{E$q%_GYj;(e-ti zMV~h#`7JN!XLW=)M(d53dtWm%?GWWCFheq7G*-x3*QZb43gY8jTi72gcd^^QJlWr; z(@O6-Z}NQcf(mi5=T)#VKZJ*8v%!jr9A3SeOA>)L3*o3Rw;7ySzEf;B52rJ{Bv#e| z7s=WJ=a+1P7W%sVTKw26Z1SqiAYdQ;Ol9zixv8+)0r2=A%&j1fh$IqBWRZy}HWK9M4rpP$G8COZnP z{ba7PuZ?iM`Dd$AQV{&dVn3@^aa4rjhP6Hr(dfMvd<0EeOs)ft2K9RzPRbRF*SrO+ra|0J1&$wJxZt8K1TOG+gdcmD(F54b3vAB#@ap_p+)g?2L9k!G|Th z=N&)*RR(5ue`A~sz{OxohVK5qD z?oXRj&V6!I>SN_rL*3oaE4_aGe3FJ_0jpy*__d)-gCa1VLQC-PbHU9ZDq1(yhcq!U ziHL{*YpG)1H`r12-*~k(iLoR(+Zj?`BM0l#?uUzCS6Amk+;*GKQbkXXhVoRKaX%e$)EC ze%d22!)G&!2J~%?mc1+K_-#b~LySJB6`>Uq80^D;j;p{IyU9v-H@EkyJ>S6|aw%f^ ziURS|!=qNP!dkCaxVi>X^bZ8$ypg&Hi}@5CU1>Fx1rjVYLQekXKdxTAI!Cj*6yxjt z$$rM_o&LB5=X^MPv*dxQJJ|Z>mmu7;ol*BUH#hmru)Dj8&!5*hFNX;RtsWRp>r(SE zoY~P--FKQ}sqipjC&s~vzK$mP7;sfwk+ifWAB(}Lo=)z_0W`&FdD*=}A4_^ap>&0;a zWU`oW?C>Z7N+-H^_l^>b)86|KD-05!1-`ug?67F@kV8Pei1h zYq=d57+7eaU!tE!*;SM#mt)y>!H69Y*>hwjS9tyUS3JK>b8fW%;@Axw9DmU0u~xkZ zXG0(k&YepT{4J;d!YC`g__uH0zWRPN4VEunMkU=63-)Jo^D}^aIu+K6iGrJ>1-g-L zsKLxM$)M3()wan=&xQ8Snnea?ag&vHfF1yx0*b>zcnUh>jYZfL9qjK{*VHJ+^2~zW zN!Dp@N(h$rB3P3;fB@GiA1-VycCjcYU%z^Fpu)3cp#=;{^72 z$H&JP78dY{=^`h}B2Q0_WTd6fd2Ykm=~13~{`fKm z0DqdxL*b(-F=63&vqvu{rOkOu1LfOP+AiD?_)`rT<+#f=dLQk%y1Lp8q_+U9?Z5zS z)?$XNfo>Qe@i{DVi>D~dx;eEw#4%+=_Jv5BnfG{jGc-3HNR6I@ zj^UpZox3pHvVY;wR{)Z~f#~rgpVNj4RM<^wbd$IZr7t=(JT$Ho7v~%9IBk1Z)P2pl z`FX2O%-UK)Y^>XIFRdfd9Tp)ILxd4&X~vJ7qKpXf+>wl_Tv41x;Wx+&#ZI!ntm1D3 zb0e-F?V;Q!bwoqKKWPwyCBfasZ`v}6a2^f|%dqnM4Mrg%BsfN7e=9!nuElTf5)xs@ zoNklFJ#=Ek*&Jrh&_9_t7(({!B!$!4rHbeN=RB*P*A|_bB-C{M?@)BEJ#G9xA%@l& zb8P(op;>>ZQX8wtZiGH;^&F-C#hj%4X7X^OiT_ZV|5JMcTzVr9h6Y}3a3T2M{{@H?Fx5cx73x+gC0_f6r$Fbafpb1b043GR=buVS zY8Dk{g)10C*Rs-0h}EwA#dN_xXU@NU_ipT)Hlq?hZ86MMHL3)^^Bk^lV#z_bLcm~g zR%VY6wg(0V3JVMU{QSD2IfpFy@bK_j-u_9TQlAZAn3e!@bHz->$zQp44FSTZ0(NtA zqQ;p;R~(9=S@#6WNC$}3+=hmRhzQbkC%^&>+Cj7DA~Ar^VcH7>X%1Q(6)r$r9~1u{ z_!EZ^l;we^n;Uu>4l6GH6{Tt5=`z19)@on8Q%OSN%u4nY)j#1A^R4}zz|x;i_Z935x#Yiequ ziebM-4`X9vms5P}$KN2Wgm`(&lvBjje#Sm938N8edU!kx+=Mvx z8d!&!`g1n_bYRj^x)&s2(5%K-ixltZqOBTFz!T*bI5vU6o5FkyBBuY+i=3LWpQ+cs z4$~F!Xrto+p4e}4{wim_>Bo<*lPNKfy+L8I3~4MMb&Jw}!TaP{3+y zOZ$-cgjBaEC}gB1KxqzOwQ)!&di;UIwCF=D5(XVB)VFbP@ZDZg)VPASZ@Eq7*~s+g zh6_#$6Y<=$1@qa_$*EI*M=U~{fPf&R3*o&n4KG*EA6bQ4_+X}Lz{&w74LJH_nFX;z zwoO2LyDSS!HV9KiS|x8MPNw0WMfHd5ife$?%ZZqqn*Mrf1ijzdKaR_M;ZL{cBdYo@ zR&?*X=7{<~1geHSvNg5@pFQ*+9dq4PPe%ulrI-N3xZ^_m&3FqICZ_k!vKL|bao`%9 zKn>(5uWk6PSWwI4rQhQL@PLCeU*ohW@8u<`IN|N>O-f3-F;&CZ%WxH4=)~o{>s?z( z+SAKhcSPfjl4yOt=x613eq3YeNRC^nlH`6_RT@*HMWRHa@UzZO2hJS=UxIqR_RZK% z&2!f&FR)?j?v2tQ#g)n><$)$ZtQLHeIq5vXjiRZI1hRGDsrZ{(Y{*iTAcn#_n4FBreUq0FYKUnp* z7xFK!4`5CkElug$f4JZ|3XQe_D~AF{g}=14v>BHGXAu{Mizmt5Lxq#q8p2)AN~eXx zNvxDN(lbaAkDJOu<_-EZOqm7UW2_tnFz z^{J_kMSI_f#x6=pik(k#Y^J-SB^LNC`fv|*0Krt|*y`$PpbsrfO+Wp#x~x0|-4w*# zGK!`k+yzGEkWutfK`@frpl(0h_n1*wxK=%1gOK{s4#3Q6#|%NzV(VBWJ`qhdxbQ+E z+Vd0K+5kpZ%l!5BcjvvsJ*Onv@tOz>P^F7+F5s>X=Vpvp!|Uo^y?RyYFw9z57LjfXtv(1jArQHO|Y^K1X&sK&RR~evH%ellqaZ;H&2Mpw|J5Us2+A-pff)OLt%_ zmg_b6cvqqpIwB&N6|KQh4yEFc=d*gcczz+Vn&OEjS)>F5Lt1L;8@ttMxX5Jl!Lr0z z$0NXQf}LLaxiAdYxo=B_kZ;17@))K7z_oSOc^#Cx_}vBOx5&(qU$H7tODqSS>Euw%0A zD&&O3Rh(eSF-(fjA=~6m2TRJYW+3Pj@0}x0$CrDy?)|AxOu3ynIgbtwKJOP%j;;dK z)h)Mtk`HL|`F#3cCAF*pHYW%*H!)J_dAe0xoM3+xOY*`Z;FfWGx$dUtTd2Zz;)@0l zzqyTo)DLcfwVE&p1j8x^5%$XvYXF){KlMiEM4tM6#9=e3G7ShCM;i^<`pt3IEh5Bk zm~G4JDdhQU^RSY zW#w8GRx3pu4r;%)-EAn*W+Q&%oN-ZaEyNf2#}g8b;2gTY0@rR8^h#dg^^A-=X=sq! zrCX(kgb);bd3HY9!`(HjiPqL75Y@}&ON|4(_9iTv;44mkby5*WXtXV4B`1d!@r?JU zjoJF?W*fbY{Bja7ZOi3JWfW0gqv7;MIaFRlgP96erCqD3Y!xsUzo%MCZ?p2!6`x)= zJ0IEfcArGw!=c0k4Iojv1wQEH4rX3WyCqNm(DXg4{zY+U_JuN!UF+J1?cLqrYStS; zdYtH>#(Chv`@MZ&isjU;rQ`H)Z zx)@NLsHCKn?s7A*RF3|=`UWroOyg2KR@rpcXBs4CnvDz8Y6dMkl@t%hO~S$5%5DAj z6JPa#D@M>%y-Rds#M5#3!7^hQKD?cso#ET3Q|E!z)^K1diLJT+>qP&QHz4Ls@b*%$ zUhy&xEu_yI(TXN%pf`NJa2FIw7hAIm|2}g%WF4W#p_?@?Pr(Ylr{|w$3$8E3+O64T zc1E@C-K`ixr#zQ{ptW>D-@j*tRo!y4pkt)~YtGpF9dkd8VB95tJ|G(2400?0)2v1_ z2P~kk0E_^K2c3MtYtieqKO6M*g08MEbC*px6T|TovaM|yICo>$ZK9ah&_DENmoe*; zRTSPBrD>0?4i^5*G4k?m@pg0st&hGQH=LamY2;@{&j4~U!(@FvB=K_|cm$Bm zDtcpaF*7$3X>|)Mv@KwL1mqm44Z~mmLOP9i?a12q>q?E7R1z?@duS!}c*#3v)17o> z@l+vu7Z<*xH;GSp_ah^3IdLjd0%ia>m(R}1i%Pkt`M|KclY4Y@BqA*Qr5KPzc?$d{ zIA3Ojr|?vxAFgt;XpPknvrbq@2qSNa?NgZHeYj?#m)vT)HJ|nH`@HWG1u;37CvVZw zDLHGTAu|bXeYX$HPIMt02Ch$mZdI^zL*o}L~s3iiI^(_cB?S^n+p% z6`pPkAd6|EIyi0=jfCo2eb&XDuQ1fh1#4D{*N0+qV}t z$1iRf?NJb}N&gvm_m(o*DByg$YpNs*ChH3pEpn^xTCa!FP)YCwUn3xBF(GJwH(|*4 zjT)#0ErFf%=Ve?r-treekx}vTIawa}vz}*L-E1$UJ_gzb2d5G7U+VH7vG0u`{r;S_0VR z0GRf-&0oF&Xk18WndhHLfO`2LHxSt}($m2)6+hjd2boQ9fBKQ_cs~*;#>~6~tY^`L z>39`7;o8tpLdALtF1_{{eM69Y%oG$78sGwskm-lOYb?|5%SiyOH`T$SEj^Wj6z%*U z69?zQH{0WX3g3KlXl?I}tRV&v)v@bUGp7g3Ddki^+r=;f2uWw`jpq+}cKT~pGFs6= z@pkzJn8x@=c83Ep^aG$CybZm+j=J^}WKPGc91P{${~t&SirkV%rw*heCXcW{nFyQKZ}3< zNdJB>F>&!^^7fhD-dX56-MeqiQsIX?D9P+c=HSwWOqeW% zQcnnUDN1(nlp7~U__scadH2~F8%8T4KYlV{k+PWY)j9>};F8oF5Z3X*<0m!C$)wZj zEOq*r?l|7c%1S`bW_5);Y@9adq(nquA3uHsUi&RFGWcdIb-FITi_frZ#m^ z*CtLtG%+wRIDY*UMv9A1gq~?Q1B=z(CL|&MK7tq!re0w`@xAbv>^sOWl1;z|LCJxb zC(sJ@3r*ylI-hRI{rGJwj==u36{SdL=3Zt4Q6+HqZc|H3ralbfxra7JxfI->q(m(& z3m&r2a=~WA}K?@L# ziF|VYH(x>y*5H~i>h|TWnNNfJFNHjQynnqhSYGA-i!%xI#+yZ*G+wTIbZXuoQq3?xQ-uc-Wd5*ZInng7_ilVVJa3H~0x%d%=>{0>SLbMHKbQCi1gOdz8`GJsZEhB- z=MDhTYKN*)*SnAPF)rT+I{N#|AQ2lax8w5QKO$*{b++W@kbu`$dVoW4a$1L~i%%0J z<{bnC1n!`;dE1GF<=#P_aWjmj8bS^*o8`7B9liT5RqR6`+rUQ496I07Xni%cMwg>U z)JXpE*lGn+PY@D-pmubwt*#ESx}iEc&=7rH=Cs~~U|i)LAelw#B*R|V1auqH>{qjp zewmdV`JU!*kMvydFBk($@Bh3LHg5L8ON@w()z%xp82ap&K_G;AueVjXOY5_j((QtK zB=6JRZ8Gr3L)6(ePzuQ`2u?;`bn9Ez~J{>VqLc=0^PY7l-#j;c?~4 z6%fKe-a$f4j4C!GybYwR9cWQXbvTd~iD^)`dsae10utAegb6;<-*@?E>0BwF0?t*m zk`;6&k6e!*QBNIvi-c-08Re=awg{vI{LLMdDr%d$p$6&Wp z{@O23Psc|OClEa(zD%(oKBS*=dF6(*6g(YP?RWXDo3RUPU zjg3<(N*+z8G*S}df=Z@0xpBrHm4C#1Gc(Csn2*m9AaQWLj9U=6KeRaBCLPRmfdGCp zLn^p~5UG2#9rN(v!(aWyF4grCC1xyr?K}|`c-oNvEDjc=I~`AnC_nbUu)G9fc2cGq z%gcXpF)(_c>%HbsAXw5fGoJ}j1=R8>BYY0`H?0igYG|>Y#fCqus(gJG z;HLu0M>0C&O|IHKhY!9-K?K-+zYLxUq9`y=lorP_?g3qU^ypE*B_89Ea$denW+wweyBB#)PjcYl;U$T>y%a37Ma4~* zmY3W0q_u!ZNW0~9dhn!wuLEc_+5q=6(}C)X>1AuLd*OkS$pRjmCe9R7^NeH{YnoMpQQ{wCh!|m$rnfT);h?4yQ znX0-#W?tdGu>f)Mr=ZeEwZ`6!C}ux4`?Z;lJl;4}+(ZcXqCN;2LCPWk-gGZH9`ZDhQz~ zRs=u|tJToq?qKVl;=Bj`PxS4sfet8LEIMC**@IQmfhNFE^|MX)Y5-V9;@V=+c#ua6~k11#|Vy=auu-5-<&u3z3Z(>Nj!Gv`6o zRPWM<9h56L!!5%O23&7|&E5|M1qH#Y)2_H3FKEM`9>v6jcjCl-n&ExJ!yU?r+b1JG zZj#rF>Q`2${Tv1?Ri(e+vHLeS9bE*s1=lM@Zg+pbXPylbhRyGTVHAm;t8!5_-uv!4 zOl7cyBjy3M%e~UiJ#oj*ioW8i^SWhd(`TncxRh=Kd{(L_0qgOuxR{-63z=}k&$-oF+BD9S@wtw zKp(CnBNB(zyjx#gQTqZIwAFNLBru$mXb;6%$4&XgCLt@QpQ~$Y%nJm>eIq~NFSXF$ z=B-WYo2`B$g2l*11^?C1`+&dTFTXV7e2v>@TIc5GU?VHUNEL?p+k*L^-K9Z+4RnWJ zdGZ8@l$111L-p-qMPvzZuva?{{0Z9I+8A^J>h8wDX3L=VgtVky{|P12PxNaS3RA3{ z=&n1i$c9`XrWF?z5z%!qM0w1xy^T)UxoyV^?HMb&#p~jUAtXGvxc3V&#lizh z-WsoQ6ar7jyFiS10nj4(N2B}s<>NZXLr%X#+d=BFq9Rm z3m!QM zI1hA~%s&F|9NJS#!v9$M+}8kHxu}hb2E46bc$DN@mCZT~!40evfP@`1qFDX9ipd%; z@;KWOgeE-|p6&&$iBq~*EacbQj4PY(+cCTWmk;i$7G^|R_QPyg{G^MAro ztoP;@DI4XU`d5Vszo_B`G-|94%>B-@0Dstby~*n{V(_Lqwt0DZKanlv2LA-3Ug0}m zbf$HtcQ!LHNUV4a?rfcsnDFK=eCZAR3HUlCrA|(^{qyGdQOdC(^k?pS*yq(3+!qOc z<|_%ftR6#t_KV<1kKkLryQxt$kYucJ{P#83VgQm8l4cM_zmgPB#;5fT(5_TzzO#9U zMO70RT^Qq$EFyS&SQW!xAQU*Kzj*RLg!(IJ!as9}-?7TSBo}|n{r{Ul{1X-bPARa% z1<@sb5z@_a^c@;9&BkoQ~DK}M7I3NnwR%(H}u>^rHll9C@l zQVtRx591SXJ9T)+(HkTr_)-f^zwgC0i1EzLasyO$ZfQvZ$RY4u_`TblV8wSqjdWKP zI&GpMSNC_5bf*6fV94oTr40u2c83400^o;Y#;}>Cc95N}wXiWg#cHq>6ciZy`*YN- z0p@}{f|Zke?Jpfgli*)EiZy_7u0Z1vViXE>&%^|rJBR+sl3hqNKvoGYEt`9|^sD%t z=DLKP7oc_vn7vg1k@CoBX=%mFv3iaEA3)~xL<)^#-puSTmV6#5w^Jqn$=3nkMW1?| z34wEBSI^7Jx)pOWCq(|x@QBKdpXC}{NnqURqyzM7Jhy?%qobp%LU2XBK6vRO0*!6~ zN>`o#o&B(yt8RfPO0FG3dU|5MYJfqyBO4)ix;6VNcX}gNBtvJq2~z+AHD3MJ0@8LC z5fe4Fv$5h_TuVSXI31O0W7jW4J!4`kWV^?JJ^(hXh>cVji6tSOP{*JH(hY&_>1e|z z!O0{4;8}n>U48f!XV7hhf&9GP&os)LRpynFi9xX`zAnHg7p4I*6y@X8j!lmk1j&Ur zAX>rKVah1U$d+5#3YTT7a8laA+&ze#=_rj$N;1^bMwVDrlLdc9X}5J<+1lQQ6gMdf z^m0APQjg)$m-S^365e}P(ExuK7}IA7vTgzv(~reshN>?Dw+)%&7OQrINc*|p^#@gU zB7_pWhf`q^{OPNJfQ8+Pk})^Wkf8(PXVah44^!+$udbEbzpAc*eUZ=DtT&;iz|ei3 zsatz_)tS(gQla)>Cztz_8dc^#1F66Z!M48ull#W&7u6@D;uo~tme+*dcjNb$Y46L=N z`}$>Frn#5&qN1-kzEfNUcFEAt5M@oNBBq8pJm#D8_?Mm`osKVZx6jtZ!Qi;jOxExt>P6lb?F3Q6qE|T^4P?H z^m%W&fwaj_A2U&_ytV;FDpQG|lI6Zug!F}=S2LfLGhv2+?k0eHgOKL~vI#{Q%vUJj zzv!}Euyj^z!Sb8$99LKVtbAasLRDAfq3p&gUc7wS12HPZAguR6CnZa9-Q9cfZ8M-~ zH`@RPPHsEJ#Z?HK?)f<$zuFZ^O%|u%$-kjAd*p33gTV=Uq;+etdB=q+jpPdiE>}3K zePf`niajMn$UZ(ko)cj5z8yhuO~>0kz4`p|k9GFW*3)*Zgo+Bl4>e|kQSxOJv}`DiO7^J08-kOCqzdl^%`3 z^~2r_CIc6H?zA6YdzPG$l*`Si?u`qp!lyvMJ6K1({&eO4OF|-Y8)-@)hzwQw8V>$M~>I3V>Ne|v1ri$@7@aa=BJxFv|Cd6@aAgI z2~lo7y$0fAtS5u;F7aIYL`QFsoczZ1QF5|T;}`K8nr9;BFwD8kR05cs_;b#K6*Jtm z+9fR)gcvWpkx7+vN@YGFVBk7M9`}{8*IQTMTR3KOl!IM?#!uEZ@s;!3dJ_)&8yY?E}isq67Rz7(DCy-fy-D_L(ko4 zch8pT-}%UJ((jTi$%wv0sYbZ_sS*R$J7qO1@LA9c26|-qHhw5T*368IL&L+kI5>HF zm8$eF!18N1Rq!Rfd`WM0?6h|L;NT!71;x(R)>UC)Y)@R+S*&F-fOqjf7~;-)2U${* z=PLdc&+h{qm&X9}$HNQcx%crk=sIdon{0yVWCYllnfc{9i1b1A?mXYq)X~Agz<|{< zq(Q%8?R_DiCQ0tAUDudCw~bDIB`o^NhyFW7&4ag zP6hzpL%XTDZiYnp4;a|cP!tdkV}ztt_QyFYD#8qa>c(REEGCZ~i;}C7MdrFv6^htk z3>u3jKhOmn`z$6Ug)IMoEmw0U!3r7G5un54e-$XNHGgRa(Dd+W$W^3b;kBNg@{5!c zc14YkA0U@%rm{`z{BUb(YPhP`Pb)sTO?FvNSNFCCHV)AeD?HHFEfuN9#UtT4>x#iA z7^%k1$;o+OV>8dHRichK1kG`}>Xq1NK4WjwgYSj4r`>#3nkW~jzIA|b5>J^4@K4B~ zL5NAA_~b;JDQ}fLE4+eQ0(7Y5u|MwV^cqQe@v2JdCASQe9#Y!a(QysPdw#AqP5ecE z0RaJC-c`UK8DF%cjL#IezD8~?^b;14-`W8&Vm7Kwphmqk-{aKd$HxQD5r}T$+>k-o zt)01e=gu7tZ%pE=S8A%Ns}Nb4>*kynK|D}UXvYe5fOpB$Ef3v(aqWsEnxqX%7kyX3 z{?`Katf)wwH;!}(t9=Rc*O4ej74>~#;g&yC-8@<~asu(>_3Ovv0D^FEaNs?+-`o`KdegCg{btcXzpT-w~yOA1l0Xy9p@f z^#TRvDRBgecxOikIOhemKGpzQ(Ylqp0rxq!oY3fv%w`v>y0rO}4v&` zQ|J9o@Ei%RUk_!&raNh(5HyP6*7n&@S2s#-9n)iq&h0BlRz5&gZ9s*mzxD=rW8;Bb zHP&G!*y?1BF=V-@7E{!?0r|x|2Pd@_(;W2Zuvr|I-2lE%VHj)!NH~G+Y~y?cM&Q!N zCqawjTR3cl8Yvnm&eYWJvE%LgijLF8tDIps77qrnaiZ{_s%-? z0;Mb4hFtjh?4^=Otns>KaU30reYOPRQjwpQPEZCU)qc_{MIMT0FJ5g_nXF{FOkXVG zy?gy%A6dG{NEmI#UA}4`l=8t*S)~gTn%@#z{6b$)k1U{wsQaISrxgXJElG16xN}Dh@airE^ z7DAQnPd@#Gj2`j=`xF^OB6IU*D(cjW!)~$*r-rF(z348}FBzD)EDs3C;3cQR*ghRv zo+KWj?k0uLOFeQgAwIXa=M@x)L*yKMh6NUprlH|yj7HjBhE<6R*B>Kpu0Q^Sq(qOi z2B9()Vv7N8#HxS$`g|w33~So|_l2NHD}OLt3}hmiX#1q`PUqj3fisvobJ34}6>|ew zPGGW$e}?(}#(?f6*O)r+LW2VX#Ypn`zM#FZfG+Gyp}%OksUfx0{ul)XV<7bvjH$tv z_oDJo`jwKyG|e5QLBd$lGBZ8g+*+m`bah7|@{-tHELprxk9}j<2Otwm?tuDKyYk{< zNRkbUjOu_Ug+Lt}kDfhyw&-avcE+(UMQYtw7HRn2wY#C=cn@S>G4roL03*ry$@^0{ z9ncFP%-e33IFKra-N<;~=;PAtY&poj2Q+*Yn7>1TooY5n33(L{zZ)JBwB>3R2AF+f zir)jHs*-2%IdNcMpeQ>1cJxcdt#T7{CKi^61dzE0*Iw7hPIs5+TaoR;XP0ip8~?($ z^6%=rCbCYR685*RNP%F)^l_=&Rm@7D-(VmA*QZEL{*ti@JI6oTlf^-RLUZ4`^ z(FjO5zX%6laHYt+&(RFFN1R?f^f~D_N7PN;_7is6_BnaxuDP)PT!c3fDW9trB)+z5 zs)Ltsd+y%7+rk=YYh%MPglcWgsj7;L_0F%%{4#R=O${E@Q@UySf4tSVb^u0g?ZJ%_ z0}r%7OlrjO7g^{|!xYZ0%3UhE_iq7}tFRx2$$=WZp=mOl?qdy8aZ=c=&}HdDJ&VcJ z$fwT*(WhTOTvPuF%f^3)y5s99mc=+06mRkFOy>8L2uGQqdW^VvWOPd z?aqU@*6YJ`AGxNPMQG`QW5q%gW_@C*ogrwv>qjND$?J`oKWpQN)%|@qmPO4xZM2h@ z$F3C;8ftEfTVg|o24%jHcD5RCZ=nFFKt_z78ft28x;7J)+T18PLP<$U#;qNYunIQ^ zk(|^BJ`CJA`chc=2j}&7O3jXs9xgJ<_yoQ8FuuV0Wr*4pkZg7ij*gBF2n<~HIzW>S z>K!@GZkFvaYUUl@SR#3E@Vj=^8x(1yqodd|b8b55z87ivb{9xSriIznnEAo0Nk}{# zoDcVHZ84C=LS|kJ5)pVa#rN;QpcogBgv&yY*dsop+*tc?gZ#LxnS-0D2}NTa{x&YjB_m$W7*E9MHxe@A)gy}}*y;!vVsG!6nG9IDP$7xa8^QkO zGpKh#iSVMZ{_!r|K4j?J)GiJVe&;z9Y~-fdk;l!=&AD?ExsB_gn$@aGRv8;o6j4?@ z_r)(SFL!Zw7v9cF^kI7mE6#aiK|KSt&DMuoDpIVt?!!NVKRR}ie`voeMS7XmS;+5_ zaKwujbloN{G%@DnC(9yIW<0kD11_6C^@;R8pc`Jv#g~9T_*eFk6CDIHyix z&B>#8!}_IQuw^X4_V1NRNu6@re1p=(9ihGxeDKRA=`wx!Yc9Jn`NzP9VYWbWIwmMJsXyz zKIwGI>8ul_(+J3^hxCJ;?k|T0Bx4O}4-be>-ehE$yRdkrmUutn^b7UF_$eX5Tp`&` z;aIW3p6KS|#>3V8LY3frwCbcVK^38JeoajxD)P6jJzsQIL3$;mv+9UG4mBNc#2+yy%hZm`-#kbkn22uP6XZnIP`~_ry#^hQ%^>XD#^$+?rh}mjs;n{ z%*-skUsD2*4wz&90(xu&kPE}d_3~r*o!yX(%wPahdVS3?fC%2(sm!FxI)>X;NSS%>vbFc>n>(dOli5XjxN+-vd zvJwsLvWNTmsVJx?Pd$44gl|0ze`kMlqSpz-3{5S-tJ_&x8Zp1S6_2FkVgDzZ;W$H0 zoe&r24p|Pir$=C*<3`@s1Y~n#qe2{ic0mCKpntGly%laC>vAma)G@1%d>e`Y`f(3% zFk@r*I{=RP6Ob*Cf~CBW*jql%_x8rWGA}=b-6Iecyx7s|Hx(~PEE}eNPBJZpHr?n| zmgui=%Ux8m_;EJzGpeNq;uAOlYGbnQxK<4WrvPeV#;b1&fy)HDSo8&~d~7gB&pXTw zB9edNz-k+1do^|S;gOM^{*e)#90mPFl6bbW1XVdUYZ}AV#EzSkhMq6Xyhd~|%-;xR zAk}Gaq_EQ6q(6c8S5os7!d=1NSq)0t(Zwd7@ct&G6B~2gQ*+&^{ANJ@LV{u%iz}2rr-GL3>Ewle&9jaMDP2TG}@VygS~h!7CL5QNlq7ZrLt8QXQuK)$Zof z=*WmSDCl7w0q^9y?GANlqlvM9-v-v9IaJp|9CC1Q0FcpfG02#6*3iz;doJ!v2~gQ~qGEM&;6!i{j@+PC`JS z${M+N`lQ_^{YRpIUUtGRnlL6W`c>9NYW35>t*!DUBkBu<;pu52GQ3=%CPlh4~eWN-W=JWiIO?m6-BAP11)@oY|eeT@3ElP@?2`o%XE&< zVZ8o1D~>JS=YQH6i(-qg`#VmN2?;sMNguOC31|QdnO6wv!{7)<3JKk;!&;pLygQ=_ z*E3c*Ik#M?;Z^pWmqbcPMZ5IVVc*@#Uoo!Ve`5YoO20op`hPNdxaiP1yhVe55}{wQ zKEc23B6e|*z3@dWsc`C5TzYW}+EBF1`#{B{tZYDjzD=$7enl<}>SPaV7siH#p5A1C zX8@&bGLlfa4b3RdkdfKLu^1tLU-A#K^Do;6zky>#PG5{nR<EhCP8R9_yfswk0V+ z46x=3rlxnGo}HukeIv`wsNm30$lIYuS;o` z*@Pl)65;-{w6S(%?kZNglq`!ZnZb+*F5w{T{%a@9-@JLF^MAMBMINEB-e~G5dYl({ z^z&lwr68-Stv!UmM)LE<#zxMJJ75)D-&#$1F??(7H!%X@e1%`;&;JcVR+2SN!ico{TIh$;o+|fcsazUkxHOuse_a{9eg3 zA#q?i_?5Q4fxW$V~` zo{JYtb0GEqS8lI|$c%7a7H%J;OH)-tdVe^~VkY?KMS49-`!rtDJ!ftn)*qVE{GV?V zfST}9??;xm_N(7e;JV}U^JljMEOknbF9AFD}By5#i7Sb|^{}FCX zm2>?o0{L%{^56YRfX%Uos{b4eb5EaE_a^uNdh|LA_*M!a(pbtCtPtNj#( zNBdQ$8mY6hckZ2&o~#Ts&gz;T>kTqTN{2u=dQO%qI)|jV`MLBgmCQpLfdC$yM2~X; z1p1v~AW!6C^U*yH+}tCy z_MBx4W4hud-+M|QpF4*RBWD;NSQ+a*nS`oiA|{?NI;XC;x1>Sc98W}_^;T8gYT@m- zlGhs40(*C6`W`*%j>?K3sB$Ddxa_#_;e+LE_SlRA>x_oV%u}VvVBEL6&4qb|{{N_o6P+=F)p(%xz5QF<;(#U&rY(XgJYn%Lj2%)!^5EDQ4o`Oga3xQ^2oCw&1rW1>F zi_hWOtZvM?9Rd><)Mv3$k$@V%A^m7aWd=)^GlV9a9fSu((76W)p@#4V0cyRjw}C}` zBl?@EvVYxQVzcYlUt`}=GD?v>2qn~UxUXwhjVnzu==4|E{r~(!KAZ+5Q_#EUBM4LL za8UrE3`q~2M;GkgNk#FjlQ&|jk~}P3h`ey$A~|OhWr>V7cXq_aWQeGbqYK)8T?1cB z`&$j|kJ^#+(P&S#QVnysIXjN~))c+{fwdmltmQfzS(#q`q8Nr znJ6{}hUmt|G1e>E{FYsNpKjS6CAv_x85ukx##`Le-Azg{X{a?r(dF^Mz{Di#)vK`! z{FZl2zjH2+~%fRqE;6nuH4k><>7M6xO)DITBJy z&vj!s2L`_3Wb9qFASsWz^0D&$`z#D9-;{T2)6;;a{KyGn)Nal`g7#{WOv>_Qu3F{0 zvLQQA9WTnYBx+&De9_Hqw#p^!WlP@Vgc8Eios@dF^#~#?gxKGIchg#Y-zop`V-CxB z-RI|}q^hGhJEk)3mC`*a+Vy>Zl$R~mb+HCGgW~rrV%2=Z)Y3tgwJ1jirMTEwIBtnF zt|z_i?xRQZul0?M_zB^(4jJPwr8HuqMszF|r(^M<-j0!(1T=rgRVSNiT_nHmZI?jf zG7b(7IAC!QkM_O1P_2udkDD8W!q5EuMcLWOI4LbD&K}IA_M2|k9_r&ohEJbjsHfy? zXKu?>@-nrt87@pRe5T!QMB%Z&fouQBVe&)N33Q-jZ)~_y*E{@R=kJMTwx>^>lId{^ zy)g1|%(N%%R679`PLW5a^0gUO z5Jxs>61l89zS5D`Kc**JNUKS44kNk$XR_< zsTkHRUGQ$V!SM?bW>Ki6=;-LcK#$93DO9au0-G^?YE}Iw?Uwu@pmkI96jgJupHa~2 z#3y0ipL}2zIXCO_X4}7hr#m&)i@ZCZDnDPf7iFZe6VNDQ=iw2e&G>N>lOSYtghNu- zRVTYNs%59Ls<<`6WO#p9d1G_Q?^)ZjOd-l~itL(l^p zFWHsjf1JOlBP&bXp{P93AbS7yZM-=0i?5|m=jXlN-#b0qeyuJK0sRNtiIL9FEL-nG zYZ(93)Fie0^IuONX_{jmA7_XWS~zn?XlT@-%2 z)sWXh-&GM2e+Wy8W2Bye4!&_eQu8o7U3GZ}&owE!d`|LRTl6~Q^;=Se(9jy-mdH1;>IK(F*adP(3x+8UF zFoXs@H7OZ&c#dk+7=brBtgU6qPqDJzCLL(N#aSSK+p+9j#-K145e*S~BI(7$%+j;P zAEND8n7Z>z1)gX2I!Iryc`d$gt36CPKi`$8oT0>|zEWPoF6#LlB2a$|O3}cE5{5)} z+qovp-AwOeXq<@;4oTu?fF&}SIgN~t+$R7E>3u_~NXXvav${G*J^kZstTa81-Km4u zu5N`-4-HAEB1viXj=gICG-Rmb&ccyTFc$G@U9hD`|BI+LW9cyU0}Es0%xq`#TAwv(f)Ymdxwc}RbXIal-Z5(x84E#<p>B$u;@!tj2`u+M0zARmi>Zx@d?YA2UTR+yuX{)9oHnz#tHiZoSx%OyuOF*d z9kOGG%eA%nr#H5?#+8&zD;pM-)Ck%xgy1%vK%nI{qlu{oP@PKYP;_a!BrlhueaR!n ztv8=v@Of?Ttvx|InxOM>>)o%eq_G|#iWfU;32g$Ui%Zc#EYGOi--;+G=KGxT#Om(Q-v74`oM6pq^yx24v&C9d1lK0&EuB24m!doVy$MoTe0FxOd z$BC~`wAr<1c+xT2jQk@BS!bgJE)YI-Mhk}*kWjsA?=0{z(;X$!ePj)UiA>4Zm|sKv z(>Ye0bygS?zgg?e|8q>_CyJ0*XY3zrWi`L9TVC^IeW}*RVyuFW`=$^d9|JC8(KTOc zzf_bRrsUB8G=RhMkflQ80eNJpHA3#g?TwP~*L(qFj(XN6T0$1NU=+Toob zTE;VjrZp|a$dByil5b;T$OsAD1`7(HR#K_AjQSXH0cu<5k)UtoJnvhP!#gfTC@Cll z+Q@$p_u?)x;$8|jTHJfoRfSjEe8g);h%Y7W{1$Qjn8F(jX>(#IBjv*S^OaXRw``Cj z6oy>h?_26VDw-eK3FhnR&b47`zs=OsWGBWVB;pc?+nSTy0w@xxPM>b>(tVzp>901@ zKR}TYT-yF(aq(fbdmaDg%JOYSTBSq<$GW*>`l|L)kt;;xJIIRnFTy{_XL6&JRAb`p z(Ff3e@hApURH**&A$B>uqN8&npFyfvcs*PZ;;NJQ`@VixH+0q zKl>)tN_`J)I-KA`IYJWXb5m4%tSbTq_sFd~v%hQc=t#_(UC_!@d5h_QX{_1i;vz$} zd&uM9yeE5MFK;m`AB4~NbxR34#SVGRwA&@exHD4WMLd|B8;Ur~(5uL-;9nlY6shyU zO#XU3RbjI{{u%?l5&6c>N! z6gg%WNC18*6|7Z+nahE`rO3qt>J`(s^+ymErzBHR4$b-E9dxm`kTVjurT^IK-;`czuo1gVz!7(t3(YJ`g9JKizq}_ zA_ilch%TS-sTp^jaA0 z%*G;{YtDWj8;oV=Lyx;sNz%87$90UI3i-%(f=}*ieDLH}^7BhG%q2c^SCKw(Bd$|l zo~z1fz|_~jJsERld@!2*G3n$|M|?0``8@g3%OMr*;f8Sj)vfO-3J2?)yEOEb8abxJ0S| zb>{TJ%;Y4YS?T%P`3-ti^3Fr=1RHMVbjTh#a^7D~MoKL`EUnUAYPP0krQIfF!iej~ z4};!JAGw^bb}Y>pPh=P3>fTSAerIUEJ=Uk;PQuj{AJdHwk2s3t#b&>L1r6bJ>2g#!n9Fp>E8c=@WyFb{G)@>#y&faCs-rhOx!NInS(-j|&>)#EVjcIIP8Ngldbj2~roY)o=+c<^nN zI)XVn4ujJbh9=F)tW`iZq<<&@g2*fc!D7r5@rbK({sOvl?1|Z?UzduD|JUkords{x zd8c0M4x=8}7=KZ+$}UrQ_kMm9XY7~Zj(IVbsa#W)&GGK;RDzog_7ySS9u0LZu1MiR zN{jBVKZr@Cq%bf}f2`!^$J@f&i>a)v{cs+_r!Z6UCj_|)NDudqL>JcC!D(@ER3G;^ zFZke^BPD-nY_YmFZ!Gz@;zgPZI>{;(EG)H}!>*~a%E+^F)mz7}|q+Liw3Bvv#9l{gk4B+c?Fo#mIN;=HXYw zwGY;k*hEG33iP(0AClcFTI?)ofmEz5I$B5T)BMGR4Yh=KsTgi#Tb`+dzv$uDslpHQ zmYb!YdyT4;CG_A&D66lI^o%=?HpdgepQG(nr+0b3iukCX`syEu5CjngyJ zy=-kcQ)#d9p-I-1*w`{ZeZoyoFE1&sadfoai+Mam?R3?1iy*ttPl+v7x&OvZu6L!S zv_iIo?F`1_w6wL%%;xwlJ?8S%B}N7K^V}|h!-8!Xhe|k#C&g4f{_XoD(E!9_(SQ@O zj1ab!?7R?Kdj5RBscG<@i9uS}dnr5VQ3nTazffpD1UWnPHh)SJ;=WssQUm8L8}Kg{ z;9v5%36Rozvl2e|M2q<1$L;d9?wp89zwf!V{Glh^t=iq~gcdKK*_E5z71 z)>3^Wib8$ane0kwwz)T~uS>xfgMj1VE?rd8(Ybzni7tH78&hBt5pBSFELxhAqoq{j z^BtEMREk7u(zA>!RYTNioZUEjOkMRWh0VwlRq`BZB;q8;SMkpFk%v2FKwQIGZBl)# z_gKqnmjto%;`~WXDinPcJ{-bWmMTlUFrLufZ)sn93h(~I!PO47`g2I_>{ox+9peHw8Nc6yINuR)`SWbMme z3MGZ#ik!pM>+~cFvD%d1IPPL9jfY1Y^N!+d-wP+2yQ>y20%GIazFaU{pL33U{TbEK z-fqz$tN>$dL$0uyY9Acj?K7lvBp~Ht`F#4NrF4A1q2^QHb7v=;}DYE9xai^gd-A4l%vQSMF*S{A%mY#!4pRobieGxXHwBaK}Gq+kY zs)^jvML+Z>rY4EJcMhQcuLPw?&YK~K<}S@-6b})3hUq3$C|6cqOS-mZXR9G1JxbZ~ zF^o1Yy4jn!riNZjj7P-dnD)#>cb>M~dYK@ah;A{_hi>9y2lHmMo)$)|W)pChG2XpX zF*HLGNC_eRX4m@zcONHGH!5ZtJ0NPqla|cyt=+aQ$l2Z;Sf{G*AA3huC03H?{K}?;niYdq(DuDRzvRG2(7H`=Ez6_ zfq$6+r}dK}kHfqJ<0fO%;Y$e3MAcSu2M4zl9)(Vf_WmxVP_?q+)meN^$5FrGL>_PN z3x+y_iC5FrSid(Et<-C1`GSM; zCBn>4>`j}WNOEj$P~Y(Wp;&9oivX1eF4i7Qg9Hnx%J8J?z@Q!vmf>~5n7-UVPMC#V zJl~z{ouc~_d77cDdZckz^(%Vu?6>L?1?1Au%7wIuBrP+g?3DJ!;g;S^76=b2s)Q-d zripvH`kJC@^u-*_PxEI(E3wa_e5c;^WTD~cS1DqZYvt#xZ|2QN<>?62T71Tg3F}h1 zmwW8Rxn>$DIYnM`*`)chzrL8ctGJYDuc?L938Z-PlGZz4?Qk4+%#ijFqQq+_Hq$tl z1!0$UvBsnV!q-04h0~L~?)#Q64eYZezoeW46rnh7!-nE)%yK7A@r82X(1YZQLh#nC zzfO4w>@Vl$R6hO-g|c)<>qwhTvq8Zg!lC$O3pUg9xt_S!e&ILxG~eN#7Z=M@KPrOs zIeg`NM1+uVwMIS5vuXK@cW7vos+I4vww;XfsqXr_{e>Qn_1m8Xx%RDB2_+7Ai#jjB zsoqqT7em*lQ>0s{zFK@?Z=jEN`3WO9uAR9mztpVVSYb@xFN96-f2BTonm~5EAXZEqeiRa>8 z%p*e;+B(7kfzekYEsPL^CCa*^wvcI9%58{@w2~8$4v38S`Cag_590OsK`M&8Cu=>5 z@4vsFnPYf-_Tnk%wE6z#9`WNC;f;HcL^xCuuYc}J;ffGy?yeLmpB7brs}mo-e4;e% z&DWzGM{K_Lvc$4CH|1y4T4pwLpGRh()TB zlroq0%fV#t^T_CEkyn-OaEkrcivw*#U=KkpfK1xZb9gb<(5?XhqzhZ4qnJ^|^~X7yC~jBI&ViT1?S z;$!_a2^yZ(Pj+RY>Lv;v6{ys#D_QBN$0<_ArRRt;4Oi*h9z2=)U9;eKX+-Xh;I-K<;_I0&;Q=5OdY=dUYpD6$}i}D!kS* z)YFT2!4tjGYr)9*H~chYDo%rpmt*vy7Ff`b!UZ&@lspLZp%gRY|KNlo%Ql{VNHgxsfAmGk@Iyy3%o}TQs(>a-Y z_DFQR$Bdc;l~yt|ReIWZ>eY^{6j>9BhmWxv(+#@}(}L+43YMz)gI-Kcb_? z;P!$e%^|fbzk~IA!?}f?R;8?wOk_+2LnR6k-JKebl^hWAIHX zCErA0XWY@X#nAKlHksd6*v1MYG%FgMkF~1k;z%n8Np}7&uHpeM2a&^QEoB zDt8?2uK%|CWB0GN#&n0X5{At4+$n*%1O=$2v2B72a5&7A2`P;ysu~$Dh%AZ2d$`bd zlY8%*Uk29vdJwM=a1f>EvLiR;Fw!NH!oFMQ#@I_xb=I_fIGq2Urbz1x0HbTVB>r?_`j0 zc^ACmXi;ZtEA!|Z%g6`&v5}aEh41z5oBy!UpwOOvE3#&xWn4>8`Fgv@BYgkXN9D8< zZ}WU)0`;)GuC?+E|G|SF^BJ_zVZ8$*s-Ar{-{1Gyxt*NtNQRq;va)o$u)u`+f-kI( zv<rCQ>yZ`A08>BZq<*f}$REM4&TTiuX_QB(X1>+l!c#XeTcq3`g*q&Cmf4J35E52Fu>pxz6Od9LFww-2P z`_{V=!yO;U&Zk25q%szV+3Ym_T9n6jwZm*pXSl#UL%tU-%*bX}_xq*0cRH0L8*s#w zY_wOuzg43?3eajjr8MhB)uBD4hLZ zr^Eq4H4WzV#o>;DcTSU%mhGrwURB9>lv|GKL!Dez<*tZJI)Ao-B{?hy=Wi2BSBYfN94~yKf{yrG&IyZw4ka|OwoIqU1T>aZF?y$ z@Jai|N-#s4!p+qs?AEim74(uKLn5Jbv?w4^?92ljB=JQpf|7;eVq}`HAaYHk$<`*_ z-H$}EqfNvxyN1N5CS7R}5m>p}m;KPmdA1X1Z2_&Zaf741)3b^3Ywdhz<^wS@=?ci% zZwhbDn9O7@@|)E^F{Yv6Y$psl5$Y7Hdj|;}I0c6&*P<3@1((=!J4!spFvWE6~ zV6cP;JYRXJ=2O*LEV9=8RSS`{yQUX+1D)uWyb_VWm^#e=jQsOO4_RA=z{Ad|chB!- zNYwBZPQU$SP$$)Ve5&LVT%IsgzMeGVwGj&+9Ceepb~LgTpXnpY;&@DRP12G70(c_D(4xh4HG5D zk$z#RJ$n2~q;^{X2kpl(+>obu4Im^g(zeDn2)iol>R9tiWS|Py4~!Tcf2l9~+Rw$z^1V}ZsH!+UfTy8> zfnD@{UU4NVmSeV1J{2|fRpXk-=6UW*6TOc1YwP_aB;tAXXwrzcyW49a6G4w#gcYI1 z*-QD3!}ZLs0n7;v3yETOFUNq(vRf+H{b5suK(A36s1zsW^jf-T8Q~}1tm?yIDr<39~x3wO%c(q27X+7m`J7Uqg^9}fjD}S6_wW_24|LUMO(SV)WBvdDJz>F>39CI z`0Y;W8wW>$_i-mOmh4ZK4!NQyg6;_{^<{@W-?I^1Pj#V2lk~a_wbl>Rzsp7Umc;uo zD0xYI5a=T3ykI0Oe#u8tO8+QhhI)EzTYILLV8|;gPbmY+_#uf#jT{N5B~QDO6xwRO z1ee1|!@aw0qa!#EH8vP5^s0#&D18}QRBbUgX&|}$nGd0{S z1#Fj-{Zq>B_Q67C3tnBe-#HooZs7VOfJ(&BGv*u-QZ}D&+>GGr<{3S{8v0|s^hFz! zA{-T}MQ(MZyo_xA(W7@16!zNEca^3_AH==!Ib`4IM#_@b?Tz;fkcr|r%Ewp(IAO)! ze$Qp2ys7mpfeWU*N%B!qik>Zl+g`}k{9k!N^BfjH3AviNyzGD-L4eewJE;Tpbe~KI zRCJxz9lzanQusAtJx6T8@k>z1l@}Fpa8xVaebw4);uBBYSm}5O6_IjWFVAq&hzSp6 zh6z=sCKviX^S$xR+_86*?D~+{k|#}2)XjqHczWlFbo#Q#Wjw^W3UBwuTZV|1w)9V) znw^S3)k^T;YEXWOx9oor?Lt$^^5o8QM(megrp^r3`Ut|8c*Hu59K#3POh_sl&mEZN z+}Xi?w78GArq#R?$m{^)dUjs=q_N8sX+#O~{~Bj&A#nWg`?IvP`=+(u&o_Yj>0f|E z`^mk)vt+`qmEX}(WO}=<9e9ZBYT(4g-QBw_t!^DX)&|_s(;0ot11JSrMpMcU%oOF; z*45spr?>MxO)ITgaF=NfiTlv*`?;Qf z_d$cM8yi+0{rIj0MH6Vb)!DN2pxD^Gz^z)q?JRp*B_s_r3``6hK>G+1v;ESgK#RnZ zc!2B3B)EWUr@T&=0q;r^h|ve$*dUvAze9r8Kn9`#xVkWzKf2iJtU}l46@tkO=WUM! zYT)E<~x8UIhUPGw_i-drLjD!Zz>QlLG&q`*2mZ~WqW0+Unu`uK6 zPWQ~4?+TVOm>yDfE-n3({4ax1f9lx1QL7OSf*_67IOjaG0@~ z$(fnC1i0Ve+XmC+mw6Uh^h+7CeYoSyX_Tunwhfb zT9{pD<01vUAdQq%ZT|iq0tMYTM7w^hHSZC?d$Z1XNGAI8Bj!+^boWEP_^={E34%gn zF_~u^d;M8&2R`HnM3PW^^CsYAsbN$~_Mm&{_-2>nUV!*iK~0lx2mi#$b_<+JTsOiC z=6@}B5=pK=NqPN#%DBlKj7(76RbH`BY9iU9k2T9JEuu_*V2R~4Ers>5Bh{CXhuwi+ zUQI5;HXnwE+wD*8X;;ofsb^^H@@jbXwHZ4l5Dwi)_Mj8jD z%u@4gyYn|}TZc5P$a{+Xea{=D`Ll;IVg1eT`wUCWlX6>zX^C}Vp<|zfqhxBnyf)(wTO4FJw3ne=ekyjjak8;+i1j{^dhgbO3$^aJEcJbc&*F_Y zSURDI2$+HJ-N?q&WyGsH4X6N-A70dLn$C=anM)m=#y;N{t~jkm_q4=tX{)_4LODJg zD0ii%DGSYtEh@D5q+EaJt#A6w9d!FkYPAIcKfjrG(Y8g`dK1)(rFpeqe;=i4T={qx z=KBTJs)~VYqg8UmXC!}}`c?|eQYavisofVw^n8n?q~8Jkl7Vy_0&$TO7ZFr)&|Hau ztKN7z@+LgsVY&ha^f8qx9yFIS5sf+cRn-4mTCTl6ji_|j4UHG#BEg0a1x1+Tb*G51 z!_YY2k@9ZAF7$UBSU?%AkgXRoTNYA`roHQr(}*BbGlK6<)pzcqGDnHLx$ z1f8CUPjvB*nwMz!#b*jO>f(d#`6M(&C?(_OB@Y1#sR!Ta1tF*!rFcs@4A683G-cno zXeB)f6~IA3l(0sM%$B>8{i33xyuH0MGfiAvT*uHS~*ii{wPN| zv;W;q#;aGas^n;z85lgFv8XysDPe#JaQxLS$d8D%tfVAODdReo=tkY$tAjXr>8Uene1*))-{v53i?EJhu)t_ay%c@vdrMK4 z_xoORQ`6@5cGAb&5AB21}oaQf` zuMd2Ao+K=%sC2eBVnGyY&o|0I$fPQesiUJ~s_c#kGAD-!|6WdQik5IzgHp5k_Lzzw z^ES1gQ{Vm6d{f|A&&$L5xE!~rS!W7N24r^Gw65}^S08iE60vH2?jz%|OOsd|>xkuT zv1@H>(_@%iSP(nUOTCUm!hy0~x?vGbGwh8`)Gf`y0}p)zkLI#|gR1H8-^=gdo94M6 z>vm+6(UbW!CvmIY$5}vITU%803V+xcl49(i6M3>B95%vmgwj4cIn4NoYLoO55fSO^ zU+hUG3f+Yih2M>HJE9-?aO2zfxMo4$_wU}7R5jYZMS`AJPP9TBjxSv+^W?Xj`c`N% zupssN^=q$n%L1dGl+kUSY;P~G&g$6M*pPM-cH__88<4uz*4Dm0b{d-5oy8uZKj+6L zZfRvDtDBb}9ct)=-r0tP#SZ1$C%}PCya`+6IBgDPoN|5lZsFBR!s$0(0ul~WF>L9` zhmK3>sfLsfAMUiUR=@0X*rVZ}Tp#j_g?AdexS*I3WZWTSA=Hy#La1nOJv7A27JdBq zCRnJfLLyCv+Tme!u)mavku|vCK|%2hrSJb7*ds=jtjRc{N6veuPEOp(Qr6bi zKc~&55qNEgM-Cel53riwvR0qm4;{#Sx?bmv{g`+gHpsmDRi}PIRm)}bdv~%Vy=NXr zx$UxO)YR0}JB)3N^x7Xk#MDzx+A=H=4yU^Vhtp2di1>1AW$_o9z;ZKY{NJ1&@AvpW z8Y{^}f~h#%=y%##NMMLCruYe6c~$R&AaX+697AqhLP63z;AjR)9-gSRSbD*ac%9N5 zdQ)K6Vlx^#33SzWU}Idl@=^Gq*>H%${hMDjiUZWeWMuf9cIYzi?w}Jt9&U$38L^g0 z?rm=`_oO16vE9cj9F_bf(uNZAz$@FWeDd*u%YI?%`bgT@R;hxJ3q_?Fq<)BtbKhO+ z1E9biF5rGwa;X(Y-R@I-cZV_?OyU#&VEnG1BF^Fk2sGty*nvPk-Q9r1UqN0#Al9!z z18_9D^lK|aAli}tp_#ZIYI0r6?Q~O{Psnm}e|6%U>mlA6)Z3u_=F1gPiW@}Umy@-W zsiAN7b+5T{i(T4z9_rPvnf4woCz>#Z_s%cQYU{h}VNk0NQULbY`U!^6nS4-g=89hw zAzKBx?m~|se*Ag{b-|vHelqW5i=Ll5>XWaWh)b!BrT$}-c7K$wu2mT&-n+L$E%>&T zHNM*Q&SOyo<1G<^Z0cEB9D*IVAJMyGQ=IV1j}P$WeO2>JgT82{Rlw!!O5M*N3SGCH z7SQ)bp*1y*`4;>H=c=sG+Eu8f|2J;a{WTXjc~- zt9CuMQ}B3T(C)H7W?v!u6N))|WgA@>JYTil&a+;1%z|T8HkRNVbKgjWt>PzC6n74K zWD|t30fB)&`!&(nuJKui1mgmDMYPWR?((n=S&l0;ur)EXknlTSCP-v>3P_ypghwqH2nIha?a^tKMu~w(4 z-Ih;CGe;Ok_CNe8Nufn{KJ8!vH(4sTamk@KMg^3T}a);#UG?f}(y0QQa!y zQkL%ai7$y!ss}q8Si~esWf{kB>*DQR$077vm?zA|pWbKTmr+V>?BK1yuVgZ1b}2jV zmCjxsX&m5bic+amtZ*J*OCOTi8fYRcWQvY_WMs}@jmce~oPdi%mPS7y_H;>6#mD|# zVJ16Snu*R+x4Za6A~qDh)_7+4-j*os-P1nT@SR=5NgX5IMY5IC-r-b-wuTrITHd&C zVOpn0%9-jae9|t1ODnc`nUF zyk{u(Me$;;F08CIj-P@0^I5JgiQ75v{$y<-63KG=c21sjPipGnq2t_~+pA@j_6kQT z`pla*SMfR6ZI=|An!4&f0-jP{&SNoAwX?TM6_WkLf2p1`Ikf`|b3>;EnSvo+TqC)=LGoI=+j1W#~oTZ?A{v_AEtcB`P}!0 zl(;>r&-t3{H}~vlxwJEF9&yt!GD@EE3QVz1>5w8EUK|nFx!J{Raqk{z1qL}%hO~Y> zV-;88+U-zMH_uP@{{eeQ@Y%-XhJOmjmdswiHIdufUY_&<-+=LXP4Xgo7wHmLG_QvF zp7DbY3zjfO`0zVuoK{7r1G~=f90=7(K%(}SWKD$Is^$%yCbY{Q>=_dwWsxAGOFT$cU-gwVipLchz_hJouPv&{Zwdb>tM^%s~*nyVUJZ4}yy9 zCVFGcK8lTmj$D|N7g%T!`CEOkK{F4`IjH>_X?}6eZrpiA{jwsipP%20D7sDejoKC$ zML$AWspv;?gC##;bgNyJ2R!R2)~tHn+2#lwl78KmQ5dxh`uq8reVS2E{N^;A4N+pL zOFm|xC`we+$~)PaurGGWP%RVQ8gmTbaE$*vWD|W%Qv`Urrrg(v_51o#{27j?N3;dp zX2U_2(?>nYojtJTQ$N*PwJ^F`#qs2V+G6hFSLTm$DYg8Eh=fCrPcmf?vrYn~*}Huk zkj3ZC4mG2A&1Nf7bn0J>#W_n%Bb*_H`bHMw;vvPN;=>Qx6?=)XeP6QX`d;3LEK*(d zr1?=aGORwRW;1x4#uunry?a0ZVG?$`$}+E7U;&yLfLKaq@3FbXI4<)yWI!^LWJ@9` z6F0^X)>w#74(8I%>3yFctIvU9xg3EX1l|tcfwTdLPkzcnuLTzOE z7q`VL_>u+6x(vW1sph5XtwEW_5BFnkJ3cV%IpCdEbKQcGz@xmim_PS<8DZs4zgP^5 zbQCCU?2asAEPm?E0fY|AS|c(`>tavdA* zGv?5cpW5N!wg!k31?-nr-ZJ<%o_SuOX^VIeeWP}4?C@aI{|-XCTvbDZ-JEn|t$ce8 z8zm4|y-+2Oif{SOvNX$>+;N3&LBH$4nLM#caNnCeu|+FKq@1~lD?3WSDV+OtF_JF5 zU~D+-Y0{`{Lrr)D{99Z=YGg=9ua0>N!y@PLQF0)TSN1)xrm9itx&FBTe=@3ZMgBbi zc3^ttcx-ZH{Rf>!_D+&_D684<+i5$inzU&0m4BX~zdSAPPWdv>+p(&axN4mfC@D#F zR9~;+g=PJ9j&f>i+His;yvz`p+v3f_H|AoBG95G`ShX*lmkwQqmbD8G{IUu#&7Z8D z0?MWr+#|e8BaY4^j@E5**4vHmBUD{2Y%9ZdohpY-YTiMG5DRR1o@EAYZ3=TK8%H5p zNmm}zw27$I8luTeLS$R3t)HR&g_lUQ~gKRwDV&w9-M7JT$ zk+M5(uL(tvoiAQuD~l5qM2!T5emx<+PxpB>x~S(YQl+J`KZroM1deh&GO|6*JHH*X zoXLN=W=}8NyZ#saSOYWe^^3~SNlL9GvE$b)EAsKl{HmjHG zUS1q^++gjp7b86$>C^>R+~0@z5@_cdbVxK$?BwLni)SzptJxH`DpsbXnT3dc7mb?p{W$D<-5CF6-0vP zM)dhsh#Ii2A&_^I1Txi3J4 z$H}IU3o?$+XP`GM&QJGxqtjX3SUOxcNi$`UY>WKC#?AxCqgpwMT%{kp@uRv%m99CX znoj14{O_pInl7;&?y=73o$KDfu`cYZ@mou7UwzyQ-{$8k*5J_ z2Yq(FxIVcWbRu{^S(RZ18SnNbUIC~4k<_-Ti&j;$#ROwsWsfX2p}uh?m2!oPkkEKKP=YvYXT zzDdV)^66$?zh$c zsn1&SV*M()6(F_!3P=jWChV)^jh)4KQdQ|gElHjkej&xkL>4%3?WKAd}k=EMlG=cZ>_-omY5(C zBdTT%+M2jgsPT+BhU5p5WMLhOKOb)b9RDPg@k~`mxh11xiZ7BUC48o3a5GmXRwk(^ zAW>Nwp?$rdk;(2EQ>N^p?QUfsOBIV9iybdf#yrC6ViT+P06(A6d6!Xxak%*ckL!Rj zQ)BcS$ z2q(gGwhEq?Rx%Vcb@zWP`enZtD|lmj&fmr=?|dQ2yV!y};doj(Q@?Vj`&N`geB3brjEFL;ahA z_<@|tDVc^`$JdqTYi6r2#vD|pHLLd}9)(Yi)|CnYUWHr6;ai7^6!>tT^?QGlokPP$ z@w*B2gT6Ws3&hH%6{5&@E7`wNIw>Hz+!_JSU9Km$KK)WDL~p&)o?8@9w9>`hk>mS- zpslq{^LVZhAbW^2({rP8E9b?0qdu+7v}jEi{kTZxXj(c;zzzUS5>y}3@GqB-JSc_B zVI{YI7!XxxUa8D4E=*!~E@8>x3uai;I5wWi38-)XRyYpTxMR&s1mLGXcH*zXa z&39Pn*m@xa1l20^S{h8d$!YW@2C3nu!TpC&6_qeSK{t!aT~fx>V4Ww_U21tR8H~JA z;F!Y8ClKR&c`En4rppQN(Sgms<5Y|0HX9i2(I7I}eUJ8S{8L92!A$sqvA+)h{}lzF zYEBEiHM|+TBGmh@9-VN#SfS1l9!S70li4VP`tb9pSJpPC1cf9t5t z{h)h5yz6fp(SfrB9D$d3+4^Z!Fa7S7euBOPGTv$4CNB_>9_;Pyu4bN%Qe->X?oM?J ztadVLy9lB*`evbexR%ux+nkXj1I16>&DoZ^=C3Rg=k=uUbJ!Ts?PhhtkhX`y#(mkz z9b5~;)K{k+Am4*CV|Q>jiwcTtuwNzd9DnC$(Vq=rT~yMdbMVN%8V8p<+QHpRIo9tG zjZM!<-a4x5Z4p|4b~kp10-_kcbGKiMP=(Ou%yZzH4C}EY)R*dNJupAoritS?`8`KS zvTU(7XPJea*$nY^$fl!f9 z2T0;kVi_+aLAC}a#S2bbNH-w3sL5OmlmPC9h~iLzL_1Vaaw5{U{!n}%@}4jx#Wwhk z68s3c0TIE$bwIa*?|kIG!ht)Ow_Pf6+x9=|vDw1P4nASL0XQUxK!SnNJRIZRC&+#o z6>rtG>SNAfYpQS-l~}r%D^e-Ad&%c=-Yhx+dSZf*LcL#v`njpjs5WjEo@ekc(#E|d zzR_o{%2V`g&K|v%onpm9#1ksPe*7{b@MMv^u3-e%Eb2rkPoHct$QS>|FDp zW9QSu^wwf5<%b`GlO9hzdFh~(4S!aB=3D8SZEQ>CATWDpBckR_aI=f!2fB*j%EuGt zO4*b<=$V|4%&W|^({zFNz}Qz~jRqVQ4BECDNy<>#J9}N!&>Z*Uvbnpb!h;8OIfTQ5 zBT7o1FQ=ewaYo2{^g{U+8A9Rk&*ri;Shu##(%o;ZL6fS9&Gamk{&?>-U0J!^t@8DV>Nv+z!ih+l8df7(YP?p;~CHA{Ruig##q329n?dVA9Mi{$0L%Bu|sO(Z|Ak~b8QCQ{&1o-8c4xQ?eF;!e2Q-Tl3;{q+T;RCH9kUh2N& zmBhGd_2Try?oeJ~W}*E@&SPSC!gTk~S5RcYrKq)}s+?Zmb#*#GH81QRzhS|$HJsEo z*Im1@awAve^jJ9A`80y~5vsFWenb;-^d|dS&ylc53ZdvW8n}!s0wtfEqc=wiiL;s4 zPpKTLOh-#CkAJQvU3tRg$jw#4^DQ9Ib$-JBAf;cn5LXh%I&0c+-js-+{jAVJGl|Ex ztix{468ZH7#Nt)om@-xmeso2&7~cui3GI4ZD`)nJHBF(#vY}+TNZ{L)G4?ok!OGZ2 zgiPQSWS#Vl%=MhL^3SZH8pEniaA*F)J$hH-R0pfsV0CvXu{$%9P~bdDFiJO+&)d(W zV~xA%3O_t2;~_DKQc=|KKhu9Wmfqu9})xGp1cT884Uxv#M8B%fuT zMaEl^q`uXeXJ$828*q!W<842`K%i&VHZ{ebvP`)8&qI}Z zT3c6Q>|@V&2a+m+z9aZu&Q|i%DJgf)&yJ}XBOVw$Qv1HQDrqsnXLWKQx>xx<>-rot zd;Khm-~Gm_4DH78dMO<7Wq0FM(+`JGv&e@=6o-OtZVhcw@I@CxDNJ58aq7qO zv;7A@50!LkU<}uR$Ji#BYz%Wg?Qcm8dp!7#O=4brAegwrnABbLl-Is27H(7Cbs;~+ z2t^;AC>||02tZ!NeiYgMz+i$-gpZR`QDSvyjz1N{JI)DSok^Bn~m?%xfIEG zNqsDcHO;4Q%~$!&iQs)~ZB}G4`Om z$GC%;H=XDp*fVWWUdByEc9xfY)16?X&EyG|bMLwTi>NzyAIn{JKicUbaEryeckeZe z9~i~A3gYRTYu^#fqrGR}_kc4K4nRa~HHLU_!B$Z#Wfn^p!w{CamhfvB0B6AY`K%X~ z?3S_-Vxf;Q%;JuR!_nfJsag+AgkP8LJ^wjM|Ccazcvc^`L8;rB)qv7o>^5p|58&cj z&l4(}E-ucYIpNdoeqB;Rr+zRUh| ztQ`Q%_nt75QlGq?dKU2w2%&^UgxQ?o+)(<**=2=*KFtdo^wH-Ku-O676ouXS*i(RC6kd`~4CgX^u?aHcM-gH1<1* zI2^f$vPPPehsit`{h6F>_;3`6m43h$G_|(R`J9JY#}2Lq zZ$Zkk*9TZ*bKariEhZci;Fz>);?C%=bCu4AyGxG##C`KeyRvKJyqn-`DJzRCDu;u*ZKC3K50bc$Bl?TiW4|x zJgF3k?V6TJcTWy4y!%c8(OE>~*S&vP>Wm5ow5u}9zy+e(r;m|% zrHv7vQoqAg`BHdZZ<{f2%(~|DYL0k85V!u37`E@Grrb=Pf5z|^d=Vp*Os`6!Qyhcru)}vn93rC)bZw&9B%XD%Q0Eqo9XT;4ROB3yLmtbkYuoUl$+pO z;G8qz)Md3^?W|F*${E{NGO%8W-%j(W_|+V;GrWz!bV1;FucU9<*Jw$n;epeS3Oq*I z%(VAuvEO-vt0hvxqN+wi%o6t`=ds4S@5^>(W)hLfIJBqS2J7&cKg7j+-j);%< z9OfRv?YMQOvZ;Yxt^R0Z)q_`aO&)kJ>2i)$?&S}s3j|ghXiNSye$F2jRl7Ur+orMc z)jdJe!go*a(;p=-Tyz*FGaKb#@?v%lt6R`4+O$m1CQ1oqwDUBHU|i;{8&}zA1O1YH z_JmW|fqihYa60l;^^CLELB4(StS6k7i-)JXZKuTY6eP^V2f}aMTs0o};vExnR31Gz zf8{ax>3N6yI2OVB@TSH5ggaz0ic{YTJWSXdbF&NyS&+Ve9#2-UV&dDKg-?wa_A zc*|@x_`7DE1oCe!SXjRLy1i#d&Q}q>VeP5qS_q$@qVAA$50q=V0WI@H$Rg} z%Pu1#NV?}^k31pb=ixKs?PGQALdsjEwYYKiudZ6&asIkpjQyP0*vO)ZSKzd?_TldQ z6|+h+m=D~^cGH+G1_TkUS`@oypnc6-w552v+3~ zNy+zE`_Q5VaOokgkuEapm6E}^F(fa44n9KF)?WFf*MU~nERLii|6}{NhT4=O`_;Yr z5g+5@QSGwN@Xz6>@eM$I8k+PMPKeG+N=6$l4v-(a2ja!uiLZu(#d=g2TA5nZfioT< zVW!Tb%HzP}g*$LoT6_B=k}YXQ(A)Vf54+6%K67Is>G|}56$$xiA-!uL-go#va-IBQeZ-E*0;3D7LN>BoUvI0Kv8iQb(L>U`XfBi>^JQ zk7drtJ`Z8Pae~a^mt}wcYz2~A>mutkRG7a%X1~02cZq4~{!&Tx*^%Ex@9~sEMPj&lYrORR7f7iKyzsONyuULT-Bn|gfx(B89$q!N*yC9opPxz;+5~Sr< zFNYJ~y3`QZD*pm5o{9n~O7Y)vGv)qh`am90!seb`l9rNm@wWge7vX0Z=<(lO;r-uI z@32q;*q>-IGY~W~RF}4((@*B;ay=)Z>Ooa>?D!7ouA1a4Z_t}m)**v}-Sh~gHUpjI z3d43nj=i%! zp|y+0aAP$#I$CO0Utb>zg@UZkEs%$)b_jNcY?Nv~l)+GuArB>KDsaKmxmeSMLLS-OyvoAPhVh;}BIz4$ zcj(rw4fOqmLlnjR`wE%x(Gtu0y1Ey~d#k|2m%*HbGix;5#e2JU?3iEH?C7cd_TSdJ zOaWOh!YlA1Ry&HrtT~3fv(kCLDVX+ryMteEkEt|)^T7iiu&uS+PeY@kG;%a~`96Go zUTy~xwfjsj=Hr*`hCK4e`~m+xqStVx_aK-3?!9|mU0t~#x7&}9Iq}=GXU|UJv*4t> zP9a6=>gvXBnrOStot=UrkTqDg`&m5L;quQ$Jg+$HPG!wmkm@&MHJ+}E-T$nKpAi%U zK(?+R=pe@M`W4AdbA3qQz`ftIJa`)WM4(HEKkIPF+ z4vvmwKC%4-S(sDA&A^70L(&AInC-fFUMu92zSsbEN@0Dmy*|;ZDtf?`D5Wkhd{kJ$ zT*>WYls|9~_%~A zK_cdhzWDz9xuM_%I)cpy``=;k{~u!3pakVy=`4w_2O)kV7{;&6WUG|NeuUUWEH}cN zu@2)XAp%6dl9=OfL~@uNHIU?0{R}$4eF@_AD|;EO5ab>f`j7vU{%C9S_w~&!E=F9v z8p&x9E0N4?yQK7CGTqtADsPEWiEj9GWhmds$f&BSN=8NocIDb5_cPSZ*hiL$8pY;c zzI-t^H?MTsZSLqW2n96~agK8lZ{K3_@bGYt_GfDtv_;M?E-p?^3LI-zIu#1_?VyAq z=xZKuL+Cb!;4bAoe>xNj1v2etnu58wxDpZ)B9U^`j>Tj|L_o}1AFniMk5>DtT{~Q8 zlFr7!kfGZc@bcD^K&07N89Q@+bI4@VExxk@-EMC_*P|d8IZay0!D{zvAD>20V8Wmz z-SGh94b?q2G^yMRcr5@{S9xRV4Mf6=fN)ySC#gVU;x?g0KL* zE{4DnY&S0;>fIMfX|;YJgXJh}eF=h_4i_}l)lGpns1q^{zIwQnEE%5GW;RlEGnD#( zMl$T{*2;?M&xGUM<$dtfd_CUGMe8^55}oXBXelu4f4ESa=f=Eo@P`)T&rHHX9gqT1 zgBc4T{~1fO!}utgG7aCxpPYi=Pj}}lNk&MhvUY+lDJe0CbxisC^=oS^jm=Uo{r&q^ zV0tfKzU<;Akg1ZL7H!2JMUF>6P|vU&F}a(SGJpG0{fArp0=U4depZb2b%M-cyI%1g_qVzz4i(w|n1D`W>kvR8+BlbW#ik+R?Ruk;08I`Yh&f0 zhU1}OCxs=BTvC%(aN$sfS&CzCK)hzDwaU^q0I_zbMoFpU{R&;lyH!LAi`0$vqtV z4r|aTvypRJ$Ek3wXr{V@54?XE67Y3FXmNoe#U}vq9Q>fkRl{Dojj zoCkch#GZdoJt*;d_!-uwIWx*V`g=z&TS2B<}a{E<{tMps5eL_|)`dI-JZ zm*?dT&5L;8e4UUP)GMW^tU%%|JZ>ayZf41Es2 ztLGre!neQJtq$M5eH-j1*R|4lI=wuXh@c>_BZGs3g=axIO=^Yn?vip*%V?=}Qextu zRZog^DVz;NCG;`J$H%N1MejquQac^(7-dMQDXK;ob|reV9TQ@GTr-Gsotv5xO8v$w zu$GBaErS={}}===HoZzj7`8p(T=agjB>lq%S|wY(EslSpr$_Msg?_4=D#7(hX16mzIO~FrCij7`ONXZw z23mdJpMCplD6t=Rlr!+~$*48{jo4G%bEB(gepV8c)6mcmK*GuL;6X62JW-y08?lPP zk046mkzTY2Ayji;Tpq(485+tx`uX!`Ry3|W018mn#Lv%PW})v*`W*Syu;^I*3wi}azDo>_Rj;?Qhz(i81T|*hXMBq(?|7NPb zo5HuvTR+`%2_1V$&Smv&bTqoUizN{l4k$WAY0M#Cog7#;H-(LLd#fWx$_voQ)Mij4hLtar-2oHh1C=OG?kFgYJ4&Ds zohX{cOeIQcZm}Y_vFp5+S}W0o=Q7f0(=HAydu4SaBv_K!@W9Ed{O-sa$>j( zVhSah{c;Wt4yGGhl(9V-v#qOzhB`e13p z@q(U%8J)0#SYt4e3rdS2gD2=upKgug^04%Q7{DFWnaVrP)Bl75>mE?fpu1SQKcJ`v z515i(iF}f%w~r547*KroQeQvMsyPO1rwvfnXw@772!m3I)vQF9?yD;;;UQ6=E;BnT zi*6dY9i<)^rbG=W;v;O&99V(^?g0pbPNoo|(&Kxa%c^zY8hK}$)32zx?+-L1P zwx+d_jE7V7*CWMjf=vHH#t<3rkBq4J#0%G?z+(sKI86jz0AQZsW{Xa4Fc8Q$3JKCDI?Sf`s z1mYbcypRj#m+;L=n;*6hppTpXN#Z0zwU!8()tR1^$URf1{}sj894H+g zK$ZP|P1@hCGsBix9su!#L(n zD?mH=HT9uUq9GqX=olC@J_R+aO7a%~`&dj2lRc4v5{0S|v%d(mu^gT$nV$fb{SEgu z{9oZvl2y2R$2=5NeS&@47)W0H^{XmC=~C-?fPEYW?W7zY0yYyDZ`n?Q5$M85vaGGG zsi>&T5P-_^*_&SE!gy{h0#CUdDwLc~Ak*>RaR0$#LY&icX5x5@wA*G;>7S3so!9%m zJlA-3RSIp@h;XR*cN#5U`=p%D*U3q8RR%=B-$vfO3uD!)GVaT;o^M|ruPg@$>3IbQ ze*kh9{p|p1CGfXB1%6;WG(h;PeOm4Ib)sxZiBZ9#*xKF(B*6rn^32YLhK1Q}PCd57 zfk4t8{o<_~s&og218YAhBf`uUjx35yV^(|R!$A?h06X+o1lcgt1%vqY+syU_LbHYi zz+D%Cmw%ZE8!@1iICcloHUIg1+V{0yp-GZ^6|;h zD3*D4RMKU=QU~zm&prSgDJ`P}9ncP*zJHD{p5YKw{R1s+2^8fYT7g(8WDm%dhXNZ_ z0_SI^%7_G^t~C&MgDVmOe0?ony&42pDP+sUqJV4;sKZ__#cbDiKcazbje({nqi=7o z17VP0Rg>lW_wNLEr7$ruUx65JZ^*#?{M4R7N=7Cn_?}|Ai>qs@RD{*)FgwS6kS-k+ z7AER#Qv!uuiRO2&O8W+D2p}6Nvo+yPuBoX3>VAH6K`6uV!9nK)l7z(hU_(bGHaz@E zrVu|T>1#WfQ_BtRnl42XBgefOh9+OoWC^}=p&3B|__7~Q6`qoeEQcOsCW#Hx`T zE$zEqJmE&dZ9|u=Dsf(HKE?p9elS*3Q=2+%Npjv_dwCPwT5vKOuGQVs1DM!%PQA1{ zMtu_#?n8NcrY`}wJQfjI87sf2Y6fICew&qH6C$w(s_)BR{k$aZ85KnW(to@#y2GQR zN%MSu*8BK)c|EIi3T>vMq9Pz50A~c28Vn%T~M0@$NTF!Uhs;o zX2!ZcpaJCRH75bawSpT9D*ijc!yKhu4~~{|7F`yozmrI4uVc5y@NjZ*MGyv%atVbZ zNFPxUv&=xjI_bBh%EqN|mzI`NvzU5>_E3_NlJ2bx3C~N-QbV&`rW^eKo-qc`wKw$V zn|;dzIZx|g9HxU5&yq)*!nU`zR#sOJQ*`RzNJl^VkaJ%(QLmG%+VFym6A}`FDr}38@Ye1nFdeaH$TgEG$v9DhB+J=Ed z`>^Th>GZQI*JGAvB?2HPI-FH2Wou(&vz304bc?X~)nKr!?{3j%`Gmowf6j@m#VS;8`s>u3ziRO;Xe{nK@Pq zB_NwXGzWGw0bpTZz`o843#c*I2Z9(c4ul^6p$!XgrIAByVnX!B%=7g|+Vtf$$at1M zLLUE30prQeAivaGs&{R3>?)U#AfSiTC;`dv=drAHehhc+PM`n<9;R0;WqYm!1)#j4 z<;CxEm_`aR-Ez!WEH#jP_=5_JN2#8v-;_--u98&&o4kgBjKBO7RU7r>sujF-=*56e zl!g$F3KX0Z{SI({qcJ9E)#g`6j(8dQSWm4m+mQiWPw>w(j|a0@9`Lt1fp8mFceK^N zPwuZ1kp-c+bpj>A|NBW;=LryA0x!-cZ(h!#}0^s7ZK{9`hMJV0jQd3El zG}*IVa??owTG#>7|HC(E;$dS$Llb~VKtfC@(fU}}egwEYV&L$i#Z&MLK;|H-YE=O# z+1B~eP@}(h`D1`Qo^SW^gF75#=`R^VIti6)8yn4zlR_dwz>9^2g=K$z#vgR@ID}M# zN7P_yfb9gp$ELOD;QUt5Pxvax%VVvos;MC+-vc%m{8W0kQDy0`#s55T9b*!mhw9?m z$YdQp0{j?A33q*$C>Pd%`^%)zk|yAfyx{6Yw8FMvXAOli0l@XeL&oFD7h<-u`-Y${ zy#vyF7^`xu#u5yUhzuw6Z2@1{!V*-y=d}^Cb^FI6MN7(}UvL;0Q1Aa36nv|0cVMG7EBcwZ&IN$+nk0y7-Nx zJyznw!aBf#D*D^l*no0>vbfLij)XKV6$nzfJ*U!GvFHaaAeHK{mBy!~eIRKEXv-ZX zrSQy5`neP}6wU=unFbW;Lc0MBq?a!PSVC$mN^frqVpk~xMz6o(E}ei}@kTpLdo26f zeKo+=J-(6+xAlYQ0#}oPfdPKwnwz^)^ME9H2>3G0GzM<_e0T?Ys?tsyKWkQ&CXheY@BjZ&z2B_8BO*F22&&A$p(>xV;4Ms#~{ifehF8;lp!TK-J~<{n0W1 zyX;g9`5W0-ss9(U@vH$=j} zXoma&aU*-Q`1EuK%Sd`2AdMFwXY$V(}_kv%~ z$ple2YRs{DCvepmVg%Mu2gGN4ft%t#K)j^xJ2zX0X0O%Mb)F?Y<)2lO1eMVJ`@cZ> z<8f^U7&8s!DMvYUQ~nFx{5Ejyt$NLC?0c5o7+3Ghiw@|YY0SUvyFZb= z9WcIP>haQ$?(&$AUMn}Lxu=>!`S3M_|DLHZUWYJ@W6?xEmD7sQCv$wC-~7Hd4nt1Z zhHQVo*IK)qEbvC_W^dKg)PaGgMPNKa4CX?B4c4A1swtj)1}`ELRX23lGP z|NS2T+62+;PKLj{hJRVxj?u7#SG}B3BkL-)jxQ@ii7wuEcOKg4mZJ1z}Zd9*V@|J((=nAa&`oR)WmDU zYZt1QZekx)l3ZFG`vXhRh=Pouf7e&Bw%%h^tNOO@C}3M>TFC(fk}mFk_00C=SE=j1j#$%%=N@ z8z9=-FxRoyhEM+h%MJ?2HGVgP_b!@2z~SCdQd04OsGsKQ21=o50l4oxT`PC=07zH9 z>ntShed|jb$yJPE0p&zG11hP%zkg?Er+19^k~GQT=6jNbe`Ru`;$5j$P$?x!%I1K+ z7L-fp-?D>xei+Jwke~46$t8OFJ4ay6DUaqR01kmB5P*xCd~?N*`+g(*77QrB1V2i& z`GW`sogLU)@7C6qP7r9&F22%NIiG+bpti4%kB^qtFwn-hySc3l1j8vf-T%7`VK8J@ zk$HWVi_fUy?BhW}&H1zcj}jBp@^V7RbTGf8d&~(ZyIDgCPj(8`+|}U^;$<%Q~UK- zFu=JX8}$Dhpq~5wT@r)|N$>T@zb81rasgc&ZxE!cpI2t;Ijd=*8yjlq_fh^O8yudG zOgk2-@f@&{>e7Ar6#{{58hm&Nw_O6sF^a#rX6Bk;Z#}*L(X1mw)hEvC>D6EYoFn`{ zL}Ows6FXaB;b;wfiI_P-#z`y-pVDNyn{xhxrC%7JfS~vU1U%&W=&;Os8-@mZdM*pCh zxwu$gB(%VyasMqP13l1Z>3%c$jNZ0mAfNOK1mE!ih(j~CYo z$-er6Kck1eEPNZ_CuC0y#-O%xW7OvW^W^(jt~cH z+~~VocrJ%7;YYJfY~DRset6)v3>^8sr`#E=2)$w+SaaAf_hvErh7Jo*?dJcM>n576 z&&kGU+?W=NHw42o<6})E$1K1eP!Rs^yI(MQYq+RQ;Vyg?FR#NNZZ`UR73Cwx&d|$| zD($^+<+U{&AIvT69n6KCx4&Q7efhS9#e(--AgC()PAC{K8qUBI4~Tg|8#4p)0C1|? z-rfcPpYeXx`p|zctZS8GayWkiNYC}T=3gMD=3|Mv%q|8Jkf1n3Q{fGwp64eU&DjYF zpdCZ_#Yh72QJOFd4HzC`h3`NvJQIB|!L3p#2YxUk&5{atd{z}-9|WRWJ{F+oE5E z`FJfTpr6cu#wqa@YsdmIiGZ5`$zW0F6%3q)rVm!Rk0sS|1&aYw+zKU$_XXM)QXr2Y z0Tbf5a4FO>_?^O^Gva%=p9pUf4)VMagp$k;*(gzi@zYAwui^50VO^K5E@lFHaG4l1rD8L@x2O+v_QHvjdMl zd=lHIV}+WxSuH;7vX0pKH2WMW_V+{*C;~T^k;=kgQ>>%4L&h#+NdxV<7%<{}&*mvH z5cn$V`eKx$Bg(Gq-{g@(orA*y`gc{DNtjWrlbxLdJ_%`9wAB1;<0&x75VoCnu(F~@ zB5UvU6E-ZH1<_}VI7OzUWK>n@-nh}-6uA02V6l5PBx68pLbJGvO|?+O(O_U~OhTv} zpFXNaiI?!Zvf}k5nc$#b(w~adO(GDyK%hla;yhKI@8txqUIi9OYHIt8L8n)Ze@@qZ z+8H3R>IK6SMS8p$SMShn-uZzZ^|7_hQAd~ue8X#co3?_5xpST{m z=1NFESYJq5v9WMi7?~+@wl|%VX_~z?Te+6`WoE}qz2ECevs!hr&BAE=EqCoSg~7{w z#GbY*s5^B^^;+5G5)Im~O-oi$riAaduO-wn<-%?~3$^|2&GyIq@*8Csi7K7yhWSR( zm`sO*$ojO{>d}?z)3xz8MxV;J?Y_L%yPy4x9!c$J>H&@8&uAI5L%;IscR=iTT`*3zSGugwkzVxbpOD>HPM4m;~KZ+e!5$R zCB?QWWiMW6XRD~iQY8ZbetKrc_hi4|!U4un+FpmTiBmdI4TT{wzFUiyx^Qb^f-#XW z(J`^lGiVqbx@Jn0j?%gqu0YR@J0vAO6G~&2e#oA8=g9^e@$2DM$6GTSx)u)AgB)e><;(Oxwi>_aO5Bmt8TPN=Z-OB9& zGg-rK8N5z67;@5>3XJn?g{u<0%WJaUZ7P7ll7c%PyI@+d?9PHi+fUe!Nw*693|A7{ zZAx`D=q)8p ze!0u?I{Ydbr5ve2zPF-|BS$V12Zv=Dd-8-OB*~!Z)hvy6^druLtA#W>9U6eN(ghav!q3EEHMmp3`E4$rLnQ z|2mzN&@-y~LKB|L6ocZU*-8RWPVe1T8N+UTgT&IV3SEU`M-!l9+~{{c(DXr>M-)0ANK}7O>PS_vy5Tm| z?X9d=b)@fb-(lm5OQOS?sCL1=76h*ks*pmY`!W%yi{PH&0xMq>?r5uA~VnmRVOWou*NEs-(~{D7Ccw}|@V zJOu48Ks8snddrXYb$z{WQ7zc9AWE}M=X==y*8>U*1NmP%Di;6F$hxX&=gH4HgBbLHbvlp9H=8>*;asay;rsR~CJ6l2YW8(|TY zkc2_`Bs!6h0(@&MbZ)IMdN|fKHhMT-?3uJO#U*f3X;mOP-VB6r&~;HVVUyQp?qlati(KDxn$2=_-)3tx7e>uoL&kgu;uYgzGuKnS zX#7(Bm8)ib6DdXS3~q@gkta1=AgKB?kt=GZUxH>Ng^{CcwH2og#Yk_3Kz(G06@)W6 z9Xn`$O5lp*3M`^1fXk2?N2Q4JMreB$NEBYd4Ihn!NtCF*niApBPsxoJfTPE6rVNRh zpFY~6N~Zc68=L128J=!lj+GQbh%p^xPQMiSMG(MLPDLq7`F^#fC-^zrbAfy%q=svS zJO_EKgaE;Pxc7ImZ^5yi7gv!dCjq`Y#5;!QauQ5z8K#ysP24q)BWIqRoQz&u`b3xe z@tH4W?60$pKrvRL^{-#yLs6FKmPh0|cJ~L?3yNB?=18st$C1I&!Vrhu6*5v9dV1XR z>pZt{x(*RIm%cz~RwBZW6+R3|>vuHqLvSNE*Iqej98#M#JV~d;VfEC>!*Tc=)R&r{ zo-U8VE*M^(cxy_8KpEa(dEVUIHC7U3WQWWdV7I?c0Kf9=PEKs|SRXOQyljPLZoLz? zS&F71a=G>zVx_XugbI$n@0v5?2PqP=-XMKO6d+3qlTkvF{xX!x#|~0@bl+}h%teU5 zzY^LgZ0&J>&W=L8{pm^X`)bXR^Hf-^Lq1_o@LL%Q7T09!)6%rXBGt1n+U={NYTpy|rK-|a+~tUACE zd~<$rL#M1HC%6+jeSO$Q7y)@RDf*5dDImsF%Q2B#LdZg;lta2`rfa36U>~kC`?6BY zh*Fr!9Fe*?iOm(*6{JMRzs3nkqz>erhzFNgN|t5-+1$rDKuuXv#(>je-K`@wf4D_G zPh%n@$?BsL6^qo+Ni5MLDJ-%;L%8mY6SSvYQ~uhX3KOHn>;moCeDlJam>8tiRW@SN zy7IoRF3QdWG2$;6USldhzkS?+{&|S7R|Gn7KE+JN-cEdVc^TUP#(F+gLkDGgDBtSv zrljD$@4-yW$B#YDXHJ|xet4r2j1U_v>=s!%2Uo?Sd=g zw2D<0#x$oRA@@6wEvBrd6zT>>Qg6@j(Vy0F(t~A8*Mh2CTX1HOgI>QF#Eo{HP)})O zQcZE}pC{WqFR9ZK<tpBRP|E7kYIoVps9_j9u~~n%w{Ei7Z~d?x9>O|r~wLTM#SZ|oTd zQ)(3L`8+A%t1MJ&fY**h^>Z5-+?J6{Go}6*rM|T}Q)c3)1bq#`ZV6g?_>}x2lyt|x zKts|$m^J!QNwU`Sm$`q_7Q1q#-7NbAD?_wquC9n%NXWW1g!7L`jv9Xxw6?x(Vk}7# zTjONRlcd4~)QaR57BB1EyS`e_rvk|`lK$r)+Kd~{bn6NW`X``^U`@g9-)2$4wzQ$G zPzXHmSnTs>uB-?3`MPlUyikpcS+qFjgxunCFid!4`7Gf~Kk$3&=Rv9K?-uYUXb-WHr@@^%nHB zVhG<0;FPrt!e*80tRkXeTxsBES`0Q;TsllVzKLYB^?JAvI;m^BPADv}L6{$qE&sMd zG`%X=_A@F7F>f1M$`Kyj0OKytWBGT*10_;Nvt-B#85oBd`bIK z=x}Jz%yju=bzI4)Ui#Z-MzWFOIV1Iz^}i#l3I~}y&+pVCgbOd0rVpW)f2^Q^mjR1E z6*`kwr}1cI_{lj4Y}CK9t$|+Tzd-3P;G)+w?e*&l$q?93`xl4K!d9wk2}6&OJB9O zCF&vT#@-*=UrCgvy01?rAd7P3$K~lhWxclUgEV4K4P-aA=H7m@KX7_Y`;5QpPT8Fl zG0dMgGe(Q5;3mbBwwW-xQYVAiN~s{L2gl_e6gcNvJme>e4&_z|gFu_>wS7fRfdnSY z(P!7LxZ$T8b)9>*H;^Su^(Im4iwuf^E8~yKja)bA6+_!X*ZuQHM;9jwL~d*Z1kRa= zuUcx0lwF44K~oHOoycnYewX;hU_FS-736fdmzzt!Y zK%!E{_MjSt+1ZkQZowa+B@!}Zrkx9zA5)X_85WQ(A4igD*<(DSP&3~|6gPZ@i#Vzu ziZn!SHu^FTeD0E1tRuxEGNHt~o82TF_Yqp>q>4w$g_C%7C;lk$F#jwuTy0%b{E@BnsCgY~F;=)%td;x_NdbYeykTT{|qo=n*1cc)o~d)325 zzvDXsj!_zq^U@P1ynzLrxoIZf9N7^Qz=QDbn4;~W5(NWr%!vmA9qw9@mu)rH!}Ba_ z-7f)@)TSwX7xncz$EaBVGvjC3{iC==@~>u32~oGPRbN^O+v<{(+AC^a36quC+F~XQFB?I>0*9S{YjtUfe)j69E*rbD z(5$k@ueG}fFh=N<*0&a1j#z-aUlji^Qq%ChH;Tqh&Ffyn%u4X%kI)ZyK47J_c+e~{ z_oO081vy!&rIP8-(FIYk#|M-!?AON@l#(hzLxg6tl_oso-jt!YAHuNMal(@#-oAgQ zS}(@rU`B;%*<}~j{wC8zjK#~AMso|^rR6oji8{G+g_2xBIBz9D@u)s+u`Hb#JQlrEa?`RDD zESn&~M#>QnY2v2hX&XP`q~;7;{i{Omd!Er&#jKJIs+JV%Y4hTTA6kD{ zBiCLaHO$O_R{60yaC-)GdC2To+Jeqf3Z%P*1*q3=#m0K66x^}1WAOV%V)g4ie{%q_ zmONiKcS`S|BsA)Ax#kb6xIGmW+T*?PH($AojMRYCc;Wl^s|k@=KDms3>SQkw?k(qM zbU7TA+AR5I75A!ZycypbP>{|ao$e5#HAS6~VN~)e)YK=O+U3I|d89o09)2oBzS{T5rXmHq&_W z_g`)bYx0%OH>{n7XyJ=4ecqd{Ek%JL$C$j1B8$AXvgX~mJw_uj;Q+_lHcg9?%2>{r z$=&g*$m_P#Iq|Pa>q1TJS!3Qrn)$l2MUPrMbNXueR6iqv@O884n^GO_XA}^|b&K^1 znbfenHRmz8qf2$z2NW+2`i@tOUbliI3|JuLV_3X6#G#{b$Hpa)iqvcCfhk#auYjstWXMmHG znxXGIH}fS_+EXHdHqJiIjZi71u4@HLvB1qM)N;u=oO1D*(u{+m8GgY$LUb>=y7gA49C*bZDK;Q(7^X&IuLwRHIFa`QqQ@u#kr zYy|yuVVV?i0~wVL!|vnR+`g}{AH+iN3V)-Ao^_A3H1OtB$TGnm|H&OcGXQTIg%y8ItO+d@@`ja(d-dS|Vn^ zT$4iGWH4d3kh9ilkJoxYyPLp?#&DTY##3X|gJC>J$(--B?wMvM?dZjZ72rVRK4%Gw z_4}~F{GbEKhXeTfwOpO_m-Y9J4cl|^&=Vu)*N7Fvk|Kf$vo|LnrZx8waTA8V3G0XE zSa64n6QkR7NAkk?F2B^_B#fo(bI!^P5-_vpzvC}hGSVi86N5tgr%p?2CGR2_`vgW!Q*To zFl$De4N2{BQi~x{iuGG88R8ymX$EB77Ti)8f+<26Rn|meBz{ z{ZQsKW-$VYW%onopPGh0HTlj=n5eQp*G*A67DPgEm*x-I*Plh^nS`3Qa%*dfu06c8 zkeE`Kvw6o`baJ^G~)=r3%OYSWsw`o+B)(aiJH5F?u<@YT^(9U?T1#} zi)k$?aWZBoDpYEnp#Pao9Nu|gYlSL#MV=Ec6Nv2ivfm$pLKCe*SyAT2!opK=Ub;Y_ zvG4R$ON#{`R0fF&Dt*wpk~+0VYI=Nn0*Q>r%Nm=59M4*z`1dcFXqlR$;zY3Eq3s;V zSm;%>%FS?a`uBJZBqQ@CA9(S7qqyG&b-Wx0V|mvC#dn`F`%E%R9Z)vLv4OXd7{>WS zh&tPpDD&O!_X064dm|l`)Y41pOhar<^`N3OItWf7w$~$=`D+rk&H0qa0AG3Vs<;=? zzwb^xJ7^`Iqi)TJ3x7C3>=GBVqA-`$!raY#?|Rjvxy6d73-5CqqZ8x{!+hGcOZ~Pl zbG=-7x4-XGdznn0^{1yrt~HVz*B~&pc*&+D8IDNWJdr4w1G|?Y$)` zT4Xok_A&c{>FaDhmtdwK7`%$=ifc9>a*ep+$9(y+pqiSO$8EXQfoHx+nGCLwz>^!e z@SGDYlJx{=8x%LPo?k%A-3+7U;Jn+qf?wT-Cq7f1<0tdqttB7jYb+KH7e?mrQa@R4!c58vnF}K@!TuB70v87i zt%FIRAx=9CSK))X90-H_Fj&0odJ9xhldFnAdBGo>*z_Cbh<#ZBA44lf5cO^|-2VWl zezzOLiG~mzoGBlF)$SaVp@8!YcS4=cQ$Ipm67m19uN~)DeTz z)Dxc`n6(JDlg&|MI83zHf?r^k^p%(F#G5-u`d0biUCg;TU)yYAQ&(=-P=Ny3PWM& z_xGz^8n%8^Ib;iqoM$$w#Rp?WQBiVIlvCd|c(Av|{%xSy)Xc2WW7T7ts8Ve+#jNr* z`R&`$7?JrAXHf0K68-9a*0okA9D^X&Sm@W0{dk~0jq;aoL;I~u^@0>_fxQ8M3hDcv zhJN<92AOynV^XO$I8M7=_$z(3=1F~DnX*2w7CvR$=FGz7aiJ#}Po6KH_a5hQaF|u7 zZR+!W$IiTznIqws(XXxa74s=&DvPc`G+OO$JQ0KI2YuD7#$(6Mk;_z-dmaY^(BG$b z`sd3y-8a7i13wQ}BEDnyuJbOPB-JIVGa?{z1((9|(cTN;4s^+)yaRKo*-bo+Ao-k; zpRnuIjKs+Z;UGBbZcB?s!sqc&om6@SC+(jFjIdB&C%mIeBR*^x$9#pip^Ian#ywZA;w*G|7W9>Ze``=|(v z?T@g0!Q}T) zQLLpMY!o-dTBa4nFe_xB8ULRyB29`oJgC1uZyM?MFsGuv9lA3fhndr3$z@=!HSs)a z5hOC54KkJ`mm*IX!ZxeTqHnh--WV%ogq=rsLt6ELg&xs2NG=2WnK&l0xa-z;66E{t zr8Ck3b+{|d>O1FzvAYvi5cqVR-&r$Uoh4AGd1r5_il5Kt-nWLLN4HHRMWjiPkicf} zut;G4kS!a;aIl)?k3_GJQWtqOKiXXz-jjTp^;yDyDA|y(MxT$FMaaf!QUl)X4D|7z z!9Ww3ass-=(bkyw-V+PeY{VCVVec81l16hp_~1`4uoIE61m4y1?g!JoZQL2`OdL~O z`h%}=vR@tmpu47K){k)5Wu~5zFFmF`GOeLCj39;Eq!PW#0PJ#n<-CR6eCg)uN9B-8 z$LkNGX9y2^q2Rf}4vvo4%~%S3DUZ?`=Q z0mCfdKi+Fn62pLZf!Ei}{`Eh==Xvw5l`Px)#sNA6#P}C0Ie?YGgRw96a2@R7_v_Rn mTCnHeuloXG{=Mw}FQP}(VVR-r_CU@DxuvLfqg38J