Возвышенная сортировка текста по отступу
Я ищу плагин Sublime Text или любую другую программу, которая может сортировать по алфавиту, но с учетом отступов.
Например,
beatsByUserPath: (userId) ->
"/api/beats/by_user/#{userId}"
sendMassMessagePath: ->
"/api/send_mass_message"
sendMessagePath: (userId) ->
"/api/send_message/#{userId}"
feedbackCreatePath: ->
"/api/feedbacks"
Будет отсортировано по именам функций. Использование сортировки по умолчанию в Sublime Text приводит к:
"/api/beats/by_user/#{userId}"
"/api/feedbacks"
"/api/send_mass_message"
"/api/send_message/#{userId}"
beatsByUserPath: (userId) ->
feedbackCreatePath: ->
sendMassMessagePath: ->
sendMessagePath: (userId) ->
Вот полный файл, который я хотел бы отсортировать.
RouteHelper =
EXTERNAL:
soundcloudConvertPath: (url) ->
url = encodeURIComponent(url)
"http://streampocket.com/?stream=#{url}"
youtubeConvertPath: (url) ->
url = encodeURIComponent(url)
"http://www.video2mp3.net/loading.php?url=#{url}"
UTIL:
imageProxy: (url) ->
url = encodeURIComponent(url)
"/image-proxy/#{url}"
API:
beatsReportPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/report"
beatsTrackDownloadPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/track_download"
beatSetDownloadPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/set_download_url"
beatsToggleVisibilityPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/toggle_visibility"
beatsToggleRecordingPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/toggle_recording"
beatsDisownPath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/disown"
beatsEditNotePath: (param) ->
beatId = param
beatId = param.id if typeof param is 'object' && param.id
"/api/beats/#{beatId}/edit_note"
beatsByUserPath: (userId) ->
"/api/beats/by_user/#{userId}"
discussPath: ->
"/api/discuss"
sendMassMessagePath: ->
"/api/send_mass_message"
sendMessagePath: (userId) ->
"/api/send_message/#{userId}"
feedbackCreatePath: ->
"/api/feedbacks"
feedbacksForRapPath: (arg) ->
rapId = if typeof rap is 'object' then arg.id else arg
"/api/feedbacks/feedback_for/#{rapId}"
followersPath: (userId) ->
"/api/followers/#{userId}"
followingPath: (userId) ->
"/api/following/#{userId}"
followPath: (userId) ->
"/api/follow/#{userId}"
unfollowPath: (userId) ->
"/api/unfollow/#{userId}"
propsPath: ->
"/api/props"
userBattlesPath_deprecated: (userId) ->
"/api/battles/for_user/#{userId}"
battlesLeaderboardPath: ->
"/api/battles/leaderboard"
battlesUsersWhoVotedForPath: (opts) ->
throw Error('RouteHelper: Expected ID and WHICH') if !opts.id || !opts.which
"/api/battles/#{opts.id}/users_who_voted_for/#{opts.which}"
rapProppersPath: (rapId) ->
"/api/raps/#{rapId}/proppers"
rapUntagPath: (rapId) ->
"/api/raps/#{rapId}/untag"
rapShowPath: (param) ->
if typeof param is 'object'
rapId = param.id
else rapId = param
"/api/raps/#{rapId}/show_v2"
userPinPath: ->
"/api/users/pin"
userBattlesPath: (userId) ->
"/api/users/#{userId}/battles"
userBeatsPath: (userId) ->
"/api/users/#{userId}/beats"
userRapsPath: (userId) ->
"/api/users/#{userId}/raps_v2"
userSetColorsPath: (userId) ->
"/api/users/#{userId}/set_colors"
userShowPath: (userId) ->
"/api/users/#{userId}"
usersWhoGaveProps: (userId) ->
"/api/users/#{userId}/users_who_gave_props"
userUnreadNotifCount: (userId) ->
"/api/users/#{userId}/unread_notif_count"
userRecordNetegoPath: ->
"/api/users/record_net_ego"
albumShowPath: (param) ->
param = param.slug if _.isObject(param)
"/albums/#{param}"
blueprintShowPathFromRap: (rap) ->
"/blueprints/#{rap.blueprint_id}"
battleDestroyPath: (battle) ->
"/battles/#{battle.id}"
battlesPath: ->
"/battles"
battleNewPath: ->
"/battles/new"
battleShowPath: (battle) ->
"/battles/#{battle.id}"
beatNewPath: ->
"/beats/new"
beatShowPath: (beat) ->
if typeof beat is 'number'
"/beats/#{beat}"
else if typeof beat is 'object'
if beat.slug
"/beats/#{beat.slug}"
else
"/beats/#{beat.id}"
beatTagShowPath: (beatTag) ->
"#{beatTag.slug}/instrumentals"
beatsSearchQueryPath: ->
"/beats/search_query"
beatsRecentSearchesPath: ->
"/beats/recent_searches"
cypherJudgeVotePath: ->
"/cyphers/judge-vote"
cypherJudgeShowPath: ->
"/cyphers/judge-show"
cypherSubmitPath: ->
"/cyphers/submit"
dashboardPath: ->
"/dashboard"
defaultRapThumbnailPath: ->
"/images/default_rap.png"
rhymePath: ->
"/rhyme"
contextPath: ->
"/context"
searchLyricsPath: ->
"/rap/search_lyrics"
editorSavePath: ->
"/editor/save"
editorPath: (param) ->
param = param.id if typeof param is 'object'
if param
"/editor/#{param}"
else
"/editor"
onRapSaveDialogPath: (rapId) ->
"/rap/#{rapId}/on_save_dialog"
lyricSyncSavePath: ->
"/lyric-sync/save"
lyricSyncDestroyPath: ->
"/lyric-sync/destroy"
notificationsPath: ->
"/notifications"
rapEditPath: (rap) ->
"/editor/#{rap.id}"
rapShowPath: (rap) ->
"/rap/#{rap.id}"
rapsForCypher: (cypherId) ->
"/cyphers/#{cypherId}/submissions"
isSubscribedPath: (listId) ->
"/is_subscribed/#{listId}"
subscribeToPath: (listId) ->
"/subscribe_to/#{listId}"
userShowPath: (username) ->
"/users/#{username}"
userNotificationSettingPath: ->
"/users/notification_setting"
@RouteHelper = RouteHelper
2 ответа
Увидев обновленный вопрос с примером полного файла, я пошел дальше и создал плагин Sublime Text с некоторыми базовыми опциями для управления сортировкой.
- устанавливать
IndentRespectfulSort
из пакета управления (см. инструкции https://packagecontrol.io/packages/Indent%20Respectful%20Sort). - Откройте консоль с помощью
Ctrl + `
или жеCmd(⌘) + `
(OSX). Предполагая, что ваш файл имеет отступ в 2 пробела, как в вопросе, и вы хотите отсортировать только имена функций, введите
view.run_command("indent_respectful_sort", {"indent": " ", "onlyDepth" : 3})
в консоль и нажмите
Enter
, Это позволит отсортировать только имена функций, соблюдая при этом остальную часть структуры.
Если вы хотите сортировать по разным опциям, вы можете обратиться к странице плагина https://github.com/mvnural/sublime-indent-respectful-sort чтобы увидеть больше опций.
Я не знаю об общем решении, поскольку определение блока (для целей сортировки) сильно зависит от контекста.
Однако для конкретного случая, который вы опубликовали, это может быть легко выполнено простым макросом со следующими шагами:
- Объединить каждый блок в одну строку (заменить каждое вхождение
->\n
с->
) - Сортировать отдельные строки
- Разблокировать каждый блок из одной строки обратно в исходную форму с отступом (заменить каждое вхождение
->
с->\n
)
Единственная проблема в том, что Sublime не записывает команды поиска и замены в макросе. Вместо этого нам нужно установить RegReplace
пакет, который предоставляет команды поиска и замены, которые могут быть записаны в макрос. (См. http://facelessuser.github.io/RegReplace/installation/ для инструкций по установке)
однажды RegReplace
установлен, просто поместите следующие два файла в Packages/User/
в вашем каталоге данных ( Какой полный путь к папке Packages для Sublime text 2 в Mac OS Lion)
Теперь вы можете запустить smart_sort
выбрав Tools -> Macros -> smart_sort
из верхнего меню.
Отказ от ответственности: если у вас более 1 строки с отступом на функцию, вам необходимо соответствующим образом изменить определения регулярных выражений.
smart_sort.sublime-macro
(макрос)
[
{
"args":
{
"replacements":
[
"merge_block_into_a_line"
]
},
"command": "reg_replace"
},
{
"args":
{
"case_sensitive": false
},
"command": "sort_lines"
},
{
"args":
{
"replacements":
[
"restore_block"
]
},
"command": "reg_replace"
}
]
reg_replace.sublime-settings
(определения reg_replace)
{
"replacements": {
"merge_block_into_a_line": {
"find": "->\\n",
"replace": "->",
"greedy": true,
"case": true
},
"restore_block": {
"find": "->",
"replace": "->\\n",
"greedy": true,
"case": true
}
}
}