exebook / deodar

Классическая двухпанельная рабочая среда (коммандер) для О.С. Линукс
The Unlicense
72 stars 8 forks source link

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

Open oxygenh opened 10 years ago

oxygenh commented 10 years ago

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

exebook commented 10 years ago

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

oxygenh commented 10 years ago

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

exebook commented 10 years ago

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

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

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

oxygenh commented 10 years ago

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

oxygenh commented 10 years ago

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

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

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

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

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 commented 10 years ago

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

exebook commented 10 years ago

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

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

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

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

ёёё код ёёё

exebook commented 10 years ago

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

oxygenh commented 10 years ago

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

oxygenh commented 10 years ago

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

exebook commented 10 years ago

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

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

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

oxygenh commented 10 years ago

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

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

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

exebook commented 10 years ago

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

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

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

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

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

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

/ далее код/

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

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

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

oxygenh commented 10 years ago

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

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

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

["c1.t"]

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

exebook commented 10 years ago

А так?

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)
}
oxygenh commented 10 years ago

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

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

["oc1.t"]

exebook commented 10 years ago

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

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)
}
oxygenh commented 10 years ago

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

exebook commented 10 years ago

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

exebook commented 10 years ago

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

exebook commented 10 years ago

86 и 82?

oxygenh commented 10 years ago

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

oxygenh commented 10 years ago

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

exebook commented 10 years ago

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

oxygenh commented 10 years ago

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

exebook commented 10 years ago

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

oxygenh commented 10 years ago

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

exebook commented 10 years ago

git pull deodar git pull intervision

oxygenh commented 10 years ago

ЗдОрово! Спасибо. Прямо так чтобы вплотную тестировать - не тестировал, просто попробовал несколько операций, которые наиболее часто помечаю/переименовываю - все заработали. Прямо слов нет как доволен. Вы большой молодец.

В общем, для полного счастья осталось только работу с архивами сделать, и, на мой взгляд, будет очень хороший файловый мэнеджер. Особенно для таких "закостенелых новичков" как я, у которых пальцы уже приняли наиболее часто используемые фаровские комбинации, а всплытие vim в mc по ф4, вместо привычного редактора вызывают панику и учащенное сердцебиение. :)

exebook commented 10 years ago

Кстати, сделал ещё в поиске файлов (Control-F) тоже поиск по маске.

Значит теперь файл "hello.js" можно найти запросом .js, а можно найти запросом *.js.