Сделайте простой инструмент для красивых комментариев

14

Вызов:

Некоторый ascii-art - трудная задача, но она облегчает чтение комментариев к коду, особенно когда код плотный. Задача состоит в том, чтобы сделать простой инструмент, который преобразует комментарии в простой ascii-art со стрелками. Комментарии для изменения отделяются пустыми комментариями.

Например, предположив синтаксис комментариев на Haskell, преобразуйте это:

--
-- Here's a thing
-- Here's another thing
-- The most important thing
-- *    *     *
--
f x=x+1*x*1*1*0

К этому:

-- /------------< Here's a thing
-- |    /-------< Here's another thing
-- |    |     /-< The most important thing
-- |    |     |
-- v    v     v
f x=x+1*x*1*1*0

Правила:

  • Ваш ответ может быть либо функцией, либо полной программой
  • Вы можете выбрать язык, с которым он работает, заменив «-» двумя или более символами, которые разделяют комментарий на каком-либо языке.
  • Если используется другой формат комментария, который требует начального и конечного разделителей, каждая строка переформатированных разделов должна быть правильным комментарием
  • Разделы, которые нужно переформатировать, отделяются пустым комментарием "\ n - \ n"
  • Помимо добавления новых строк, программа не должна изменять какие-либо входные данные, кроме разделенных разделов
  • Комментарий, заполненный произвольным количеством пробелов, может появиться непосредственно перед правильно отформатированным разделом вывода.
  • Стандартные лазейки запрещены

Дополнительные примеры:

(input)
--
--
(output)
nothing


(input)
[Code Here]
--
-- important
--    *
--
(output)
[Code Here]
--    /-< important
--    |
--    v


(input)
--
-- Do
-- Re
-- Mi
-- Fa
-- So
-- *****
--
(output)
-- /-----< Do
-- |/----< Re
-- ||/---< Mi
-- |||/--< Fa
-- ||||/-< So
-- |||||
-- vvvvv

Подсчет очков:

  • Побеждает несколько байтов
  • Представления без объяснений или нетривиальный пример ввода / вывода не будут рассматриваться (хотя я оставлю льготный период, чтобы дать время, чтобы добавить такие)
Майкл Кляйн
источник
2
Что если для разделения комментария необходим только один символ?
Адам
Пока это действительный комментарий на языке, все в порядке
Майкл Кляйн
Можно предположить, что каждый раздел комментариев, который подлежит переформатированию, будет содержать ровно одну строку звездочек маркера положения, верно? Будет ли эта строка всегда последней?
manatwork
Да, точно один и всегда последний (комментарий перед конечным разделителем)
Майкл Кляйн
И количество звездочек будет равно количеству предыдущих строк в этом разделе, верно?
Манатворк

Ответы:

4

Рубин, 160 знаков

->c{c.gsub(/^--$(.+?)^--$/m){*t,a=$&.lines[1..-2]
a&&a.chop!&&(t.map{|l|a[?*]=?/
l[0,2]=a.gsub(/(?<=\/).*/){?-*$&.size}+'-<'
a[?/]=?|
l}<<a+$/+a.tr(?|,?v))*''}}

Образец прогона:

2.1.5 :001 > puts ->c{c.gsub(/^--$(.+?)^--$/m){*t,a=$&.lines[1..-2];a&&a.chop!&&(t.map{|l|a[?*]=?/;l[0,2]=a.gsub(/(?<=\/).*/){?-*$&.size}+'-<';a[?/]=?|;l}<<a+$/+a.tr(?|,?v))*''}}["
2.1.5 :002"> --
2.1.5 :003"> -- Here's a thing
2.1.5 :004"> -- Here's another thing
2.1.5 :005"> -- The most important thing
2.1.5 :006"> -- *    *     *
2.1.5 :007"> --
2.1.5 :008"> f x=x+1*x*1*1*0
2.1.5 :009"> "]

