АБТФ: большая и малая карты

Прошло достаточно много времени с тех пор, как я писал про Аффигительно Большой Текстовый Файл. Это не значит, что тема стоит на месте — просто на все не хватает времени.

Основные новости следующие:

  1. Я дополнил навигацию по разделам и теперь могу произвольно выделять-вырезать-копировать-удалять отдельные заметки через d]] y[[ v]] и тому подобные комбинации клавиш.
  2. 
    " --------- jumper ------------
    map ]] /^[#@]
    map [[ ?^[#@]
    " --------- jumper ------------
    
    

    Все заголовки у меня начинаются с # в Структуре и с @ в дневниковых заметках. То есть по ]] и [[ можно прыгать от заголовка к заголовку, а скажем по d]] удалить текущую заметку в буфер и вставит ее в каком-нибудь новом месте. Через v]]]]]]d можно скопировать три заметки подряд и так далее. Получилось очень удобно.

  3. Файл подсветки я переписал под «стандартные» цвета, так что теперь могу менять цветовые схемы как заблагорассудится не боясь, что какая-то часть подсветки не попадет по цвету.
  4. И главное. Используя вимаутлайнер, я построил на его базе древовидную систему работы с блогом, которую условно назвал Большой и Малой Картами.

Идея Карты блога пришла мне в голову, когда я читал старую-старую книгу о юниксе Рассела Сейджа.

У него описывалась утилита, выводящая запущенные процессы в виде дерева. Мне понравилась простота метода которым оно создавалось. В принципе, можно было аналогичным образом составить дерево заголовков моего блога.

Каждый заголовок начинается с «диеза» — #. Количество диезов показывает уровень вложенности. Самый верхний заголовок раздела это:

# Заголовок1

Заголовок второго уровня — это заголовок:

## Заголовок2

И так далее.

Достаточно написать скрипт — на питоне, баше или вообще через sed, который

а) Пройдется по тексту блога и выберет из него все строки, начинающиеся с диеза

б) в собранных строчках поменяет диез на табуляцию.

В итоге из списка:

# заголовок1
...
## подзаголовок11
...
## подзаголовок12
...
# заголовок2
...
## подзаголовок21
...
### подподзаголовок211
...
## подзаголовок22
...
### подподзаголовок221
...

Получим дерево:

   заголовок1
         подзаголовок11
         подзаголовок12
   заголовок2
         подзаголовок21
             подподзаголовок211
         подзаголовок22
             подподзаголовок221

Которое само по себе уже наглядно и дает представление о том, что происходит в блоге. Фактически — это наглядная карта блога. Но можно пойти и дальше. Есть вим-аутлайнер, который хранит аутлайны именно как текст, где каждый уровень заголовка выделяется с помощью табуляции. То есть ничего не нужно изобретать — достаточно сгенерировать такое дерево заголовков и скормить его вим-аутлайнеру, а он уже позаботится об удобном представлении этого дерева со всеми преимуществами аутлайна.

Карту я получил, но мне хотелось большего. Хотелось, чтобы карта была живой — то есть чтобы заголовки работали в качестве ссылок. И ткнув в заголовок можно было сразу перейти к этому рзделу в блоге. Поискав в документации, я нашел, что если в тексте указано имя файла — можно встав на это имя и набрав gf (go-file) перейти к нужному файлу. А если после имени файла указан номер строки (например main.txt :: 54256) то по gF можно прыгнуть сразу к файлу main.txt на строку 54256.

То, что нужно. Номера строк можно было собрать с помощью скрипта, генерирующего карту. То есть теперь генерация карты происходила так:

а) Просмотреь текст блога. Выбрать из него все строки, начинающиеся с диеза

б) Для каждого найденного заголовка запомнить номер строки, где он был найден

в) в собранных строках поменять диез на табуляцию и дописать к получившейся строке адрес вида ИмяФайла :: НомерСтроки

Таким образом получалось полноценное содержание, которое сначала по хоткею грузилось в отдельный буфер и использовалось, как карта файла. gF я дополнительно переназначил на привычный Enter.

Получилось удобно.

Свой опыт я описал в отдельной заметке.

Но как оказалось это не предел.


