Своя подсветка синтаксиса в IDE Delphi. Пример

Мне очень нравятся Build Events в Delphi. Это когда с проектом можно связать некую команду (например, cmd-скрипт), которая будет выполняться перед сборкой (или после сборки) приложения. Будь то по F9, либо при внешней сборке с помощью MSBuild. Мне это нужно для актуализации автогенерируемого кода, используемого проектом.
На днях занимался оптимизацией Prebuild-события, постоянно правил свой cmd-скрипт, и мне очень быстро надоело переключаться между Delphi и Notepad++ (в котором редактировал скрипт). Немного покопавшись в ToolsApi, у меня получилось сделать подсветку синтаксиса для CMD/BAT-файлов.
Выглядит это так:
CMDHighlighter
Это в меню Tools Options. Как это выглядит в самом редакторе – см. ниже.
Пока сделал на скорую руку (осторожно, черновой код!), исходник доступен тут: https://github.com/delphinotes/Useful/tree/master/CMDHighlighter
Устанавливается так:

  1. Открываем CMDHighlighter.dproj.
  2. В опциях проекта указываем суффикс – в зависимости от версии Delphi (210 – это для Delphi XE7), см. последний столбец http://docwiki.embarcadero.com/RADStudio/XE7/en/Compiler_Versions
    PackageOptions
  3. В Project Manager’е делаем Install.
    Если не захочет устанавливаться, то можно удалить dproj-файл, открыть dpk-файл и сделать как в пункте 2.
  4. Подсветка установлена, теперь необходимо связать её с cmd-файлами. Рекомендую делать так:
    • File Close All
    • Tools Options –> Editor Options Source Options –> New…Ввести CMD/BAT, нажать OK
    • В поле Extensions ввести cmd;bat
    • Установить флажок Use syntax highlight и выбрать CMD/BAT Highlighter в комбобоксе:
      SourceOptions
    • Остальные флажки и значения – по вкусу.

А вот как выглядит кусочек моего Prebuild-скрипта:
Sample
Спасибо за внимание 🙂

Читать на сайте автора.

Запуск сторонних программ в Android Studio

При работе с беспроводным подключением устройства, часто приходится запускать bat файл с командами подключения для adb.
Например таким:

C:Androidsdkplatform-toolsadb connect 192.168.0.10:5555

Чтобы ускорить эту работу, можно добавить запуск bat скрипта прямо в Android Studio.
В этом нам поможет инструмент External Tools.
В нем теоретически можно настроить запуск любой сторонней программы.
Для добавления скрипта идём в File->Settings->Editor->External Tools и нажмем +
Безымянный
Далее все интуитивно понятно.Безымянный
Как сделать свои горячие клавиши, я уже объяснял тут.

Для наглядности приведу окно настройки

БезымянныйCtrl+Shift+Q и устройство подключено (если конечно ip не сменился)

Читать на сайте автора.

Как я боролся с iOS 8.1.3

rouse

Давно я не брал в руки йОС, но давеча мне говорят: «ну-ка, покажи нам на айпаде пару новых идей»! Я говорю: «сей момент»! И показываю.

Читать на сайте автора.

Обезжириваем apk

Что из себя представляет apk файл?

Это просто архив с ресурсами и кодом приложения.

Если, например, картинки и файлы xml ужать серьезно не получится, то вот сам код ужать можно.

Возможно, это потому, как в каждом проекте есть не используемые части библиотек.

Наше IDE  по умолчанию соберёт все, что только есть, и конечный apk получится большим.

Стоить заметить , что в старой виртуальной машине есть ограничение Dalvik 65K methods limit, т.е.вы можете ссылаться на очень большое число методов в DEX файле, но вызывать можете только первые 65536, потому что это вся память, которая у вас есть для инструкции вызова метода, львиную долю которых может съесть одна только Google Play Services.
В недавно в неё включили аналитику, которая до этого была отдельной библиотекой.
Поэтому Google Play Services растет, как на дрожжах.
На помощь нам пришла сама Google, т.к.начиная с версии 6.5 сервисы Google Play могут подключаться в виде нескольких небольших клиентских библиотек.
Нам остается только выбрать необходимые модули, а не таскаться со всей пачкой сервисов.

Весь пакет описанных сервисов подключается в файле build.gralde вот так:

dependencies {
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.google.android.gms:play-services:+'
}

Библиотеку поддержки appcompat, я не знаю как можно урезать, а вот вторую знаю, мы возьмем только модуль с рекламой (ads) :

