Советы скриптописцамОпыт. Наблюдения. Особенности. Глюки. Недокументированные возможности |
Список команд (command list) можно использовать не только по прямому назначению. По сути дела, список команд - многомерный массив, ведь в строке-команде можно хранить кучу информации! Например, функция cl.AddLeft имеет четыре аргумента (команда, параметры, рабочая директория, способ запуска), где можно упорядоченно хранить данные и извлекать их поодиночке. А как вам возможность добавить туда любое количество команд, каждая со своими аргументами? Более того, список можно даже сохранить в pcf-файл!
Налицо очевидные преимущества перед использованием плагинов vec и map. Во-первых, они загружаются отдельно и, строго говоря, нуждаются в выгрузке, а список команд всегда "под рукой". Во-вторых, нет проблем с передачей списка в качестве параметра другому скрипту. В-третьих, вектора и "карты" одномерны, в отличие от списка.
Есть и недостатки. Главное - в списках отсутствуют возможности сортировки. Кроме того, не дай Бог случайно запустить на выполнение команду, которая совсем для этого не предназначалась! Однако последнее весьма маловероятно. Что же касется сортировки, то, если она понадобится, можно скопировать данные из списка в вектор, отсортировать, скопировать обратно и удалить вектор.
Бывает, что скрипт, по всем признакам долженствующий работать, выдает ошибку. В 90% случаев дело в неправильной оценке "долженствования" и причина неработоспособности - ошибка программиста. Но если "проверка глазами" и отладочная печать вновь и вновь показывают безошибочность кода, можно попробовать иерархически выполнить следующие действия:
Особенно много глюков, судя по всему, содержится в плагине vec. Чаще всего программа жалуется на выходящий за пределы индекс. В этих случаях перезагрузка PowerPro почти всегда ошибку устраняет.
И, наконец, нередко появление глюка наблюдается при следующей последовательности событий:
Запуск скрипта -> сообщение об ошибке -> обнаружение и исправление ошибки -> запуск скрипта -> сообщение о другой ошибке
Достаточно ощутима (в зависимости от сложности скрипта) вероятность того, что последнее сообщение не соответствует действительности.
А однажды случилось так, что ни многократные перезагрузки, ни чистка реестра, ни переустановка обеих программ (Total Commander и PowerPro) не помогли - Total Commander почти на любое действие отвечал сообщением "File not found". Если такое случилось, попробуйте запустить из Total Commander любую внешнюю программу, заведомо исправно работающую. Если сообщение об ошибке вылезает вновь, перезагрузкой или даже переустановкой программы не обойтись. Я похвалил себя, что регулярно делал копии реестра из резервной операционки - иначе пришлось бы переустанавливать Windows.
win.debug(allglobals)
позволит узнать много интересного о скрипте и сэкономить память.
Напомню, что по умолчанию всякая переменная в PowerPro является глобальной, что, вообще говоря, неразумно. Забыв описать некую переменную как локальную, мы впустую расходуем память, но это лишь полбеды. Гораздо хуже, если в другом скрипте вы будет использовать совершенно другую по смыслу переменную с тем же именем! Конечно, ситуация маловероятная, но тем труднее будет найти ошибку, если она произойдет! Короче говоря:
Только-только начиная осваивать премудрости скриптинга, я иногда доходил до бешенства - простейшие команды либо не работали, либо, что было еще загадочнее, работали через раз. Вскоре я понял причину и с тех пор проблем у меня стало гораздо меньше.
Дело в том, что все, абсолютно все операции, которые, на взгляд пользователя, выполняются мгновенно, требуют пусть и малого, но все-таки конечного времени. Открытие/закрытие окна/файла, чтение/запись файла, посылка сообщений окну, даже занесение значения в оперативную память - все требует времени для выполнения, хоть оно и исчисляется миллисекундами. Одна из моих ошибок на первых порах состояла в том, что я выдавал команды подряд, без паузы. В результате иногда первая команда успевала выполниться к моменту выполнения второй, а иногда нет, что и порождало загадочные непостоянные сбои.
Не зря Bruce Switzer такое внимание уделяет команде wait и снабжает ее столь многочисленными модификациями. Однозначных рекомендаций, к сожалению, здесь дать не может даже он. Конкретное время зависит от тысячи причин - операционной системы, аппаратного обеспечения, загруженности памяти в момент выполнения скрипта, резидентных программ и многого другого. Так что постараюсь сформулировать лишь самые общие советы тем, кто пишет свои скрипты (причем не обязательно на языке PowerPro):
Здесья почти дословно воспроизвожу свою переписку с автором PowerPro, начатую этим моим сообщением.
Создадим простой скрипт:
local v = vec.createfromwords("1 2") local w = v v[0] = 5 win.debug(w[0]) quit
В окно отладки выводится "5". Но это кажется странным: мы создали вектор, затем присвоили его значение (а следовательно, все элементы) другому вектору, а затем изменили один элемент первого. Поскольку это изменение произошло после присваивания значения первого вектора второму оно, следовательно, не должно влиять на первый, так? Оказалось, не так.
Проверим на подобном скрипте, но оперирующем с обычными переменными:
local v = 1 local w = v v = 5 win.debug(w) quit
Результат будет "1", что полностью соответствует ожиданиям.
Автор ответил, что оператор присваивания вида
a = b
где обе переменные объявлены как вектора, присваивает второму (b) не элементы, а ссылку на область памяти ("указатель" - pointer - в терминах С++), содержащую элементы первого вектора (a). Таким образом, любые операции над вектором a автоматически применяются к вектору a.
На мой взгляд, это нелогично. Зачем иметь две идентичные копии одного и того же вектора? Но даже если это поведение и логично, оно должно быть описано в документации. Программист на С++, располагая и переменной, и указателем на нее, сам решает, когда присваивать переменную, а когда – ссылку: поведение программы в общем случае будет другим. В PowerPro нет понятия указателя, и поведение операторов, присваивающих именно указатель, надо оговаривать особо.
Автор пообещал добавить к плагину vec функцию, копирующему во второй вектор именно элементы первого, без необходимости организации цикла, как это происходит сейчас.
На главную |