deodar icon indicating copy to clipboard operation
deodar copied to clipboard

Добавить обработку символов подстановки ...

Open oxygenh opened this issue 10 years ago • 32 comments

в окно копирования/перемещения, сложно ли? Ну, чтобы можно было файл скопировать но копия была с новым именем, но не выписывать всё имя если надо поменять расшрение а написать классически *.newext. По привычке попробовал скопировать файл myfile.txt в myfile.tx_ написав *.??_ в строке диалога а получил файл, который так и назвался - *.??_

oxygenh avatar Apr 06 '14 08:04 oxygenh

да уже работаю над этим, это оказалось действительно немного сложно. а последний раз я такое делал лет 20 назад на паскале)

exebook avatar Apr 06 '14 12:04 exebook

Понятно. Тем не менее, еще раз поблагодарю за труд.

oxygenh avatar Apr 06 '14 17:04 oxygenh

Окончательно запутавшись в том как это сделать, создал вопрос на stackoverflow: http://stackoverflow.com/questions/22933587/implementing-wildcard-file-copy-rename-test-txt-js-test-js

пока что наверное сделаю самую по самому простому.

Вообще не ясно, в Линуксе * вполне приемлемое имя файла.

exebook avatar Apr 08 '14 09:04 exebook

Я попробовал написать на паскале функцию, возвращающую true если имя файла соответствует маске, и false в противном случае. Конкретно для этого исью она не совсем то, но, например, для возможности групповой пометки/разметки (которая по серому плюсу обычно в командерах) вполне себе. Сейчас еще не совсем готова (есть глюк в некоторых случаях, когда в маске присутствует '*'), как отлажу покажу (если есть интерес). Она хоть и паскальная, но мне кажется возможности обработки строк и рекурсивные функции в js тоже должны быть, так что переписать особо труда не займёт. Ну и от этой функции к функции переименования по маске один шаг.

oxygenh avatar Apr 08 '14 19:04 oxygenh

Вот такая паскальная функция

{
  Пока попробуем просто отлавливать на соответствие строки маске.
  В маске используем только символы '*' и '?'. / Считаем что в маске
  не используется комбинаций '?*','*?' или '**'

  Я также смотрю сквозь пальцы на разный регистр символов в строке 
  и в иаске. В принципе просто в коде вставить перевод всего к верхнему
  регистру и не парится

   Одна из важных штук не дающих покоя, что названия файлов в Линуксах
   могут содержать "волшебные" символы, используемые в масках.  На этих
   примерах не тестировал. Возможно работать не будет
}

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

Ой, что то код переиначился при отправке. Видимо эти маркдаунские дела. Я их еще не освоил...

oxygenh avatar Apr 08 '14 20:04 oxygenh

Ну, если что, то в качестве домашнего задания по изучению node.js , могу попробовать переписать её на жаваскрипте

oxygenh avatar Apr 08 '14 20:04 oxygenh

Для сравнения с маской (матчинга) вроде бы достаточно простейшего регулярного выражения (а они в JavaScript включены):

function maskMatch(path, mask) {
    mask = mask.replace('.', '\\.')
    mask = mask.replace('*', '.+?')
    var r = new RegExp(mask, '')
    return path.match(r)
}

Труднее разобраться с копированием/переменованием если новое имя (таргет) содержит знаки подстановки.