-- /------------< Here's a thing
-- |    /-------< Here's another thing
-- |    |     /-< The most important thing
-- |    |     |
-- v    v     v
f x=x+1*x*1*1*0
 => nil 

Краткое описание:

.lines splits the section to array items ─────────╮
                                                  ▽

.gsub extracts ⎧   --                             0         
these sections ⎪   -- Here's a thing              1   t[0]   
for processing ⎨   -- Here's another thing        2   t[1]   
and replaces   ⎪   -- The most important thing    ⋮   t[2]   
them with the  ⎪   -- *    *     *               -2   a      
pretty version ⎩   --                            -1          
rest untouched —   f x=x+1*x*1*1*0
                                                      △
only the needed lines get into variables ─────────────╯



a = "-- *    *     *" + "-<"           inside .gsub's block
        ↓↓                             the first 2 characters
t[0] = "-- Here's a thing"             of t's each item are
t[1] = "-- Here's another thing"       replaced with a's value
t[2] = "-- The most important thing"   and the the separator



not only t's items are transformed inside .gsub's block,
but a's value also gets changed in multiple small steps

                       change a's value    change the value    change a's value
   a's initial value   before insertion   being inserted now   after insertion
   ╭───────────────╮   ╭───────────────╮   ╭───────────────╮   ╭───────────────╮

0  "-- *    *     *" → "-- /    *     *" → "-- /-----------" → "-- |    *     *"
1  "-- |    *     *" → "-- |    /     *" → "-- |    /------" → "-- |    |     *"
2  "-- |    |     *" → "-- |    |     /" → "-- |    |     /" → "-- |    |     |"

                       ╰───────────────╯   ╰───────────────╯   ╰───────────────╯
                      change first * to /  change everything  change first / to |
                                          after / with string
                                          of - of same length
manatwork
источник
5

JavaScript (ES6), 418 , 237 , 233 , 236 байтов

f=(s)=>(d='\n//',s.split(d+'\n').map((x,y)=>y%2?'//'+(l=x.slice(2).split(d),t=l.pop().split('*'),l.map((i,j)=>t.map((k,m)=>m==j?k+'/':m<j?k+'|':k.replace(/ /g,'-')+'-').join('')+'<'+i).join(d)+d+t.join('|')+d+t.join('v')):x).join('\n'))

Вот так, это моя первая подача на CG. Я думаю, что это совсем не то же самое, что вашингтонский Гедес. Закончилось на 54 байта короче, чем его первый проход. Сокращение всего этого вручную было изнурительным. Единственное, о чем я сожалею, так это о том, что я пока не могу устранить цикл while, что также позволило бы мне сократить прибыль.

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

Снял еще несколько байтов и заставил пример работать на себя. (Вам понадобится больший монитор.) :)

Забыл целое письмо в спецификации! К счастью, добавление начального '<' было крошечным, тривиальным исправлением.

Эммет Р.
источник
3

Python 2, 299 байт

Ожидает завершающий перевод строки во входных данных

i=input().split('--\n')
a=0
for j in i:
 a+=1
 if a%2:print j,;continue
 if''==j:continue
 l=j.split('\n');n=l[-2];r=l[:-2];R=[n.replace('*','v'),n.replace('*','|')];L=R[1]
 for x in range(len(l)-2)[::-1]:L=L[:L.rfind('|')]+'/';R+=[L.ljust(n.rfind('*')+2,'-')+'< '+r[x][3:]]
 print'\n'.join(R[::-1])

Объяснение / Пример

Входные данные:

[Code Here]
--
-- important
--    *
--

Разбивает вход по --\n. Каждая вторая строка является блоком комментариев с разделителями.

['[Code Here]\n',
'-- important\n-- stuff\n--    *  *\n',
'']

Пробегает каждую строку Если строка не является комментарием, то просто печатает строку. В противном случае:

Разбивает каждую строку в блоке комментариев.

['-- important', '-- stuff', '--    *  *', '']

Делает нижние две строки, заменяя строки *s на vи |.