dependencies {
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.google.android.gms:play-services-ads:+'
}

Знак + обозначает, что нужно брать последнюю версию.
Чтобы обрезать не нужный код, так же был придуман инструмент ProGuard.
Как ясно сказано в документации, он может обрезать, оптимизировать и обфусцировать (сделать не читаемым) наш код.
Для его включения нужно выставить в build.gralde свойство minifyEnabled в true и добавить файл proguard-rules.txt в папку app.

 buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }

В этом файле нужно прописать правила для работы proguard.
Как я понял, достаточно указать в нем классы, упомянутые в манифесте.

-keep public class <MainActivity>

И так мы можем обрезать все с помощью proguard, можем взять библиотеку полегче, а можем сделать и то и другое, а потом посмотреть на полученный apk.

Теперь покажу, что получилось после всех этих манипуляций.

СнимокРазница очевидна, удачного обезжиривания!

 

Читать на сайте автора.

Используем True Type шрифт для хранения иконок

Это сообщение описывает шаги, необходимые для создания Android приложения, которое использует True Type шрифт (Font Awesome), с целью хранения иконок. Использование шрифта для хранения иконок

Читать на сайте автора.

Горячие клавиши в Android Studio

В прошлой статье я уже начал изготовлять из Android Studio нечто похожее на Eclipse. Там был выбрана схема клавиш (Keymap)  как в Eclipse.

Теперь разберёмся, как сделать кучу полезных действий при сохранении.

В Eclipse  есть настройка Save Actions, т.е. при сохранении вы ещё какие-то действия производите с кодом.

Находится она по пути Preferenses-Java-Editor-Save Actions

БезымянныйТут я ставлю форматировать код (Ctrl+Shift+F) и подправить все сторонние пакеты в заголовке (Ctrl+Shift+O).

В общем экономим целых два нажатия горячих клавиш!

Как это удобно — не опишешь словами.Лучше один раз попробовать.

А вот теперь поищем такую настройку в Android Studio и не найдем.

Но голь на выдумку хитра и товарищи предложили переопределить сочетание Ctrl+S  на запуск макроса, который всю эту работу быстренько и проделает!

Макрос можно записать не отходя от кассы: Edit — Macros- StartMacroRecording

— делаем форматирование (Ctrl+Shift+F)

— организуем импорты (Ctrl+Shift+O)

— по вкусу добавить свои действия

Как  сделали, что хотели, сохраняем макрос под свои именем (например formatted save).

Теперь идем File-Settings-Keymap-Macros выделяем наш макрос и жмем правой кнопкой мыши по нему в меню Add Keyboard ShortCut.

БезымянныйIDE скажет, что у нас есть конфликт с другой горячей клавишей, но мы его переопределим.

БезымянныйБезымянныйВот и всё, так можно и в магазине стенку убрать, если постараться)

Читать на сайте автора.

Как хранить числа в объектах TStringList

rouse

Как хранить числа в объектах TStringList прекрасно известно: MyStrings.AddObject( MyString, TObject( MyNumber ) )…казалось бы. Однако, мне (да вот — дошла очередь и до меня) пришлось

Читать на сайте автора.

Как несовершенны константные аргументы

rouse

Я тут попал в такие чудеса на виражах, что уже хотел застрелить компилятор и повеситься на шею кому-нибудь с жилеткой, чтобы рыдать аки дитя малое.

Читать на сайте автора.

Почему системный файловый диалог меняет текущий каталог?

Это перевод Why does the common file dialog change the current directory? Автор: Реймонд Чен.

Когда вы перемещаетесь по папкам в системном диалоге открытия (или сохранения) файлов, то диалог вызывает функцию Set­Current­Directory, передавая ей каталог, в который вы перешли (эй, не заставляйте меня возрождать уголок зануды).

Окей, возможно, вашей первой реакцией будет: «Правда? Я вообще не знал, что он так делает!» Что ж, это ещё одна страница в истории проклятия текущего каталога.

Хорошо, но теперь возникает вопрос: «А зачем диалог это делает?»

Вообще-то, вы уже должны знать ответ на этот вопрос. Многие программы рассчитывают, что текущий каталог совпадает с каталогом открываемого документа.