заметка из блога: 2010-05-09 01:53

читаю статью про эппловскую записную книжку «Proteus». Наводит на мысли.

1. Сейчас я открываю Вим через апплет на панели Гнома, открывающий main-блог.

Если нужен другой файл — часто открываю тот же main-блог и ухожу к другому файлу через :e . или :e <имя файла>.

Первая мысль — вывести в качестве апплета ссылку на otl-содержание main-файла.

Вторая мысль — сделать особое содержание — включить в заголовок имена друих блогов (smvk.txt, c4.txt, work.txt итд).

Третья мысль. Почему бы не генерить общий index.otl (в нем — первым уровнем имена блогов, дальше — зпаголовки блогов) и открывать именно его. Можно выиграть достаточно много времени на доступ.

При желании можно тем же макаром генерить дневниковые заметки. То есть делать файл flow.otl, куда в порядке дат сводить записи потоков из всех файлов. При желании можно включать либо строку контекста (у автора статьи это очень клевая идея), либо даже всю заметку целиком.(см ниже еще идеи по)


Еще идея по «большому содержанию» — в индекс можно добавить списки файлов (или даже содержание целиком!) из d.txt, out.otl, lab*.txt — разумеется с добавлением путей итд. Там, где это необходимо содержание можно добавлять целиком, а прочее — просто ссылками, дабы не тратить время на.

Имхо статья к этому толкает — универсальный доступ к своим текстам через Большую Карту.


Статья, о которой шла речь оказалась просто кладезью, породившей массу идей.

Для начала я действительно свел содержания всех текстовых файлов в index.otl, который теперь грузился первым и из которого можно было попасть к любой статье в блогах. Причем это можно было сделать, как двигаясь по дереву заметок, так и через поиск, набирая что-нибудь вроде /блоготех.

Побочным эффектом оказалась скорость работы. Вместо того, чтобы загружать вим и в нем большой файл, как это было раньше, теперь у меня сначала срабатывал скрипт, генерировавший содержание (он получился простым и срабатывал молниеносно) и буквально взлетал вим, показывая карту. Мне это чем-то напомнило старый трюк Раскина, Copycat, которого при загрузке показывал экран с результатами предыдущей работы, от чего создавалось впечатление что система стартует сразу после включения.

Результаты сказались очень быстро. Я заметил, что если раньше большая часть заметок и мыслей ухоила в Дневник (гораздо проще отбить таймстамп и написать заметку, чем вспоминать название заголовка и копаться в дебрях Структуры), то теперь мне стало удобно находить нужные разделы и писать свои идеи сразу по нужному адресу. Раньше идеи скапливались в Дневнике и либо требовали дополнительного разбора, либо вообще оседали в нем насовсем. Теперь все сразу шло по адресу, больше того за разделами стало можно следить «с птичьего полета», не говоря уже о том, что доступ к нужной информации очень ускорился.

Следующим «побочным эффектом» оказалась возможность добавлять в index.otl ссылки на другие текстовые файлы, лежащие где-то в системе. Это было просто сделать — достаточно добавить в скрипт, который генерировал карту, несколько строк, печатающих линки на нужные файлы. Сначала это были линки на текучку — тексты лабораторных и лекций, файлы с расчетами и исходники программ. Потом я добавил ссылку на .vimrc. Потом добавил ссылку на питоновский скрипт, генерирующий карту, чтобы можно было сразу добавлять нужные ссылки. В итоге index.otl из карты блогов вырос в действительно Большую Карту, обеспечивающую оперативный доступ во все ключевые точки системы и не содержащую при этом ничего лишнего.

Линки можно группировать по разделам, выделяя подразделы табами (у меня, например, образовались папки rc, bin, work).

Например, когда я начинаю настраивать conky — я добавляю в карту в раздел rc ссылку на .conkyrc и больше не копаюсь в разделах в поисках искомого конфига — теперь он под рукой, на расстоянии двух кликов. Сейчас сложно представить, как я жил без этого раньше.

Есть еще два глобальных хоткея. F11 вызывает карту в текущее окно (:b index.otl). И F9 который обновляет карту. Можно было бы привязать обновление карты к ее открытию, но практически получилось, что быстрее работать со статическим образом, обновляя его только когда это необходимо.