Код оформляется тремя обратными одинарными кавычками на пустой строке (клавиша слева от 1 без шифта (в руской раскладке буква ё). После открывающих кавычек можно ещё язык подсветки указать, например javascript

ёёё код ёёё

exebook avatar Apr 09 '14 03:04 exebook

Для домашнего задания предлагаю испытать (потестировать) эту функцию, что я выше написал, я её не испытывал пока.

exebook avatar Apr 09 '14 03:04 exebook

Хорошо. Сегодня с работы попробую погонять тестики

oxygenh avatar Apr 09 '14 03:04 oxygenh

Попробовал погонять. Вот найденные баги:

  • Не реализована обработка символа подстановки '?'

  • >maskMatch('doc1.part1.txt','1.txt')

    >["1.txt"]

  • Вот такое прокатывает (что, собственно говоря, и правильно): >maskMatch('doc1.part1.txt','d*.*.txt')

    >["doc1.part1.txt"] а вот такое не прокатывает (а, вроде как, должно): >maskMatch('doc1.part1.txt','*.p*.txt')

    >null

oxygenh avatar Apr 09 '14 08:04 oxygenh

Да, вопросец... Должно или нет, написано вот тут: http://superuser.com/questions/475874/how-does-the-windows-rename-command-interpret-wildcards в разделе SourceMask

хотя, опять-же, вопрос, надо ли делать так как в винде, или опираться на своё понимание.

Вопрос: действительно ли можно найти практичное применение двум звёздочкам в одной маске, или это просто фантазия и теория? На вскидку не припоминаю, чтобы мне когда либо хотелось использовать две * в одной маске.

exebook avatar Apr 09 '14 08:04 exebook

Я в английском понимаю очень плохо. Основывался на проверке выделения FAR менеджером. Попробую перевести указанный источник.

Вопрос: действительно ли можно найти практичное применение двум звёздочкам в одной маске, или это просто фантазия и теория? Так в приведенном мною примере как раз близко к реальной жизни рассмотрено. Например выбрать файлы определенного расширения, в имени которых в любом месте встречается нужная последовательность символов. Вот и получаем маску *seq*.ext . Как раз 2 звездочки.

А про знак вопроса что скажете?

oxygenh avatar Apr 09 '14 08:04 oxygenh

Про знак вопроса скажу, то он пока просто не реализован, надо добавить.

Сейчас сижу бъюсь с функцией переменования, уже 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')

exebook avatar Apr 09 '14 09:04 exebook

вот со знаком вопроса в маске поиска.

function maskMatch(path, mask) {
    mask = mask.replace('.', '\\.')
    mask = mask.replace('?', '.')
    mask = mask.replace('*', '.+?')
    var r = new RegExp(mask, '')
    return path.match(r)
}

exebook avatar Apr 09 '14 09:04 exebook

Про знак вопроса скажу, то он пока просто не реализован, надо добавить.

Сейчас сижу бъюсь с функцией переменования, уже 14 тестов проходит (12 пока нет)

/ далее код/

мамадарагая!

вот со знаком вопроса в маске поиска.

Нука, нука, попробую погонять...

oxygenh avatar Apr 09 '14 09:04 oxygenh

вот со знаком вопроса в маске поиска.

Кажется, немного, неточно работает:

maskMatch('doc1.txt','??1.*')

["c1.t"]

Возвращает не null, т.е. удовлетворяет условию. В то время, как в маске единица стоит на третьей позиции, а в строке - на четвертой.

oxygenh avatar Apr 09 '14 09:04 oxygenh

А так?

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)
}

exebook avatar Apr 09 '14 09:04 exebook

Всё равно не прокатывет

maskMatch('doc1.txt','??1.*')

["oc1.t"]

oxygenh avatar Apr 09 '14 09:04 oxygenh

А, ну конечно, он же находит совпадение (матч) в середине, надо поставить ограничители ^ и $

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)
}

exebook avatar Apr 09 '14 09:04 exebook

О! Работает! И знак вопроса, и две звездочки. ЗдОрово! Сделаете реализацию непосредственно в Деодаре для пометки/разметки серым плюсом?

oxygenh avatar Apr 09 '14 09:04 oxygenh

Не знаю насчёт серого плюса, у меня на ноуте же. Нажмите пожалуста Control-K в деодаре, выскочит окошко кодов клавы, и скажите код серого плюса, тогда сделаю. Для ноутов наверное надо изобретать новый хоткей, сейчас же ноуты у многих. Может Control-S или Control-M. Control-A уже есть, выделяет всё или снимает всё выделение, Control-S рядышком.

exebook avatar Apr 09 '14 10:04 exebook

Ну и "серый минус" заодно

exebook avatar Apr 09 '14 10:04 exebook

86 и 82?

exebook avatar Apr 09 '14 10:04 exebook

Ой, с кодами пока и не скажу. На работе сейчакс винда, а дома тоже ноут без серых кнопок. Хотя чисто номинально они с Fn должны нажиматься... Давайте по Control-S тогда, как вы предложили.

oxygenh avatar Apr 09 '14 11:04 oxygenh

Если под виндой коды клавиш, то серый плюс - 107, серый минус - 106 Наверное в Линуксе такие же...

oxygenh avatar Apr 09 '14 11:04 oxygenh

А вот и нет, Windows и X-Windows имеют настолько разные коды клавиш, что даже удивительно. Например ENTER в Windows-13 в X-Windows-36. Впрочем, это мелочи.

exebook avatar Apr 09 '14 14:04 exebook

Попробовал сейчас дома на ноуте по Дебианом. Всё так: серый плюс - 86, минус - 82 Как можно будет обновлять Деодар , отпишитесь, пожалуйста.

oxygenh avatar Apr 09 '14 16:04 oxygenh

Закинул обновление с поддержкой масок, как для выделения так и при копировании. Пробуйте) Но испытаний пока почти не было.

exebook avatar Apr 10 '14 13:04 exebook

Спасибо. Ура. Вечерком посмотрю. А как лучше обновиться GIT PULL или с 'modules' ?

oxygenh avatar Apr 10 '14 13:04 oxygenh

git pull deodar git pull intervision

exebook avatar Apr 10 '14 14:04 exebook