Open oxygenh opened 10 years ago
да уже работаю над этим, это оказалось действительно немного сложно. а последний раз я такое делал лет 20 назад на паскале)
Понятно. Тем не менее, еще раз поблагодарю за труд.
Окончательно запутавшись в том как это сделать, создал вопрос на stackoverflow: http://stackoverflow.com/questions/22933587/implementing-wildcard-file-copy-rename-test-txt-js-test-js
пока что наверное сделаю самую по самому простому.
Вообще не ясно, в Линуксе * вполне приемлемое имя файла.
Я попробовал написать на паскале функцию, возвращающую true если имя файла соответствует маске, и false в противном случае. Конкретно для этого исью она не совсем то, но, например, для возможности групповой пометки/разметки (которая по серому плюсу обычно в командерах) вполне себе. Сейчас еще не совсем готова (есть глюк в некоторых случаях, когда в маске присутствует '*'), как отлажу покажу (если есть интерес). Она хоть и паскальная, но мне кажется возможности обработки строк и рекурсивные функции в js тоже должны быть, так что переписать особо труда не займёт. Ну и от этой функции к функции переименования по маске один шаг.
Вот такая паскальная функция
{
Пока попробуем просто отлавливать на соответствие строки маске.
В маске используем только символы '*' и '?'. / Считаем что в маске
не используется комбинаций '?*','*?' или '**'
Я также смотрю сквозь пальцы на разный регистр символов в строке
и в иаске. В принципе просто в коде вставить перевод всего к верхнему
регистру и не парится
Одна из важных штук не дающих покоя, что названия файлов в Линуксах
могут содержать "волшебные" символы, используемые в масках. На этих
примерах не тестировал. Возможно работать не будет
}
function ParseString(var s,m:string):boolean;
begin
Writeln('ParseString('+s+','+m+');');
ParseString:=true;
if (Length(m)=0) or (Length(s)=0) then exit;
ParseString:=false;
{если первым символом '*'
тут самая хитрая обработка.
Если первый символ строки равен
второму (тому что после звездочки) символу маски, то отцепляем
от маски первый символ и передаем обработку рекурсивно далее.
Если первый символ строки не равен второму (тому, что после
звездочки) символу в маске, то отщипывем первый символ уже от
строки и передаем обработку рекурсивно далее}
if m[1]='*' then begin
if s[1]=m[2] then begin
m:=Copy(m,2,length(m)-1);
ParseString:=ParseString(s,m);
end else begin
s:=Copy(s,2,length(s)-1);
ParseString:=ParseString(s,m);
end;
exit;
end; //end of if m[1]='*'
{если первым символом '?'
С '?' вроде всё понятно: Если маска начинается с вопроса(ов) то
отбрасываем с начала соответсвующее количество символов, а в маске
отбрасываем сами вопросы.}
if m[1]='?' then begin
m:=Copy(m,2,length(m)-1);
s:=Copy(s,2,length(s)-1);
ParseString:=ParseString(s,m);
exit;
end;
{если первым символом не '*' и не '?'
тут всё просто: проверяем на совпадение первого символа строки
и первого символа маски}
if (m[1]<>'*') and (m[1]<>'?') then begin
if s[1]=m[1] then begin
m:=Copy(m,2,length(m)-1);
s:=Copy(s,2,length(s)-1);
ParseString:=ParseString(s,m);
end else ParseString:=false;
exit;
end;
end; //end of ParseString
Ой, что то код переиначился при отправке. Видимо эти маркдаунские дела. Я их еще не освоил...
Ну, если что, то в качестве домашнего задания по изучению node.js , могу попробовать переписать её на жаваскрипте
Для сравнения с маской (матчинга) вроде бы достаточно простейшего регулярного выражения (а они в JavaScript включены):
function maskMatch(path, mask) {
mask = mask.replace('.', '\\.')
mask = mask.replace('*', '.+?')
var r = new RegExp(mask, '')
return path.match(r)
}
Труднее разобраться с копированием/переменованием если новое имя (таргет) содержит знаки подстановки.
Код оформляется тремя обратными одинарными кавычками на пустой строке (клавиша слева от 1 без шифта (в руской раскладке буква ё). После открывающих кавычек можно ещё язык подсветки указать, например javascript
ёёё код ёёё
Для домашнего задания предлагаю испытать (потестировать) эту функцию, что я выше написал, я её не испытывал пока.
Хорошо. Сегодня с работы попробую погонять тестики
Попробовал погонять. Вот найденные баги:
>maskMatch('doc1.part1.txt','1.txt')
>["1.txt"]
Вот такое прокатывает (что, собственно говоря, и правильно):
>maskMatch('doc1.part1.txt','d*.*.txt')
>["doc1.part1.txt"]
а вот такое не прокатывает (а, вроде как, должно):
>maskMatch('doc1.part1.txt','*.p*.txt')
>null
Да, вопросец... Должно или нет, написано вот тут: http://superuser.com/questions/475874/how-does-the-windows-rename-command-interpret-wildcards в разделе SourceMask
хотя, опять-же, вопрос, надо ли делать так как в винде, или опираться на своё понимание.
Вопрос: действительно ли можно найти практичное применение двум звёздочкам в одной маске, или это просто фантазия и теория? На вскидку не припоминаю, чтобы мне когда либо хотелось использовать две * в одной маске.
Я в английском понимаю очень плохо. Основывался на проверке выделения FAR менеджером. Попробую перевести указанный источник.
Вопрос: действительно ли можно найти практичное применение двум звёздочкам в одной маске, или это просто фантазия и теория? Так в приведенном мною примере как раз близко к реальной жизни рассмотрено. Например выбрать файлы определенного расширения, в имени которых в любом месте встречается нужная последовательность символов. Вот и получаем маску
*seq*.ext
. Как раз 2 звездочки.
А про знак вопроса что скажете?
Про знак вопроса скажу, то он пока просто не реализован, надо добавить.
Сейчас сижу бъюсь с функцией переменования, уже 14 тестов проходит (12 пока нет)
fog = console.log
fog = function(){}
function t(path, mask, test) {
var x = 0, R = ''
for (var m = 0; m < mask.length; m++) {
var ch = mask[m]
if (ch != '.' && ch != '*' && ch != '?') {
fog('-->c')
var q = path[x]
if (q != '.') x++
R += ch
} else if (ch == '?') {
fog('-->?')
q = path[x]
if (q && q != '.') R += q, x++
} else if (ch == '*' && m == mask.length - 1) {
fog('-->*|')
while (x < path.length) R += path[x++]
} else if (ch == '*') {
if (mask[m + 1] == '.') {
fog('-->*.')
var z = mask[m + 1]
for (var i = path.length - 1; i >= 0; i--) if (path[i] == '.') break
if (i == -1) {
var u = path.substr(x, path.length)
i = path.length
R += u + '.'
} else {
var u = path.substr(x, i - x + 1)
R += u
}
x = i + 1
m++
} else if (mask[m + 1] == '?') {
fog('-->*?')
u = path.substr(x, path.length)
R += u
m++
x = path.length
} else {
fog('-->*')
var z = mask[m + 1]
for (var i = path.length - 1; i >= 0; i--) if (path[i] == z) break
var u = path.substr(x, i - x)
R += u
x = i + 1
}
} else if (ch == '.') {
fog('-->.')
fog('tochko')
while (x < path.length) {
if (path[x] == '.') {
// R += '.'
break
}
R += path[x]
x++
}
R += '.'
}
fog('-->['+R+']')
}
log(R == test, path, mask, '<'+test+'>', '['+R+']')
}
//t('a','?????.?????','a')
//return
t('1','A?Z*','AZ')
t('12','A?Z*','A2Z')
t('1.txt','A?Z*','AZ.txt')
t('12.txt','A?Z*','A2Z.txt')
t('123','A?Z*','A2Z')
t('123.txt','A?Z*','A2Z.txt')
t('1234','A?Z*','A2Z4')
t('1234.txt','A?Z*','A2Z4.txt')
t('a','*.txt','a.txt')
t('b.dat','*.txt','b.txt')
t('c.x.y','*.txt','c.x.txt')
t('a','*?.bak','a.bak')
t('b.dat','*?.bak','b.dat.bak')
t('c.x.y','*?.bak','c.x.y.bak')
t('a','?????.?????','a')
t('a.b','?????.?????','a.b')
t('a.b.c','?????.?????','a.b')
t('part1.part2.part3','?????.?????','part1.part2')
t('123456.123456.123456','?????.?????','12345.12345')
t('abcd_12345.txt','*_NEW.*','abc_NEW.txt')
t('abc_newt_1.dat','*_NEW.*','abc_newt_NEW.txt')
t('abcd_123.a_b','*_NEW.*','abcd_123.a_NEW')
t('part1.part2','?x.????999.*rForTheCourse','px.part999.rForTheCourse')
t('part1.part2.part3','?x.????999.*rForTheCourse','px.part999.parForTheCourse')
t('a.b.c','?x.????999.*rForTheCourse','ax.b999.crForTheCourse')
t('a.b.CarPart3BEER','?x.????999.*rForTheCourse','ax.b999.CarParForTheCourse')
вот со знаком вопроса в маске поиска.
function maskMatch(path, mask) {
mask = mask.replace('.', '\\.')
mask = mask.replace('?', '.')
mask = mask.replace('*', '.+?')
var r = new RegExp(mask, '')
return path.match(r)
}
Про знак вопроса скажу, то он пока просто не реализован, надо добавить.
Сейчас сижу бъюсь с функцией переменования, уже 14 тестов проходит (12 пока нет)
/ далее код/
мамадарагая!
вот со знаком вопроса в маске поиска.
Нука, нука, попробую погонять...
вот со знаком вопроса в маске поиска.
Кажется, немного, неточно работает:
maskMatch('doc1.txt','??1.*')
["c1.t"]
Возвращает не null, т.е. удовлетворяет условию. В то время, как в маске единица стоит на третьей позиции, а в строке - на четвертой.
А так?
function maskMatch(path, mask) {
mask = mask.replace(/\./g, '\\.')
mask = mask.replace(/\?/g, '.')
mask = mask.replace(/\*/g, '.+?')
var r = new RegExp(mask, '')
return path.match(r)
}
Всё равно не прокатывет
maskMatch('doc1.txt','??1.*')
["oc1.t"]
А, ну конечно, он же находит совпадение (матч) в середине, надо поставить ограничители ^
и $
function maskMatch(path, mask) {
mask = mask.replace(/\./g, '\\.')
mask = mask.replace(/\?/g, '.')
mask = mask.replace(/\*/g, '.+?')
var r = new RegExp('^'+mask+'$', '')
return path.match(r)
}
О! Работает! И знак вопроса, и две звездочки. ЗдОрово! Сделаете реализацию непосредственно в Деодаре для пометки/разметки серым плюсом?
Не знаю насчёт серого плюса, у меня на ноуте же. Нажмите пожалуста Control-K
в деодаре, выскочит окошко кодов клавы, и скажите код серого плюса, тогда сделаю. Для ноутов наверное надо изобретать новый хоткей, сейчас же ноуты у многих. Может Control-S
или Control-M
. Control-A
уже есть, выделяет всё или снимает всё выделение, Control-S
рядышком.
Ну и "серый минус" заодно
86 и 82?
Ой, с кодами пока и не скажу. На работе сейчакс винда, а дома тоже ноут без серых кнопок. Хотя чисто номинально они с Fn должны нажиматься... Давайте по Control-S
тогда, как вы предложили.
Если под виндой коды клавиш, то серый плюс - 107, серый минус - 106 Наверное в Линуксе такие же...
А вот и нет, Windows и X-Windows имеют настолько разные коды клавиш, что даже удивительно. Например ENTER в Windows-13 в X-Windows-36. Впрочем, это мелочи.
Попробовал сейчас дома на ноуте по Дебианом. Всё так: серый плюс - 86, минус - 82 Как можно будет обновлять Деодар , отпишитесь, пожалуйста.
Закинул обновление с поддержкой масок, как для выделения так и при копировании. Пробуйте) Но испытаний пока почти не было.
Спасибо. Ура. Вечерком посмотрю. А как лучше обновиться GIT PULL
или с 'modules' ?
git pull deodar git pull intervision
ЗдОрово! Спасибо. Прямо так чтобы вплотную тестировать - не тестировал, просто попробовал несколько операций, которые наиболее часто помечаю/переименовываю - все заработали. Прямо слов нет как доволен. Вы большой молодец.
В общем, для полного счастья осталось только работу с архивами сделать, и, на мой взгляд, будет очень хороший файловый мэнеджер. Особенно для таких "закостенелых новичков" как я, у которых пальцы уже приняли наиболее часто используемые фаровские комбинации, а всплытие vim в mc по ф4, вместо привычного редактора вызывают панику и учащенное сердцебиение. :)
Кстати, сделал ещё в поиске файлов (Control-F) тоже поиск по маске.
Значит теперь файл "hello.js" можно найти запросом .js
, а можно найти запросом *.js
.
в окно копирования/перемещения, сложно ли? Ну, чтобы можно было файл скопировать но копия была с новым именем, но не выписывать всё имя если надо поменять расшрение а написать классически .newext. По привычке попробовал скопировать файл myfile.txt в myfile.tx_ написав .?? в строке диалога а получил файл, который так и назвался - *.??