Большая карта оказалась чертовски удобной штукой, но примерно месяц спустя, разбирая и перетасовывая свои старые заметки я понял, что было бы здорово иметь локальный эквивалент карты — для отдельного блога, причем в боковом меню, а не в виде отдельного буфера. Вырезал заметку, открыл боковое «дерево «, прыгнул в нужный раздел и вставил заметку туда.

Почти ничего нового не пришлось изобретать. Когда-то я написал маленький скрипт, который открывал подобное меню для выбора тегов. Оставалось вместо тегов подставить в это меню содержание и привязать егго закрытие и открытие к хоткею (еще с предыдущего скрипта за боковым меню закрепилась F12).

Теперь абтф в сочетании с большой и малой картами представляет собой вполне законченную и стройную систему.

Скрипты я привожу ниже и на всякий случай повторяю: система создана с помощь вима и питона, но это потому, что эти инструменты удобны именно для меня. Никто не мешает, например, генерировать карту через bash-, или perl-, или PHP-скрипт.

Большая Карта

z.py — отвечает за генерацию «дерева» Большой Карты


# -*- coding: utf8 -*-

def main():

    ''' список файлов блога '''
    blogolist = ['main.txt',
                 'c4.txt',
                 'work.txt',
                 'turblog.txt',
                 'cites.txt',
                 'anotherw.txt',
                 'smvk.txt']

    ''' список ссылок на другие файлы системы'''
    endlist = [ "rc",
                "   ~/.vimrc",
                "   ~/.gvimrc",
                "   ~/.conkyrc",
                "   ~/.config/openbox/rc.xml",
                "   ~/.config/openbox/autostart.sh",
                "   ~/.config/openbox/menu.xml",
                "   ~/.vim/syntax/blog_e.vim",
                "   ~/.vim/syntax/book_e.vim",
                "other",
                "   ../cs_flame/trunk/f.otl",
                "   /media/SONY",
                "z.py",
                "zsm.py",
                "year.otl",
                "dater.otl",
                "~/hive/python/lab12.txt",
                "~/hive/python/lab11.txt",
                "~/hive/myprog/tester/01/questor.py",
                "~/hive/myprog/tester/01/tk.py",
                "~/hive/myprog/tester/01/.",
                "моделайн",
                "| vim:foldlevel=0 ar go-=m go-=T go-=r go-=L go-=e tw=72 ts=3 sw=3 fo-=t path+=.,.."]

    ###################################################################################
    #                                основной блок                                    #
    ###################################################################################

    for blog in blogolist:

        tm = blog

        # открываем файл и считываем оттуда текст

        fh = open(tm,'rb')
        line = fh.readlines()
        fh.close()

        zag = [] # список заголовков
        num = [] # номера строк
        link = []# сборник линков на заголовки

        # проходим по тексту и модифицируем содержимое

        for i in range(len(line)):
            stroka = line[i]
            if stroka[0] == '#':
                zag.append(stroka)
                num.append(i)


        for j in range(len(zag)):
            zag[j] = zag[j].replace('#','\t')
            link.append(str(zag[j].partition(' ')[0] + '| '+ tm + ' : ' +str(num[j]+1)))

        # выдаем в stdout заголовок файла
        # print blog
        print "  "+blog

        # выдаем в stdout содержимое
        for j in range(len(zag)):
            print(zag[j]+'\t'+link[j])
        print "\t\tдля записи в журнал:"
        print ('\t\t| '+ tm + ' : ' +str(len(line)+1))

        if tm == 'main.txt':
            endlist.append(tm + ' : ' +str(len(line)+1))


    # print "\t\tдля дневниковой записи:"
    # print ('\t\t| main.txt : ' +str(len(line)+1))


    for i in endlist:
        print i

if __name__ == "__main__":
  main()

.vimrc — привязки для работы


" вызов Большой Карты по F11
" --------------------------------
map <F11> :b index.otl<CR>

" reindexer
"  переиндексирует главное содержание
" --------------------------------
map <F9> :!python z.py > index.otl<CR>