['--    v  v', '--    |  |']

Для каждой строки комментариев (в обратном направлении) удалите крайний правый столбец, добавьте /, -добавьте и добавьте комментарий.

'--    |  /'
'--    /'
'--    /----< important'

Распечатать все

--    /----< important
--    |  /-< stuff
--    |  |
--    v  v

Меньше гольфа:

i=input().split('--\n')
a=0
for j in i:
 a+=1
 if a%2:print j,;continue # Not commment
 if''==j:continue # Empty comment
 l=j.split('\n') # Split comment into lines
 r=l[:-2]
 # Replace line of *s with v and | respectively
 R=[l[-2].replace('*','v'),l[-2].replace('*','|')]
 L=R[1][3:] # line of |
 for x in range(len(l)-2)[::-1]: # For each comment line
  L=L[:L.rfind('|')]+'/' #Remove rightmost column
  # Add a line with '-- ',columns, and comment
  R+=['-- '+L.ljust(n.rfind('*')-1,'-')+'< '+r[x][3:]]
 print'\n'.join(R[::-1]) #Print all comment lines
TFeld
источник
1

JavaScript (ES6), 253

Как анонимная функция, с кодом для форматирования в виде строкового параметра и возвратом отформатированного кода.

Примечания

  1. Пара маркерных комментариев должна содержать правильный текст (строки комментариев, затем звезды)
  2. ... или пара не должна содержать ничего (дополнительный пример 1)
t=>(t=t.split`
`,t.map((r,i)=>r=='--'?(c++&&l.map((r,j)=>(p+=q[j],z+=~q[j].length,t[i-n+j]=p+`/${'-'.repeat(z+1)}<`+r.slice(3),p+=`|`),q=l.pop(c=p=``)||p,z=q.length,q=q.split`*`,t[i]=p+q.join`v`,t[i-1]=p+q.join`|`),l=[]):n=l.push(r),c=0,l=[]),t.join`
`)

Меньше гольфа

f=t=>{
  t = t.split`\n`; // string to array of lines
  l = []; // special coment text
  c = 0; // counter of marker comment '--'
  t.forEach((r,i)=>{ // for each line of t - r: current line, i: index
    if (r == '--') // if marker comment
    {
       ++ c; // increment marker counter
       if (c > 1) // this is a closing marker
       {
          c = 0; // reset marker counter
          if (n > 0) // n is the length of array l
             q = l.pop(); // get last line from l, have to be the star line
          else
             q = ''; // no text comment, no star line 
          p = '';  // prefix for drawing the tree
          z = q.length; // length of star line, used to draw the tree horiz lines
          q = q.split('*'); // split to get star count and position
          // each element in q is the spaces between stars
          // modifiy the current and previous text line 
          t[i] = p + q.join`v`; // current row was '--', becomes the V line
          t[i-1] = p + q.join`|`; // previous row was the star line, becomes the last tree line
          l.forEach((r,j)=>{ // for each line in l, r: current line, j: index
             // each line in tree is: prefix("-- |  |"...) + ... "---< " + text
             p = p + q[j]; // adjust prefix
             z = z - q[j].length - 1 // adjust length of '---'
             // modify text in t
             t[i-n+j] = p // prefix
                + '/' + '-'.repeat(z+1) + '<'  // horiz line and <
                + r.slice(3); // text, removed '-- '
             p = p + '|'; // add vertical bar to prefix
          });
       } // end if closing comment
       l = []; // reset l
    }  
    else // not a special comment marker
       n = l.push(r) // add current line to l, set n to array size
  });
  return t.join`\n` // join to a single string
}

Тестовое задание

edc65
источник
Это пропускает второй блок комментариев для меня на Chrome 47 без ошибок. Кроме того, дерьмо, я раньше не видел, чтобы вы могли использовать любой синтаксис комментариев с любым языком .
Эммет Р.
О, да, ты прав. @EmmettR. Благодарю. Я постараюсь это исправить
edc65