Но, оказывается, существует способ сказать: «Нет, я — это не такая ламерская программа. Я не делаю предположений о текущем каталоге, я могу работать с любым. Так что не меняй текущий каталог». Вы можете сделать это, передав флаг OFN_NO­CHANGE­DIR (а если ваша программа использует интерфейс IFile­Dialog, то опция NO­CHANGE­DIR включена перманентно — ура Прогрессу!).

Прим.пер.: для Delphi флаг OFN_NO­CHANGE­DIR соответствует значению ofNoChangeDir в TCommonDialog.Options (значение fdoNoChangeDir в TCustomFileDialog.Options всегда игнорируется), а интерфейс IFile­Dialog используется Delphi в «диалогах Vista» (например, TFileOpenDialog), а также в стандартных файловых диалогах — автоматически на Vista+ при условии подключения манифеста (только в новых IDE, конечно же). В последнем случае опция ofNoChangeDir игнорируется.

Но теперь, когда вы знаете про второе проклятие текущего каталога, вы можете использовать его против первого проклятия.

Если вы смогли определить программу, удерживающую открытым каталог, и вы подозреваете, что программа пала жертвой проклятия текущего каталога, то вы можете зайти в эту программу и открыть в ней файловый диалог (например, Файл / Открыть… или Файл / Сохранить как…). В этом диалоге вы меняете папку на, скажем, корень диска или на рабочий стол. А затем закрываете (отменяете) диалог.

Поскольку системный файловый диалог изменяет текущий каталог, то вы, фактически, внедрили вызов Set­Current­Directory прямо в целевой процесс, уводя, таким образом, текущий каталог с каталога, который вы хотите удалить. Заметьте, однако, что этот трюк сработает только если это приложение не передаёт флаг OFN_NO­CHANGE­DIR в вызов Get­Save­File­Name.

Для Проводника вы можете вызвать файловый диалог нажатием Win + R и кнопки «Обзор» — и в версиях Windows вплоть до Windows XP Проводник не передаёт флаг OFN_NO­CHANGE­DIR.

Читать на сайте автора.

Ваш отладочный код может быть уязвимостью в безопасности: подгрузка опциональной отладочной DLL без указания полного пути

Это перевод Your debugging code can be a security vulnerability: Loading optional debugging DLLs without a full path. Автор: Реймонд Чен.

Запомните: плохих парней не заботит, если вы добавили код лишь для целей отладки. Если есть код — они его атакуют.

Посмотрите на такой код:

type
TDocLoadingProc = procedure(Stream: TStream);

var
OnDocLoading: TDocLoadingProc;

procedure LoadDebuggingHooks;
var
hmodDebug: HMODULE;
begin
hmodDebug := LoadLibrary('DebugHooks.dll');
if hmodDebug = 0 then
Exit;
OnDocLoading := GetProcAddress(hmodDebug, 'OnDocLoading');
end;

function LoadDocument({...}): HRESULT;
begin
// ...
if Assigned(OnDocLoading)
// Дадим отладочной ловушке изменить документ перед загрузкой
OnDocLoading(DocStream);
// ...
end;

Если вы хотите отлаживать вашу программу, вы копируете DebugHooks.dll в папку приложения. Код выше ищет эту DLL и загружает её, если она есть. Для примера я включил код одной из возможных ловушек из этой отладочной DLL. Идея примера (и это просто пример, так что давайте не будем обсуждать, хороший ли это пример) состоит в том, что непосредственно перед загрузкой документа мы вызываем функцию OnDocLoading. Эта функция может обернуть переданный ей поток в другой поток, так что содержимое потока можно логгировать при его чтении — в попытке локализовать на чём стопорится загрузка документа. Или её можно использовать для инъекции ошибок ввода-вывода с целью тестирования. В общем, используйте своё воображение.

Но этот отладочный код также содержит уязвимость.

Вспомните, что пути для поиска DLL ищут библиотеки в таком порядке:

  1. Каталог приложения;
  2. Каталог system32;
  3. Каталог system;
  4. Каталог Windows;
  5. Текущий каталог;
  6. Пути из PATH.

Когда вы отлаживаете программу, вы копируете DebugHooks.dll в папку приложения, откуда она и загружается (шаг 1 в списке выше). Но если вы не отлаживаете свою программу, то шаг 1 пропускается, и поиск продолжается дальше. DLL не будет найдена на шаге 2, 3 и 4, и в итоге мы достигаем шага 5: текущего каталога.

И теперь вас хакнули.

Как правило, ваше приложение не имеет прямого контроля над текущим каталогом. Пользователь может запустить вашу программу из любого каталога — и это каталог станет вашим текущим каталогом. И когда вызов LoadLibrary будет искать DLL в текущем каталоге, плохие парни могут положить в него их собственную DLL, ваша программа станет жертвой инъекции кода.

Это особенно опасно, если ваше приложение ассоциировано с каким-то типом файла, поскольку пользователь может запустить вашу программу просто дважды-щёлкнув по файлу, с которым вы ассоциированы.

Когда вы дважды-щёлкаете по файлу, Проводник устанавливает текущий каталог для приложения-обработчика этого файла равным каталогу, в котором расположен этот файл. Это необходимо для правильной работы приложений, которые ищут в текущем каталоге вспомогательные файлы. Например, представьте гипотетическое приложение LitWare Writer, ассоциированное с файлами *.LIT. Документ приложения LitWare Writer, представленный файлом ABC.LIT — это просто представитель семейства файлов: ABC.LIT (главный документ), ABC.LTC (индекс документа и содержание), ABC.LDC (словарь грамматики для документа), ABC.LLT (пользовательский шаблон для документа) и так далее. Когда вы открываете документ C:PROPOSALABC.LIT, LitWare Writer ищет остальные части документа в текущей папке, вместо C:PROPOSAL. Чтобы помочь таким приложениям найти все необходимые файлы, Проводник указывает функции CreateProcess, что текущий каталог для приложения LitWare Writer должен быть равен C:PROPOSAL.

Так, вы можете сказать, что программы вроде этого LitWare Writer (которые ищут файлы в текущей папке вместо папки с главным документом) плохо написаны, и я в этом с вами соглашусь. Однако Windows нужно работать даже с плохо написанными программами (упреждающее ехидное замечание: Windows сама плохо написана). В реальном мире есть слишком много плохо написанных программ, некоторые из которых являются лидерами в своих сегментах (см. выше упреждающий остроумный комментарий), и если Windows перестанет их запускать, люди скажут, что это вина Windows, а не этих программ.

Мне даже не надо закрывать глаза, чтобы представить, как нам присылают баг-отчёт с этим поведением:

«Эта программа отлично работает в MS-DOS, но в Windows она не работает. Тупая Windows».

Клиент не будет счастлив услышать следующий ответ: «Вообще-то, эта программа никогда и не работала верно, ей просто везло все эти X лет. Авторы этой программы никогда не рассматривали случай, если открываемый документ расположен вне текущего каталога. Им это сошло с рук, потому что обычно вы открываете файлы в MS-DOS следующим образом: вы переходите в каталог с документом и потом набираете LWW ABC.LIT. Но если вы выполните в MS-DOS LWW C:PROPOSALABC.LIT, то увидите то же (неверное) поведение программы. Иными словами, это поведение системы — не баг, а дизайн».

Ответ на «Это поведение по проекту» обычно звучит как «Я скажу так, что дизайн, который не даёт мне выполнять мою работу — отстойный дизайн» или кратко: «Нет, это не дизайн, это баг» (вы не верите мне, что такое происходит? Просто почитайте Slashdot).

Итак, чтобы все такие программы продолжили бы работу в Windows, система устанавливает текущий каталог для программы в каталог, содержащий открываемый документ. Это вовсе не чрезмерное и не безрассудное решение — ведь благодаря ему начала работать программа. Не то чтобы запускаемой программе было важно конкретное значение текущего каталога — ведь у неё нет контроля над ним!

Но сказанное также означает, что если вы запустили программу двойным щелчком по ассоциированному документу, то программа будет удерживать каталог с документом — потому что этот каталог будет текущим. Если только, конечно, сама программа потом не изменит свой текущий каталог.

Бонус-замечание: изначально я написал эту серию заметок более двух лет назад. Но даже тогда я не считал их чем-то удивительным, новаторским или интересным. Но, похоже, некоторые люди вновь открыли это несколько месяцев назад, и вылезли из кожи вон, чтобы присвоить себе лавры первооткрывателей. Это как новое поколение подростков, которые думают, что они изобрели секс. Чисто для протокола: вот некоторые официальные инструкции (и, чтобы расставить все точки над i: это официальные инструкции по атаке на текущий каталог, а не официальные инструкции по сексу).

Историческое замечание: почему вообще есть текущий каталог? Ответ: это идёт со времён CP/M. В CP/M не было PATH. Всё запускалось из текущего каталога. Сегодняшнее состояние вещей — это цепочка из обратных совместимостей.

Читать на сайте автора.