"  хоткеи Большой Карты
" --------------------------------
au BufNewFile,BufRead *.otl map <buffer> gf gF
au BufNewFile,BufRead *.otl map <buffer> <CR> gF
au BufNewFile,BufRead index.otl map <buffer> <RightMouse> gF

Малая Карта

Малая карта основана на старом скрипте — собственно в той заметке и объясняется как оно работает.

zsm.py — генерирует Малую Карту


# -*- coding: utf8 -*-

import sys

def main():

    name = sys.argv[1:]
    tm = str(name[-1])

    # открываем файл и считываем оттуда текст

    fh = open(tm,'rb')
    line = fh.readlines()
    fh.close()

    zag = [] # список заголовков

    # проходим по тексту и модифицируем содержимое

    for i in range(len(line)):
        stroka = line[i]
        if stroka[0] == '#':
            zag.append(stroka.replace('#','\t'))

    # выдаем в stdout содержимое
    for j in zag:
        print j,

    # дополняем содержимое моделайном
    print ('\t\t| '+ tm + ' : ' +str(len(line)+1))
    print "| vim:foldlevel=1 ar go-=m go-=T go-=r go-=L go-=e tw=72 ts=3 sw=3 fo-=t path+=.,.."

if __name__ == "__main__":
  main()

Привязки для .vimrc


" Малая Карта ---------------------------------------------------
" здесь и далее - МалаяКарта == МК

" Основная идея - по F12 открыть боковое окно с деревом файла.
" по энтеру файл прокручивается к нужному заголовку
" по повторному F12 - закрывается

function! SmallMap_Close()
    " закрываем окно МК

    execute "bd!"
    normal zt

    " варианты на правое-нижнее открытие меню
    "set nosplitright
    "set nosplitbelow

endfunction

function! SmallMap()
    " проверяется - где находится курсор


    " варианты на правое-нижнее открытие меню
    "set splitright
    "set splitbelow

    if bufname("%") == "sm.otl"
    " если внутри sm.otl - то файл проматывается на заголовок курсора

        " сохраняем значение буфера q

        let MainBuf = @"
        let TempQ = @q
        let @q = ''

        " копируем тег в q
        "на всякий случай - проверяется открыта ли вкладка
        normal zo
        "меняем табы на шарпы - так проще чем работать с переменными
        execute "s/\t/#/g"
        "копируем заголовок в q - без абзаца в конце
        normal 0v$h"qy
        "меняем шарпы на табы - чтобы вернуть файл к исходной позиции
        execute "s/#/\t/g"

        " полученный заголовок сохраняем в переменной
        let Zagolovok = @q
        " восстанавливаем содержимое регистра
        let @q = TempQ
        let @" = MainBuf

        " прыгаем в окно большого файла
        execute "normal \<C-W>w"

        call cursor(1,1) " переставляет курсор в начало
        call search('^'.Zagolovok) " находит заданный заголовок

        " откручиваем заголовок в самую верхнюю строку
        normal zt

        " прыгаем назад в меню
        execute "normal \<C-W>w"


    else
    " если нет - создаем sm.otl и переназначаем Enter и F12

        "создаем МК
        execute "!python zsm.py % > sm.otl"
        "открываем файл МК в боковом сплите (возможны разные варианты)
        execute "40vsplit sm.otl"

        map <buffer> <Return> :call SmallMap()<CR>
        " теперь Enter вызывает SmallMap и соответственно проматывает файл
        map <buffer> <F12> :call SmallMap_Close()<CR>
        " теперь F12 вызывает SmallMap_Close и закрывает файл
    endif
endfunction

map <F12> :call SmallMap()<CR>

вот примерно и все что я хотел сказать о Большой и Малой Картах.

Реклама

3 Responses to АБТФ: большая и малая карты

  1. Уф… На ночь глядя не осилил. :) Буду утром читать.

  2. Ну… текст большой все-таки. Кроме того, у меня где-то на задворках подсознания бродит идея свести все в полный туториал, вместо разрозненных постов по всем журналам.

  3. […] содержания. У меня есть удобный инструмент в виде Малой Карты, а сегодня обнаружилось тоже удобное и, на удивление, […]

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: